Search Unity

Question Converting/Rewriting a Standard shader in the ShaderGraph

Discussion in 'Shader Graph' started by PhoenixAdvanced, Dec 6, 2019.

  1. PhoenixAdvanced

    PhoenixAdvanced

    Joined:
    Sep 30, 2016
    Posts:
    316
    Hello,

    I am currently very, very gingerly looking into porting an existing project to the HDRP. It will take a lot of work, but I have decided to look at the feasibility of converting my custom shaders. My project is basically a perpetual research project, and I am worried that if I don't port to HDRP eventually the built-in pipeline will become obsolete.

    I have made some progress, but I have never used the shadergraph before, so I would appreciate some general advice.

    This is my current shader. It uses some code from the proprietary Stix Games Grass shader, which I have removed, but the rest of the code I have written myself, so it should be fine to show here.

    Basically, it is used to procedurally texture a large planet, which has been divided into chunks.

    I am sending in the planet textures, and a "planet height" value, as well as a "relative terrain height" value.

    I am then very crudely blending between the textures using the relative terrain height, to texture the planet chunk based on the height of the vertices.

    I have posted the shader below.

    This image:
    https://i.imgur.com/JhEfpzv.png

    Is a proof of concept that I made in shader graph. It is based on a resource that I found online here:
    https://pantarei.xyz/posts/snowline-tutorial/

    I am applying it to a sphere, and it seems to split the sphere into two textures, but it doesn't blend them, and it doesn't take into account the "relative height" of the pixels.

    Is there any shader graph example that would cover this? Or, more seriously, is there anything that my original shader does that the shader graph is incapable of?

    Thanks!

    Code (CSharp):
    1. Shader "Stix Games/Terrainnormal2"
    2. {
    3.     Properties
    4.     {
    5.         _planetheight("planetheight" , float) = 0.5
    6.         _firsttex("First Texture", 2D) = "white" {}
    7.         _secondtex("Second Texture", 2D) = "white" {}
    8.         _thirdtex("Third Texture", 2D) = "white" {}
    9.         _fourthtex("fourth Texture", 2D) = "white" {}
    10.         _fifthtex("Fifth Texture", 2D) = "white" {}
    11.         _sixthtex("Sixth Texture", 2D) = "white" {}
    12.         _seventhtex("Seventh Texture", 2D) = "white" {}
    13.         _sixthnormal("sixthnormal", 2D) = "bump" {}
    14.         _seventhnormal("seventhnormal", 2D) = "bump" {}
    15.        //Snipped, Grass specific code
    16.  
    17.         _GrassTex00("Grass Texture", 2D) = "white" {}
    18.      //Snipped, Grass specific code
    19.  
    20.         _GrassTex01("Grass Texture", 2D) = "white" {}    
    21.      //Snipped, Grass specific code
    22.  
    23.         _GrassTex02("Grass Texture", 2D) = "white" {}
    24.      //Snipped, Grass specific code
    25.  
    26.         _GrassTex03("Grass Texture", 2D) = "white" {}
    27.      //Snipped, Grass specific code
    28.  
    29.         _GrassTex04("Grass Texture", 2D) = "white" {}
    30.      //Snipped, Grass specific code
    31.  
    32.         _GrassTex05("Grass Texture", 2D) = "white" {}
    33.      //Snipped, Grass specific code
    34.     }
    35.         SubShader
    36.         {
    37.             Tags{ "Queue" = "Geometry" "RenderType" = "StixGamesGrass" "RenderPipeline" = "HDRP"}
    38.             LOD 1000
    39.             CGPROGRAM
    40.             #pragma surface surf Lambert vertex:vert
    41.             #pragma target 5.0
    42.  
    43.             struct Input {
    44.                 float2 uv_firsttex;
    45.                 float2 uv_secondtex;
    46.                 float2 uv_thirdtex;
    47.                 float2 uv_fourthtex;
    48.                 float2 uv_fifthtex;
    49.                 float2 uv_sixthtex;
    50.                 float2 uv_seventhtex;
    51.                 float2 uv_sixthnormal;
    52.                 float2 uv_seventhnormal;
    53.                 float3 worldPos;
    54.                 float relativeTerrainHeight;
    55.             };
    56.  
    57.         void vert(inout appdata_full v, out Input o) {
    58.             UNITY_INITIALIZE_OUTPUT(Input, o);
    59.             o.relativeTerrainHeight = v.texcoord1.x;
    60.         }
    61.  
    62.             sampler2D _firsttex;
    63.             sampler2D _secondtex;
    64.             sampler2D _thirdtex;
    65.             sampler2D _fourthtex;
    66.             sampler2D _fifthtex;
    67.             sampler2D _sixthtex;
    68.             sampler2D _seventhtex;
    69.             sampler2D _sixthnormal;
    70.             sampler2D _seventhnormal;
    71.             float _planetheight;
    72.  
    73.             void surf(Input IN, inout SurfaceOutput o) {
    74.                 float4 tex1 = tex2D(_firsttex, IN.uv_firsttex);
    75.                 float4 tex2 = tex2D(_secondtex, IN.uv_secondtex);
    76.                 float4 tex3 = tex2D(_thirdtex, IN.uv_thirdtex);
    77.                 float4 tex4 = tex2D(_fourthtex, IN.uv_fourthtex);
    78.                 float4 tex5 = tex2D(_fifthtex, IN.uv_fifthtex);
    79.                 float4 tex6 = tex2D(_sixthtex, IN.uv_sixthtex);
    80.                 float4 tex7 = tex2D(_seventhtex, IN.uv_seventhtex);
    81.                 float terrainheight = IN.relativeTerrainHeight;
    82.                 float terrainminheight = 0;
    83.                 float terrainmaxheight = _planetheight;
    84.                 float scaledmin = 0;
    85.                 float scaledmax = 50;
    86.                 float scaledheight = (((terrainheight - terrainminheight) * (scaledmax - scaledmin)) / (terrainmaxheight - terrainminheight)) + scaledmin;
    87.                 float blendregion = 2.5;
    88.  
    89.                 if (scaledheight > 40) {
    90.                     if (scaledheight > 40 + blendregion)
    91.                     o.Albedo = tex2D(_firsttex, IN.uv_firsttex).rgb;
    92.                     else {//blend
    93.                         float OldMin = 40;
    94.                         float OldMax = 40 + blendregion;
    95.                         float NewValue = (((scaledheight - OldMin) * (1 - 0)) / (OldMax - OldMin)) + 0;
    96.                         float a1 = 1 - NewValue;
    97.                         float a2 = NewValue;
    98.                         o.Albedo = (tex2*a1) + (tex1*a2);
    99.                     }
    100.                 }
    101.                 else if (scaledheight > 30) {
    102.                     if (scaledheight > 30 + blendregion)
    103.                     o.Albedo = tex2D(_secondtex, IN.uv_secondtex).rgb;
    104.                     else {//blend
    105.                         float OldMin = 30;
    106.                         float OldMax = 30 + blendregion;
    107.                         float NewValue = (((scaledheight - OldMin) * (1 - 0)) / (OldMax - OldMin)) + 0;
    108.                         float a1 = 1 - NewValue;
    109.                         float a2 = NewValue;
    110.                         o.Albedo = (tex3*a1) + (tex2*a2);
    111.                     }
    112.                 }
    113.                 else if (scaledheight > 20) {
    114.                     if (scaledheight > 20 + blendregion)
    115.                     o.Albedo = tex2D(_thirdtex, IN.uv_thirdtex).rgb;
    116.                     else {//blend
    117.                         float OldMin = 20;
    118.                         float OldMax = 20 + blendregion;
    119.                         float NewValue = (((scaledheight - OldMin) * (1 - 0)) / (OldMax - OldMin)) + 0;
    120.                         float a1 = 1 - NewValue;
    121.                         float a2 = NewValue;
    122.                         o.Albedo = (tex4*a1) + (tex3*a2);
    123.                     }
    124.                 }
    125.                 else if (scaledheight > 10) {
    126.                     if (scaledheight > 10 + blendregion)
    127.                     o.Albedo = tex2D(_fourthtex, IN.uv_fourthtex).rgb;
    128.                     else {//blend
    129.                         float OldMin = 10;
    130.                         float OldMax = 10 + blendregion;
    131.                         float NewValue = (((scaledheight - OldMin) * (1 - 0)) / (OldMax - OldMin)) + 0;
    132.                         float a1 = 1 - NewValue;
    133.                         float a2 = NewValue;
    134.                         o.Albedo = (tex5*a1) + (tex4*a2);
    135.                     }
    136.                 }
    137.                 else if (scaledheight > 1) {
    138.                     if (scaledheight > 1 + blendregion)
    139.                     o.Albedo = tex2D(_fifthtex, IN.uv_fifthtex).rgb;
    140.                     else {//blend
    141.                         float OldMin = 1;
    142.                         float OldMax = 1 + blendregion;
    143.                         float NewValue = (((scaledheight - OldMin) * (1 - 0)) / (OldMax - OldMin)) + 0;
    144.                         float a1 = 1 - NewValue;
    145.                         float a2 = NewValue;
    146.                         o.Albedo = (tex6*a1) + (tex5*a2);
    147.                     }
    148.                 }
    149.                 else if (scaledheight > 0.01) {
    150.                     if (scaledheight > 0.5 + blendregion)
    151.                     o.Albedo = tex2D(_sixthtex, IN.uv_sixthtex).rgb;
    152.                     else {//blend      
    153.                         float OldMin = 0.5;
    154.                         float OldMax = 0.5 + 0.5;
    155.                         float NewValue = (((scaledheight - OldMin) * (1 - 0)) / (OldMax - OldMin)) + 0.0;
    156.                         float4 col = lerp(tex7,tex6,NewValue);
    157.                         o.Albedo = col.rgb;
    158.                         half3 n1 = UnpackScaleNormal(tex2D(_sixthnormal,IN.uv_sixthnormal),3);
    159.                         half3 n2 = UnpackScaleNormal(tex2D(_seventhnormal,IN.uv_seventhnormal),3);
    160.                         half3 norm = lerp(n2,n1,NewValue);
    161.                         o.Normal = norm;
    162.                     }
    163.                 }
    164.                 else              
    165.                     o.Albedo = tex2D(_seventhtex, IN.uv_seventhtex).rgb;              
    166.             }
    167.             ENDCG
    168.         }
    169.             CustomEditor "GrassEditor"
    170. }
     
  2. PhoenixAdvanced

    PhoenixAdvanced

    Joined:
    Sep 30, 2016
    Posts:
    316
    I have made some progress with this.

    I haven't tested it with an actual terrain object yet, so the normal mapping, UV mapping, etc, could be very wrong, and it also only works for three textures.

    This is what I have so far:

    https://imgur.com/N25rVEB

    I can add and blend the textures, but the texture at the middle of the three (the sand one) shows over the texture at the top (the grass). This doesn't happen for the rock texture at the bottom.

    Before I add any more textures, I would like to try to solve this.

    I'm also not sure if using a multiple node at the end is correct. I tried a "branch" node, but it left a visible seam in the middle of the texture. Is this the correct way to "combine" two textures together?

    Thanks!