Search Unity

Help needed: Terrain shader with custom blending

Discussion in 'Shaders' started by spiritworld, Sep 18, 2021.

  1. spiritworld

    spiritworld

    Joined:
    Nov 26, 2014
    Posts:
    23
    I'm trying to make customized version of Unity's built-in terrain shader. My goal is sharp, or "masked" blending between textures but I can't wrap my head around how.

    Started with this tutorial Making Sharply Blended Toon Terrain in Unity! - YouTube but it's too straight.

    I basically want this (Source: InnoGames Techblog):

    image2019-4-3_16-4-25-1024x508.png


    If anyone interested here's the current version with worldNormal snow added (u need also custom Input struct. download TerrainSplatmapCustom.txt, and change extension to .cginc).

    Code (CSharp):
    1. // Unity built-in shader source. Copyright (c) 2016 Unity Technologies. MIT license (see license.txt)
    2.  
    3. Shader "Nature/Terrain/DiffuseCustom" {
    4.     Properties {
    5.  
    6.         _NoiseTex("Distortion", 2D) = "bump" {}
    7.  
    8.         _SnowLevel ("_SnowLevel", Range(-1, 1)) = 0
    9.         _Noise ("Noise", Range(0, 5)) = 0
    10.         [HideInInspector] _SnowDirection ("Snow Direction", Vector) = (0, 1, 0)
    11.  
    12.         // used in fallback on old cards & base map
    13.         [HideInInspector] _MainTex ("BaseMap (RGB)", 2D) = "white" {}
    14.         [HideInInspector] _Color ("Main Color", Color) = (1,1,1,1)
    15.         [HideInInspector] _TerrainHolesTexture("Holes Map (RGB)", 2D) = "white" {}
    16.         [HideInInspector] _SnowColor ("Snow color", Color) = (1, 1, 1, 1)
    17.         [HideInInspector] _RimIntensity("Rim Intensity", Range (0, 1)) = 0.1
    18.         [HideInInspector] _Shininess ("Shininess", Range(0,1)) = 0.22
    19.  
    20.     }
    21.  
    22.     CGINCLUDE
    23.     #pragma surface surf Lambert vertex:SplatmapVert finalcolor:SplatmapFinalColor finalprepass:SplatmapFinalPrepass finalgbuffer:SplatmapFinalGBuffer addshadow fullforwardshadows
    24.     #pragma instancing_options assumeuniformscaling nomatrices nolightprobe nolightmap forwardadd
    25.     #pragma multi_compile_fog
    26.     #pragma target 4.0
    27.     #include "TerrainSplatmapCustom.cginc"
    28.  
    29.     sampler2D _NoiseTex;
    30.  
    31.     fixed4 _SnowColor;
    32.     half _Shininess, _Noise;
    33.  
    34.     uniform half _SnowLevel;
    35.     uniform half _RimIntensity;
    36.     uniform half3 _SnowDirection;
    37.  
    38.     void surf(Input IN, inout SurfaceOutput o)
    39.     {
    40.         half4 splat_control;
    41.         half weight;
    42.         fixed4 mixedDiffuse;
    43.         SplatmapMix(IN, splat_control, weight, mixedDiffuse, o.Normal);
    44.  
    45.         float3 noiseSample = tex2D(_NoiseTex, IN.uv_NoiseTex);
    46.  
    47.         // snow emission
    48.         half VdotN = dot(normalize(IN.viewDir), o.Normal);
    49.         half rim = pow(1.0 - saturate(VdotN), _RimIntensity);
    50.         rim = smoothstep(rim - 0.1, rim + 0.1, VdotN);
    51.         fixed snowEmission = (1.0 - rim) * _RimIntensity * fixed3(0.26, 0.19, 0.16);
    52.  
    53.         // snow mask
    54.         half3 worldNormal = normalize(WorldNormalVector(IN, o.Normal));
    55.         float upMask = dot(worldNormal, _SnowDirection);
    56.  
    57.         half3 blendMask = -mixedDiffuse.rgb * 0.5 + 0.5;
    58.         half upMaskMod = (upMask * noiseSample.r * 0.1) + upMask;
    59.  
    60.         blendMask.r += ((upMaskMod + _SnowLevel) * noiseSample.r) * 2;
    61.  
    62.         upMask = step(upMaskMod - blendMask.r, _SnowLevel);  
    63.         upMask = saturate(pow(upMask, 10.0));
    64.  
    65.         half3 snowColor = _SnowColor.rgb + snowEmission;
    66.         half3 terrainColor = mixedDiffuse.rgb;
    67.  
    68.         o.Albedo = lerp(terrainColor, snowColor, upMask);
    69.         o.Alpha = weight;
    70.     }
    71.     ENDCG
    72.  
    73.     Category {
    74.         Tags {
    75.             "Queue" = "Geometry-99"
    76.             "RenderType" = "Opaque"
    77.         }
    78.         // TODO: Seems like "#pragma target 3.0 _NORMALMAP" can't fallback correctly on less capable devices?
    79.         // Use two sub-shaders to simulate different features for different targets and still fallback correctly.
    80.         SubShader { // for sm3.0+ targets
    81.             CGPROGRAM
    82.             #pragma target 3.0
    83.             #pragma multi_compile_local_fragment __ _ALPHATEST_ON
    84.             #pragma multi_compile_local __ _NORMALMAP
    85.             ENDCG
    86.  
    87.             UsePass "Hidden/Nature/Terrain/Utilities/PICKING"
    88.             UsePass "Hidden/Nature/Terrain/Utilities/SELECTION"
    89.         }
    90.     }
    91.  
    92.     Dependency "BaseMapShader"    = "Hidden/TerrainEngine/Splatmap/Diffuse-Base"
    93.     Dependency "BaseMapGenShader" = "Hidden/TerrainEngine/Splatmap/Diffuse-BaseGen"
    94.     Dependency "Details0"         = "Hidden/TerrainEngine/Details/Vertexlit"
    95.     Dependency "Details1"         = "Hidden/TerrainEngine/Details/WavingDoublePass"
    96.     Dependency "Details2"         = "Hidden/TerrainEngine/Details/BillboardWavingDoublePass"
    97.     Dependency "Tree0"            = "Hidden/TerrainEngine/BillboardTree"
    98.  
    99.     Fallback "Diffuse"
    100. }
    Source for snow masking Up-Vector Masking in Shaders - Jordan Stevens (jordanstevenstechart.com)
     

    Attached Files:

unityunity