Mix Shaders Question -- Multiple Textures, Recolorable?
I'm pretty new to writing shaders so I'm having some difficulty making something work. Basically, as I've shown in this diagram:
I want to be able to get a final texture that's a combination of a base color, a flat-color pattern that can be set to whatever color, and a fur texture that overlays everything. I cannot figure out how I should be recoloring the layered-on texture, nor if I should be doing this via a shader or by modifying a new texture outside the shader. I've tried messing around with mix shaders, but I just can't figure out how to get the results I want. I want to be able to do this with multiple layered-on patterns with colors defined by external code. Any help would be greatly appreciated!
Answer by Namey5 · Nov 24, 2016 at 04:40 AM
Shader "Custom/Shader" {
Properties {
_BaseColor ("Base Color", Color) = "white"
_PatternColor ("Pattern Color", Color) = "white"
_Pattern ("Pattern", 2D) = "white" {}
_Overlay ("Overlay", 2D) = "white" {}
}
SubShader {
Pass {
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#pragma target 3.0
#include "UnityCG.cginc"
struct v2f {
float4 pos : SV_POSITION;
float2 uv : TEXCOORD0;
};
v2f vert (appdata_base v) {
v2f o;
o.pos = mul (UNITY_MATRIX_MVP, v.vertex);
o.uv = v.texcoord.xy;
return o;
}
sampler2D _Pattern;
float4 _Pattern_ST;
sampler2D _Overlay;
float4 _Overlay_ST;
fixed4 _BaseColor;
fixed4 _PatternColor;
half4 frag (v2f i) : SV_Target
{
half4 c = lerp (_BaseColor, _PatternColor, tex2D (_Pattern, TRANSFORM_TEX (i.uv, _Pattern)).r) * tex2D (_Overlay, TRANSFORM_TEX (i.uv, _Overlay));
c.a = 1.0;
return c;
}
ENDCG
}
}
}
This should fit your original proposal. If you need to add more textures, etc. you can dissect the elements of this shader,
This is excellent! $$anonymous$$y only problem is that I'm honestly not sure how to add additional patterns. I feel like I understand it until the lerp part.... at that point I'm not sure how to add the secondary texture (like I said, very new with shaders).
Here's what I have so far:
Shader "Custom/$$anonymous$$onsterShader" {
Properties {
_BaseColor ("Base Color", Color) = (1,1,1,1)
_PatternColor ("Pattern Color", Color) = (1,1,1,1)
_Pattern2Color ("Pattern2 Color", Color) = (1,1,1,1)
_Pattern ("Pattern", 2D) = "white" {}
_Pattern2 ("Pattern2", 2D) = "white" {}
_Overlay ("Overlay", 2D) = "white" {}
}
SubShader {
Pass {
CGPROGRA$$anonymous$$
#pragma vertex vert
#pragma fragment frag
#pragma target 3.0
#include "UnityCG.cginc"
struct v2f {
float4 pos : SV_POSITION;
float2 uv : TEXCOORD0;
};
v2f vert (appdata_base v) {
v2f o;
o.pos = mul (UNITY_$$anonymous$$ATRIX_$$anonymous$$VP, v.vertex);
o.uv = v.texcoord.xy;
return o;
}
sampler2D _Pattern;
float4 _Pattern_ST;
sampler2D _Pattern2;
float4 _Pattern2_ST;
sampler2D _Overlay;
float4 _Overlay_ST;
fixed4 _BaseColor;
fixed4 _PatternColor;
fixed4 _Pattern2Color;
half4 frag (v2f i) : SV_Target
{
half4 c = lerp (_BaseColor, _PatternColor, tex2D (_Pattern, TRANSFOR$$anonymous$$_TEX (i.uv, _Pattern)).r) * tex2D (_Overlay, TRANSFOR$$anonymous$$_TEX (i.uv, _Overlay));
c.a = 1.0;
return c;
}
ENDCG
}
}
}
You've got it pretty much right. What the lerp function does is it takes a value between 0 and 1 as the third input (in this case we use the red channel of the pattern texture to keep it grayscale), and transitions between the first and second value. 0 for the third value will return entirely the first value (colour in this case), whilst 1 will return the second, and anything inbetween will morph. In this case, because lerp only takes 2 values and a transition value, we have to do something a bit different.
half4 c = lerp (_BaseColor, _PatternColor, tex2D (_Pattern, TRANSFOR$$anonymous$$_TEX (i.uv, _Pattern)).r);
half4 c2 = lerp (c, _Pattern2Color, tex2D (_Pattern2, TRANSFOR$$anonymous$$_TEX (i.uv, _Pattern2)).r);
return c2 * tex2D (_Overlay, TRANSFOR$$anonymous$$_TEX (i.uv, _Overlay));
I have split it up into more variables to make it easier to understand. In this case, we blend between the base colour and the first pattern colour, and store it in a variable. Then, we blend between that variable and the second pattern colour. It's a bit confusing because I've used the 'TRANSFOR$$anonymous$$TEX' macro, which isn't necessary, but what it does is it allows for the texture controls in the inspector (in the shader known as '$$anonymous$$yTexture_ST') to distort the texture coordinates.
Okay, yeah, I think I understand now. The logic makes sense to me, but the specific syntax for shaders kind of feels really new to me.
One final question-- I notice that when I use this code, the second pattern only shows up where the first pattern is, like it's masked by it. I think an extra step might have to be taken to combine their alphas?
Parse error: syntax error, unexpected TVAL_STRING, expecting '(' at line 5
Replace these lines;
_BaseColor ("Base Color", Color) = "white"
_PatternColor ("Pattern Color", Color) = "white"
with this;
_BaseColor ("Base Color", Color) = (1,1,1,1)
_PatternColor ("Pattern Color", Color) = (1,1,1,1)
I probably fixed that in one of the old comments, but UA has since made most comments more than a year old unreadable for some reason.
Your answer
Follow this Question
Related Questions
Texture offset not working with shader 0 Answers
VRPN in Unity 1 Answer
add variable to Instantiated objects then destroy it in another function 1 Answer
How to rotate normal map texture 0 Answers