Changing the vertex color by script

Hi,

I’m having trouble trying to change the vertex color from my script ( I do not want to change the color via the material because I don’t want to break batching ). 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;
		
		foreach( GameObject go in gos )
		{
		
			var mf = go.GetComponent<MeshFilter>();
			var colors = new Color[ mf.sharedMesh.vertexCount];
			
			if( colorNumber == 0 )
			{
				
				for(var i = 0; i < colors.Length; i++)
				{
					colors *= new Color( 1, 0, 0, 1 );*
  •  		}*
    
  •  		mf.mesh.colors = colors;*
    
  •  		colorNumber = 1;*
    
  •  		continue;*
    
  •  	}*
    
  •  	if( colorNumber == 1 )*
    
  •  	{*
    
  •  		for(var i = 0; i < colors.Length; i++)*
    
  •  		{*
    

_ colors = new Color( 0, 1, 0, 1 );_
* }*

* mf.mesh.colors = colors;*
* colorNumber = 2;*
* continue;*
* }*

* if( colorNumber == 2 )*
* {*

* for(var i = 0; i < colors.Length; i++)*
* {*
_ colors = new Color( 0, 0, 1, 1 );
}
_

* mf.mesh.colors = colors;*
* colorNumber = 3;*
* continue;*
* }*

* if( colorNumber == 3 )*
* {*

* for(var i = 0; i < colors.Length; i++)*
* {*
_ colors = new Color( 0.5f, 0.25f, 0, 1 );
* }*_

* mf.mesh.colors = colors;*
* colorNumber = 4;*
* continue;*
* }*

* if( colorNumber == 4 )*
* {*

* for(var i = 0; i < colors.Length; i++)*
* {*
_ colors = new Color( 1f, 0, 0.2f, 1 );
* }*_

* mf.mesh.colors = colors;*
* colorNumber = 0;*
* continue;*
* }*
* }*
* }*

Both the shader and C# scripts run without error, but like I said, the color of the game objects 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.
I do not want to change the color via the material as this will break batching and I want to keep these game objects in the same draw call.
Any help is much appreciated. Thanks

The shader you posted does not read a vertex colour or pass a colour from the vertex to the fragment…

     struct vertexInput
     {

      half4 vertex : POSITION;
      half3 normal : NORMAL;
      half4 texcoord : TEXCOORD0;
      half4 tangent : TANGENT;
      half4 color : COLOR; //Add this
     };

     struct vertexOutput
     {

      half4 pos : SV_POSITION;
      half4 tex : TEXCOORD0;
      half4 color : TEXCOORD6; //Add this
      fixed4 lightDirection : TEXCOORD1;
      fixed3 viewDirection : TEXCOORD2;
      fixed3 normalWorld : TEXCOORD3;
      fixed3 tangentWorld : TEXCOORD4;
      fixed3 binormalWorld : TEXCOORD5;
     };

Then you need to assign the colour to the output in the Vertex shader:

      o.color = v.color;

And return it multiplied by your calculations in the Fragment shader:

     return fixed4( lightFinal * _Color.rgb * i.color.rgb, 1.0 );

OK, OK, after a bit of research I found my solution in the documentation:

http://unity3d.com/support/documentation/Components/SL-VertexProgramInputs.html

I was failed to pass the color input value in the structs ( vertexInput/vertexOutput ). I also realized that you have to declare it as color because I tried doing it through troubleshooting and just declaring it as “col”. That is not accepted by unity. It needs to use the word “colour” with the semantic “COLOR” and no other in order for it to work.

Anyways, for those who are looking in the future. This is my final shader script:

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;
				fixed4 color : COLOR;
			};
			
			struct vertexOutput
			{
			
				half4 pos : SV_POSITION;
				half4 tex : TEXCOORD0;
				fixed4 lightDirection : TEXCOORD1;
				fixed3 viewDirection : TEXCOORD2;
				fixed3 normalWorld : TEXCOORD3;
				fixed3 tangentWorld : TEXCOORD4;
				fixed3 binormalWorld : TEXCOORD5;
				fixed4 color : COLOR;
			};
			
			
			//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.color = v.color;
				
				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 * i.color, 1.0 );
			}
			
			ENDCG
		}
	}
	//Fallback "Diffuse"
}