Huge fps drop with shader for texture combining

I’ve got this shader for combining up to 4 textures in 1:

Shader "Custom/TexCombinations" {

    Properties {
        _Cutoff ("Cutoff", Range(0,1)) = 0.5        
         _Color ("Main Color", Color) = (1,1,1,1)
        _MainTex ("Tex", 2D)   = ""
        _MainTex1 ("Tex1", 2D) = ""
        _MainTex2 ("Tex2", 2D) = ""
        _MainTex3 ("Tex3", 2D) = ""
    }

    SubShader {
   
        Tags{ "Queue"="AlphaTest" "RenderType"="TransparentCutout" }
       
        LOD 200

        CGPROGRAM
        #pragma surface surf Lambert alphatest:_Cutoff
        sampler2D _MainTex;
        fixed4 _Color;
       
        struct Input {    float2 uv_MainTex;   };
       
        void surf (Input IN, inout SurfaceOutput o) {
            fixed4 c = tex2D(_MainTex, IN.uv_MainTex) * _Color;
            o.Albedo = c.rgb;   
            o.Alpha = c.a;
        }
        ENDCG

        CGPROGRAM
        #pragma surface surf Lambert alphatest:_Cutoff
        sampler2D _MainTex1;
        fixed4 _Color;
       
        struct Input {    float2 uv_MainTex;   };
       
        void surf (Input IN, inout SurfaceOutput o) {
            fixed4 c = tex2D(_MainTex1, IN.uv_MainTex) * _Color;
            o.Albedo = c.rgb;   
            o.Alpha = c.a;
        }
        ENDCG
       
        CGPROGRAM
        #pragma surface surf Lambert alphatest:_Cutoff
        sampler2D _MainTex2;
        fixed4 _Color;
       
        struct Input {    float2 uv_MainTex;   };
       
        void surf (Input IN, inout SurfaceOutput o) {
            fixed4 c = tex2D(_MainTex2, IN.uv_MainTex) * _Color;
            o.Albedo = c.rgb;   
            o.Alpha = c.a;
        }
        ENDCG
       
        CGPROGRAM
        #pragma surface surf Lambert alphatest:_Cutoff
        sampler2D _MainTex3;
        fixed4 _Color;
       
        struct Input {    float2 uv_MainTex;   };
       
        void surf (Input IN, inout SurfaceOutput o) {
            fixed4 c = tex2D(_MainTex3, IN.uv_MainTex) * _Color;
            o.Albedo = c.rgb;   
            o.Alpha = c.a;
        }
        ENDCG


    }

    Fallback "TransparentDiffuse"
}

TransparentDiffuse shader

Shader "TransparentDiffuse"
{
        Properties
        {
                _Color ("Main Color", Color) = (1,1,1,1)
                _MainTex ("Base (RGB) Trans (A)", 2D) = "white" {}
        }
        SubShader
        {
                Tags {"Queue"="AlphaTest" "IgnoreProjector"="True" "RenderType"="TransparentCutout"}
                blend SrcAlpha OneMinusSrcAlpha
              
                LOD 200
                ZWrite Off
                CGPROGRAM
                #pragma surface surf Lambert exclude_path:prepass
              
                sampler2D _MainTex;
                fixed4 _Color;
              
                struct Input
                {
                        float2 uv_MainTex;
                };
              
                void surf (Input IN, inout SurfaceOutput o)
                {
                        fixed4 c = tex2D(_MainTex, IN.uv_MainTex) * _Color;
                        o.Albedo = c.rgb;
                        o.Alpha = c.a;
                }
                ENDCG
        }
      
      
        SubShader
        {
                Pass
                {
                        Tags {"Queue"="Transparent" "IgnoreProjector"="True" "RenderType"="Transparent"}
                        ZWrite Off
                        Blend SrcAlpha OneMinusSrcAlpha
                        Material
                        {
                                Diffuse [_Color]
                                Ambient [_Color]     
                        }
                        Lighting On
                        SetTexture [_MainTex]
                        {
                                Combine texture * primary DOUBLE, texture * primary
                        }
                }
        }
Fallback "VertexLit"
}

For this result (two planes. one with this shader):


2073924--135344--result2.png

Any idea about how to do this faster? Im noob at shading so I feel like doing something is wrong here.

You could get it a bit faster with CG/Frag instead of surface shader but it’s probably not much faster. Essentially, you are bottlenecked by texture reads and from the lower screenshot, probably draw calls. In all, this is a terrible way to work.

A better way may be a 4-texture vertex splat shader, where each vertex colour on the mesh dictates how much of that texture is shown. You can apply something like this to one large mesh, instead of your current approach on loads of little quads.

@crol1 you do realize you can just add all of the textures in a single surface shader?
Just use max() to get the brightest color…

Could this run faster than using 4 additional “layers” of quads with cutout shader on each? (currently using this)

Ive got procedural world but probably if I will split it to big chunks like 10x10 with splat shader this will run much faster cause 1 quad will replace 50…

@zoran404 , @hippocoder thanks!

Well firstly we don’t have profiler information so that would help. Secondly, if you combine all these into one large mesh and atlas the different texture combinations it might be fastest of all.