- 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