Combining a distortion and masking shader.

I’m still fairly new to shaders and don’t entirely understand how they work. I’ve searched a lot on combining two shaders into one, but it seems like it really depends on which shaders you are combining so most of the others posts I find don’t really help me with my issue.

I have two shaders that work perfectly separately, (a wavy, distortion shader and a masking shader) but I need to combine them to achieve the effect I’m going for. I’m a little lost on how to do it. Here is the distortion shader:

    Shader "Custom/DistortionShader" {
         Properties {
             _MainTex ("Base (RGB)", 2D) = "white" {}
             _Alpha("Alpha", range(0, 1)) = 1
             _SpeedX("SpeedX", float)=1.5
             _SpeedY("SpeedY", float)=1.5
             _Scale("Scale", range(0.005, 0.2))=0.03
             _TileX("TileX", float)=5
             _TileY("TileY", float)=5
         }
         
         SubShader {
             Tags { "Queue"="Transparent" "RenderType"="Transparent" }
             LOD 200
            
             CGPROGRAM
             #pragma surface surf Lambert alpha
      
             sampler2D _MainTex;
             float4 uv_MainTex_ST;
      
      		 float _Alpha;
             float _SpeedX;
             float _SpeedY;
             float _Scale;
             float _TileX;
             float _TileY;
      
             struct Input {
                 float2 uv_MainTex;
             };
      
      
             void surf (Input IN, inout SurfaceOutput o)
             {
                 float2 uv = IN.uv_MainTex;
                 uv.x += sin ((uv.x+uv.y)*_TileX+_Time.g *_SpeedX)*_Scale;
                 uv.x += cos (uv.y*_TileY+_Time.g *_SpeedY)*_Scale;
      
                 half4 c = tex2D (_MainTex, uv);
                 o.Albedo = c.rgb * _Alpha;
				 o.Alpha = c.a * _Alpha;
             }
             ENDCG
         }
         FallBack "Diffuse"
     }

And here is the masking shader:

Shader "Custom/MaskedTexture"
{
   Properties
   {
      _MainTex ("Base (RGB)", 2D) = "white" {}
      _Mask ("Culling Mask", 2D) = "white" {}
      _Cutoff ("Alpha cutoff", Range (0,1)) = 0.1
   }

   SubShader
   {
      Tags {"Queue"="Transparent"}
      Lighting Off
      ZWrite Off
      Blend SrcAlpha OneMinusSrcAlpha 
      AlphaTest GEqual [_Cutoff]
      Pass
      {
         SetTexture [_Mask] {combine texture}
         SetTexture [_MainTex] {combine texture, previous}
      }
   }
}

Your masking shader is based on an older texturing method, which Unity has phased out parts of as of Unity 5.

That said, adding the mask to the distortion shader is by no means difficult – it simply depends on how you want to add it in. You can choose to scale the distortion effect, you can blend between a regular and distorted appearance (thereby creating a slightly “ghostly” look to any part of the mask not at 100% opacity).

It also depends on how you plan to use the mask texture. Do you plan to use only one of the R/G/B/A channels? Do you plan to utilize all of them? That part becomes entirely up to you.

That said, here are a few excerpts to throw in as some food for thought:

Properties {
              _MainTex ("Base (RGB)", 2D) = "white" {}
              // 2 new lines
              _Mask ("Culling Mask", 2D) = "white" {}
              _Cutoff ("Alpha cutoff", Range (0,1)) = 0.1
              _Alpha("Alpha", range(0, 1)) = 1
              // ...
}

              #pragma surface surf Lambert alpha
       
              sampler2D _MainTex;
              float4 uv_MainTex_ST;
              // 3 new lines
              sampler2D _Mask;
              float4 uv_Mask_ST;
              float _Cutoff;
       
              float _Alpha;
              // ...

              struct Input {
                  float2 uv_MainTex;
                  // 1 new line
                  float2 uv_Mask;
              };

                  // ...

                  // Version 1: Scale distortion effect by texture (alpha channel example)
                  float2 uv = IN.uv_MainTex;
                  // 2 new lines, 2 changed lines
                  float2 maskuv = IN.uv_Mask;
                  half4 mask = tex2D (_Mask, maskuv);
                  uv.x += sin ((uv.x+uv.y)*_TileX+_Time.g *_SpeedX)*_Scale*mask.a;
                  uv.x += cos (uv.y*_TileY+_Time.g *_SpeedY)*_Scale*mask.a;
                  // ...

                  // Version 2: Blend between distorted and regular (alpha channel example)
                  half4 c = tex2D (_MainTex, uv);
                  // 3 new lines, 2 changed lines
                  half4 cleanTex = tex2D (_MainTex, IN.uv_MainTex);
                  half4 mask = tex2D (_Mask, IN.uv_Mask);
                  half4 finalTexture = lerp(cleanTex, c, mask.a);
                  o.Albedo = finalTexture.rgb * _Alpha;
                  o.Alpha = finalTexture.a * _Alpha;
                  // ...

There are numerous ways to approach this, and it really simply depends on what you’re looking to do. Try experimenting. Adding a new texture is as simple as copying parts related to _MainTex and renaming them. Then, play around with color and see what works best for your needs.

Note: My shader code is untested – I apologize for any typographical errors.

Just add the mask texture to the existing Distortion shader and apply the mask’s alpha to the output.

Add the properties:

_Mask ("Culling Mask", 2D) = "white" {}
_Cutoff ("Alpha cutoff", Range (0,1)) = 0.1

Update the variables

sampler2D _Mask;
float4 uv_Mask_ST;

struct Input {
    float2 uv_MainTex;
    float2 uv_Mask;
};

Update the surf shader pragma to consider alpha cutoff

#pragma surface surf Lambert alpha alphatest:_Cutoff

Sample the mask texture

float2 uvMask = IN.uv_Mask;
half4 mask = tex2D (_Mask, uvMask);

Apply the mask’s alpha to output

o.Alpha = c.a * _Alpha * mask.a;