Search Unity

Tessellation, Geometry Shader Error

Discussion in 'Shaders' started by macdude2, Jan 20, 2017.

  1. macdude2

    macdude2

    Joined:
    Sep 22, 2010
    Posts:
    686
    Just wondering if anyone knows if its possible to create a vertex shader that has both tessellation and geometry components within it? Looking at the shader pipeline (vertex -> tessellation (hull -> domain) -> geometry -> fragment), it seems like this should be possible. I found a vertex based geometry shader and a tessellation one and have tried to combine them, but I get a really weird error:

    GLSL Compilation failed: ERROR: 0.6: Identifier name gl_Position cannot start with gl_

    Anyone know where this may be coming from? There are no errors in the disassembly other than that no shader variant can be compiled. Thanks for any help!

    This is the code I've been working on:
    Code (CSharp):
    1.  
    2.  
    3. Shader "Custom/Water" {
    4.  
    5.     Properties
    6.     {
    7.         _Color("Color", Color) = (1,0,0,1)
    8.         _TessEdge ("Edge Tess", Range(1,64)) = 2
    9.         _SpecColor("Specular Material Color", Color) = (1,1,1,1)
    10.         _Shininess("Shininess", Float) = 1.0
    11.         _WaveLength("Wave length", Float) = 0.5
    12.         _WaveHeight("Wave height", Float) = 0.5
    13.         _WaveSpeed("Wave speed", Float) = 1.0
    14.         _RandomHeight("Random height", Float) = 0.5
    15.         _RandomSpeed("Random Speed", Float) = 0.5
    16.     }
    17.     SubShader
    18.     {
    19.    
    20.         Tags { "Queue"="Transparent" "IgnoreProjector"="True" "RenderType"="Transparent" }
    21.         Blend SrcAlpha OneMinusSrcAlpha
    22.  
    23.         Pass
    24.         {
    25.  
    26.             CGPROGRAM
    27.             #include "UnityCG.cginc"
    28.             #pragma vertex vert
    29.             #pragma geometry geom
    30.             #pragma fragment frag
    31.             #pragma hull tess
    32.             #pragma domain dom
    33.  
    34.             float rand(float3 co)
    35.             {
    36.                 return frac(sin(dot(co.xyz ,float3(12.9898,78.233,45.5432))) * 43758.5453);
    37.             }
    38.  
    39.             float rand2(float3 co)
    40.             {
    41.                 return frac(sin(dot(co.xyz ,float3(19.9128,75.2,34.5122))) * 12765.5213);
    42.             }
    43.  
    44.             float _WaveLength;
    45.             float _WaveHeight;
    46.             float _WaveSpeed;
    47.             float _RandomHeight;
    48.             float _RandomSpeed;
    49.             float _TessEdge;
    50.            
    51.             uniform float4 _LightColor0;
    52.  
    53.             uniform float4 _Color;
    54.             uniform float4 _SpecColor;
    55.             uniform float _Shininess;
    56.  
    57.             struct v2h
    58.             {
    59.                 float4  pos : SV_POSITION;
    60.                 float3    norm : NORMAL;
    61.                  float2  uv : TEXCOORD0;
    62.             };
    63.            
    64.             struct g2f
    65.             {
    66.                 float4  pos : SV_POSITION;
    67.                 float3  norm : NORMAL;
    68.                 float2  uv : TEXCOORD0;          
    69.                 float3 diffuseColor : TEXCOORD1;
    70.                 float3 specularColor : TEXCOORD2;
    71.             };
    72.  
    73.             struct hsc
    74.             {
    75.                    float TessFactor[3]    : SV_TessFactor;
    76.                 float InsideTessFactor : SV_InsideTessFactor;
    77.             };
    78.  
    79.             struct h2d
    80.             {
    81.                 float3 pos    : POS;
    82.             };
    83.  
    84.             struct d2g
    85.             {
    86.                 float4 pos   : SV_POSITION;
    87.                  float2  uv : TEXCOORD0;
    88.  
    89.             };
    90.  
    91.             v2h vert(appdata_full v)
    92.             {
    93.                 float3 v0 = mul(unity_ObjectToWorld, v.vertex).xyz;
    94.  
    95.                 float phase0 = (_WaveHeight)* sin((_Time[1] * _WaveSpeed) + (v0.x * _WaveLength) + (v0.z * _WaveLength) + rand2(v0.xzz));
    96.                 float phase0_1 = (_RandomHeight)*sin(cos(rand(v0.xzz) * _RandomHeight * cos(_Time[1] * _RandomSpeed * sin(rand(v0.xxz)))));
    97.                
    98.                 v0.y += phase0 + phase0_1;
    99.  
    100.                 v.vertex.xyz = mul((float3x3)unity_WorldToObject, v0);
    101.  
    102.                 v2h OUT;
    103.                 OUT.pos = v.vertex;
    104.                 OUT.norm = v.normal;
    105.                 OUT.uv = v.texcoord;
    106.                 return OUT;
    107.             }
    108.  
    109.             hsc hullconst( InputPatch<v2h, 3> Input )
    110.             {
    111.                 hsc Output = (hsc)0;
    112.                 Output.TessFactor[0] = Output.TessFactor[1] = Output.TessFactor[2] = _TessEdge;
    113.                 Output.InsideTessFactor = _TessEdge;  
    114.                 return Output;
    115.             }
    116.  
    117.             [domain("tri")]
    118.             [partitioning("integer")]
    119.             [outputtopology("triangle_cw")]
    120.             [patchconstantfunc("hullconst")]
    121.             [outputcontrolpoints(3)]
    122.             h2d tess( InputPatch<v2h, 3> Input, uint uCPID : SV_OutputControlPointID )
    123.             {
    124.                 h2d Output = (h2d)0;
    125.                 Output.pos = Input[uCPID].pos.xyz;
    126.                 return Output;
    127.             }
    128.    
    129.             [domain("tri")]
    130.             d2g dom( hsc HSConstantData,
    131.                         const OutputPatch<h2d, 3> Input,
    132.                         float3 BarycentricCoords : SV_DomainLocation)
    133.             {
    134.                 d2g Output = (d2g)0;
    135.    
    136.                 float fU = BarycentricCoords.x;
    137.                 float fV = BarycentricCoords.y;
    138.                 float fW = BarycentricCoords.z;
    139.      
    140.                 float3 pos = Input[0].pos * fU + Input[1].pos * fV + Input[2].pos * fW;
    141.      
    142.                 Output.pos = mul (UNITY_MATRIX_MVP, float4(pos.xyz,1.0));
    143.          
    144.                 return Output;
    145.             }
    146.    
    147.             [maxvertexcount(3)]
    148.             void geom(triangle d2g IN[3], inout TriangleStream<g2f> triStream)
    149.             {
    150.                 float3 v0 = IN[0].pos.xyz;
    151.                 float3 v1 = IN[1].pos.xyz;
    152.                 float3 v2 = IN[2].pos.xyz;
    153.  
    154.                 float3 centerPos = (v0 + v1 + v2) / 3.0;
    155.  
    156.                 float3 vn = normalize(cross(v1 - v0, v2 - v0));
    157.                
    158.                 float4x4 modelMatrix = unity_ObjectToWorld;
    159.                 float4x4 modelMatrixInverse = unity_WorldToObject;
    160.  
    161.                 float3 normalDirection = normalize(
    162.                     mul(float4(vn, 0.0), modelMatrixInverse).xyz);
    163.                 float3 viewDirection = normalize(_WorldSpaceCameraPos
    164.                     - mul(modelMatrix, float4(centerPos, 0.0)).xyz);
    165.                 float3 lightDirection = normalize(_WorldSpaceLightPos0.xyz);
    166.                 float attenuation = 1.0;
    167.  
    168.                 float3 ambientLighting =
    169.                     UNITY_LIGHTMODEL_AMBIENT.rgb * _Color.rgb;
    170.  
    171.                 float3 diffuseReflection =
    172.                     attenuation * _LightColor0.rgb * _Color.rgb
    173.                     * max(0.0, dot(normalDirection, lightDirection));
    174.  
    175.                 float3 specularReflection;
    176.                 if (dot(normalDirection, lightDirection) < 0.0)
    177.                 {
    178.                     specularReflection = float3(0.0, 0.0, 0.0);
    179.                 }
    180.                 else
    181.                 {
    182.                     specularReflection = attenuation * _LightColor0.rgb
    183.                         * _SpecColor.rgb * pow(max(0.0, dot(
    184.                             reflect(-lightDirection, normalDirection),
    185.                             viewDirection)), _Shininess);
    186.                 }
    187.  
    188.                 g2f OUT;
    189.                 OUT.pos = mul(UNITY_MATRIX_MVP, IN[0].pos);
    190.                 OUT.norm = vn;
    191.                 OUT.uv = IN[0].uv;
    192.                 OUT.diffuseColor = ambientLighting + diffuseReflection;
    193.                 OUT.specularColor = specularReflection;
    194.                 triStream.Append(OUT);
    195.  
    196.                 OUT.pos = mul(UNITY_MATRIX_MVP, IN[1].pos);
    197.                 OUT.norm = vn;
    198.                 OUT.uv = IN[1].uv;
    199.                 OUT.diffuseColor = ambientLighting + diffuseReflection;
    200.                 OUT.specularColor = specularReflection;
    201.                 triStream.Append(OUT);
    202.  
    203.                 OUT.pos = mul(UNITY_MATRIX_MVP, IN[2].pos);
    204.                 OUT.norm = vn;
    205.                 OUT.uv = IN[2].uv;
    206.                 OUT.diffuseColor = ambientLighting + diffuseReflection;
    207.                 OUT.specularColor = specularReflection;
    208.                 triStream.Append(OUT);
    209.             }
    210.            
    211.             half4 frag(g2f IN) : COLOR
    212.             {
    213.                 return float4(IN.specularColor +
    214.                 IN.diffuseColor, _Color.a);
    215.             }
    216.            
    217.             ENDCG
    218.  
    219.         }
    220.     }
    221. }
     
  2. jbernard_

    jbernard_

    Joined:
    Jun 14, 2016
    Posts:
    2
    I actually thought this wasn't possible as I couldn't find an example or info in the docs and failed while back. But just tested it and it seems you can.

    Looking at your shader, I believe you should use "SV_POSITION" only in your g2f struct. The other attributes should use a TEXCOORD semantic.
     
  3. macdude2

    macdude2

    Joined:
    Sep 22, 2010
    Posts:
    686
    Interesting, I'll have to try that. I actually did get this shader working a while back tho, ended up having to change the tess and hullconst functions. Tessellation with geometry is quite a cool combination actually!
     
  4. haijun

    haijun

    Joined:
    Feb 4, 2015
    Posts:
    8
    Hey! I'm also trying to figure out how to make tessellation works with geometry. Do you mind post what you have at the end so that I can learn from it? Thanks!
     
  5. Przemyslaw_Zaworski

    Przemyslaw_Zaworski

    Joined:
    Jun 9, 2017
    Posts:
    328
    Tessellation with geometry shader - simple example:

    Code (CSharp):
    1. Shader "Tessellation with Geometry"
    2. {
    3.     Properties
    4.     {  
    5.         _TessellationFactor ("Tessellation Factor", Range(0, 64)) = 16
    6.         _QuadSize ("Quad Size", Float) = 0.05
    7.     }
    8.     SubShader
    9.     {
    10.         Pass
    11.         {  
    12.             CGPROGRAM
    13.  
    14.             #pragma vertex VSMain
    15.             #pragma hull HSMain
    16.             #pragma domain DSMain
    17.             #pragma geometry GSMain
    18.             #pragma fragment PSMain
    19.             #pragma target 5.0
    20.  
    21.             float _TessellationFactor, _QuadSize;
    22.  
    23.             struct CONTROL_POINT
    24.             {
    25.                 float4 position : SV_POSITION;
    26.             };
    27.            
    28.             CONTROL_POINT VSMain (float4 vertex:POSITION)
    29.             {
    30.                 CONTROL_POINT vs;
    31.                 vs.position = vertex;
    32.                 return vs;
    33.             }
    34.             void constantsHS (InputPatch<CONTROL_POINT,3> V, out float edge[3]:SV_TessFactor, out float inside:SV_InsideTessFactor)
    35.             {
    36.                 edge[0] = edge[1] = edge[2] = _TessellationFactor;
    37.                 inside = _TessellationFactor;
    38.             }
    39.  
    40.             [domain("tri")]
    41.             [partitioning("integer")]
    42.             [outputtopology("triangle_cw")]
    43.             [patchconstantfunc("constantsHS")]
    44.             [outputcontrolpoints(3)]
    45.            
    46.             CONTROL_POINT HSMain (InputPatch<CONTROL_POINT,3> V, uint ID : SV_OutputControlPointID)
    47.             {
    48.                 return V[ID];
    49.             }
    50.  
    51.             [domain("tri")]
    52.             CONTROL_POINT DSMain ( float edge[3]:SV_TessFactor, float inside:SV_InsideTessFactor, const OutputPatch<CONTROL_POINT,3> P, float3 K : SV_DomainLocation)
    53.             {
    54.                 CONTROL_POINT ds;
    55.                 ds.position =  float4(P[0].position.xyz*K.x + P[1].position.xyz*K.y + P[2].position.xyz*K.z, 1.0);
    56.                 return ds;
    57.             }
    58.  
    59.             [maxvertexcount(64)]
    60.             void GSMain( triangle CONTROL_POINT patch[3], inout TriangleStream<CONTROL_POINT> stream )
    61.             {
    62.                 CONTROL_POINT GS;
    63.                 float3 delta = float3 (_QuadSize, 0.00, 0.00);
    64.                 float3 center = float3((patch[0].position.xyz + patch[1].position.xyz + patch[2].position.xyz) / 3);
    65.                 GS.position = UnityObjectToClipPos(center + delta.yyy);
    66.                 stream.Append(GS);
    67.                 GS.position = UnityObjectToClipPos(center + delta.yyx);
    68.                 stream.Append(GS);
    69.                 GS.position = UnityObjectToClipPos(center + delta.xyy);
    70.                 stream.Append(GS);
    71.                 GS.position = UnityObjectToClipPos(center + delta.xyy);
    72.                 stream.Append(GS);
    73.                 GS.position = UnityObjectToClipPos(center + delta.xyx);
    74.                 stream.Append(GS);
    75.                 GS.position = UnityObjectToClipPos(center + delta.yyx);
    76.                 stream.Append(GS);
    77.                 stream.RestartStrip();
    78.             }
    79.            
    80.             float4 PSMain (CONTROL_POINT ps) : SV_Target
    81.             {
    82.                 return 0;
    83.             }
    84.             ENDCG
    85.         }
    86.     }
    87.  
    88. }

    Geometry shader creates quad in the center of input tessellation triangle.
    upload_2019-4-12_11-46-21.png
     
    commadorecoder64 and customphase like this.