Terrain Shader with multiple splat textures

Hey people, I was looking at a terrain shader which can support multiple splat textures. Just didn’t know how to get hold of them. After serfing the webz, I found a post by FlatterZange
Original Post

Moin Ich bastel gerade einen alternativen shader für ein Unity terrain von mir das ich als .OBJ model exportiert habe.

Das schlimmste war alle Shader im inet haben einen maximalen Splat Texture Count von 4.

Allso habe ich heute mal einen mit 8 gebaut da ich schon mehr als 4 Texturen auf meinem Unity terrain nutze und das auch so bleiben soll^^

Basieren tut er auf den Internen Unity Terrain shadern nur mit besseren Blending dank Lerp.

Dieser Shader benötigt 2 SplatMasken findet allso nur anwendung mit mehr als 4 Splat Texturen.

Wer intresse dran hat:

Shader "TMG/TMG_8SplatShader_Diffuse" {
Properties {
_Control ("Control Mask 1 (RGBA)", 2D) = "red" {}
_Splat0 ("Layer 0 (R)", 2D) = "white" {}
_Splat1 ("Layer 1 (G)", 2D) = "white" {}
_Splat2 ("Layer 2 (", 2D) = "white" {}
_Splat3 ("Layer 3 (A)", 2D) = "white" {}
_Control2 ("Control Mask 2 (RGBA)", 2D) = "red" {}
_Splat4 ("Layer 4 (R)", 2D) = "white" {}
_Splat5 ("Layer 5 (G)", 2D) = "white" {}
_Splat6 ("Layer 6 (", 2D) = "white" {}
_Splat7 ("Layer 7 (A)", 2D) = "white" {}
}

SubShader {
Tags {
"SplatCount" = "4"
"Queue" = "Geometry-100"
"IgnoreProjector"="False"
"RenderType" = "Opaque"
}
CGPROGRAM
#pragma surface surf Lambert
struct Input {
float2 uv_Control : TEXCOORD0;
float2 uv_Splat0 : TEXCOORD1;
float2 uv_Splat1 : TEXCOORD2;
float2 uv_Splat2 : TEXCOORD3;
float2 uv_Splat3 : TEXCOORD4;
};
sampler2D _Control;
sampler2D _Splat0,_Splat1,_Splat2,_Splat3;
void surf (Input IN, inout SurfaceOutput o) {
fixed4 splat_control = tex2D (_Control, IN.uv_Control);
fixed3 col  = fixed3(0,0,0);

float4 tmp = tex2D (_Splat0, IN.uv_Splat0);
col = lerp(col, tmp.rgb, splat_control.r * tmp.a);
tmp = tex2D (_Splat1, IN.uv_Splat1);
col = lerp(col, tmp.rgb, splat_control.g * tmp.a);
tmp = tex2D (_Splat2, IN.uv_Splat2);
col = lerp(col, tmp.rgb, splat_control.b * tmp.a);
tmp = tex2D (_Splat3, IN.uv_Splat3);
col = lerp(col, tmp.rgb, splat_control.a * tmp.a);

o.Albedo = col;
}
ENDCG

Tags {
"SplatCount" = "4"
"Queue" = "Geometry-99"
"IgnoreProjector"="False"
"RenderType" = "Opaque"
}
CGPROGRAM
#pragma surface surf Lambert decal:add
struct Input {
float2 uv_Control2 : TEXCOORD5;
float2 uv_Splat4 : TEXCOORD6;
float2 uv_Splat5 : TEXCOORD7;
float2 uv_Splat6 : TEXCOORD8;
float2 uv_Splat7 : TEXCOORD9;
};
sampler2D _Control2;
sampler2D _Splat4,_Splat5,_Splat6,_Splat7;
void surf (Input IN, inout SurfaceOutput o) {
fixed4 splat_control2 = tex2D (_Control2, IN.uv_Control2);
fixed3 col = fixed3(0,0,0);

float4 tmp = tex2D (_Splat4, IN.uv_Splat4);
col = lerp(col, tmp.rgb, splat_control2.r * tmp.a);
tmp = tex2D (_Splat5, IN.uv_Splat5);
col = lerp(col, tmp.rgb, splat_control2.g * tmp.a);
tmp = tex2D (_Splat6, IN.uv_Splat6);
col = lerp(col, tmp.rgb, splat_control2.b * tmp.a);
tmp = tex2D (_Splat7, IN.uv_Splat7);
col = lerp(col, tmp.rgb, splat_control2.a * tmp.a);

o.Albedo = col;
}
ENDCG
}
// Fallback to Diffuse
Fallback "Diffuse"
}

Ich bau gerade das dazugehörige BumpScript das alle 8 layer auch mit NormalMaps und regelbaren Specular effeckt dargestellt werden können.

Dazu mehr Später.

Grüsse.

After changing the shader a tiny bit (removing “in my opinion” unnecessary uv coords from the Input struct) otherwise it could throw errors “did you want to incude #pragma target 3.0”, etc.
Here it is:

Adjusted shader

Shader "Custom/TerrainHeightShader" {
    Properties{
        _Control("Control Mask 1 (RGBA)", 2D) = "red" {}
        _Splat0("Layer 0 (R)", 2D) = "white" {}
        _Splat1("Layer 1 (G)", 2D) = "white" {}
        _Splat2("Layer 2 (B)", 2D) = "white" {}
        _Splat3("Layer 3 (A)", 2D) = "white" {}
        _Control2("Control Mask 2 (RGBA)", 2D) = "red" {}
        _Splat4("Layer 4 (R)", 2D) = "white" {}
        _Splat5("Layer 5 (G)", 2D) = "white" {}
        _Splat6("Layer 6 (B)", 2D) = "white" {}
        _Splat7("Layer 7 (A)", 2D) = "white" {}
     }

    SubShader{
        Tags{
            "SplatCount" = "8"
            "Queue" = "Geometry-100"
            "IgnoreProjector" = "False"
            "RenderType" = "Opaque"
        }
        CGPROGRAM
        #pragma surface surf Lambert
        struct Input {
            float2 uv_Control : TEXCOORD0;
            float2 uv_Splat0 : TEXCOORD1;
        };
        sampler2D _Control;
        sampler2D _Splat0,_Splat1,_Splat2,_Splat3;

        void surf(Input IN, inout SurfaceOutput o) {
            fixed4 splat_control = tex2D(_Control, IN.uv_Control);
            fixed3 col = fixed3(0,0,0);

            float4 tmp = tex2D(_Splat0, IN.uv_Splat0);
            col = lerp(col, tmp.rgb, splat_control.r * tmp.a);
            tmp = tex2D(_Splat1, IN.uv_Splat0);
            col = lerp(col, tmp.rgb, splat_control.g * tmp.a);
            tmp = tex2D(_Splat2, IN.uv_Splat0);
            col = lerp(col, tmp.rgb, splat_control.b * tmp.a);
            tmp = tex2D(_Splat3, IN.uv_Splat0);
            col = lerp(col, tmp.rgb, splat_control.a * tmp.a);

            o.Albedo = col;
        }
        ENDCG

        Tags{
            "SplatCount" = "4"
            "Queue" = "Geometry-99"
            "IgnoreProjector" = "False"
            "RenderType" = "Opaque"
        }
        CGPROGRAM
            #pragma surface surf Lambert decal:add
            struct Input {
                float2 uv_Control2 : TEXCOORD5;
                float2 uv_Splat4 : TEXCOORD6;
            };
            sampler2D _Control2;
            sampler2D _Splat4,_Splat5,_Splat6,_Splat7;

            void surf(Input IN, inout SurfaceOutput o) {
                fixed4 splat_control2 = tex2D(_Control2, IN.uv_Control2);
                fixed3 col = fixed3(0,0,0);

                float4 tmp = tex2D(_Splat4, IN.uv_Splat4);
                col = lerp(col, tmp.rgb, splat_control2.r * tmp.a);
                tmp = tex2D(_Splat5, IN.uv_Splat4);
                col = lerp(col, tmp.rgb, splat_control2.g * tmp.a);
                tmp = tex2D(_Splat6, IN.uv_Splat4);
                col = lerp(col, tmp.rgb, splat_control2.b * tmp.a);
                tmp = tex2D(_Splat7, IN.uv_Splat4);
                col = lerp(col, tmp.rgb, splat_control2.a * tmp.a);

                o.Albedo = col;
            }//end surf()
        ENDCG
    }//End SubShader

    Fallback "Diffuse"
}
1 Like

Additional info, trying to get 8 splat maps working in one shader,
This might be useful

also this

And this

Meh …Just use MicroSplat from asset store

Hello, sorry for the necro bump.
Is it possible to use a one pass shader with two control textures and make it compatible with the unity terrain painting tool?