Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Voting for the Unity Awards are OPEN! We’re looking to celebrate creators across games, industry, film, and many more categories. Cast your vote now for all categories
    Dismiss Notice
  3. Dismiss Notice

Ok once again, is it possible to combine a surface shader with vertex and frag shader?

Discussion in 'Shaders' started by markashburner, Apr 11, 2018.

  1. markashburner

    markashburner

    Joined:
    Aug 14, 2015
    Posts:
    212
    Ok I have seen this topic come up before but it still has me stumped.

    I have tried combining this vertex and frag shader with a surface shader using one pass for the vertex and frag shader and then the surface shader below.

    Here is the vertex and frag shader on it's own:

    Code (CSharp):
    1. Shader "ShaderMan/PlanetSurface"
    2. {
    3.     Properties
    4.     {
    5.         _MainTex ("MainTex", 2D) = "white" {}
    6.         _FractalDivergance("Fractal Divergance", Range(0, 4)) = 1.0
    7.     }
    8.     SubShader
    9.     {
    10.     Tags { "RenderType" = "Transparent" "Queue" = "Transparent" }
    11.     Pass
    12.     {
    13.     ZWrite Off
    14.     Blend SrcAlpha OneMinusSrcAlpha
    15.     CGPROGRAM
    16.     #pragma  vertex vert
    17.     #pragma fragment frag
    18.     #include "UnityCG.cginc"
    19.     struct VertexInput {
    20.     fixed4 vertex : POSITION;
    21.     fixed2 uv:TEXCOORD0;
    22.     fixed4 tangent : TANGENT;
    23.     fixed3 normal : NORMAL;
    24.     //VertexInput
    25.     };
    26.     struct VertexOutput {
    27.     fixed4 pos : SV_POSITION;
    28.     fixed2 uv:TEXCOORD0;
    29.     //VertexOutput
    30.     };
    31.     //Variables
    32.     sampler2D _MainTex;
    33.     float _FractalDivergance;
    34.     // One way to avoid tex2D tile repetition one using one small tex2D to cover a huge area.
    35.     // Based on Voronoise (https://www.shadertoy.com/view/Xd23Dh), a random offset is applied to
    36.     // the tex2D UVs per Voronoi cell. Distance to the cell is used to smooth the transitions
    37.     // between cells.
    38.     // More info here: http://www.iquilezles.org/www/articles/tex2Drepetition/tex2Drepetition.htm
    39.     fixed4 hash4( fixed2 p ) { return frac(sin(fixed4( 1.0+dot(p,fixed2(37.0,17.0)),
    40.                                                   2.0+dot(p,fixed2(11.0,47.0)),
    41.                                                   3.0+dot(p,fixed2(41.0,29.0)),
    42.                                                   4.0+dot(p,fixed2(23.0,31.0)))) * _FractalDivergance); }
    43.     fixed3 tex2DNoTile( sampler2D samp, in fixed2 uv, fixed v )
    44.     {
    45.         fixed2 p = floor( uv );
    46.         fixed2 f = frac( uv );
    47.         // derivatives (for correct mipmapping)
    48.         fixed2 _ddx = ddx( uv );
    49.         fixed2 _ddy = ddy( uv );
    50.         fixed3 va = fixed3(0.0,0.0,0.0);
    51.         fixed w1 = 0.0;
    52.         fixed w2 = 0.0;
    53.         [unroll(3)]
    54.         for (int j = -1; j <= 1; j++)
    55.         {
    56.             [unroll(3)]
    57.             for (int i = -1; i <= 1; i++)
    58.             {
    59.                 fixed2 g = fixed2(fixed(i), fixed(j));
    60.                 fixed4 o = hash4(p + g);
    61.                 fixed2 r = g - f + o.xy;
    62.                 fixed d = dot(r, r);
    63.                 fixed w = exp(-5.0*d);
    64.                 fixed3 c = tex2D(samp, uv + v * o.zw, _ddx, _ddy).xyz;
    65.                 va += w * c;
    66.                 w1 += w;
    67.                 w2 += w * w;
    68.             }
    69.         }
    70.         // normal averaging --> lowers contrasts
    71.         //return va/w1;
    72.         // contrast preserving average
    73.         fixed mean = 0;// tex2DGrad( samp, uv, ddx*16.0, ddy*16.0 ).x;
    74.         fixed3 res = mean + (va-w1*mean)/sqrt(w2);
    75.         return lerp( va/w1, res, v );
    76.     }
    77.     VertexOutput vert (VertexInput v)
    78.     {
    79.         VertexOutput o;
    80.         o.pos = UnityObjectToClipPos (v.vertex);
    81.         o.uv = v.uv;
    82.         return o;
    83.     }
    84.     fixed4 frag(VertexOutput i) : SV_Target
    85.     {
    86.         fixed2 uv = i.uv /1;
    87.         fixed f = 1;
    88.         fixed s = 1;
    89.         fixed3 col = tex2DNoTile( _MainTex, 10 * uv, 1).xyz;
    90.         return fixed4( col, 1.0 );
    91.     }
    92.     ENDCG
    93.     }
    94.   }
    95. }
    96.  
    And here is my attempt at combining the vertex and frag shader with a Lambert surface shader:

    Code (CSharp):
    1. Shader "ShaderMan/PlanetSurface"
    2. {
    3.     Properties
    4.     {
    5.         _MainTex ("MainTex", 2D) = "white" {}
    6.         _Nor1 ("Normal 0", 2D) = "bump" {}
    7.         _FractalDivergance("Fractal Divergance", Range(0, 4)) = 1.0
    8.      
    9.         _myColor ("Example Color", Color) = (1,1,1,1)
    10.     }
    11.     SubShader
    12.     {
    13.     Tags { "RenderType" = "Opaque" }
    14.     LOD 200
    15.  
    16.  
    17.     Pass
    18.     {
    19.     ZWrite Off
    20.     Blend SrcAlpha OneMinusSrcAlpha
    21.     CGPROGRAM
    22.     #pragma  vertex vert
    23.     #pragma fragment frag
    24.     #include "UnityCG.cginc"
    25.     struct VertexInput {
    26.     fixed4 vertex : POSITION;
    27.     fixed2 uv:TEXCOORD0;
    28.     fixed4 tangent : TANGENT;
    29.     fixed3 normal : NORMAL;
    30.     //VertexInput
    31.     };
    32.     struct VertexOutput {
    33.     fixed4 pos : SV_POSITION;
    34.     fixed2 uv:TEXCOORD0;
    35.     //VertexOutput
    36.     };
    37.     //Variables
    38.     sampler2D _MainTex;
    39.     float _FractalDivergance;
    40.     float _Scale;
    41.     // One way to avoid tex2D tile repetition one using one small tex2D to cover a huge area.
    42.     // Based on Voronoise (https://www.shadertoy.com/view/Xd23Dh), a random offset is applied to
    43.     // the tex2D UVs per Voronoi cell. Distance to the cell is used to smooth the transitions
    44.     // between cells.
    45.     // More info here: http://www.iquilezles.org/www/articles/tex2Drepetition/tex2Drepetition.htm
    46.     fixed4 hash4( fixed2 p ) { return frac(sin(fixed4( 1.0+dot(p,fixed2(37.0,17.0)),
    47.                                                   2.0+dot(p,fixed2(11.0,47.0)),
    48.                                                   3.0+dot(p,fixed2(41.0,29.0)),
    49.                                                   4.0+dot(p,fixed2(23.0,31.0)))) * _FractalDivergance); }
    50.     fixed3 tex2DNoTile( sampler2D samp, in fixed2 uv, fixed v )
    51.     {
    52.         fixed2 p = floor( uv );
    53.         fixed2 f = frac( uv );
    54.         // derivatives (for correct mipmapping)
    55.         fixed2 _ddx = ddx( uv );
    56.         fixed2 _ddy = ddy( uv );
    57.         fixed3 va = fixed3(0.0,0.0,0.0);
    58.         fixed w1 = 0.0;
    59.         fixed w2 = 0.001;
    60.  
    61.  
    62.         [unroll(3)]
    63.         for (int j = -1; j <= 1; j++)
    64.         {
    65.             [unroll(3)]
    66.             for (int i = -1; i <= 1; i++)
    67.             {
    68.                 fixed2 g = fixed2(fixed(i), fixed(j));
    69.                 fixed4 o = hash4(p + g);
    70.                 fixed2 r = g - f + o.xy;
    71.                 fixed d = dot(r, r);
    72.                 fixed w = exp(-5.0*d);
    73.                 fixed3 c = tex2D(samp, uv + v * o.zw, _ddx, _ddy).xyz;
    74.                 va += w * c;
    75.                 w1 += w;
    76.                 w2 += w * w;
    77.             }
    78.         }
    79.         // normal averaging --> lowers contrasts
    80.         //return va/w1;
    81.         // contrast preserving average
    82.         fixed mean = 0;// tex2DGrad( samp, uv, ddx*16.0, ddy*16.0 ).x;
    83.         fixed3 res = mean + (va-w1*mean)/sqrt(w2);
    84.         return lerp( va/w1, res, v );
    85.     }
    86.     VertexOutput vert (VertexInput v)
    87.     {
    88.         VertexOutput o;
    89.         o.pos = UnityObjectToClipPos (v.vertex);
    90.         o.uv = v.uv;
    91.         return o;
    92.     }
    93.     fixed4 frag(VertexOutput i) : SV_Target
    94.     {
    95.         fixed2 uv = i.uv /1;
    96.         fixed f = 1;
    97.         fixed s = 1;
    98.         fixed3 col = tex2DNoTile( _MainTex, 10 * uv, 1).rgb;
    99.         return fixed4( col, 1.0 );
    100.     }
    101.     ENDCG
    102.  
    103.  
    104.     }
    105.     CGPROGRAM
    106.             #pragma surface surf Lambert
    107.  
    108.             struct Input {
    109.                 float2 uvMainTex;
    110.                 float3 worldRefl;
    111.             };
    112.  
    113.             sampler2D _MainTex;
    114.  
    115.             fixed4 _myColor;
    116.             fixed4 _myEmisiion;
    117.             fixed4 _myNormal;
    118.      
    119.          
    120.             void surf (Input IN, inout SurfaceOutput o){
    121.                 o.Albedo = (tex2D(_MainTex, IN.uvMainTex)* _myColor).rgb;
    122.          
    123.             }
    124.      
    125.         ENDCG
    126.   }
    127.   Fallback "Diffuse"
    128. }
    What happens here is that the surface shader completely overwrites the vertex and frag shader and the texture is no longer produced as well. If I instead place the surface shader on top of the pile then the vertex and frag shader in the pass below completely overwrites the surface shader.

    Now my question is simple, is it possible to combine these two types of shaders with passes? Or do they both just completely overwrite each other?

    I would really appreciate a response.

    Thanks
     
    Last edited: Apr 11, 2018
  2. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,229
    Yes, but...

    Because that what the shader is being told to do. Both the vertex fragment shader and the surface shader are opaque, so they'll just draw over the other. The fragment shader may have a blend mode set, but you're using alpha blending and outputting an alpha of 1, which means it'll act like it's opaque.

    Even if you change the blend mode, there's really no reason to have this be two passes. Instead you should be copying the tex2DNoTile function into the CGPROGRAM block of the surface shader and use that instead of tex2D in the surf function.
     
  3. markashburner

    markashburner

    Joined:
    Aug 14, 2015
    Posts:
    212
    yes but the #pragma of the surface shader does not accept vertex, frag and surface together?
     
  4. MadeFromPolygons

    MadeFromPolygons

    Joined:
    Oct 5, 2013
    Posts:
    3,874
    So write the surface shader in a seperate pass?
     
  5. Remy_Unity

    Remy_Unity

    Unity Technologies

    Joined:
    Oct 3, 2017
    Posts:
    629
    You don't need the vertex fragment. If I understood correctly, you want to use "tex2DNoTile" to have a non tiling texture on a planet, right ?
    Like bdolus said, what you need to do is to move the needed functions for tex2DNoTile from your vertex fragment code to and include, or directly in the surface shader, and in there, use tex2DNoTile instead of tex2D to sample the main texture.
     
    MadeFromPolygons likes this.
  6. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,229
    This is what
    Exactly. The the vert and frag functions themselves aren’t the important part here. They do exist to make the mesh render, but otherwise don’t do anything special. Literally you just want to delete that pass entirely. The surface shader doesn’t have them since it generates those functions automatically behind the scenes.
     
    Last edited: Apr 12, 2018
  7. markashburner

    markashburner

    Joined:
    Aug 14, 2015
    Posts:
    212
    Yeah I have tried doing that and I just run into a ton of errors.

    The surface shader seems to have a huge issue with this part of the code:

    Code (CSharp):
    1.  [unroll(3)]
    2.         for (int j = -1; j <= 1; j++)
    3.         {
    4.             [unroll(3)]
    5.             for (int i = -1; i <= 1; i++)
    6.             {
    7.                 fixed2 g = fixed2(fixed(i), fixed(j));
    8.                 fixed4 o = hash4(p + g);
    9.                 fixed2 r = g - f + o.xy;
    10.                 fixed d = dot(r, r);
    11.                 fixed w = exp(-5.0*d);
    12.                 fixed3 c = tex2D(samp, uv + v * o.zw, _ddx, _ddy).xyz;
    13.                 va += w * c;
    14.                 w1 += w;
    15.                 w2 += w * w;
    16.             }
    17.         }
    Here is my attempt so far at trying to write this into a surface shader but I get stuck at the part below:

    Code (CSharp):
    1. Shader "Custom/TerrainSurface" {
    2.     Properties {
    3.         _Color ("Color", Color) = (1,1,1,1)
    4.         _MainTex ("Albedo (RGB)", 2D) = "white" {}
    5.         _FractalDivergance("Fractal Divergance", Range(0, 4)) = 1.0
    6.         _Glossiness ("Smoothness", Range(0,1)) = 0.5
    7.         _Metallic ("Metallic", Range(0,1)) = 0.0
    8.     }
    9.     SubShader {
    10.         Tags { "RenderType"="Opaque" }
    11.         LOD 200
    12.  
    13.         CGPROGRAM
    14.         // Physically based Standard lighting model, and enable shadows on all light types
    15.         #pragma surface surf Standard fullforwardshadows
    16.  
    17.         // Use shader model 3.0 target, to get nicer looking lighting
    18.         #pragma target 3.0
    19.  
    20.         sampler2D _MainTex;
    21.  
    22.         struct Input {
    23.             float2 uv_MainTex;
    24.         };
    25.  
    26.         half _Glossiness;
    27.         half _Metallic;
    28.         fixed4 _Color;
    29.         float _FractalDivergance;
    30.  
    31. fixed4 hash4( fixed2 p ) { return frac(sin(fixed4( 1.0+dot(p,fixed2(37.0,17.0)),
    32.                                                   2.0+dot(p,fixed2(11.0,47.0)),
    33.                                                   3.0+dot(p,fixed2(41.0,29.0)),
    34.                                                   4.0+dot(p,fixed2(23.0,31.0)))) * _FractalDivergance); }
    35.  
    36.  
    37. fixed3 tex2DNoTile( sampler2D samp, in fixed2 uv, fixed v )
    38.     {
    39.     fixed2 p = floor( uv );
    40.         fixed2 f = frac( uv );
    41.         // derivatives (for correct mipmapping)
    42.         fixed2 _ddx = ddx( uv );
    43.         fixed2 _ddy = ddy( uv );
    44.         fixed3 va = fixed3(0.0,0.0,0.0);
    45.         fixed w1 = 0.0;
    46.         fixed w2 = 0.0;
    47.      
    48.         //This is where I run into lots of errors:
    49.         /*
    50.          [unroll(3)]
    51.         for (int j = -1; j <= 1; j++)
    52.         {
    53.             [unroll(3)]
    54.             for (int i = -1; i <= 1; i++)
    55.             {
    56.                 fixed2 g = fixed2(fixed(i), fixed(j));
    57.                 fixed4 o = hash4(p + g);
    58.                 fixed2 r = g - f + o.xy;
    59.                 fixed d = dot(r, r);
    60.                 fixed w = exp(-5.0*d);
    61.                 fixed3 c = tex2D(samp, uv + v * o.zw, _ddx, _ddy).xyz;
    62.                 va += w * c;
    63.                 w1 += w;
    64.                 w2 += w * w;
    65.             }
    66.         }*/
    67.  
    68.         fixed mean = 0;
    69.         fixed3 res = mean + (va-w1*mean)/sqrt(w2);
    70.         return lerp( va/w1, res, v );
    71.     }
    72.  
    73.  
    74.         // Add instancing support for this shader. You need to check 'Enable Instancing' on materials that use the shader.
    75.         // See https://docs.unity3d.com/Manual/GPUInstancing.html for more information about instancing.
    76.         // #pragma instancing_options assumeuniformscaling
    77.         UNITY_INSTANCING_BUFFER_START(Props)
    78.             // put more per-instance properties here
    79.         UNITY_INSTANCING_BUFFER_END(Props)
    80.  
    81.         void surf (Input IN, inout SurfaceOutputStandard o) {
    82.             // Albedo comes from a texture tinted by color
    83.             fixed4 c = tex2D (_MainTex, IN.uv_MainTex) * _Color;
    84.             o.Albedo = c.rgb;
    85.             // Metallic and smoothness come from slider variables
    86.             o.Metallic = _Metallic;
    87.             o.Smoothness = _Glossiness;
    88.             o.Alpha = c.a;
    89.         }
    90.         ENDCG
    91.     }
    92.     FallBack "Diffuse"
    93. }
    94.  
     
    Last edited: Apr 13, 2018