How to use shader to control the rendering of each text character(letter)? Or, how to correctly pass custom data into vert/frag?
sorry if the description is difficult to undersand or not accurate. English is not my first language. I'm doing my best :)
I'm trying to implement a 3-color vertical gradient text shader.
I found a example shader, but it renders the texture's gradient colors as a whole. I want to apply the entire gradient range on each character/letter.
So I tried to pass the height and minimum Y-pos of each character into the shader via UIVertex.uv1, using them to find out the actual vertical ratio of each pixel in a single character, which you can see in my code below.
But the result was always wrong: I can't correctly read the minimum Y-pos (and the character height as well, perhaps). The shader works fine when I force the minimum Y-pos (i.e. charMinY) to 0. I don't know where it went wrong, since I'm not sure how I can have a debug output for variables in vert(). Is data changed when it passes from vert() to frag()? Or is it changed in vert() in the beginning?
I'm a beginner of shader programming and don't know much about the theory yet. Plz tell me if there is anything I should know :)
HERE ARE THE CODES
C# part of setting custom data, including the size of a single character and its left-bottom corner in the texture, all in UV unit.
 public class TextUVRemapper : BaseMeshEffect
 {
     public override void ModifyMesh(VertexHelper vh)
     {
         if(!IsActive())
         {
             return;
         }
         List<UIVertex> verts = new List<UIVertex>(vh.currentVertCount);
         vh.GetUIVertexStream(verts);
         var meshVertsCount = 6;
         for (int i = 0; i < verts.Count; i += meshVertsCount)
         {
             var uvsize = verts[i + 2].uv0 - verts[i + 0].uv0;
             var startUV = verts[i + 0].uv0;
             Debug.Log("uv height: " + uvsize.y + "; Tex start Y: " + startUV.y);
             for (int j = i; j < i + meshVertsCount; j++)
             {
                 var v = verts[j];
                 v.uv1 = new Vector4(uvsize.x, uvsize.y, startUV.x, 0.5f);
                 verts[j] = v;
             }
         }
         vh.Clear();
         vh.AddUIVertexTriangleStream(verts);
     }
 }
Below is the shader part. I commented some so hopefully you can know what I was thinking :)
Shader "GUI/Text Vertical 3-Color Shader" { Properties { _MainTex ("Font Texture", 2D) = "white" {} _Color ("Text Color", Color) = (1,1,1,1) _ColorTop ("Top Color", Color) = (1,1,1,1) _ColorBot ("Bottom Color", Color) = (1,1,1,1) _Middle("Middle", Range(0.001, 0.999)) = 0.5 }
 SubShader {
     ...
     Pass {
         CGPROGRAM
         #pragma vertex vert
         #pragma fragment frag
         #include "UnityCG.cginc"
         struct appdata_t {
             float4 vertex : POSITION;
             fixed4 color : COLOR;
             float2 texcoord : TEXCOORD0;
             float4 params : TEXCOORD1; // here is the custom data
         };
         struct v2f {
             float4 vertex : SV_POSITION;
             fixed4 color : COLOR;
             
             // x and y: as usual.  
             // z: character's height. 
             // w: character's minimum y-pos
             float4 texcoord : TEXCOORD0; 
         };
         sampler2D _MainTex;
         uniform float4 _MainTex_ST;
         uniform fixed4 _Color;
         uniform fixed4 _ColorTop;
         uniform fixed4 _ColorBot;
         float _Middle;
         v2f vert (appdata_t v)
         {
             v2f o;
             // charSize is the size of a single rendered text letter
             // which is passed in via UIVertex.uv1.x & UIVertex.uv1.y
             float2 charSize;
             if(v.params.x == 0 && v.params.y == 0) {
                 charSize = float2(.999,.999);
             } else {
                 charSize = float2(v.params.x, v.params.y);
             }
             //charSize = TRANSFORM_TEX(charSize, _MainTex); // <--- i'm not sure if i should do this.
            if(v.params.w == 1) v.params.w = 0; // <--- this line is for testing. seems all v.params.w passed in are 1..
             // charMinPos is the uv of the letter's bottom-left corner.
             float2 charMinPos = float2(v.params.z, v.params.w);
             //charMinPos = TRANSFORM_TEX(charMinPos, _MainTex); // <--- i'm not sure if i should do this.
             o.vertex = mul(UNITY_MATRIX_MVP, v.vertex);
             o.color = v.color * _Color;
             float2 uv;
             uv = TRANSFORM_TEX(v.texcoord,_MainTex);
             o.texcoord = float4(uv.x, uv.y, charSize.y, charMinPos.y); // z & w are for letter's demensional info
             return o;
         }
         fixed4 frag (v2f i) : SV_Target
         {
             float fragY = i.texcoord.y;
             // THESE 2 VALUES ARE SUPPOSED TO BE PASSED BY vert
             float charHeight = i.texcoord.z;
             float charMinY = i.texcoord.w;
             half midY = charMinY + _Middle * charHeight; // the middle-color's Y pos of the letter
             half t = fragY/midY;
             float a = t;
             float b = charHeight;
             float c = charMinY;
             // return float4(a,b,c,1); // <-- test value output
             // below is the calculation of the gradient color, depending on frag's Y pos.
             fixed4 col = lerp(_ColorTop, i.color,
                 fragY / midY
             ) * step(fragY, midY);
             col += lerp(i.color, _ColorBot,
                 (fragY - midY) / ((1 - _Middle) * charHeight)
             ) * step(midY, fragY);
             col.a *= tex2D(_MainTex, i.texcoord).a;
             //col.a = 1;  // i used this to see the render result
             return col;
         }
         ENDCG
     }
 }
 }
I've stuck on this for two days! I could really use some help! Thank you a ton in advance!
Your answer
 
 
              koobas.hobune.stream
koobas.hobune.stream 
                       
                
                       
			     
			 
                