Search Unity

Help with Custom Terrain AddPass Shader

Discussion in 'Shaders' started by Koropokuruh, Jan 30, 2017.

  1. Koropokuruh

    Koropokuruh

    Joined:
    Mar 23, 2010
    Posts:
    18
    I've been adventuring myself in scripting shaders for unity, followed some tutorials, made some on my own and finally tried to adventure into making a terrain shader.

    So I've looked into this tutorial :
    https://alastaira.wordpress.com/2013/12/07/custom-unity-terrain-material-shaders/

    Looked the builtin shaders...

    And found this article on Gamasutra:
    http://www.gamasutra.com/blogs/Andr...196339/Advanced_Terrain_Texture_Splatting.php

    And tried to make a new terrain shader.
    But I'm having trouble with the AddPass shader, it's not working. Tried a lot of things and still didn't work. It seems like it's falling back and when I remove the fallback it just paints all the textures from the first pass all mixed up.

    Here's a screenshot:


    Is there a way to fix these so I can have more than 4 textures in my terrain?

    Here are the shaders (did not apply normal maps yet):
    FirstPass shader:

    Code (CSharp):
    1. Shader "Raed Wulf/Terrain/BlendTexture" {
    2.     Properties{
    3.         //control splat map
    4.         [HideInInspector] _Control("Control (RGBA)", 2D) = "red" {}
    5.  
    6.         //textures Alpha is height
    7.         [HideInInspector] _Splat3("Layer 3 (A)", 2D) = "white" {}
    8.         [HideInInspector] _Splat2("Layer 2 (B)", 2D) = "white" {}
    9.         [HideInInspector] _Splat1("Layer 1 (G)", 2D) = "white" {}
    10.         [HideInInspector] _Splat0("Layer 0 (R)", 2D) = "white" {}
    11.  
    12.         //normal maps
    13.         [HideInInspector] _Normal3("Normal 3 (A)", 2D) = "bump" {}
    14.         [HideInInspector] _Normal2("Normal 2 (B)", 2D) = "bump" {}
    15.         [HideInInspector] _Normal1("Normal 1 (G)", 2D) = "bump" {}
    16.         [HideInInspector] _Normal0("Normal 0 (R)", 2D) = "bump" {}
    17.  
    18.         // used in fallback on old cards & base map
    19.         [HideInInspector] _MainTex("BaseMap (RGB)", 2D) = "white" {}
    20.         [HideInInspector] _Color("Main Color", Color) = (1,1,1,1)
    21.     }
    22.  
    23.     SubShader{
    24.         Tags{
    25.             "SplatCount" = "4"
    26.             "Queue" = "Geometry-100"
    27.             "RenderType" = "Opaque"
    28.         }
    29.  
    30.         CGPROGRAM
    31.         #pragma surface surf Lambert exclude_path:forward
    32.         #pragma multi_compile_fog
    33.         #pragma target 3.0
    34.         // needs more than 8 texcoords
    35.         #pragma exclude_renderers gles
    36.         #include "UnityPBSLighting.cginc"
    37.  
    38.         // Access the Shaderlab properties
    39.         uniform sampler2D _Control;
    40.         uniform sampler2D _Splat0,_Splat1,_Splat2,_Splat3;
    41.    
    42.  
    43.         // Surface shader input structure
    44.         struct Input {
    45.             float2 uv_Control : TEXCOORD0;
    46.             float2 uv_Splat0 : TEXCOORD1;
    47.             float2 uv_Splat1 : TEXCOORD2;
    48.             float2 uv_Splat2 : TEXCOORD3;
    49.             float2 uv_Splat3 : TEXCOORD4;
    50.         };
    51.  
    52.         float4 blend(float4 texA, float aA, float4 texB, float aB)
    53.         {
    54.  
    55.             float depth = 0.1;
    56.             float ma = max(texA.a + aA, texB.a + aB) - depth;
    57.  
    58.             float b1 = max(texA.a + aA - ma, 0.0);
    59.             float b2 = max(texB.a + aB - ma, 0.0);
    60.  
    61.             return (texA * b1 + texB * b2) / (b1 + b2);
    62.  
    63.         }
    64.  
    65.        
    66.         // Surface Shader function
    67.         void surf(Input IN, inout SurfaceOutput o) {
    68.             fixed4 tex0 = tex2D(_Splat0, IN.uv_Splat0);
    69.             fixed4 tex1 = tex2D(_Splat1, IN.uv_Splat1);
    70.             fixed4 tex2 = tex2D(_Splat2, IN.uv_Splat2);
    71.             fixed4 tex3 = tex2D(_Splat3, IN.uv_Splat3);
    72.  
    73.             fixed4 splat_control = tex2D(_Control, IN.uv_Control);
    74.             fixed4 col;
    75.  
    76.             col = blend(tex0, splat_control.r, tex1, splat_control.g);
    77.             col = blend(col, splat_control.r + splat_control.g, tex2, splat_control.b);
    78.             col = blend(col, splat_control.r + splat_control.g + splat_control.b, tex3, splat_control.a);
    79.  
    80.             o.Albedo = col.rgb;
    81.             o.Alpha = col.a;        
    82.  
    83.         }
    84.         ENDCG
    85.     }
    86.  
    87.         Dependency "AddPassShader" = "Hidden/Raed Wulf/Terrain/BlendTexture-AddPass"
    88.         Dependency "BaseMapShader" = "Diffuse"
    89.  
    90.         Fallback "Nature/Terrain/Diffuse"
    91. }
    AddPass Shader:

    Code (CSharp):
    1. Shader "Hidden/Raed Wulf/Terrain/BlendTexture-AddPass" {
    2.     Properties{
    3.         //control splat map
    4.         [HideInInspector] _Control("Control (RGBA)", 2D) = "red" {}
    5.  
    6.         //textures Alpha is height
    7.         [HideInInspector] _Splat3("Layer 3 (A)", 2D) = "white" {}
    8.         [HideInInspector] _Splat2("Layer 2 (B)", 2D) = "white" {}
    9.         [HideInInspector] _Splat1("Layer 1 (G)", 2D) = "white" {}
    10.         [HideInInspector] _Splat0("Layer 0 (R)", 2D) = "white" {}
    11.  
    12.         //normal maps
    13.         [HideInInspector] _Normal3("Normal 3 (A)", 2D) = "bump" {}
    14.         [HideInInspector] _Normal2("Normal 2 (B)", 2D) = "bump" {}
    15.         [HideInInspector] _Normal1("Normal 1 (G)", 2D) = "bump" {}
    16.         [HideInInspector] _Normal0("Normal 0 (R)", 2D) = "bump" {}
    17.  
    18.         // used in fallback on old cards & base map
    19.         [HideInInspector] _MainTex("BaseMap (RGB)", 2D) = "white" {}
    20.         [HideInInspector] _Color("Main Color", Color) = (1,1,1,1)
    21.    
    22.     }
    23.  
    24.     SubShader{
    25.         Tags{
    26.             "SplatCount" = "4"
    27.             "Queue" = "Geometry-99"
    28.             "IgnoreProjector" = "True"
    29.             "RenderType" = "Opaque"
    30.         }
    31.  
    32.         CGPROGRAM
    33.         #pragma surface surf Lambert exclude_path:forward decal:add
    34.         #pragma multi_compile_fog
    35.         #pragma target 3.0
    36.         // needs more than 8 texcoords
    37.         #pragma exclude_renderers gles
    38.         #include "UnityPBSLighting.cginc"
    39.    
    40.         // Access the Shaderlab properties
    41.         uniform sampler2D _Control;
    42.         uniform sampler2D _Splat0,_Splat1,_Splat2,_Splat3;
    43.  
    44.         // Surface shader input structure
    45.         struct Input {
    46.             float2 uv_Control : TEXCOORD0;
    47.             float2 uv_Splat0 : TEXCOORD1;
    48.             float2 uv_Splat1 : TEXCOORD2;
    49.             float2 uv_Splat2 : TEXCOORD3;
    50.             float2 uv_Splat3 : TEXCOORD4;
    51.         };
    52.  
    53.         float4 blend(float4 texA, float aA, float4 texB, float aB)
    54.         {
    55.  
    56.             float depth = 0.1;
    57.             float ma = max(texA.a + aA, texB.a + aB) - depth;
    58.  
    59.             float b1 = max(texA.a + aA - ma, 0.0);
    60.             float b2 = max(texB.a + aB - ma, 0.0);
    61.  
    62.             return (texA * b1 + texB * b2) / (b1 + b2);
    63.  
    64.         }
    65.  
    66.        
    67.         // Surface Shader function
    68.         void surf(Input IN, inout SurfaceOutput o) {
    69.             fixed4 tex0 = tex2D(_Splat0, IN.uv_Splat0);
    70.             fixed4 tex1 = tex2D(_Splat1, IN.uv_Splat1);
    71.             fixed4 tex2 = tex2D(_Splat2, IN.uv_Splat2);
    72.             fixed4 tex3 = tex2D(_Splat3, IN.uv_Splat3);
    73.  
    74.             fixed4 splat_control = tex2D(_Control, IN.uv_Control);
    75.             fixed4 col;
    76.  
    77.             col = blend(tex0, splat_control.r, tex1, splat_control.g);
    78.             col = blend(col, splat_control.r + splat_control.g, tex2, splat_control.b);
    79.             col = blend(col, splat_control.r + splat_control.g + splat_control.b, tex3, splat_control.a);
    80.  
    81.             o.Albedo = col.rgb;
    82.             o.Alpha = 0.0;
    83.                    
    84.         }
    85.         ENDCG
    86.     }
    87.  
    88.         Fallback "Hidden/TerrainEngine/Splatmap/Diffuse-AddPass"
    89.         //Fallback off
    90. }
    Thanks in Advanced!
     
    Last edited: Jan 30, 2017
  2. xiaoxiaosh

    xiaoxiaosh

    Joined:
    May 12, 2017
    Posts:
    1
    addpass will blend firstpass pixel alpha
    you can change this line:
    o.Alpha = 0.0;
    to:
    o.Alpha=dot(float4(tex0.a,tex1.a,tex2.a,tex3.a),splat_control);
    good luck!
     
    UnityLighting and IgorAherne like this.