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"
}
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@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!
– numberkruncherbtw, this is my very first vertex/fragment shader :-)
– numberkruncherNice 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@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.
– numberkruncher