Search Unity

Textmeshpro Bitmap Shadow Shader Help

Discussion in 'Shaders' started by TimeAxis, Jan 5, 2022.

  1. TimeAxis

    TimeAxis

    Joined:
    Jun 13, 2020
    Posts:
    1
    I'm trying to create a shader that renders a drop-shadow behind textmeshpro bitmap text, by making a pass where it renders the shadow (offset according to ShadowOffset), and then another pass where it renders the actual text.

    Unfortunately I can't seem to get multiple passes to work. It's only rendering the first pass. When I adjust the Shadow Offset, it moves the entire text around as if I were moving the text's vertex offset.

    Here is my code (I essentially just took TextMeshPro/Mobile/Bitmap.shader and copied and pasted the render pass with an added offset. Haven't messed with the color yet at this point. I commented out the SubShader section at the bottom because I didn't know what it was for and it didn't seem to make a difference one way or the other). Could anyone point me to where I'm going wrong here?

    Code (csharp):
    1. Shader "TextMeshPro/Mobile/Bitmap-Shadow" {
    2.  
    3. Properties {
    4.     _MainTex        ("Font Atlas", 2D) = "white" {}
    5.     [HDR]_Color        ("Text Color", Color) = (1,1,1,1)
    6.     _DiffusePower    ("Diffuse Power", Range(1.0,4.0)) = 1.0
    7.     _ShadowColor("Shadow", Color) = (0,0,0,1)
    8.     _ShadowOffset("ShadowOffset", Vector) = (1,-1,0,0)
    9.  
    10.     _VertexOffsetX("Vertex OffsetX", float) = 0
    11.     _VertexOffsetY("Vertex OffsetY", float) = 0
    12.     _MaskSoftnessX("Mask SoftnessX", float) = 0
    13.     _MaskSoftnessY("Mask SoftnessY", float) = 0
    14.  
    15.     _ClipRect("Clip Rect", vector) = (-32767, -32767, 32767, 32767)
    16.  
    17.     _StencilComp("Stencil Comparison", Float) = 8
    18.     _Stencil("Stencil ID", Float) = 0
    19.     _StencilOp("Stencil Operation", Float) = 0
    20.     _StencilWriteMask("Stencil Write Mask", Float) = 255
    21.     _StencilReadMask("Stencil Read Mask", Float) = 255
    22.  
    23.     _CullMode("Cull Mode", Float) = 0
    24.     _ColorMask("Color Mask", Float) = 15
    25.  
    26.     [MaterialToggle] PixelSnap("Pixel snap", Float) = 0
    27.  
    28. }
    29.  
    30. SubShader {
    31.  
    32.     Tags { "Queue"="Transparent" "IgnoreProjector"="True" "RenderType"="Transparent" }
    33.  
    34.     Stencil
    35.     {
    36.         Ref[_Stencil]
    37.         Comp[_StencilComp]
    38.         Pass[_StencilOp]
    39.         ReadMask[_StencilReadMask]
    40.         WriteMask[_StencilWriteMask]
    41.     }
    42.  
    43.  
    44.     Lighting Off
    45.     Cull [_CullMode]
    46.     ZTest [unity_GUIZTestMode]
    47.     ZWrite Off
    48.     Fog { Mode Off }
    49.     Blend SrcAlpha OneMinusSrcAlpha
    50.     ColorMask[_ColorMask]
    51.  
    52.     // Draw Shadow
    53.     Pass {
    54.         CGPROGRAM
    55.         #pragma vertex vert
    56.         #pragma fragment frag
    57.         #pragma fragmentoption ARB_precision_hint_fastest
    58.  
    59.         #pragma multi_compile __ UNITY_UI_CLIP_RECT
    60.         #pragma multi_compile __ UNITY_UI_ALPHACLIP
    61.  
    62.  
    63.         #include "UnityCG.cginc"
    64.  
    65.         struct appdata_t {
    66.             float4 vertex : POSITION;
    67.             fixed4 color : COLOR;
    68.             float2 texcoord0 : TEXCOORD0;
    69.             float2 texcoord1 : TEXCOORD1;
    70.         };
    71.  
    72.         struct v2f {
    73.             float4 vertex        : POSITION;
    74.             fixed4 color : COLOR;
    75.             float2 texcoord0    : TEXCOORD0;
    76.             float4 mask            : TEXCOORD2;
    77.         };
    78.  
    79.         sampler2D     _MainTex;
    80.         fixed4        _Color;
    81.         float        _DiffusePower;
    82.  
    83.         uniform float        _VertexOffsetX;
    84.         uniform float        _VertexOffsetY;
    85.         uniform float4        _ClipRect;
    86.         uniform float        _MaskSoftnessX;
    87.         uniform float        _MaskSoftnessY;
    88.         uniform float4        _ShadowOffset;
    89.  
    90.         v2f vert(appdata_t v)
    91.         {
    92.             v2f OUT;
    93.             float4 vert = v.vertex;
    94.             vert.x += _VertexOffsetX + _ShadowOffset.x;
    95.             vert.y += _VertexOffsetY + _ShadowOffset.y;
    96.  
    97.             vert.xy += (vert.w * 0.5) / _ScreenParams.xy;
    98.  
    99.             OUT.vertex = UnityPixelSnap(UnityObjectToClipPos(vert));
    100.             OUT.color = v.color;
    101.             OUT.color *= _Color;
    102.             OUT.color.rgb *= _DiffusePower;
    103.             OUT.texcoord0 = v.texcoord0;
    104.  
    105.             float2 pixelSize = OUT.vertex.w;
    106.             //pixelSize /= abs(float2(_ScreenParams.x * UNITY_MATRIX_P[0][0], _ScreenParams.y * UNITY_MATRIX_P[1][1]));
    107.  
    108.             // Clamp _ClipRect to 16bit.
    109.             float4 clampedRect = clamp(_ClipRect, -2e10, 2e10);
    110.             OUT.mask = float4(vert.xy * 2 - clampedRect.xy - clampedRect.zw, 0.25 / (0.25 * half2(_MaskSoftnessX, _MaskSoftnessY) + pixelSize.xy));
    111.  
    112.             return OUT;
    113.         }
    114.  
    115.         fixed4 frag(v2f IN) : COLOR
    116.         {
    117.             fixed4 color = fixed4(IN.color.rgb, IN.color.a * tex2D(_MainTex, IN.texcoord0).a);
    118.  
    119.         // Alternative implementation to UnityGet2DClipping with support for softness.
    120.         #if UNITY_UI_CLIP_RECT
    121.             half2 m = saturate((_ClipRect.zw - _ClipRect.xy - abs(IN.mask.xy)) * IN.mask.zw);
    122.             color *= m.x * m.y;
    123.         #endif
    124.  
    125.         #if UNITY_UI_ALPHACLIP
    126.             clip(color.a - 0.001);
    127.         #endif
    128.  
    129.         return color;
    130.         }
    131.     ENDCG
    132.     }
    133.  
    134.     // Draw Text
    135.     Pass {
    136.         CGPROGRAM
    137.         #pragma vertex vert
    138.         #pragma fragment frag
    139.         #pragma fragmentoption ARB_precision_hint_fastest
    140.  
    141.         #pragma multi_compile __ UNITY_UI_CLIP_RECT
    142.         #pragma multi_compile __ UNITY_UI_ALPHACLIP
    143.  
    144.  
    145.         #include "UnityCG.cginc"
    146.  
    147.         struct appdata_t {
    148.             float4 vertex : POSITION;
    149.             fixed4 color : COLOR;
    150.             float2 texcoord0 : TEXCOORD0;
    151.             float2 texcoord1 : TEXCOORD1;
    152.         };
    153.  
    154.         struct v2f {
    155.             float4 vertex        : POSITION;
    156.             fixed4 color        : COLOR;
    157.             float2 texcoord0    : TEXCOORD0;
    158.             float4 mask            : TEXCOORD2;
    159.         };
    160.  
    161.         sampler2D     _MainTex;
    162.         fixed4        _Color;
    163.         float        _DiffusePower;
    164.  
    165.         uniform float        _VertexOffsetX;
    166.         uniform float        _VertexOffsetY;
    167.         uniform float4        _ClipRect;
    168.         uniform float        _MaskSoftnessX;
    169.         uniform float        _MaskSoftnessY;
    170.         uniform float4        _ShadowOffset;
    171.  
    172.         v2f vert (appdata_t v)
    173.         {
    174.             v2f OUT;
    175.             float4 vert = v.vertex;
    176.             vert.x += _VertexOffsetX;
    177.             vert.y += _VertexOffsetY;
    178.  
    179.             vert.xy += (vert.w * 0.5) / _ScreenParams.xy;
    180.  
    181.             OUT.vertex = UnityPixelSnap(UnityObjectToClipPos(vert));
    182.             OUT.color = v.color;
    183.             OUT.color *= _Color;
    184.             OUT.color.rgb *= _DiffusePower;
    185.             OUT.texcoord0 = v.texcoord0;
    186.  
    187.             float2 pixelSize = OUT.vertex.w;
    188.             //pixelSize /= abs(float2(_ScreenParams.x * UNITY_MATRIX_P[0][0], _ScreenParams.y * UNITY_MATRIX_P[1][1]));
    189.  
    190.             // Clamp _ClipRect to 16bit.
    191.             float4 clampedRect = clamp(_ClipRect, -2e10, 2e10);
    192.             OUT.mask = float4(vert.xy * 2 - clampedRect.xy - clampedRect.zw, 0.25 / (0.25 * half2(_MaskSoftnessX, _MaskSoftnessY) + pixelSize.xy));
    193.  
    194.             return OUT;
    195.         }
    196.  
    197.         fixed4 frag (v2f IN) : COLOR
    198.         {
    199.             fixed4 color = fixed4(IN.color.rgb, IN.color.a * tex2D(_MainTex, IN.texcoord0).a);
    200.  
    201.             // Alternative implementation to UnityGet2DClipping with support for softness.
    202.             #if UNITY_UI_CLIP_RECT
    203.                 half2 m = saturate((_ClipRect.zw - _ClipRect.xy - abs(IN.mask.xy)) * IN.mask.zw);
    204.                 color *= m.x * m.y;
    205.             #endif
    206.  
    207.             #if UNITY_UI_ALPHACLIP
    208.                 clip(color.a - 0.001);
    209.             #endif
    210.  
    211.             return color;
    212.         }
    213.         ENDCG
    214.     }
    215. }
    216.  
    217. /*SubShader {
    218.     Tags { "Queue"="Transparent" "IgnoreProjector"="True" "RenderType"="Transparent" }
    219.     Lighting Off Cull Off ZTest Always ZWrite Off Fog { Mode Off }
    220.     Blend SrcAlpha OneMinusSrcAlpha
    221.     BindChannels {
    222.         Bind "Color", color
    223.         Bind "Vertex", vertex
    224.         Bind "TexCoord", texcoord0
    225.     }
    226.     Pass {
    227.         SetTexture [_MainTex] {
    228.             constantColor [_Color] combine constant * primary, constant * texture
    229.         }
    230.     }
    231. }*/
    232.  
    233. //CustomEditor "TMPro.EditorUtilities.TMP_BitmapShaderGUI"
    234. }
    235.