- Home /
 
Shaders - changing the vertex color via script
Hi,
I'm having trouble trying to change the vertex color from my script. I have a shader that I thought was correctly written to do what I'm trying to accomplish, but I must have an error in it somewhere. The script works, but the game objects that I'm trying to change the color of, remain the same color.
Here is my shader:
 Shader "My Shaders/Normal Maps/OptimizedNormal"
 {
     
     Properties
     {
     
         _Color( "ColorTint", Color ) = ( 1.0, 1.0, 1.0, 1.0 )
         _BumpMap( "NormalTexture", 2D ) = "bump" {}
         _BumpDepth( "BumpDepth", Range( 0.0, 1.0 ) ) = 1
         _SpecColor( "SpecularColor", Color ) = ( 1.0, 1.0, 1.0, 1.0 )
         _Shininess( "Shininess", float ) = 10
     }
     
     SubShader
     {
         
         Pass
         {
         
             Tags { "LightMode" = "ForwardBase" }
             
             CGPROGRAM
             #pragma vertex vert
             #pragma fragment frag
             #pragma fragmentoption ARB_precision_hint_fastest
             
             //user defined variables
             uniform fixed4 _Color;
             uniform sampler2D _BumpMap;
             uniform fixed _BumpDepth;
             uniform half4 _BumpMap_ST;
             uniform fixed4 _SpecColor;
             uniform half _Shininess;
             
             //unity defined variables
             uniform half4 _LightColor0;
             
             //base input structs
             struct vertexInput
             {
             
                 half4 vertex : POSITION;
                 half3 normal : NORMAL;
                 half4 texcoord : TEXCOORD0;
                 half4 tangent : TANGENT;
             };
             
             struct vertexOutput
             {
             
                 half4 pos : SV_POSITION;
                 half4 tex : TEXCOORD0;
                 fixed4 lightDirection : TEXCOORD1;
                 fixed3 viewDirection : TEXCOORD2;
                 fixed3 normalWorld : TEXCOORD3;
                 fixed3 tangentWorld : TEXCOORD4;
                 fixed3 binormalWorld : TEXCOORD5;
             };
             
             
             //vertex function
             vertexOutput vert( vertexInput v )
             {
             
                 vertexOutput o;
                 o.normalWorld = normalize( mul( half4( v.normal, 0.0 ), _World2Object ).xyz );
                 o.tangentWorld = normalize( mul( _Object2World, v.tangent ).xyz );
                 o.binormalWorld = normalize( cross( o.normalWorld, o.tangentWorld ) * v.tangent.w );
                 
                 half4 posWorld = mul( _Object2World, v.vertex );
                 o.pos = mul( UNITY_MATRIX_MVP, v.vertex );
                 o.tex = v.texcoord;
                 
                 o.viewDirection = normalize( _WorldSpaceCameraPos.xyz - posWorld.xyz );
                 
                 half3 fragmentToLightSource = _WorldSpaceLightPos0.xyz - posWorld.xyz;
                 
                 o.lightDirection = fixed4( 
                     normalize( lerp( _WorldSpaceLightPos0.xyz, fragmentToLightSource, _WorldSpaceLightPos0.w ) ),
                     lerp( 1.0, 1.0/length( fragmentToLightSource ), _WorldSpaceLightPos0.w ) );
                 
                 return o;
             }
             
             //fragment function
             fixed4 frag( vertexOutput i ) : COLOR
             {
                 
                 //texture Maps
                 fixed4 texN = tex2D( _BumpMap, i.tex.xy * _BumpMap_ST.xy + _BumpMap_ST.zw );
                 
                 //unPackNormal function
                 fixed3 localCoords = fixed3( 2.0 * texN.ag - float2( 1.0, 1.0 ), _BumpDepth );
                 
                 //normal transpose matrix
                 fixed3x3 local2WorldTranspose = fixed3x3(
                     i.tangentWorld,
                     i.binormalWorld,
                     i.normalWorld
                 );
                 
                 //calculate normal direction
                 fixed3 normalDirection = normalize( mul( localCoords, local2WorldTranspose ) );
                 
                 //Lighting
                 //dot product
                 fixed nDotL = saturate( dot( normalDirection, i.lightDirection.xyz ) );
                 
                 fixed3 diffuseReflection = i.lightDirection.w * _LightColor0.xyz * nDotL;
                 fixed3 specularReflection = diffuseReflection * _SpecColor.xyz * pow( saturate( dot( reflect( -i.lightDirection.xyz, normalDirection ), i.viewDirection ) ), _Shininess);
                 
                 fixed3 lightFinal = UNITY_LIGHTMODEL_AMBIENT.xyz + diffuseReflection + ( specularReflection );
                 
                 return fixed4( lightFinal * _Color.rgb, 1.0 );
             }
             
             ENDCG
         }
     }
     //Fallback "Diffuse"
 }
 
               I thought that declaring _Color as uniform allows me to change the default value of the verts from my C# script, but the objects remain white. This is the C# script that I wrote for changing the verts color:
  void Start ()
 {               
                 GameObject[] gos;
         gos = GameObject.FindGameObjectsWithTag( "Container" );
         int colorNumber = 0;
         print ("here1");
         
         foreach( GameObject go in gos )
         {
         
             var mf = go.GetComponent<MeshFilter>();
             var colors = new Color[ mf.sharedMesh.vertexCount];
             print ("here2");
             Debug.Log(colors.Length);
             
             if( colorNumber == 0 )
             {
                 print ("here3");
                 for(var i = 0; i < colors.Length; i++)
                 {
                     colors[i] = new Color( 1, 0, 0, 1 );
                 }
                 
                 mf.mesh.colors = colors;
                 colorNumber = 1;
             }
             
             if( colorNumber == 1 )
             {
                 print ("here4");
                 for(var i = 0; i < colors.Length; i++)
                 {
                     colors[i] = new Color( 0, 1, 0, 1 );
                 }
                 
                 mf.mesh.colors = colors;
                 colorNumber = 2;
             }
             
             if( colorNumber == 2 )
             {
                 
                 for(var i = 0; i < colors.Length; i++)
                 {
                     colors[i] = new Color( 0, 0, 1, 1 );
                     
                 }
                 mf.mesh.colors = colors;
                 colorNumber = 3;
             }
             
             if( colorNumber == 3 )
             {
                 
                 for(var i = 0; i < colors.Length; i++)
                 {
                     colors[i] = new Color( 0.5f, 0.25f, 0, 1 );
                 }
                 mf.mesh.colors = colors;
                 colorNumber = 4;
             }
             
             if( colorNumber == 4 )
             {
                 
                 for(var i = 0; i < colors.Length; i++)
                 {
                     colors[i] = new Color( 0.3f, 0, 0.2f, 1 );
                 }
                 mf.mesh.colors = colors;
                 colorNumber = 0;
             }
         }
 }
 
               Both the shader and C# scripts run without error, but like I said, the color of the game object just remains as the default white that I set in the top of the shader.
Does anyone know where I'm going wrong? I have a feeling that I haven't got something right in the shader.
Any help is much appreciated. Thanks
Answer by raimon.massanet · Oct 03, 2013 at 07:57 AM
You should change your shader's property by setting the material's property. Something like:
material.SetColor("_Color", someColor)
Assuming your shader is assigned to the material of the gameObject. 
If I do that, then it will break batching of the prefabs instances. It's not an option. I need to change the color of the vertices to keep the objects in one draw call otherwise I would just do it in the editor. Thanks for the thought though.
Where do you read the color property of the vertices?
The way you declared _Color, the only way of changing it that I know of is using material.Setcolor. I wonder why I got a negative vote for answering that, but anyway... If you want to read the color of the vertex, which you seem not to be doing now, I believe you need to declare the vertex input struct like:
struct vertexInput { half4 vertex : POSITION; half3 normal : NOR$$anonymous$$AL; half4 texcoord : TEXCOORD0; half4 tangent : TANGENT; float4 color : COLOR; };
and use the color property in the shader. I haven't tested but I think it should work. 
Sorry about the negative vote. I was trying to make it so it was an unanswered question again. I ended up asking it again because I think less people pay attention to answered questions, but I ended up finding the solution after reading the documentation a bit. I tried to give you a thumbs up, but it won't let me reverse my vote. Your solution in your comment is the same that I applied. Thanks for your time and sorry again
That's O$$anonymous$$. So, I get a negative vote for a correct answer and there is no way of undoing it? That's a shame.
Well.. $$anonymous$$y question was how to change the vertex color by script and you detailed how the material color was changed in your answer, therefore it wasn't a correct answer until your comment yesterday referring to the shader appeared. All the same, I still appreciate you helping and I didn't want to give you a negative vote, just wanted to release your answer somehow to make it become an unanswered question, which I found out isn't possible. $$anonymous$$y bad. Thanks
Your answer
 
             Follow this Question
Related Questions
Changing the vertex color by script 2 Answers
Quad vertex color shader 0 Answers
Rendering full-screen gradient background without overdraw? 1 Answer
How to setup Shader Variant Collection 0 Answers
Local position in vertex shader? 1 Answer