- Home /
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[i] = 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[i] = 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[i] = 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[i] = 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[i] = 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
While verbose, your code to change the vertex colors looks like it should do the job. Try this shader to see if the problem is a shader issue:
Thanks for the suggestion robertbu. I was able to change the color with that shader. I'm still having no luck with my own shader though. So, my C# script works fine and although my shader runs without errors, I'm not able to change the vertex color. So, I'm not including something in my shader.
Does anyone have an idea about what's happening?
In order to use vertex colors, you need a Shader that implements vertex colors. Only a $$anonymous$$ority of shaders use vertex colors. There are other shaders that support vertex colors on the Wiki and elsewhere on the net. I don't know if there is on that supports the feature set you need.
Cool, I'm certain that I have only missed a small thing within the shader, but I haven't nailed it down yet. I'm sure that I only need to modify it a tad and it will work. I have completely customized/optimized the shader for my desired feature set, but the only thing that isn't working is the vertex color input. I will continue researching and I will post my solution when I find it..... That is only if someone can't beat me to it and answer my question.
Anyways, I probably speak for a lot of people trying to figure out program$$anonymous$$g and asking questions on here by saying that I appreciate your help robertbu, you're a machine on unity answers!! I was wondering to myself if you ever get time to work on your own stuff!! You seem to answer questions 24/7 on here and you've helped me better understand a lot of things.. Big thanks!
Answer by whydoidoit · Oct 04, 2013 at 04:42 AM
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 );
Hahaha, where were you like 30 $$anonymous$$utes ago?!! Thanks whydoidiot
Answer by highpockets · Oct 04, 2013 at 04:51 AM
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"
}
Your answer
Follow this Question
Related Questions
Shaders - changing the vertex color via script 1 Answer
Local position in vertex shader? 1 Answer
Quad vertex color shader 0 Answers