- Home /
How to make a Shader with multiple textures and an alpha mask?
I'm trying to make a shader that allows me to blend multiple textures and then mask them all at once. So far I have figured out how to blend 3 textures OR mask 1 texture, but I haven't been able to mask 3 blended textures. I'm very new to working with shaders. Thanks for the help!
Here is my code:
Shader "Custom/testShader" {
Properties {
_Color ("Color Tint (A = Opacity)", Color) = (1,1,1,1)
_Blend1 ("Blend", Range (0, 1)) = 0.0
_Blend2 ("Blend", Range (0, 1)) = 0.0
_MainTex1 ("Base (RGB)", 2D) = "red"
_MainTex2 ("Base (RGB)", 2D) = "blue"
_MainTex3 ("Base (RGB)", 2D) = "green"
_Mask ("Culling Mask", 2D) = "white" {}
_Cutoff ("Alpha cutoff", Range (0,1)) = 0.1
}
SubShader {
Tags {"Queue"="Transparent"}
Lighting On
ZWrite Off
Blend SrcAlpha OneMinusSrcAlpha
AlphaTest GEqual [_Cutoff]
Pass {
Material {
Diffuse [_Color]
Ambient [_Color]
}
SetTexture [_Mask] {combine texture}
SetTexture [_MainTex1]{combine texture, previous}
SetTexture [_MainTex2] {
constantColor (0, 0, 0, [_Blend1])
combine texture lerp (constant) previous
}
SetTexture [_MainTex3] {
constantColor (0, 0, 0, [_Blend2])
combine texture lerp (constant) previous
}
}
}
}
Answer by toddisarockstar · Mar 14, 2017 at 11:04 PM
I ran into your same problem just a couple weeks ago. I was actually surprised unity didnt have anything like this as one of there default shaders.
Anyways, I just wrote my own! it works great. You can use it if you would like.
When you make your map texture, just paint with black red green and blue colors to assign where the four actual textures go. the alpha channel of the map texture will mask all textures.
be sure to set the amount of textures you are using in the inspector
You can use it if you would like.
The "map" texture doesn't need to be assigned as an actual map in the inspector. it just works
Shader "todds/Transparent 4Textures" {
Properties {
// _Color ("Overall Color", Color) = (1,0.5,0.5,1)
_ac ("alpha cutoff for textures", Range(.0,1)) = 0
_acm ("alpha cutoff for map", Range(.0,1)) = 0
_t1 ("texture in black", 2D) = "white" {}
_tint1 ("Tint1", Color) = (1.0, 1, 1, 0)
_t2 ("texture in red", 2D) = "white" {}
_tint2 ("Tint2", Color) = (1.0, 1, 1, 0)
_rc ("amplify red", Range(1,80)) = 0.0
_t3 ("texture in blue", 2D) = "white" {}
_tint3 ("Tint3", Color) = (1.0,1,1,0)
_rb ("amplify blue", Range(1,80)) = 0.0
_t5 ("texture in green", 2D) = "white" {}
_tint5 ("Tint4", Color) = (1.0,1,1,0)
_rg ("amplify green", Range(1,80)) = 0.0
_t4 ("texture map", 2D) = "white" {}
num ("Number of textures used", Int) = 5
}
SubShader {
Tags { "Queue"="Transparent" "RenderType"="Transparent" }
LOD 200
CGPROGRAM
#pragma surface surf Lambert alpha
int num;
float _rc;
float _rb;float _rg;
float _ac;
float _acm;
sampler2D _t1;
sampler2D _t2;
sampler2D _t3;
sampler2D _t4;
sampler2D _t5;
fixed4 _tint1;
fixed4 _tint2;
fixed4 _tint3;
fixed4 _tint5;
struct Input {
float2 uv_t1;
float2 uv_t2;
float2 uv_t3;
float2 uv_t4;
float2 uv_t5;
};
void surf (Input IN, inout SurfaceOutput o) {
float f;float f2;
half4 pix2;
half4 pix = tex2D (_t1, IN.uv_t1)*_tint1;
pix.a=tex2D (_t1, IN.uv_t1).a;
half4 map = tex2D (_t4, IN.uv_t4);
float alph;
if(num>1){
alph=tex2D (_t2, IN.uv_t2).a;
if(alph>_ac){
f=map.r;
if(f>0){
f=f*_rc;
if(f>1){f=1;}
f*=alph;
f2=1-f;
pix=pix*f2;
pix=pix+tex2D (_t2, IN.uv_t2)*f*_tint2;
pix.a+=tex2D (_t2, IN.uv_t2).a*f;
}}
if(num>2){
alph=tex2D (_t3, IN.uv_t3).a;
if(alph>_ac){
f=map.b;
if(f>0){
f=f*_rb;
if(f>1){f=1;}
f*=alph;
f2=1-f;
pix=pix*f2;
pix=pix+tex2D (_t3, IN.uv_t3)*f*_tint3;}
pix.a+=tex2D (_t3, IN.uv_t3).a*f;
}
if(num>3){
alph=tex2D (_t5, IN.uv_t5).a;
if(alph>_ac){
f=map.g;
if(f>0){
f=f*_rg;
if(f>1){f=1;}
f*=alph;
f2=1-f;
pix=pix*f2;
pix=pix+tex2D (_t5, IN.uv_t5)*f*_tint5;}
pix.a+=tex2D (_t5, IN.uv_t5).a*f;
}
}}
}
o.Albedo = pix.rgb;
f=pix.a;
if(map.a<_acm){map.a=0;}
if(map.a<pix.a){f=map.a;}
o.Alpha = f;
}
ENDCG
}
FallBack "Diffuse"
}
Hey, thanks!
I will try it out and get back to you.
Okay, I've played with it a bit and it seems pretty cool. I may not have figured it out completely but I'm not sure if it can do what I was looking for. $$anonymous$$aybe you can still help me.
Is there a way to multiply the 3 textures together so that they blend on top of each other? And with the map, can I use it to completely hide and show the same parts of all 3 textures (Like an alpha channel)? In my code above I use a black and white image for the "_$$anonymous$$ask" texture, and it hides parts of another texture. I just can't figure out how to get it to mask more than one other texture.
Thanks again!
I have updated my answer for you. I have adjusted my shader to fully support transparency in all the textures. Also the map texture's alpha channel works as a mask for all the textures!!!
your base color is now black ins$$anonymous$$d of white (black is absence of all colors).
and i added a fourth texture represented by green.
in the inspector be sure to set the number of textures you are useing.
and now this shader should have no problem mixing any or all of the textures if you play with the color on the map!!!
this should definately do what you need now!!!!
Is it possible to pull the blend color information from vertex colors ins$$anonymous$$d of a map texture?
Really thanks! It works, but I used it otherwise. I just SetTexture some 2D pictures to each texture, and it works fine
Answer by Marks98 · Jul 11, 2018 at 09:05 PM
Hi.
I have a problem.
I don't understant how i can use this shader. I need transparent shader to my terrain but when i fill out all the textures only one is showing. What i do wrong?
Can somebody help me please?
Thank you ,Marks
Your answer
Follow this Question
Related Questions
Implement texture masking into simple existing shader 1 Answer
How to apply refraction at marked texture pixels while the rest is being rendered normal? 1 Answer
Shader: Cutout behavior mixed with masking behavior 0 Answers
Through bullet holes on the objects 0 Answers
Stencil inside Stencil? (Multiple masks on same object) 1 Answer