Maybe theres a simple answer but this one has me stumped. I'm creating a mesh in c# with a 'pizza' shape i.e. first vertex is in center and the rest are evenly spaced around it at some radius. The 'U' value is set to 0 in the center and 1 in all of the edge vertices. I have a simple unlit shader which will lerp between two colors based on the u value. So I'm looking for a smooth lerp but it seems that along the edges of the triangles this value remains 0. Note that with a many sided polygon this effect is hardly noticeable. The shader im using: Code (CSharp): Shader "Custom/UShader" { Properties { _ColorU0 ("Color U-0", Color) = (1,1,1,1) _ColorU1 ("Color U-1", Color) = (0,0,0,1) } SubShader { Pass { CGPROGRAM #pragma vertex vert #pragma fragment frag #include "UnityCG.cginc" struct appdata { float4 vertex : POSITION; float2 uv : TEXCOORD0; }; struct v2f { float2 uv : TEXCOORD0; float4 vertex : SV_POSITION; }; v2f vert (appdata v) { v2f o; o.vertex = UnityObjectToClipPos(v.vertex); o.uv = v.uv; return o; } fixed4 _ColorU0; fixed4 _ColorU1; fixed4 frag (v2f i) : SV_Target { fixed4 colU = lerp(_ColorU0,_ColorU1,i.uv.x); return colU; } ENDCG } } }
Nope, this is just an optical illusion. The resulting image is correct, but the human brain is really good at noticing patterns, and in this case it's seeing two linear gradients with different directions and making the edge appear more prominent. You could reduce the effect of this by modifying the curve of the i.uv.x by how close it is to a corner, probably using i.uv.y. Alternate the uv.y between 0.0 and 1.0 and then do abs(i.uv.y * 2.0 - 1.0). Then do some kind of pow on the i.uv.x, and potentially the resulting i.uv.y. How much is going to be different for ever corner. fixed4 col = lerp(_Color0, _Color1, pow(i.uv.x, lerp(1.0, 0.75, abs(i.uv.y * 2.0 - 1.0)));
So I spent a bit last night playing with exponentials and couldnt really get my head around it. Then dead set i woke up at 5am with a new idea, just use vertex positions and pythagoras theorem The image is of a polygon with a radius of 1 Code (CSharp): Shader "Custom/RadialShader" { Properties { _ColCenter ("Center Color", Color) = (0,0,0,1) _ColEdge ("Edge Color", Color) = (1,1,1,1) } SubShader { Pass { CGPROGRAM #pragma vertex vert #pragma fragment frag #include "UnityCG.cginc" struct appdata { float4 vertex : POSITION; float2 uv : TEXCOORD0; }; struct v2f { float2 uv : TEXCOORD0; float4 objPos : TEXCOORD1; float4 vertex : SV_POSITION; }; v2f vert (appdata v) { v2f o; o.vertex = UnityObjectToClipPos(v.vertex); o.objPos = v.vertex; o.uv = v.uv; return o; } fixed4 _ColCenter; fixed4 _ColEdge; fixed4 frag (v2f i) : SV_Target { //c2 = a2 + b2 float a = i.objPos.x; float b = abs(i.objPos.y); float c = sqrt(pow(a,2)+pow(b,2)); return lerp(_ColCenter,_ColEdge,c); } ENDCG } } }
Ah, if all you wanted was a perfect circular gradient regardless of the polygon shape, then yes, Pythagorean theorem works. The faster GPU-ized version of which would be. float c = sqrt(dot(i.objPos.xy, i.objPos.xy)); You can also just use the built in length function to do the same thing. float c = length(i.objPos.xy); It's better to store the objPos.xy in UVs though, as batching will alter the mesh's vertex positions as seen by the shader.