summaryrefslogtreecommitdiff
path: root/VRCSDK3AvatarsLegacy/Assets/_PoiyomiShaders/Shaders/Includes/CGI_PoiMSDF.cginc
blob: 1644edee303c220910922340eac333bc49451746 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
#ifndef POI_MSDF
    #define POI_MSDF
    
    sampler2D _TextGlyphs; float4 _TextGlyphs_ST; float4 _TextGlyphs_TexelSize;
    uint _TextFPSUV, _TextTimeUV, _TextPositionUV;
    float _TextPixelRange;
    
    float _TextFPSEnabled, _TextPositionEnabled, _TextTimeEnabled;
    
    
    float4 _TextFPSColor;
    half _TextFPSEmissionStrength;
    fixed4 _TextFPSPadding;
    half2 _TextFPSOffset, _TextFPSScale;
    half _TextFPSRotation;
    
    fixed _TextPositionVertical;
    float4 _TextPositionColor;
    half _TextPositionEmissionStrength;
    fixed4 _TextPositionPadding;
    half2 _TextPositionOffset, _TextPositionScale;
    half _TextPositionRotation;
    
    float4 _TextTimeColor;
    half _TextTimeEmissionStrength;
    fixed4 _TextTimePadding;
    half2 _TextTimeOffset, _TextTimeScale;
    half _TextTimeRotation;
    
    #define glyphWidth 0.0625
    
    #define ASCII_LEFT_PARENTHESIS 40
    #define ASCII_RIGHT_PARENTHESIS 41
    #define ASCII_POSITIVE 43
    #define ASCII_PERIOD 46
    #define ASCII_NEGATIVE 45
    #define ASCII_COMMA 44
    #define ASCII_E 69
    #define ASCII_F 70
    #define ASCII_I 73
    #define ASCII_M 77
    #define ASCII_O 79
    #define ASCII_P 80
    #define ASCII_S 83
    #define ASCII_T 54
    #define ASCII_SEMICOLON 58
    
    float3 globalTextEmission;
    
    half2 getAsciiCoordinate(float index)
    {
        return half2((index - 1) / 16, 1 - ((floor(index / 16 - glyphWidth)) / 16));
    }
    
    float median(float r, float g, float b)
    {
        return max(min(r, g), min(max(r, g), b));
    }
    
    void ApplyPositionText(inout float4 albedo, float2 uv)
    {
        float3 cameraPos = clamp(getCameraPosition(), -999, 999);
        float3 absCameraPos = abs(cameraPos);
        float totalCharacters = 20;
        float positionArray[20];
        positionArray[0] = cameraPos.x >= 0 ? ASCII_NEGATIVE: ASCII_POSITIVE;
        positionArray[1] = floor((absCameraPos.x * .01) % 10) + 48;
        positionArray[2] = floor((absCameraPos.x * .1) % 10) + 48;
        positionArray[3] = floor(absCameraPos.x % 10) + 48;
        positionArray[4] = ASCII_PERIOD;
        positionArray[5] = floor((absCameraPos.x * 10) % 10) + 48;
        positionArray[6] = ASCII_COMMA;
        positionArray[7] = cameraPos.y >= 0 ? ASCII_NEGATIVE: ASCII_POSITIVE;
        positionArray[8] = floor((absCameraPos.y * .01) % 10) + 48;
        positionArray[9] = floor((absCameraPos.y * .1) % 10) + 48;
        positionArray[10] = floor(absCameraPos.y % 10) + 48;
        positionArray[11] = ASCII_PERIOD;
        positionArray[12] = floor((absCameraPos.y * 10) % 10) + 48;
        positionArray[13] = ASCII_COMMA;
        positionArray[14] = cameraPos.z >= 0 ? ASCII_NEGATIVE: ASCII_POSITIVE;
        positionArray[15] = floor((absCameraPos.z * .01) % 10) + 48;
        positionArray[16] = floor((absCameraPos.z * .1) % 10) + 48;
        positionArray[17] = floor(absCameraPos.z % 10) + 48;
        positionArray[18] = ASCII_PERIOD;
        positionArray[19] = floor((absCameraPos.z * 10) % 10) + 48;
        
        uv = TransformUV(_TextPositionOffset, _TextPositionRotation, _TextPositionScale, uv);
        
        if (uv.x > 1 || uv.x < 0 || uv.y > 1 || uv.y < 0)
        {
            return;
        }
        
        float currentCharacter = floor(uv.x * totalCharacters);
        half2 glyphPos = getAsciiCoordinate(positionArray[currentCharacter]);
        
        float2 startUV = float2(1 / totalCharacters * currentCharacter, 0);
        float2 endUV = float2(1 / totalCharacters * (currentCharacter + 1), 1);
        
        _TextPositionPadding *= 1 / totalCharacters;
        uv = remapClamped(uv, startUV, endUV, float2(glyphPos.x + _TextPositionPadding.x, glyphPos.y - glyphWidth + _TextPositionPadding.y), float2(glyphPos.x + glyphWidth - _TextPositionPadding.z, glyphPos.y - _TextPositionPadding.w));
                
        if (uv.x > glyphPos.x + glyphWidth - _TextPositionPadding.z - .001 || uv.x < glyphPos.x + _TextPositionPadding.x + .001 || uv.y > glyphPos.y - _TextPositionPadding.w - .001 || uv.y < glyphPos.y - glyphWidth + _TextPositionPadding.y + .001)
        {
            return;
        }
        
        float3 samp = tex2D(_TextGlyphs, TRANSFORM_TEX(uv, _TextGlyphs)).rgb;
        float2 msdfUnit = _TextPixelRange / _TextGlyphs_TexelSize.zw;
        float sigDist = median(samp.r, samp.g, samp.b) - 0.5;
        sigDist *= max(dot(msdfUnit, 0.5 / fwidth(uv)), 1);
        float opacity = clamp(sigDist + 0.5, 0, 1);
        albedo.rgb = lerp(albedo.rgb, _TextPositionColor.rgb, opacity * _TextPositionColor.a);
        globalTextEmission += _TextPositionColor.rgb * opacity * _TextPositionEmissionStrength;
    }
    
    void ApplyTimeText(inout float4 albedo, float2 uv)
    {
        float instanceTime = _Time.y;
        float hours = instanceTime / 3600;
        float minutes = (instanceTime / 60) % 60;
        float seconds = instanceTime % 60;
        float totalCharacters = 8;
        float timeArray[8];
        timeArray[0] = floor((hours * .1) % 10) + 48;
        timeArray[1] = floor(hours % 10) + 48;
        timeArray[2] = ASCII_SEMICOLON;
        timeArray[3] = floor((minutes * .1) % 10) + 48;
        timeArray[4] = floor(minutes % 10) + 48;
        timeArray[5] = ASCII_SEMICOLON;
        timeArray[6] = floor((seconds * .1) % 10) + 48;
        timeArray[7] = floor(seconds % 10) + 48;
        
        uv = TransformUV(_TextTimeOffset, _TextTimeRotation, _TextTimeScale, uv);
        
        if(uv.x > 1 || uv.x < 0 || uv.y > 1 || uv.y < 0)
        {
            return;
        }
        
        float currentCharacter = floor(uv.x * totalCharacters);
        half2 glyphPos = getAsciiCoordinate(timeArray[currentCharacter]);
        // 0.1428571 = 1/7 = 1 / totalCharacters
        float startUV = 1 / totalCharacters * currentCharacter;
        float endUV = 1 / totalCharacters * (currentCharacter + 1);
        _TextTimePadding *= 1 / totalCharacters;
        uv = remapClamped(uv, float2(startUV, 0), float2(endUV, 1), float2(glyphPos.x + _TextTimePadding.x, glyphPos.y - glyphWidth + _TextTimePadding.y), float2(glyphPos.x + glyphWidth - _TextTimePadding.z, glyphPos.y - _TextTimePadding.w));
        
        if (uv.x > glyphPos.x + glyphWidth - _TextTimePadding.z - .001 || uv.x < glyphPos.x + _TextTimePadding.x + .001 || uv.y > glyphPos.y - _TextTimePadding.w - .001 || uv.y < glyphPos.y - glyphWidth + _TextTimePadding.y + .001)
        {
            return;
        }

        float3 samp = tex2D(_TextGlyphs, TRANSFORM_TEX(uv, _TextGlyphs)).rgb;
        float2 msdfUnit = _TextPixelRange / _TextGlyphs_TexelSize.zw;
        float sigDist = median(samp.r, samp.g, samp.b) - 0.5;
        sigDist *= max(dot(msdfUnit, 0.5 / fwidth(uv)), 1);
        float opacity = clamp(sigDist + 0.5, 0, 1);
        albedo.rgb = lerp(albedo.rgb, _TextTimeColor.rgb, opacity * _TextTimeColor.a);
        globalTextEmission += _TextTimeColor.rgb * opacity * _TextTimeEmissionStrength;
    }
    
    void ApplyFPSText(inout float4 albedo, float2 uv)
    {
        float smoothDeltaTime = clamp(unity_DeltaTime.w, 0, 999);
        float totalCharacters = 7;
        float fpsArray[7];
        fpsArray[0] = ASCII_F;
        fpsArray[1] = ASCII_P;
        fpsArray[2] = ASCII_S;
        fpsArray[3] = ASCII_SEMICOLON;
        fpsArray[4] = floor((smoothDeltaTime * .01) % 10) + 48;
        fpsArray[5] = floor((smoothDeltaTime * .1) % 10) + 48;
        fpsArray[6] = floor(smoothDeltaTime % 10) + 48;
        
        uv = TransformUV(_TextFPSOffset, _TextFPSRotation, _TextFPSScale, uv);
        
        if(uv.x > 1 || uv.x < 0 || uv.y > 1 || uv.y < 0)
        {
            return;
        }
        
        float currentCharacter = floor(uv.x * totalCharacters);
        half2 glyphPos = getAsciiCoordinate(fpsArray[currentCharacter]);
        // 0.1428571 = 1/7 = 1 / totalCharacters
        float startUV = 1 / totalCharacters * currentCharacter;
        float endUV = 1 / totalCharacters * (currentCharacter + 1);
        _TextFPSPadding *= 1 / totalCharacters;
        uv = remapClamped(uv, float2(startUV, 0), float2(endUV, 1), float2(glyphPos.x + _TextFPSPadding.x, glyphPos.y - glyphWidth + _TextFPSPadding.y), float2(glyphPos.x + glyphWidth - _TextFPSPadding.z, glyphPos.y - _TextFPSPadding.w));
        
        if (uv.x > glyphPos.x + glyphWidth - _TextFPSPadding.z - .001 || uv.x < glyphPos.x + _TextFPSPadding.x + .001 || uv.y > glyphPos.y - _TextFPSPadding.w - .001 || uv.y < glyphPos.y - glyphWidth + _TextFPSPadding.y + .001)
        {
            return;
        }
        
        float3 samp = tex2D(_TextGlyphs, TRANSFORM_TEX(uv, _TextGlyphs)).rgb;
        float2 msdfUnit = _TextPixelRange / _TextGlyphs_TexelSize.zw;
        float sigDist = median(samp.r, samp.g, samp.b) - 0.5;
        sigDist *= max(dot(msdfUnit, 0.5 / fwidth(uv)), 1);
        float opacity = clamp(sigDist + 0.5, 0, 1);
        albedo.rgb = lerp(albedo.rgb, _TextFPSColor.rgb, opacity * _TextFPSColor.a);
        globalTextEmission += _TextFPSColor.rgb * opacity * _TextFPSEmissionStrength;
    }
    
    void ApplyTextOverlayColor(inout float4 albedo)
    {
        globalTextEmission = 0;
        half positionalOpacity = 0;
        #ifdef EFFECT_BUMP
            UNITY_BRANCH
            if(_TextFPSEnabled)
            {
                ApplyFPSText(albedo, poiMesh.uv[_TextFPSUV]);
            }
            UNITY_BRANCH
            if(_TextPositionEnabled)
            {
                ApplyPositionText(albedo, poiMesh.uv[_TextPositionUV]);
            }
            UNITY_BRANCH
            if(_TextTimeEnabled)
            {
                ApplyTimeText(albedo, poiMesh.uv[_TextTimeUV]);
            }
        #endif
    }
    
    void ApplyTextOverlayEmission(inout float3 emission)
    {
        emission += globalTextEmission;
    }
    
    
    
#endif