- Home /
Shader with two textures separated by an alpha channel?
I have a bunch of wall assets which look like this (quick screenshot, the full texture tiles):

I am trying to make the red parts animate and move horizontally, whereas the gray foreground parts stay static. Currently this is my solution:
- Use two planes with separate textures, one 0.001 units behind the other. 
- For the foreground, use a cutout alpha shader to mask out the parts that should be red/animated. 
- For the background, use a separate texture with a script that changes the X offset and time it so that it tiles. 
While this works, it's clumsy to use two planes for each wall section, it makes it harder to snap to a grid since it often snaps to the element with an offset, and it uses more draw calls through separate materials.
Is there a way to make a shader which has these properties?
- Use a diffuse map which is masked by its alpha channel. 
- Use a second diffuse map which uses no alpha and always renders below the first one. 
- Have the second diffuse map be targetable with a script so its offset can be animated separately. 
This way I could do it all in a single plane with no (or minimal) extra draw calls and it'd all work much more elegantly. I'm not very knowledgeable on shaders and any material on this kind of approach I found online was either incomplete or obsolete at this point. This is a mobile-targeted game so optimally there'd only be a diffuse map and it'd be lit with a lightmap.
Yes. With the standard shader, you can use the Secondary$$anonymous$$aps area. Sliding offset2 will animate the red parts of yours. In a custom shader, generally you make/animate both textures and end with: finCol=lerp(col2,col1,col1.a);
Answer by toddisarockstar · May 14, 2017 at 10:59 PM
is this what you need ?
 Shader "2 layers transparent" {
     Properties {
        // _Color ("Overall Color", Color) = (1,0.5,0.5,1)
         _t1 ("texture in white", 2D) = "white" {}
         _tint1 ("Tint1", Color) = (1.0, 0.6, 0.6, 1.0)
         
         _t2 ("texture in red", 2D) = "white" {}
         _tint2 ("Tint2", Color) = (1.0, 0.6, 0.6, 1.0)
         
         _t3 ("use for alpha channel", 2D) = "white" {}
 
         
         _rc ("low cutoff", Range(1,80)) = 1.0 
     
         
     }
     SubShader {
         //Tags { "RenderType"="Opaque" }
         LOD 200
         
         CGPROGRAM
         #pragma surface surf Lambert
         float _rc;
 
         
         sampler2D _t1;
         sampler2D _t2;
         sampler2D _t3;
 
         
         fixed4 _tint1;
         fixed4 _tint2;
 
 
         
         struct Input {
             
             float2 uv_t1;
             float2 uv_t2;
             float2 uv_t3;
 
             
         };
       
 
         void surf (Input IN, inout SurfaceOutput o) {
             
             float f;
             
             half4 pix = tex2D (_t1, IN.uv_t1)*_tint1;
             half4 pix2 = tex2D (_t2, IN.uv_t2)*_tint2;
             f=tex2D (_t3, IN.uv_t3).a;
             
             f=f*_rc;
             if(f>1){f=1;}
             f=1-f;
             pix=pix*f;
             f=1-f;
             pix=pix+pix2*f;
             
             
             
             o.Albedo = pix.rgb;
             
         }
         ENDCG
     } 
     FallBack "Diffuse"
 }
 
Thanks! This seems to work well in displaying the texture properly, though I'm having some problems making the animation - I've named the texture to be animated "Background" in the shader, and got a script with this code:
 void Update () {
 
         meshRenderer.material.SetTextureOffset("Background", meshRenderer.material.GetTextureOffset("Background") + new Vector2((0.01f * Time.deltaTime), 0f));
         if (meshRenderer.material.GetTextureOffset("Background").x >= offsetAmount)
             meshRenderer.material.SetTextureOffset("Background", defaultPos);
 
     }
When running the game I got a "$$anonymous$$aterial doesn't have a texture property 'Background'" error - any thoughts on this?
 //animate like this
 
 float newoff;
 newoff = newoff + Time.deltaTime;
 if(newoff>1){newoff=0;}
 
 gameObject.renderer.material.SetTextureOffset("_t2",new Vector2(newoff,0f));
when you are looking up a texture in a shader, you have to reference the variable in the shader script that is holding the texture......not the name of the actual asset. if you look near the top of the script, i named the variable holding the second texture as "_t2". It doesn't matter the name of the texture you drag into it.
also i was just re reading your question. i wrote this so that it would make it look like blood running through tubes. did you want to have the position of the red tubes to move? i could give you another shorter script for that if that's all you what wanted to do. otherwise you would move the offset of both "_t2" and "_t3".
actually with this script you could both move the position of the tubes with "_t3" and if you moved "_t2" a bit faster you would get an effect of stuff moving through the tubes at the same time!!!
Replacing "Background" with the correct variable worked well, thanks!
Indeed all I need to do is animate the red part, and keep the alpha and foreground still- your shader seems to do the job fine so far, thank you for the assistance :)
Your answer
 
 
             Follow this Question
Related Questions
Soft edge shader - Issues when objects using same material overlap 0 Answers
(c#) Transparency Problem - Toggle not Gradient 1 Answer
Shader: separate alpha texture, independent offset 1 Answer
Boat wake/foam 0 Answers
How can i get mixed texture from one shader and set it for another object with another shader? 0 Answers
 koobas.hobune.stream
koobas.hobune.stream 
                       
               
 
			 
                