How to import vertex colour animation?

I have animated vertex colours using Blender which give the effect of dimming lights. How can I import this animation into Unity?

As an alternative approach, is it possible to create an iOS friendly shader that would achieve the following:

  • Red channel of vertex colour is used for one set of lighting
  • Blue channel of vertex colour is used for second set of lighting
  • Shader has 2 properties (lightAmount1 and lightAmount2) floating point 0 to 1
  • Calculate emission colour (RGB) from:

    min(1.0, lightAmount1 * vertexcolor.red + lightAmount2 * vertexcolor.blue)

If this is possible, then I could animate those two properties.

The shader is totally "possible". From looking at that code, I'd say you ought to use the mix instruction instead of two multiplies, and find a way to eliminate the min, because it doesn't seem like anything more than unnecessary complexity, but that's about all I can say, without knowing what else you need in the shader.

@Jessy The shader literally needs to be vertex lit with a texture and two simulated light sources. What sort of shader would I need to write? I have only written basic shaders before. Are you by any chance JessyUV from YouTube? If so, those are some great tutorials!

btw, this is my very first vertex/fragment shader :-)

Nice work! I would think it wouldn't be hard to create a surface shader based on that; have you tried? The first page of that wikibook has instructions for running the Editor in OpenGL; did you have the error even in that mode?

@Jessy cheers, the GLSL shaders work when I add the command line switch. I was under the impression that surface shaders performed slow on iOS because they operate on a per-pixel basis, so I didn't give it much thought. I wanted to use a basic surface shader with a light cookie (it looked really nice and added a lot of atmosphere) but I was warned that it would perform poorly on iOS.

1 Answer

1

Many thanks to Jessy for helping with this question.

Vertex colours can be animated using a shader by introducing two properties. One for each simulated light source. The red colour component of a vertex colour can be used to illuminate one light source whilst the blue for another. It is easily possible to have 4 simulated light sources (R, G, B, A).

I have called these properties Emission A and Emission B and a value of 0 indicates that the vertex colour component should not contribute to lighting whereas 1 indicates full contribution.

These properties can be easily animated using the animation editor in Unity. Alternatively it is also possible to script the animation if need be.

I want to use these values to simulate two light sources smoothly dimming, but I suspect that there are many other applications of this technique.

I am aiming for iOS platforms and so have created two alternative implementations to compare performance. I do not at this time know which of the two variants performs more efficiently.

EDIT: The first approach seems to perform more efficiently than the second. The first approach does not include vertex lighting. I will add that to the answer if I can figure it out.

Cg Vertex and Fragment shader as follows:

Shader "Custom/Animated Vertex Emission" {
Properties {
	_MainTex ("Texture", 2D) = "white" {}
	_EmissionA ("Emission A", Range(0, 1)) = 1
	_EmissionB ("Emission B", Range(0, 1)) = 0
}

	Pass {
	CGPROGRAM
		#pragma vertex vert
		
		#pragma fragment frag
		#pragma fragmentoption ARB_fog_exp2
		#pragma fragmentoption ARB_precision_hint_fastest
		
		#include "UnityCG.cginc"
		
		struct appdata {
			float4 vertex	: POSITION;
			float4 texcoord	: TEXCOORD0;
			float4 color	: COLOR;
		};
		
		struct v2f {
			float4 pos		: SV_POSITION;
			float2 uv		: TEXCOORD0;
			fixed4 color	: COLOR;
		};
		
		sampler2D _MainTex;
		float _EmissionA;
		float _EmissionB;
		
		float4 _MainTex_ST;
		
		v2f vert(appdata v) {
			v2f o;
			o.pos = mul (UNITY_MATRIX_MVP, v.vertex);
			
			float c = min(1, _EmissionA * v.color.r + _EmissionB * v.color.b);
			o.color = float4(c, c, c, 1);
			o.uv = TRANSFORM_TEX(v.texcoord, _MainTex);
			
			return o;
		}
		
		half4 frag(v2f i) : COLOR {
			half4 outColor = tex2D(_MainTex, i.uv);
			return outColor * i.color;
		}
	ENDCG
	}

}

Fallback "Custom/Unlit"

}

Unity Surface Shader:

Shader "Custom/Animated Vertex Emission" {
Properties {
	_MainTex ("Texture", 2D) = "white" {}
	_EmissionA ("Emission A", Range(0, 1)) = 1
	_EmissionB ("Emission B", Range(0, 1)) = 0
}

SubShader {
	Tags { "RenderType"="Opaque" }

	CGPROGRAM
		#pragma surface surf Lambert

		struct Input {
			float2 uv_MainTex;
			float3 color		: COLOR;
		};

		sampler2D _MainTex;

		float _EmissionA;
		float _EmissionB;

		void surf(Input IN, inout SurfaceOutput o) {
			float3 temp = tex2D(_MainTex, IN.uv_MainTex).rgb;

			float c = min(1, _EmissionA * IN.color.r + _EmissionB * IN.color.b);
			o.Albedo = half3(c * temp.r, c * temp.g, c * temp.b);
		}
	ENDCG
}

Fallback "Custom/Unlit"

}