Search Unity

  1. Good news ✨ We have more Unite Now videos available for you to watch on-demand! Come check them out and ask our experts any questions!
    Dismiss Notice

Possible to pass surface shader tessellation output to vert/frag?

Discussion in 'Shaders' started by Alabatross, Jun 13, 2015.

  1. Alabatross

    Alabatross

    Joined:
    Dec 15, 2012
    Posts:
    223
    Let me start off by saying I'm a beginner at this stuff

    Right now I have a shader setup I was trying that's like below (I edited it just to make it simpler to look over the structure)

    I basically tried to do a surface pass just to get the tessellation, and then do my vert/frag for the lighting. The result is two separate objects overlapping, my original object and a solid black tessellated version of that object.

    Is there some way I'm supposed to pass my output from the surface shader TO my vert/frag or is this not even possible?

    Code (CSharp):
    1.  
    2. Shader "TestCustom"
    3. {
    4.     Properties
    5.     {    
    6.         _Tess ("Tessellation", Range(1,32)) = 4
    7.         _Displacement ("Displacement", Range(0, 1.0)) = 0.3
    8.     }
    9.  
    10.     SubShader {
    11.       // Tags { "Queue"="Transparent" "RenderType"="Transparent" }
    12.        //Blend One OneMinusSrcAlpha made ocean colored even with 0 alph
    13.        Blend SrcAlpha OneMinusSrcAlpha
    14.            Cull Off
    15.             Tags { "Queue"="Transparent-1" "IgnoreProjector"="True" "RenderType"="Transparent"}
    16.             Fog {Mode Off}
    17.         LOD 2
    18.    
    19.         GrabPass { "_RefractionNoDistort" }  
    20.    
    21.        
    22.             CGPROGRAM
    23.             #pragma surface surf BlinnPhong addshadow fullforwardshadows vertex:disp tessellate:tessFixed nolightmap
    24.             #pragma target 5.0
    25.  
    26.             struct appdata {
    27.                 float4 vertex : POSITION;
    28.                 float4 tangent : TANGENT;
    29.                 float3 normal : NORMAL;
    30.                 float2 texcoord : TEXCOORD0;
    31.             };
    32.  
    33.             float _Tess;
    34.  
    35.             float4 tessFixed()
    36.             {
    37.                 return _Tess;
    38.             }
    39.  
    40.             sampler2D _Bump;
    41.             float _Displacement;
    42.  
    43.             void disp (inout appdata v)
    44.             {
    45.                 float d = tex2Dlod(_Bump, float4(v.texcoord.xy,0,0)).r * _Displacement;
    46.                 v.vertex.xyz += v.normal * d;
    47.             }
    48.  
    49.             struct Input {
    50.                 float2 uv_MainTex;
    51.             };
    52.  
    53.             sampler2D _MainTex;
    54.             sampler2D _NormalMap;
    55.             fixed4 _Color;
    56.  
    57.             void surf (Input IN, inout SurfaceOutput o) {
    58.                 half4 c = tex2D (_MainTex, IN.uv_MainTex) * _Color;
    59.                 o.Albedo = c.rgb;
    60.                 o.Specular = 0.2;
    61.                 o.Gloss = 1.0;
    62.                 o.Normal = UnpackNormal(tex2D(_NormalMap, IN.uv_MainTex));
    63.             }
    64.             ENDCG
    65.    
    66.    
    67.    
    68.         Pass {
    69.  
    70.             CGPROGRAM
    71.             //#pragma exclude_renderers xbox360      
    72.             #pragma vertex vert
    73.             #pragma fragment frag
    74.             #pragma target 3.0
    75.      
    76.  
    77.             struct v2f
    78.             {
    79.            
    80.            
    81.                    
    82.             };
    83.  
    84.    
    85.  
    86.    
    87.             v2f vert (appdata_tan v)
    88.        
    89.             {      
    90.            
    91.            
    92.                  
    93.                 return o;
    94.             }
    95.  
    96.        
    97.  
    98.             half4 frag (v2f i) : COLOR
    99.             {          
    100.          
    101.            
    102.                 return half4;
    103.             }
    104.             ENDCG
    105.        
    106.        
    107.         }
    108.    
    109.    
    110.    
    111.    
    112.     }
    113. }
    114.  
    115.  
     
    Last edited: Jun 13, 2015
  2. Alabatross

    Alabatross

    Joined:
    Dec 15, 2012
    Posts:
    223
  3. Plutoman

    Plutoman

    Joined:
    May 24, 2013
    Posts:
    257
    Sadly, it is not possible. To utilize custom data, you will need to write a hull/domain shader and add the tessellation.

    If you are interested, Shader Forge can add tessellation and will compute the vert/frag shader. Or, if you're reasonably comfortable with modifying code yourself, here's some of my code below! I've removed my portions of it. If you already have a vertex/frag shader though then you can probably integrate it right together.

    I keep seeing questions about this posted, so for future reference to anyone who sees this, here's a tessellation shader where you can modify the vert and frag easily.

    To give proper credit though, Shader Forge did give me the quick start on understanding shaders and this is primarily built from that until I reached the limits of node-based programming (then again, I'm on the limits of GPU's and Unity's shader compiler.. tex2Darray would be glorious right now). So, I'd recommend it if you have any intention of doing work with shaders. It'll simplify a lot of processes and make prototyping easy until you want to optimize it. Hopefully this helps anyone get the basics!

    Edit: Made a few touch-ups since I'm posting it to the public.. lol. Plus a few clarifications. The code is commented. It's almost drop-in and use if you copy the vert/frag sections from a shader in.

    Code (csharp):
    1.  
    2. SubShader {
    3.         Tags {
    4.             "RenderType"="Opaque"
    5.         }
    6.  
    7.         Pass {
    8.             Name "DEFERRED"
    9.             Tags {
    10.                 "LightMode"="Deferred"
    11.             }
    12.  
    13.             CGPROGRAM
    14.             #pragma hull hull
    15.             #pragma domain domain
    16.             #pragma vertex tessvert
    17.             #pragma fragment frag
    18.             #define UNITY_PASS_DEFERRED
    19.             #include "UnityCG.cginc"
    20.             #include "Tessellation.cginc"
    21.             #include "UnityPBSLighting.cginc"
    22.             #include "UnityStandardBRDF.cginc"
    23.             #pragma fragmentoption ARB_precision_hint_fastest
    24.             #pragma multi_compile_shadowcaster
    25.             #pragma exclude_renderers xbox360 ps3
    26.             #pragma target 5.0
    27.        
    28.             // If you modify the input, either by removing or adding,
    29.             // you have to modify the domain portion of the shader below.
    30.             // You may also have to modify the TessVertex portion, too.
    31.             struct VertexInput {
    32.                 float4 vertex : POSITION;
    33.                 float3 normal : NORMAL;
    34.                 float4 tangent : TANGENT;
    35.                 float2 texcoord0 : TEXCOORD0;
    36.                 float2 texcoord1 : TEXCOORD1;
    37.                 float2 texcoord2 : TEXCOORD2;
    38.                 float2 texcoord3 : TEXCOORD3;
    39.                 float4 vertexColor : COLOR;
    40.             };
    41.        
    42.             struct VertexOutput {
    43.                 float4 pos : SV_POSITION;
    44.                 float2 uv0 : TEXCOORD0;
    45.                 float2 uv1 : TEXCOORD1;
    46.                 float2 uv2 : TEXCOORD2;
    47.                 float2 uv3 : TEXCOORD3;
    48.                 float4 posWorld : TEXCOORD4;
    49.                 float3 normalDir : TEXCOORD5;
    50.                 float4 vertexColor : COLOR;
    51.             };
    52.        
    53.             // Vertex portion goes here!
    54.             VertexOutput vert (VertexInput v) {
    55.                 VertexOutput o = (VertexOutput)0;
    56.                 o.uv0 = v.texcoord0;
    57.                 o.uv1 = v.texcoord1;
    58.                 o.uv2 = v.texcoord2;
    59.                 o.uv3 = v.texcoord3;
    60.                 o.vertexColor = v.vertexColor;
    61.                 o.normalDir = UnityObjectToWorldNormal(v.normal);
    62.                 o.posWorld = mul(_Object2World, v.vertex);
    63.                 o.pos = mul(UNITY_MATRIX_MVP, v.vertex);
    64.                 return o;
    65.             }
    66.        
    67.             #ifdef UNITY_CAN_COMPILE_TESSELLATION
    68.                 struct TessVertex {
    69.                     float4 vertex : INTERNALTESSPOS;
    70.                     float3 normal : NORMAL;
    71.                     float4 tangent : TANGENT;
    72.                     float2 texcoord0 : TEXCOORD0;
    73.                     float2 texcoord1 : TEXCOORD1;
    74.                     float2 texcoord2 : TEXCOORD2;
    75.                     float2 texcoord3 : TEXCOORD3;
    76.                     float4 vertexColor : COLOR;
    77.                 };
    78.            
    79.                 struct OutputPatchConstant {
    80.                     float edge[3]         : SV_TessFactor;
    81.                     float inside          : SV_InsideTessFactor;
    82.                     // I previously had other components here, but they aren't needed for this.
    83.                 };
    84.            
    85.                 TessVertex tessvert (VertexInput v) {
    86.                     TessVertex o;
    87.                     o.vertex = v.vertex;
    88.                     o.normal = v.normal;
    89.                     o.tangent = v.tangent;
    90.                     o.texcoord0 = v.texcoord0;
    91.                     o.texcoord1 = v.texcoord1;
    92.                     o.texcoord2 = v.texcoord2;
    93.                     o.texcoord3 = v.texcoord3;
    94.                     o.vertexColor = v.vertexColor;
    95.                     return o;
    96.                 }
    97.            
    98.                 void displacement (inout VertexInput v)
    99.                 {
    100.                     // compute displacement here!
    101.                     // Sampling a texture requires sampling with tex2Dlod(...)
    102.                     // http://http.developer.nvidia.com/Cg/tex2Dlod.html
    103.                     // Example: float h = tex2Dlod(_HeightTex, float4(TRANSFORM_TEX(v.texcoord, _HeightTex), 0, 0));
    104.                
    105.                     // My final setup (after getting the height value)
    106.                     // v.vertex.xyz += (v.normal*(((1.0 - h)*2.0+-1.0)*((-1.0)*_Depth)));
    107.                 }
    108.            
    109.                 float4 Tessellation(TessVertex v, TessVertex v1, TessVertex v2){
    110.                     // You can also do UnityEdgeLengthBasedTessCull(...)
    111.                     // Or you can return a flat constant for uniform tessellation
    112.                     return UnityEdgeLengthBasedTess(v.vertex, v1.vertex, v2.vertex, _Tessellation);
    113.                 }
    114.            
    115.                 OutputPatchConstant hullconst (InputPatch<TessVertex,3> v) {
    116.                     OutputPatchConstant o;
    117.                     float4 ts = Tessellation( v[0], v[1], v[2] );
    118.                     o.edge[0] = ts.x;
    119.                     o.edge[1] = ts.y;
    120.                     o.edge[2] = ts.z;
    121.                     o.inside = ts.w;
    122.                     return o;
    123.                 }
    124.            
    125.                 [domain("tri")]
    126.                 [partitioning("fractional_odd")]
    127.                 [outputtopology("triangle_cw")]
    128.                 [patchconstantfunc("hullconst")]
    129.                 [outputcontrolpoints(3)]
    130.                 TessVertex hull (InputPatch<TessVertex,3> v, uint id : SV_OutputControlPointID) {
    131.                     return v[id];
    132.                 }
    133.            
    134.                 [domain("tri")]
    135.                 VertexOutput domain (OutputPatchConstant tessFactors, const OutputPatch<TessVertex,3> vi, float3 bary : SV_DomainLocation) {
    136.                     VertexInput v = (VertexInput)0;
    137.                     v.vertex = vi[0].vertex*bary.x + vi[1].vertex*bary.y + vi[2].vertex*bary.z;
    138.                     v.normal = vi[0].normal*bary.x + vi[1].normal*bary.y + vi[2].normal*bary.z;
    139.                     v.tangent = vi[0].tangent*bary.x + vi[1].tangent*bary.y + vi[2].tangent*bary.z;
    140.                     v.texcoord0 = vi[0].texcoord0*bary.x + vi[1].texcoord0*bary.y + vi[2].texcoord0*bary.z;
    141.                     v.texcoord1 = vi[0].texcoord1*bary.x + vi[1].texcoord1*bary.y + vi[2].texcoord1*bary.z;
    142.                     v.texcoord2 = vi[0].texcoord2*bary.x + vi[1].texcoord2*bary.y + vi[2].texcoord2*bary.z;
    143.                     v.texcoord3 = vi[0].texcoord3*bary.x + vi[1].texcoord3*bary.y + vi[2].texcoord3*bary.z;
    144.                     v.vertexColor = vi[0].vertexColor*bary.x + vi[1].vertexColor*bary.y + vi[2].vertexColor*bary.z;
    145.                     displacement(v);
    146.                     VertexOutput o = vert(v);
    147.                     return o;
    148.                 }
    149.            
    150.             #endif
    151.  
    152.             // This also works!
    153.             // fixed4 frag( VertexOutput i ) : COLOR
    154.             // {
    155.             //     //frag shader goes here!
    156.             // }
    157.  
    158.             void frag(
    159.                 VertexOutput i,
    160.                 out half4 outDiffuse : SV_Target0,
    161.                 out half4 outSpecSmoothness : SV_Target1,
    162.                 out half4 outNormal : SV_Target2,
    163.                 out half4 outEmission : SV_Target3 )
    164.             {
    165.                 //frag shader goes here!
    166.             }
    167.             ENDCG
    168.         }
    169.  
     
    Last edited: Jun 16, 2015
    Iron-Warrior and Aaron-Meyers like this.
  4. Phantomx

    Phantomx

    Joined:
    Oct 30, 2012
    Posts:
    202
    Hey thanks for sharing this it helps a lot!
    I just have one issue and I wonder if you would be able to help....
    I want to use this with GrabPass and distort what is behind the surface. It works fine with forward and deferred, but as soon as I turn on HDR I get some funky stuff as you can see in this screenshot:



    Looks like the shadow gets distorted but you can still see the original shape of the object. happens only in Deferred + HDR with tesellation, regular frag shader doesn't do that.

    here's the shader code:

    Code (CSharp):
    1.  
    2. Shader "DX11 - Deferred"{
    3.     Properties {
    4.         _Tess ("Tessellation", Range(1,32)) = 4
    5.         _MainTex ("Base (RGB)", 2D) = "white" {}
    6.         _DispTex ("Disp Texture", 2D) = "gray" {}
    7.         _BumpMap ("Normalmap", 2D) = "bump" {}
    8.         _Displacement ("Displacement", Range(0, 1.0)) = 0.3
    9.         _Color ("Color", color) = (1,1,1,0)
    10.         _SpecColor ("Spec color", color) = (0.5,0.5,0.5,0.5)
    11.         _Distortion ("Distortion", Range(0, 128)) = 32
    12.     }
    13.  
    14.     SubShader {
    15.  
    16.         Tags { "Queue"="Transparent" "RenderType"="Opaque" }
    17.  
    18.          GrabPass
    19.         {
    20.             Name "BASE"
    21.             Tags {
    22.                 "LightMode" = "Always"
    23.             }
    24.         }
    25.  
    26.         Pass {
    27.                Tags {"LightMode" = "ForwardBase"}
    28.             Name "FORWARD"
    29.             ZWrite Off
    30.             Blend SrcAlpha OneMinusSrcAlpha
    31.             CGPROGRAM
    32.             #pragma hull hull
    33.             #pragma domain domain
    34.             #pragma vertex tessvert
    35.             #pragma fragment frag
    36.             #define UNITY_PASS_DEFERRED
    37.             #include "UnityCG.cginc"
    38.             #include "Tessellation.cginc"
    39.             #include "UnityPBSLighting.cginc"
    40.             #include "UnityStandardBRDF.cginc"
    41.             #pragma fragmentoption ARB_precision_hint_fastest
    42.             #pragma exclude_renderers xbox360 ps3
    43.             #pragma target 5.0
    44.  
    45.             sampler2D _GrabTexture;
    46.             half4 _GrabTexture_TexelSize;
    47.             sampler2D _MainTex;
    48.             sampler2D _BumpMap;
    49.             float _Tess;
    50.             float _Distortion;
    51.             fixed4 _Color;
    52.  
    53.             struct VertexInput {
    54.                 float4 vertex : POSITION;
    55.                 float2 texcoord0 : TEXCOORD0;
    56.             };
    57.      
    58.             struct VertexOutput {
    59.                 float4 pos : SV_POSITION;
    60.                 float2 uv0 : TEXCOORD0;
    61.                 float4 GrabUV : TEXCOORD3;
    62.             };
    63.      
    64.             // Vertex portion goes here!
    65.             VertexOutput vert (VertexInput v) {
    66.                 VertexOutput o = (VertexOutput)0;
    67.                 o.uv0 = v.texcoord0;
    68.                 o.pos = mul(UNITY_MATRIX_MVP, v.vertex);
    69.                 o.GrabUV = ComputeGrabScreenPos(o.pos);
    70.  
    71.                 return o;
    72.             }
    73.      
    74.             #ifdef UNITY_CAN_COMPILE_TESSELLATION
    75.                 struct TessVertex {
    76.                     float4 vertex : INTERNALTESSPOS;
    77.                     float2 texcoord0 : TEXCOORD0;
    78.                 };
    79.          
    80.                 struct OutputPatchConstant {
    81.                     float edge[3]         : SV_TessFactor;
    82.                     float inside          : SV_InsideTessFactor;
    83.                 };
    84.          
    85.                 TessVertex tessvert (VertexInput v) {
    86.                     TessVertex o;
    87.                     o.vertex = v.vertex;
    88.                     return o;
    89.                 }
    90.          
    91.                 void displacement (inout VertexInput v)
    92.                 {
    93.                    
    94.                 }
    95.          
    96.                 float4 Tessellation(TessVertex v, TessVertex v1, TessVertex v2){
    97.                    
    98.                     return UnityEdgeLengthBasedTess(v.vertex, v1.vertex, v2.vertex, _Tess);
    99.                 }
    100.          
    101.                 OutputPatchConstant hullconst (InputPatch<TessVertex,3> v) {
    102.                     OutputPatchConstant o;
    103.                     float4 ts = Tessellation( v[0], v[1], v[2] );
    104.                     o.edge[0] = ts.x;
    105.                     o.edge[1] = ts.y;
    106.                     o.edge[2] = ts.z;
    107.                     o.inside = ts.w;
    108.                     return o;
    109.                 }
    110.          
    111.                 [domain("tri")]
    112.                 [partitioning("fractional_odd")]
    113.                 [outputtopology("triangle_cw")]
    114.                 [patchconstantfunc("hullconst")]
    115.                 [outputcontrolpoints(3)]
    116.                 TessVertex hull (InputPatch<TessVertex,3> v, uint id : SV_OutputControlPointID) {
    117.                     return v[id];
    118.                 }
    119.          
    120.                 [domain("tri")]
    121.                 VertexOutput domain (OutputPatchConstant tessFactors, const OutputPatch<TessVertex,3> vi, float3 bary : SV_DomainLocation) {
    122.                     VertexInput v = (VertexInput)0;
    123.                     v.vertex = vi[0].vertex*bary.x + vi[1].vertex*bary.y + vi[2].vertex*bary.z;
    124.                     v.texcoord0 = vi[0].texcoord0*bary.x + vi[1].texcoord0*bary.y + vi[2].texcoord0*bary.z;
    125.                  
    126.                     displacement(v);
    127.                     VertexOutput o = vert(v);
    128.                     return o;
    129.                 }
    130.          
    131.             #endif
    132.  
    133. // Just want forwardMode but still be usable with deferred
    134.              fixed4 frag( VertexOutput i ) : SV_Target
    135.              {
    136.  
    137.                 half2 bump = UnpackNormal(tex2D(_BumpMap, i.uv0)).rg;
    138.                 float2 offset1 = bump * _Distortion * _GrabTexture_TexelSize.xy;
    139.                 i.GrabUV.xy = offset1 * i.GrabUV.z + i.GrabUV.xy;
    140.  
    141.                 half4 col = tex2Dproj( _GrabTexture, UNITY_PROJ_COORD(i.GrabUV));
    142.  
    143.                  return col * _Color;
    144.        
    145.              }
    146.             ENDCG
    147.         }
    148.     }
    149. }
    150.  
    Thanks!
     
unityunity