Search Unity

Problem with Vertex Color Lerp Shader..Preview window is correct, model is wrong.

Discussion in 'Shaders' started by Matthew Scott, Mar 16, 2014.

  1. Matthew Scott

    Matthew Scott

    Joined:
    Jan 16, 2013
    Posts:
    33
    Hi everyone! :D

    I've been began writing a particle shader of sorts which allows me to set a high and low color for the model. Essentially, all it does is calculate the local height of each vertex ranging from lowest to highest -1 -> 1 and converts it's position to lerp factor e.g. if the height is 0 then the lerp factor would be 0.5. It then uses a color lerp between low and high to present the final color outcome with is then multiplied with the albedo.rgb.

    This shader also contains a simple method of light scattering (which i have disabled by setting LightDir to 0000 to help clearly demonstrate my issue) using the directional light color and the dot product between each vertex according to it's direction to the center of the object and the directional lights direction. I have one question :confused:...and one problem. :(

    Question: Rather than feeding the world location of the object into the shader via script...is there a way I can work it out in the shader.

    Problem: Below I have posted my shader code and a picture of the problem. As you can see in the preview window, the colour lerp on the sphere works correctly and blends from white at the top, to blue at the bottom. But why is it that I get orange towards the top when I apply it to these particles in the scene? The same happens if I set the bottom to a colour like red....the top particles in the screen appear light blue/cyan...and other color combinations don't work properly either...but top white and bottom black seems to be okay...

    From what I have learnt so far....the problem seems to begin when I multiply the lerped color by the _LightColor0, the dotP doesn't seem to have an issues....

    Any help/explanation with this problem would be greatly appreciated, as would any advice on optimization...I'm really only starting out with shaders, and discovering all the amazing things you can accomplish with them!

    Code (csharp):
    1. Shader "Test/ParticleTest"{
    2.  
    3.     Properties{
    4.         _MainTex ("Texture", 2D) = "white" {}                   //Main Texture
    5.         _Position ("Position", Vector) = (0, 0, 0, 0)           //World position of the object (In via scripting)
    6.         _LightDir ("LightDir", Vector) = (0, 0, 0, 0)           //Normalised vector of the Dir Light (In via scripting)
    7.         _HighColor ("High Color", Color) = (1, 1, 1, 1)         //The high colour of the particles
    8.         _LowColor ("Low Color", Color) = (1, 1, 1, 1)           //The low colour of the particles
    9.         _Scattering ("Scattering", Range (-1, 1)) = 1.0         //How much scattering is allowed
    10.         _Power ("Power", Range (-1, 1)) = 0.5                   //How much overall lighting is applied
    11.     }
    12.    
    13.    
    14.     SubShader{
    15.         Tags { "RenderType" = "Opaque" }
    16.         Cull Off
    17.         Lighting Off
    18.  
    19.         CGPROGRAM
    20.         #pragma exclude_renderers flash
    21.         #pragma surface surf WrapLambert vertex:vert
    22.      
    23.         struct Input {
    24.             float2 uv_MainTex;
    25.             float3 newCol;
    26.             float3 finalCol;
    27.             half vertLocPos;
    28.         };
    29.  
    30.         float4 _Position;
    31.         float4 _LightDir;
    32.         float4 _HighColor;
    33.         float4 _LowColor;
    34.         float _Scattering;
    35.         float _Power;
    36.      
    37.         void vert (inout appdata_full v, out Input o){
    38.             UNITY_INITIALIZE_OUTPUT(Input, o);
    39.  
    40.             fixed3 high = _HighColor.rgb;
    41.             fixed3 low = _LowColor.rgb;
    42.             float vertLerpFact = (v.vertex.y - - 1) * 0.5;
    43.             float3 highLowColor = lerp(low, high, vertLerpFact);
    44.            
    45.             float4 vertWorldPos = mul(_Object2World, v.vertex);
    46.             half dotP = (dot(normalize(_Position-vertWorldPos), _LightDir)) * 0.5 + _Scattering;
    47.  
    48.  
    49.             //o.newCol = _LightColor0.rgb * dotP; //FIXME - THIS IS JUST LIGHT SCATTERING
    50.             o.newCol = _LightColor0.rgb * highLowColor * dotP; //FIXME - THIS IS SCATTERING WITH HIGH LOW COLOURS MULTIPLIED - Results okay but incorrect colours show with some combinations
    51.             //o.newCol = ((_LightColor0.rgb + highLowColor) * 0.5) * dotP; //FIXME - THIS IS SCATTERING WITH HIGH LOW COLOURS USING DIFFERENT METHOD - Results are bleached/overbright does not solve colour errors.
    52.         }
    53.    
    54.         half4 LightingWrapLambert(SurfaceOutput s, half3 lightDir, half atten){
    55.             half NdotL = dot (s.Normal, lightDir);
    56.             half diff = NdotL * 0.5 + _Power;
    57.             half4 c;
    58.             c.rgb = s.Albedo * _LightColor0.rgb * (diff * atten * 2);
    59.             c.a = s.Alpha;
    60.             return c;
    61.         }
    62.  
    63.         sampler2D _MainTex;
    64.             void surf (Input IN, inout SurfaceOutput o){
    65.             o.Albedo = tex2D (_MainTex, IN.uv_MainTex).rgb;
    66.             o.Albedo *= IN.newCol;
    67.         }
    68.        
    69.         ENDCG
    70.        
    71.     }
    72.     //Fallback "Diffuse"
    73. }
    $Problem1.jpg
    $Problem2.jpg
     
    Last edited: Mar 16, 2014
  2. Matthew Scott

    Matthew Scott

    Joined:
    Jan 16, 2013
    Posts:
    33
    Turns out i needed to saturate the final albedo in the surf function, then multiply the result by my DotProduct. I'd still appreciate any helpful tips/advice. Also, how would I smooth out my dot product calculation so it's not quite so sudden of a change through the center of the object?