- Home /
SkinnedMeshRenderer modifying vertex colours?
I am making procedural trees, and procedurally generating bones so that they can animate more realistically. Here is a screenshot:
The triangles are untextured.
The trees should be uniformly coloured per tree (apart from the white tips you can see occasionally) according to my code, but changing the orientation of the bones in the skeleton, while affecting the mesh correctly, appears to be changing the colours of the vertices somehow. Anyone know why? As far as I can tell they should be totally unlit and simply draw in the colour I tell them to be drawn in at the end of the vertex shader. The surface shader simply uses that colour, and adding commands to remove the lighting like noambient and novertexlights makes no apparent difference.
Here's my shader:
Shader "Starboretum/Flora2" {
Properties {
}
SubShader {
Tags {
"Queue" = "Geometry"
"RenderType" = "Opaque"
}
Cull Off
CGPROGRAM
#pragma surface surf NoLighting vertex:vert addshadow
#pragma glsl_no_auto_normalization
#include "UnityCG.cginc"
float _IterationProgress;
struct appdata {
float4 vertex : POSITION;
float3 normal : NORMAL;
float4 tangent : TANGENT;
float4 texcoord : TEXCOORD0;
float4 texcoord1 : TEXCOORD1;
fixed4 color : COLOR;
};
struct Input
{
float4 color : COLOR;
};
fixed4 LightingNoLighting(SurfaceOutput s, fixed3 lightDir, fixed atten)
{
fixed4 c;
c.rgb = s.Albedo;
c.a = s.Alpha;
return c;
}
void surf (Input IN, inout SurfaceOutput o)
{
o.Albedo = (half3)IN.color.rgb;
}
float3 UnPackVector3(float src)
{
return (frac(float3(1.0f, 256.0f, 65536.0f) * src) * 2) - 1;
}
void vert (inout appdata_full v)
{
// get the vertex position
float4 position = mul(_Object2World, v.vertex);
// obtain the direction of this segment
float3 dir = UnPackVector3(v.texcoord1.x);
float3 camDir = _WorldSpaceCameraPos - position.xyz;
// widen the stem from prev width -> width
float width = lerp(v.texcoord.y, v.texcoord1.y, _IterationProgress);
// get a vector perpendicular to the direction to the camera
float3 left = normalize(cross(dir, camDir));
left *= v.texcoord.x; // reverse it if necessary
// expand the line segment by the width
v.vertex.xyz += left * width;
v.color = float4(lerp(v.color.rgb, v.tangent.xyz, _IterationProgress),1);
}
ENDCG
}
FallBack "VertexLit"
}
v.color and v.tangent are the same value - the colour of the vertex. When the tree is standing with all bones at the bindpose the colour is indeed uniform.
compiled shader code: http://pastebin.com/v1uej0mL
Apparently this is due to the Surface shader doing some extra secret magic on its own, so I created a vert + frag shader to do this which works fine. However, it throws up a problem of being unable to cast shadows (I was using #pragma addshadow to get that working). Since that's another problem, I'll create a separate thread.
Answer by Alex_May · Jan 11, 2015 at 04:05 PM
Here is a vertex and fragment CG shader with a shadowcaster pass (I didn't add a receiver pass because these billboarded polys might look weird with shadows). It renders the fragment colours correctly and casts shadows.
Shader "Starboretum/Flora3"
{
Properties
{
_Color ("Main Color", Color) = (1,1,1,1)
}
SubShader
{
Tags
{
"Queue" = "Geometry"
"RenderType" = "Opaque"
}
LOD 200
Pass
{
Lighting Off
Cull Off
CGPROGRAM
#include "UnityCG.cginc"
#include "AutoLight.cginc"
#pragma vertex vert
#pragma fragment frag
struct FragIn
{
float4 pos : SV_POSITION;
float4 col : COLOR0;
};
float3 UnPackVector3(float src)
{
return (frac(float3(1.0f, 256.0f, 65536.0f) * src) * 2) - 1;
}
FragIn vert(appdata_full v)
{
FragIn o;
float4 position = mul(_Object2World, v.vertex);
// obtain the direction of this segment
float3 dir = UnPackVector3(v.texcoord1.x);
float3 camDir = _WorldSpaceCameraPos - position.xyz;
// widen the stem from prev width -> width
float width = v.texcoord.y;
// get a vector perpendicular to the direction to the camera
float3 left = normalize(cross(dir, camDir));
left *= v.texcoord.x; // reverse it if necessary
// expand the line segment by the width
v.vertex.xyz += left * width;
o.pos = mul(UNITY_MATRIX_MVP, v.vertex);
o.col = v.color;
return o;
}
float4 frag(FragIn i) : COLOR
{
return i.col;
}
ENDCG
}
// Pass to render object as a shadow caster
Pass
{
Name "ShadowCaster"
Tags { "LightMode" = "ShadowCaster" }
Fog {Mode Off}
ZWrite On ZTest LEqual Cull Off
Offset 1, 1
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#pragma multi_compile_shadowcaster
#pragma fragmentoption ARB_precision_hint_fastest
#include "UnityCG.cginc"
struct v2f {
V2F_SHADOW_CASTER;
};
float3 UnPackVector3(float src)
{
return (frac(float3(1.0f, 256.0f, 65536.0f) * src) * 2) - 1;
}
v2f vert( appdata_full v )
{
v2f o;
float4 position = mul(_Object2World, v.vertex);
// obtain the direction of this segment
float3 dir = UnPackVector3(v.texcoord1.x);
float3 camDir = _WorldSpaceCameraPos - position.xyz;
// widen the stem from prev width -> width
float width = v.texcoord.y;
// get a vector perpendicular to the direction to the camera
float3 left = normalize(cross(dir, camDir));
left *= v.texcoord.x; // reverse it if necessary
// expand the line segment by the width
v.vertex.xyz += left * width;
o.pos = mul(UNITY_MATRIX_MVP, v.vertex);
TRANSFER_SHADOW_CASTER(o)
return o;
}
float4 frag( v2f i ) : COLOR
{
SHADOW_CASTER_FRAGMENT(i)
}
ENDCG
}
}
FallBack "VertexLit"
}
The shadowcaster code comes from Farfarrer's post here: http://forum.unity3d.com/threads/i-put-a-shadowcollector-pass-in-my-shader-but-why-does-it-cant-recieves-shadow-why.160010/#post-1094855 which apparently comes from the built-in shaders.
Your answer
![](https://koobas.hobune.stream/wayback/20220613180043im_/https://answers.unity.com/themes/thub/images/avi.jpg)
Follow this Question
Related Questions
Realtime emission material during runtime 0 Answers
Dynamic Light on a Procedural Map problem! 1 Answer
Finding a Point Relative to a Bone 0 Answers
Can we get skinnedMeshRender.bones in unity source after choose optimize game object? 0 Answers
How to edit the new particle surface shader? / Make it so particles receive light from all angles 0 Answers