A game about forced loneliness, made by TACStudios
1// Simplified SDF shader:
2// - No Shading Option (bevel / bump / env map)
3// - No Glow Option
4// - Softness is applied on both side of the outline
5
6Shader "TextMeshPro/Mobile/Distance Field - 2 Pass" {
7
8Properties {
9 _FaceColor ("Face Color", Color) = (1,1,1,1)
10 _FaceDilate ("Face Dilate", Range(-1,1)) = 0
11
12 _OutlineColor ("Outline Color", Color) = (0,0,0,1)
13 _OutlineWidth ("Outline Thickness", Range(0,1)) = 0
14 _OutlineSoftness ("Outline Softness", Range(0,1)) = 0
15
16 _UnderlayColor ("Border Color", Color) = (0,0,0,.5)
17 _UnderlayOffsetX ("Border OffsetX", Range(-1,1)) = 0
18 _UnderlayOffsetY ("Border OffsetY", Range(-1,1)) = 0
19 _UnderlayDilate ("Border Dilate", Range(-1,1)) = 0
20 _UnderlaySoftness ("Border Softness", Range(0,1)) = 0
21
22 _WeightNormal ("Weight Normal", float) = 0
23 _WeightBold ("Weight Bold", float) = .5
24
25 _ShaderFlags ("Flags", float) = 0
26 _ScaleRatioA ("Scale RatioA", float) = 1
27 _ScaleRatioB ("Scale RatioB", float) = 1
28 _ScaleRatioC ("Scale RatioC", float) = 1
29
30 _MainTex ("Font Atlas", 2D) = "white" {}
31 _TextureWidth ("Texture Width", float) = 512
32 _TextureHeight ("Texture Height", float) = 512
33 _GradientScale ("Gradient Scale", float) = 5
34 _ScaleX ("Scale X", float) = 1
35 _ScaleY ("Scale Y", float) = 1
36 _PerspectiveFilter ("Perspective Correction", Range(0, 1)) = 0.875
37 _Sharpness ("Sharpness", Range(-1,1)) = 0
38
39 _VertexOffsetX ("Vertex OffsetX", float) = 0
40 _VertexOffsetY ("Vertex OffsetY", float) = 0
41
42 _ClipRect ("Clip Rect", vector) = (-32767, -32767, 32767, 32767)
43 _MaskSoftnessX ("Mask SoftnessX", float) = 0
44 _MaskSoftnessY ("Mask SoftnessY", float) = 0
45
46 _StencilComp ("Stencil Comparison", Float) = 8
47 _Stencil ("Stencil ID", Float) = 0
48 _StencilOp ("Stencil Operation", Float) = 0
49 _StencilWriteMask ("Stencil Write Mask", Float) = 255
50 _StencilReadMask ("Stencil Read Mask", Float) = 255
51
52 _CullMode ("Cull Mode", Float) = 0
53 _ColorMask ("Color Mask", Float) = 15
54}
55
56SubShader {
57
58 // Draw Outline and Underlay
59 Name "Outline"
60
61 Tags
62 {
63 "Queue"="Transparent"
64 "IgnoreProjector"="True"
65 "RenderType"="Transparent"
66 }
67
68 Stencil
69 {
70 Ref [_Stencil]
71 Comp [_StencilComp]
72 Pass [_StencilOp]
73 ReadMask [_StencilReadMask]
74 WriteMask [_StencilWriteMask]
75 }
76
77 Cull [_CullMode]
78 ZWrite Off
79 Lighting Off
80 Fog { Mode Off }
81 ZTest [unity_GUIZTestMode]
82 Blend One OneMinusSrcAlpha
83 ColorMask [_ColorMask]
84
85 Pass {
86 CGPROGRAM
87 #pragma vertex VertShader
88 #pragma fragment PixShader
89 #pragma shader_feature __ OUTLINE_ON
90 #pragma shader_feature __ UNDERLAY_ON UNDERLAY_INNER
91
92 #pragma multi_compile __ UNITY_UI_CLIP_RECT
93 #pragma multi_compile __ UNITY_UI_ALPHACLIP
94
95 #include "UnityCG.cginc"
96 #include "UnityUI.cginc"
97 #include "TMPro_Properties.cginc"
98
99 struct vertex_t {
100 UNITY_VERTEX_INPUT_INSTANCE_ID
101 float4 vertex : POSITION;
102 float3 normal : NORMAL;
103 fixed4 color : COLOR;
104 float4 texcoord0 : TEXCOORD0;
105 float2 texcoord1 : TEXCOORD1;
106 };
107
108 struct pixel_t {
109 UNITY_VERTEX_INPUT_INSTANCE_ID
110 UNITY_VERTEX_OUTPUT_STEREO
111 float4 vertex : SV_POSITION;
112 fixed4 faceColor : COLOR;
113 fixed4 outlineColor : COLOR1;
114 float4 texcoord0 : TEXCOORD0; // Texture UV, Mask UV
115 half4 param : TEXCOORD1; // Scale(x), BiasIn(y), BiasOut(z), Bias(w)
116 half4 mask : TEXCOORD2; // Position in clip space(xy), Softness(zw)
117 #if (UNDERLAY_ON | UNDERLAY_INNER)
118 float4 texcoord1 : TEXCOORD3; // Texture UV, alpha, reserved
119 half2 underlayParam : TEXCOORD4; // Scale(x), Bias(y)
120 #endif
121 };
122
123 float _UIMaskSoftnessX;
124 float _UIMaskSoftnessY;
125
126 pixel_t VertShader(vertex_t input)
127 {
128 pixel_t output;
129
130 UNITY_INITIALIZE_OUTPUT(pixel_t, output);
131 UNITY_SETUP_INSTANCE_ID(input);
132 UNITY_TRANSFER_INSTANCE_ID(input, output);
133 UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(output);
134
135 const float bold = step(input.texcoord0.w, 0);
136
137 float4 vert = input.vertex;
138 vert.x += _VertexOffsetX;
139 vert.y += _VertexOffsetY;
140 float4 vPosition = UnityObjectToClipPos(vert);
141
142 float2 pixelSize = vPosition.w;
143 pixelSize /= float2(_ScaleX, _ScaleY) * abs(mul((float2x2)UNITY_MATRIX_P, _ScreenParams.xy));
144
145 float scale = rsqrt(dot(pixelSize, pixelSize));
146 scale *= abs(input.texcoord0.w) * _GradientScale * (_Sharpness + 1);
147 if(UNITY_MATRIX_P[3][3] == 0) scale = lerp(abs(scale) * (1 - _PerspectiveFilter), scale, abs(dot(UnityObjectToWorldNormal(input.normal.xyz), normalize(WorldSpaceViewDir(vert)))));
148
149 float weight = lerp(_WeightNormal, _WeightBold, bold) / 4.0;
150 weight = (weight + _FaceDilate) * _ScaleRatioA * 0.5;
151
152 float layerScale = scale;
153
154 scale /= 1 + (_OutlineSoftness * _ScaleRatioA * scale);
155 float bias = (0.5 - weight) * scale - 0.5;
156 const float outline = _OutlineWidth * _ScaleRatioA * 0.5 * scale;
157
158 float opacity = input.color.a;
159 #if (UNDERLAY_ON | UNDERLAY_INNER)
160 opacity = 1.0;
161 #endif
162
163 fixed4 faceColor = fixed4(input.color.rgb, opacity) * _FaceColor;
164 faceColor.rgb *= faceColor.a;
165
166 fixed4 outlineColor = _OutlineColor;
167 outlineColor.a *= opacity;
168 outlineColor.rgb *= outlineColor.a;
169 //outlineColor = lerp(faceColor, outlineColor, sqrt(min(1.0, outline * 2)));
170
171 #if (UNDERLAY_ON | UNDERLAY_INNER)
172 layerScale /= 1 + ((_UnderlaySoftness * _ScaleRatioC) * layerScale);
173 float layerBias = (.5 - weight) * layerScale - .5 - ((_UnderlayDilate * _ScaleRatioC) * .5 * layerScale);
174
175 float x = -(_UnderlayOffsetX * _ScaleRatioC) * _GradientScale / _TextureWidth;
176 float y = -(_UnderlayOffsetY * _ScaleRatioC) * _GradientScale / _TextureHeight;
177 float2 layerOffset = float2(x, y);
178 #endif
179
180 // Generate UV for the Masking Texture
181 float4 clampedRect = clamp(_ClipRect, -2e10, 2e10);
182 float2 maskUV = (vert.xy - clampedRect.xy) / (clampedRect.zw - clampedRect.xy);
183
184 // Populate structure for pixel shader
185 output.vertex = vPosition;
186 output.faceColor = faceColor;
187 output.outlineColor = outlineColor;
188 output.texcoord0 = float4(input.texcoord0.x, input.texcoord0.y, maskUV.x, maskUV.y);
189 output.param = half4(scale, bias - outline, bias + outline, bias);
190
191 const half2 maskSoftness = half2(max(_UIMaskSoftnessX, _MaskSoftnessX), max(_UIMaskSoftnessY, _MaskSoftnessY));
192 output.mask = half4(vert.xy * 2 - clampedRect.xy - clampedRect.zw, 0.25 / (0.25 * maskSoftness + pixelSize.xy));
193 #if (UNDERLAY_ON || UNDERLAY_INNER)
194 output.texcoord1 = float4(input.texcoord0 + layerOffset, input.color.a, 0);
195 output.underlayParam = half2(layerScale, layerBias);
196 #endif
197
198 return output;
199 }
200
201
202 // PIXEL SHADER
203 fixed4 PixShader(pixel_t input) : SV_Target
204 {
205 UNITY_SETUP_INSTANCE_ID(input);
206
207 half d = tex2D(_MainTex, input.texcoord0.xy).a * input.param.x;
208 half4 c = half4(0, 0, 0, 0);
209
210 #if OUTLINE_ON
211 c = input.outlineColor * saturate(d - input.param.y);
212 #endif
213
214 #if UNDERLAY_ON
215 d = tex2D(_MainTex, input.texcoord1.xy).a * input.underlayParam.x;
216 c += float4(_UnderlayColor.rgb * _UnderlayColor.a, _UnderlayColor.a) * saturate(d - input.underlayParam.y) * (1 - c.a);
217 #endif
218
219 #if UNDERLAY_INNER
220 half sd = saturate(d - input.param.z);
221 d = tex2D(_MainTex, input.texcoord1.xy).a * input.underlayParam.x;
222 c += float4(_UnderlayColor.rgb * _UnderlayColor.a, _UnderlayColor.a) * (1 - saturate(d - input.underlayParam.y)) * sd * (1 - c.a);
223 #endif
224
225 // Alternative implementation to UnityGet2DClipping with support for softness.
226 #if UNITY_UI_CLIP_RECT
227 half2 m = saturate((_ClipRect.zw - _ClipRect.xy - abs(input.mask.xy)) * input.mask.zw);
228 c *= m.x * m.y;
229 #endif
230
231 #if (UNDERLAY_ON | UNDERLAY_INNER)
232 c *= input.texcoord1.z;
233 #endif
234
235 #if UNITY_UI_ALPHACLIP
236 clip(c.a - 0.001);
237 #endif
238
239 return c;
240 }
241 ENDCG
242 }
243
244
245 // Draw face
246 Name "Face"
247
248 Tags
249 {
250 "Queue"="Transparent"
251 "IgnoreProjector"="True"
252 "RenderType"="Transparent"
253 }
254
255 Stencil
256 {
257 Ref [_Stencil]
258 Comp [_StencilComp]
259 Pass [_StencilOp]
260 ReadMask [_StencilReadMask]
261 WriteMask [_StencilWriteMask]
262 }
263
264 Cull [_CullMode]
265 ZWrite Off
266 Lighting Off
267 Fog { Mode Off }
268 ZTest [unity_GUIZTestMode]
269 Blend One OneMinusSrcAlpha
270 ColorMask [_ColorMask]
271
272 Pass {
273 CGPROGRAM
274 #pragma vertex VertShader
275 #pragma fragment PixShader
276
277 #pragma multi_compile __ UNITY_UI_CLIP_RECT
278 #pragma multi_compile __ UNITY_UI_ALPHACLIP
279
280 #include "UnityCG.cginc"
281 #include "UnityUI.cginc"
282 #include "TMPro_Properties.cginc"
283
284 struct vertex_t {
285 UNITY_VERTEX_INPUT_INSTANCE_ID
286 float4 vertex : POSITION;
287 float3 normal : NORMAL;
288 fixed4 color : COLOR;
289 float4 texcoord0 : TEXCOORD0;
290 float2 texcoord1 : TEXCOORD1;
291 };
292
293 struct pixel_t {
294 UNITY_VERTEX_INPUT_INSTANCE_ID
295 UNITY_VERTEX_OUTPUT_STEREO
296 float4 vertex : SV_POSITION;
297 fixed4 faceColor : COLOR;
298 float4 texcoord0 : TEXCOORD0; // Texture UV, Mask UV
299 half2 param : TEXCOORD1; // Scale(x), BiasIn(y), BiasOut(z), Bias(w)
300 half4 mask : TEXCOORD2; // Position in clip space(xy), Softness(zw)
301 };
302
303 float _UIMaskSoftnessX;
304 float _UIMaskSoftnessY;
305 int _UIVertexColorAlwaysGammaSpace;
306
307
308 pixel_t VertShader(vertex_t input)
309 {
310 pixel_t output;
311
312 UNITY_INITIALIZE_OUTPUT(pixel_t, output);
313 UNITY_SETUP_INSTANCE_ID(input);
314 UNITY_TRANSFER_INSTANCE_ID(input, output);
315 UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(output);
316
317 const float bold = step(input.texcoord0.w, 0);
318
319 float4 vert = input.vertex;
320 vert.x += _VertexOffsetX;
321 vert.y += _VertexOffsetY;
322 float4 vPosition = UnityObjectToClipPos(vert);
323
324 float2 pixelSize = vPosition.w;
325 pixelSize /= float2(_ScaleX, _ScaleY) * abs(mul((float2x2)UNITY_MATRIX_P, _ScreenParams.xy));
326
327 float scale = rsqrt(dot(pixelSize, pixelSize));
328 scale *= abs(input.texcoord0.w) * _GradientScale * (_Sharpness + 1);
329 if(UNITY_MATRIX_P[3][3] == 0) scale = lerp(abs(scale) * (1 - _PerspectiveFilter), scale, abs(dot(UnityObjectToWorldNormal(input.normal.xyz), normalize(WorldSpaceViewDir(vert)))));
330
331 float weight = lerp(_WeightNormal, _WeightBold, bold) / 4.0;
332 weight = (weight + _FaceDilate) * _ScaleRatioA * 0.5;
333
334 scale /= 1 + (_OutlineSoftness * _ScaleRatioA * scale);
335 float bias = (0.5 - weight) * scale - 0.5;
336
337 if (_UIVertexColorAlwaysGammaSpace && !IsGammaSpace())
338 {
339 input.color.rgb = UIGammaToLinear(input.color.rgb);
340 }
341 float opacity = input.color.a;
342
343 fixed4 faceColor = fixed4(input.color.rgb, opacity) * _FaceColor;
344 faceColor.rgb *= faceColor.a;
345
346 // Generate UV for the Masking Texture
347 float4 clampedRect = clamp(_ClipRect, -2e10, 2e10);
348 float2 maskUV = (vert.xy - clampedRect.xy) / (clampedRect.zw - clampedRect.xy);
349
350 // Populate structure for pixel shader
351 output.vertex = vPosition;
352 output.faceColor = faceColor;
353 output.texcoord0 = float4(input.texcoord0.x, input.texcoord0.y, maskUV.x, maskUV.y);
354 output.param = half2(scale, bias);
355
356 const half2 maskSoftness = half2(max(_UIMaskSoftnessX, _MaskSoftnessX), max(_UIMaskSoftnessY, _MaskSoftnessY));
357 output.mask = half4(vert.xy * 2 - clampedRect.xy - clampedRect.zw, 0.25 / (0.25 * maskSoftness + pixelSize.xy));
358
359 return output;
360 }
361
362
363 // PIXEL SHADER
364 fixed4 PixShader(pixel_t input) : SV_Target
365 {
366 UNITY_SETUP_INSTANCE_ID(input);
367
368 half d = tex2D(_MainTex, input.texcoord0.xy).a * input.param.x;
369 half4 c = input.faceColor * saturate(d - input.param.y);
370
371 // Alternative implementation to UnityGet2DClipping with support for softness.
372 #if UNITY_UI_CLIP_RECT
373 half2 m = saturate((_ClipRect.zw - _ClipRect.xy - abs(input.mask.xy)) * input.mask.zw);
374 c *= m.x * m.y;
375 #endif
376
377 #if UNITY_UI_ALPHACLIP
378 clip(c.a - 0.001);
379 #endif
380
381 return c;
382 }
383 ENDCG
384 }
385
386}
387
388CustomEditor "TMPro.EditorUtilities.TMP_SDFShaderGUI"
389}