How would I go about customizing multiple colors on a material? The best example I can think of is something akin to Halo’s customization options – You can set a primary color and a secondary color. Are those separate models, separate textures? I’m honestly not sure at all how that works.
This is a somewhat complicated topic, though the solutions aren’t actually that complicated in of themselves. One way to do this is to use multiple materials on a model and change a tint color on each material. From a content creation side this is a single model, but internally each material becomes it’s own model that gets rendered separately. You can also do it by having lots of different textures with all possible combinations but this is needlessly wasteful.
The easiest way to do it, and how most games handle it, is by using a mask texture where two color channels of a texture are used as masks to modify the underlying texture color, usually with a simple multiply.
_TintColorA (“Tint Color A”, Color) = (1, 1, 1, 1)
_TintColorB (“Tint Color B”, Color) = (1, 1, 1, 1)
_TintMask (“Tint Mask”, 2D) = “black”
…
fixed4 albedo = tex2D(_MainTex, i.uv);
fixed4 mask = tex2D(_TintMask, i.uv);
fixed maskA = mask.r; // red channel is the first mask
fixed maskB = mask.g; // green channel is the second mask
fixed3 tint = fixed3(1.0, 1.0, 1.0);
tint = lerp(tint, _TintColorB, maskB);
tint = lerp(tint, _TintColorA, maskA);
albedo.rgb *= tint;
After a while of playing around with it, I managed to figure it out with your help. Writing shaders always feels like the highest level of sorcery. I can’t guarantee that this is any kind of well-written code, but here is the full shader based on what bgolus suggested for anyone who stumbles upon this:
Shader "Custom/DualColorMask" {
Properties {
//_Color ("Color", Color) = (1,1,1,1)
_MainTex ("Albedo (RGB)", 2D) = "white" {}
_Glossiness ("Smoothness", Range(0,1)) = 0.5
_Metallic ("Metallic", Range(0,1)) = 0.0
_TintColorA("Tint Color A", Color) = (1, 1, 1, 1)
_TintColorB("Tint Color B", Color) = (1, 1, 1, 1)
_TintMask("Tint Mask", 2D) = "black"
}
SubShader {
Tags { "RenderType"="Opaque" }
LOD 200
CGPROGRAM
// Physically based Standard lighting model, and enable shadows on all light types
#pragma surface surf Standard fullforwardshadows
// Use shader model 3.0 target, to get nicer looking lighting
#pragma target 3.0
sampler2D _MainTex;
sampler2D _TintMask;
struct Input {
float2 uv_MainTex;
float2 uv_TintMask;
};
half _Glossiness;
half _Metallic;
fixed4 _Color;
fixed4 _TintColorA;
fixed4 _TintColorB;
void surf (Input IN, inout SurfaceOutputStandard o) {
// Albedo comes from a texture tinted by color
//fixed4 c = tex2D (_MainTex, IN.uv_MainTex) * _Color;
fixed4 albedo = tex2D(_MainTex, IN.uv_MainTex);
fixed4 mask = tex2D(_TintMask, IN.uv_TintMask);
fixed maskA = mask.r; // red channel is the first mask
fixed maskB = mask.g; // green channel is the second mask
fixed3 tint = fixed3(1.0, 1.0, 1.0);
tint = lerp(tint, _TintColorB, maskB);
tint = lerp(tint, _TintColorA, maskA);
albedo.rgb *= tint;
o.Albedo = albedo.rgb;
// Metallic and smoothness come from slider variables
o.Metallic = _Metallic;
o.Smoothness = _Glossiness;
o.Alpha = albedo.a;
}
ENDCG
}
FallBack "Diffuse"
}
This works similar to a regular material. You apply your texture, but you also have a “tint mask” image to apply as well. To make a tint mask, you start with a black image (the tint mask ignores black). Your first color on the tint mask will be red, and your second color will be green. Drop the mask in to the material and change the colors – everything green and red will be changed according to what color you set.