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. We have updated the language to the Editor Terms based on feedback from our employees and community. Learn more.
    Dismiss Notice
  3. Join us on November 16th, 2023, between 1 pm and 9 pm CET for Ask the Experts Online on Discord and on Unity Discussions.
    Dismiss Notice

vertex fragment domain hull shader > tessellation with shadows

Discussion in 'Shaders' started by mgto, Jan 31, 2015.

  1. mgto

    mgto

    Joined:
    May 30, 2013
    Posts:
    22
    Heyho!

    After a week of research regarding tessellation I managed to build a edge length based tessellation shader based on example shaders I found on the internetz.

    I have another shader with working shadows. Now I want to combine both..


    I understand how the flow through both shader works and tessellation itself works flawless, shadows too. But now I have a bit of a problem to understand how to attach the tessellation shader to unitys shadow pipeline.

    I found this interesting post but they are talking about a geometry program shader
    http://forum.unity3d.com/threads/is-it-possible-to-use-geometry-shader-with-surface-shaders.164905/

    Is it the way to go to expand the unityCG and AutoLight cginc files? (which would be ok)

    also adding a shadow collector and caster pass.

    I have unity 4 and 5 on my hands but I guess it makes no difference, right?

    I'm currently working on it but I have the feeling this is not thought through. Could someone with more knowledge check the above thread and explain if that's how it should be done? Is there definitely no support for something like TRANSFER_VERTEX_TO_FRAGMENT(o) for a hull - domain shader right now and in the near future?

    cheers
     
  2. mgto

    mgto

    Joined:
    May 30, 2013
    Posts:
    22
    ok to answer my own question. It is the way to go! It doesn't matter if he is using an geometry program. it's the same method.

    So in very short (showing only the shadow relevant code) it is:

    Code (CSharp):
    1.  
    2.  
    3. /############### base pass
    4.  
    5. struct HullType
    6. {
    7.     float4 pos : SV_POSITION;
    8.     float2 uv : TEXCOORD0;
    9.     float3 normal : NORMAL;
    10.     float4 tangent : TANGENT;
    11.     float4 color: COLOR;
    12. };
    13.  
    14. struct PixelInputType
    15. {
    16.     LIGHTING_COORDS(4,5)  
    17. };
    18. //--------------------------------------------------------------------------------------
    19.  
    20.  
    21. //--------------------------------------------------------------------------------------
    22. // Domain Shader - Geometry Pass
    23. //--------------------------------------------------------------------------------------
    24. [domain("tri")]
    25. PixelInputType DS(ConstantOutputType input, float3 domainCoord : SV_DomainLocation, const OutputPatch<HullType, 3> patch)
    26. {  
    27.     TRANSFER_GEOM_TO_FRAGMENT(output, output.pos);
    28. }
    29. //--------------------------------------------------------------------------------------
    30.  
    31.  
    32.  
    33.  
    34.  
    35. // /############### collector / caster pass
    36.  
    37.  
    38.  
    39.        //--------------------------------------------------------------------------------------
    40. // TYPEDEFS - Shadow Pass
    41. //--------------------------------------------------------------------------------------
    42.  
    43. struct HullType_S
    44. {
    45.     #ifdef SHADOW_CASTER_PASS
    46.         V2F_SHADOW_CASTER; // (this one blocks TexCoord 0 to 4 and defines pos) //float4 pos : SV_POSITION;
    47.     #else
    48.         V2F_SHADOW_COLLECTOR; // (this one blocks TexCoord 0 to 4 and defines pos) //float4 pos : SV_POSITION;
    49.     #endif
    50. };
    51. struct PixelInputType_S
    52. {
    53.     #ifdef SHADOW_CASTER_PASS
    54.         V2F_SHADOW_CASTER; // (this one blocks TexCoord 0 to 4 and defines pos) //float4 pos : SV_POSITION;
    55.     #else
    56.         V2F_SHADOW_COLLECTOR; // (this one blocks TexCoord 0 to 4 and defines pos) //float4 pos : SV_POSITION;
    57.     #endif
    58. };
    59. //--------------------------------------------------------------------------------------
    60.  
    61.  
    62. //--------------------------------------------------------------------------------------
    63. // Domain Shader - Shadow Pass
    64. //--------------------------------------------------------------------------------------
    65. [domain("tri")]
    66. PixelInputType_S DS_S(ConstantOutputType input, float3 domainCoord : SV_DomainLocation, const OutputPatch<HullType_S, 3> patch)
    67. {      
    68.  
    69.     // here it makes a lot more sense but the method must fit the domain shader
    70.     #if defined (SHADOW_COLLECTOR_PASS)    
    71.         TRANSFER_SHADOW_COLLECTOR(output, vertexPosition)  
    72.     #elif defined (SHADOW_CASTER_PASS)      
    73.         TRANSFER_SHADOW_CASTER(output, vertexPosition)
    74.     #endif
    75.  
    76.  
    77. }
    78. //--------------------------------------------------------------------------------------
    79. //--------------------------------------------------------------------------------------
    80. // Pixel Shader - Shadow Pass
    81. //--------------------------------------------------------------------------------------
    82.  
    83. float4 PS_S(PixelInputType_S i) : COLOR
    84. {
    85.     #if defined (SHADOW_COLLECTOR_PASS)
    86.         SHADOW_COLLECTOR_FRAGMENT(i)
    87.     #elif defined (SHADOW_CASTER_PASS)  
    88.         SHADOW_CASTER_FRAGMENT(i)
    89.     #endif    
    90. }
    91.  
    92.  
    93.  
     
  3. mgto

    mgto

    Joined:
    May 30, 2013
    Posts:
    22
    But I have another question: why does the shader doesn't render "multi_compile_fwdadd" correctly?


    If I only output the Forward Add Pass like that

    Code (CSharp):
    1.  
    2. ...
    3. // forward add pass
    4.     Pass {
    5.         Name "FORWARDADD"    
    6.         Tags {"LightMode" = "ForwardAdd"}
    7.         //Blend One One
    8.         //Blend Zero One // only ambient
    9.         Blend One Zero     // only direct light
    10.  
    11.         CGPROGRAM
    12.  
    13. #pragma target 5.0      
    14.      #pragma vertex VS  
    15.      #pragma fragment PS
    16.      #pragma hull HS  
    17.      #pragma domain DS  
    18.    
    19.      #pragma multi_compile_fwdadd
    20.      #pragma fragmentoption ARB_precision_hint_fastest
    21.      #pragma only_renderers d3d11
    22.      
    23.      //----------------------------------------------------------
    24.      #define UNITY_PASS_FORWARDADD
    25.      #include "UnityCG.cginc"
    26.      #include "cginc/DwarfMines_UnityCG.cginc"
    27.      #include "AutoLight.cginc"
    28.      #include "cginc/DwarfMines_AutoLight.cginc"
    29.      //#include "Lighting.cginc"
    30.      //----------------------------------------------------------
    31.      
    32.      sampler2D _MainTex;
    33.      
    34.      //-------------------------------------------------------
    35.      uniform half _DisplacementFactor;  
    36.      uniform half _StaticTessellationFactor;
    37.      uniform half _MaxDynamicTesselation;
    38.      
    39.      #include "cginc/DwarfMines_Tessellation.cginc"
    40.      //-------------------------------------------------------
    41.      
    42.  
    43.      //--------------------------------------------------------------------------------------
    44.      // Pixel Shader
    45.      //--------------------------------------------------------------------------------------
    46.      float4 PS(PixelInputType v) : COLOR
    47.      {
    48.         float4 returnColor = float4(0.0, 1.0, 0.0, 1.0);      
    49.        
    50.        float atten = LIGHT_ATTENUATION(v); // This gets you the attenuation + shadow value.
    51.        
    52.        float3 lightDirection;
    53.        if (0.0f == _WorldSpaceLightPos0.w) // directional light?  
    54.          lightDirection = normalize(float3(_WorldSpaceLightPos0.xyz));  
    55.        else // point or spot light  
    56.          lightDirection =  normalize(float3(_WorldSpaceLightPos0.xyz - v.pos.xyz));
    57.          
    58.        float lightIntensity = saturate(dot(v.normal_w,lightDirection));
    59.  
    60.        if(lightIntensity > 0.0f)      
    61.          returnColor += lightIntensity;        
    62.  
    63.        float3 diffuse = tex2D (_MainTex, v.uv).rgb;
    64.        returnColor.rgb = atten*lightIntensity;      
    65.  
    66.        return saturate(returnColor);
    67.      }
    68.      
    69.      ENDCG
    70.    
    71.    } // end pass "forward add"
    72.    //-----------------------------
    73.  
    I get this behaviour
    (center sphere is a reference with my working shader without tessellation)
    What I expect: see the red light illuminate the plane and the 2nd sphere with attenuation and whatnot.