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

Render only geometry, that was created by a geometry shader, to depth buffer.

Discussion in 'Shaders' started by Elias-Minor, Aug 5, 2018.

  1. Elias-Minor

    Elias-Minor

    Joined:
    Mar 12, 2015
    Posts:
    6
    Hey there,

    I was researching for hours now and couldn't find any solution.
    The problem is, that I create geometry (billboards) with a geometry shader, but the original mesh is still the only thing that writes to the z-buffer of the camera (I want to add depth of field later).
    Here is a little picture that describes my problem:
    geometry_shader_zbuffer_problem.png
    Is there a solution for this issue?
    Maybe there is a manual way to set the depth values?

    Thanks in advance for your time and help!
     
  2. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,230
    The depth texture and depth buffer are different things.

    When using the forward render path, the depth texture is generated by rendering the scene with the shader’s shadowcaster pass prior to rendering the main forward passes, which has its own completely separate z buffer. If your shader is using a Fallback shader, it likely has a default shadowcaster pass which is rendering your original mesh.
     
  3. Elias-Minor

    Elias-Minor

    Joined:
    Mar 12, 2015
    Posts:
    6
    Thank you for your reply!

    So is it possible to write my own shadowcaster pass for a geometry shader? Do you know some documentation about writing shadowcaster?
    A backup solution would be that the shader is rendered after the post-process shader (everything is scharp). Do you know how to achieve this?

    Thank you in advance.
     
  4. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,230
    Of course. There's a basic example of a shadow caster pass here:
    https://docs.unity3d.com/Manual/SL-VertexFragmentShaderExamples.html

    There's some magic in those macro functions that Catlike Coding goes into a little bit here:
    https://catlikecoding.com/unity/tutorials/rendering/part-7/

    I also have this example shader which I wrote for some other post I can no longer find:
    Code (CSharp):
    1. Shader "Custom/Geometry Shader Shadow Test" {
    2.     Properties {
    3.     }
    4.     SubShader {
    5.         Cull off
    6.         Pass {
    7.             Tags { "LightMode" = "ForwardBase" }
    8.             CGPROGRAM
    9.             #pragma vertex vertex
    10.             #pragma geometry geometry
    11.             #pragma fragment fragment
    12.             #include "AutoLight.cginc"
    13.             #include "UnityCG.cginc"
    14.             #include "Lighting.cginc"
    15.             #pragma multi_compile_fwdbase nolightmap nodirlightmap nodynlightmap novertexlight
    16.             struct v2g {
    17.                 float4 pos: POSITION;
    18.                 float3 normal: NORMAL;
    19.                 SHADOW_COORDS(1)
    20.             };
    21.             struct g2f {
    22.                 float4 pos: SV_POSITION;
    23.                 float3 normal: NORMAL;
    24.                 fixed4 col: COLOR2;
    25.                 LIGHTING_COORDS(1, 2)
    26.             };
    27.             v2g vertex(appdata_base v) {
    28.                 v2g o;
    29.                 o.pos = v.vertex;
    30.                 o.normal = v.normal;
    31.                 TRANSFER_SHADOW(o)
    32.                 return o;
    33.             }
    34.             [maxvertexcount(50)]
    35.             void geometry(triangle v2g IN[3], inout TriangleStream < g2f > tristream){
    36.                 float4 VertexA = IN[0].pos;
    37.                 float4 VertexB = IN[1].pos;
    38.                 float4 VertexC = IN[2].pos;
    39.                 g2f o = (g2f) 0;
    40.                 o.pos = UnityObjectToClipPos(VertexA);
    41.                 o.normal = IN[0].normal;
    42.                 o.col = fixed4(1.f, 0, 0, 1.f);
    43.                 TRANSFER_VERTEX_TO_FRAGMENT(o);
    44.                 tristream.Append(o);
    45.                 o.pos = UnityObjectToClipPos(VertexB);
    46.                 o.normal = IN[1].normal;
    47.                 o.col = fixed4(0, 0, 1.f, 1.f);
    48.                 TRANSFER_VERTEX_TO_FRAGMENT(o);
    49.                 tristream.Append(o);
    50.                 o.pos = UnityObjectToClipPos(VertexC);
    51.                 o.normal = IN[2].normal;
    52.                 o.col = fixed4(0, 1.f, 0, 1.f);
    53.                 TRANSFER_VERTEX_TO_FRAGMENT(o);
    54.                 tristream.Append(o);
    55.                 tristream.RestartStrip();
    56.                 o.pos = UnityObjectToClipPos(VertexA);
    57.                 o.normal = IN[0].normal;
    58.                 o.col = fixed4(1.f, 0, 0, 1.f);
    59.                 TRANSFER_VERTEX_TO_FRAGMENT(o);
    60.                 tristream.Append(o);
    61.                 o.pos = UnityObjectToClipPos(VertexB);
    62.                 o.normal = IN[1].normal;
    63.                 o.col = fixed4(0, 0, 1.f, 1.f);
    64.                 TRANSFER_VERTEX_TO_FRAGMENT(o);
    65.                 tristream.Append(o);
    66.                 o.pos = UnityObjectToClipPos(VertexA + float4(IN[0].normal, 1.f));
    67.                 o.normal = IN[2].normal;
    68.                 o.col = fixed4(0, 1.f, 0, 1.f);
    69.                 TRANSFER_VERTEX_TO_FRAGMENT(o);
    70.                 tristream.Append(o);
    71.                 tristream.RestartStrip();
    72.             }
    73.             fixed4 fragment(g2f i) : SV_Target {
    74.                 fixed4 col = i.col;
    75.                 fixed shadow = SHADOW_ATTENUATION(i);
    76.                 float3 norm = UnityObjectToWorldNormal(i.normal);
    77.                 half nl = max(0, dot(norm, _WorldSpaceLightPos0.xyz));
    78.                 fixed3 diff = nl * _LightColor0.rgb;
    79.                 fixed3 ambientL = ShadeSH9(half4(norm, 1));
    80.                 fixed3 lighting = diff * shadow + ambientL;
    81.                 col.rgb *= lighting;
    82.                 return col;
    83.             }
    84.             ENDCG
    85.         }
    86.         Pass {
    87.             Tags { "LightMode" = "ShadowCaster" }
    88.             CGPROGRAM
    89.             #pragma vertex vertex
    90.             #pragma geometry geometry
    91.             #pragma fragment fragment
    92.             #include "UnityCG.cginc"
    93.             #pragma multi_compile_shadowcaster
    94.             struct v2g {
    95.                 float4 vertex: POSITION;
    96.                 float3 normal: NORMAL;
    97.             };
    98.             struct g2f {
    99.                 V2F_SHADOW_CASTER;
    100.             };
    101.             v2g vertex(appdata_base v)
    102.             {
    103.                 v2g o;
    104.                 o.vertex = v.vertex;
    105.                 o.normal = v.normal;
    106.                 return o;
    107.             }
    108.             [maxvertexcount(80)]
    109.             void geometry(triangle v2g IN[3], inout TriangleStream < g2f > tristream){
    110.                 g2f o = (g2f) 0;
    111.                  v2g v = (v2g) 0;
    112.  
    113.                 v = IN[0];
    114.                 TRANSFER_SHADOW_CASTER_NORMALOFFSET(o);
    115.                 tristream.Append(o);
    116.                 v = IN[1];
    117.                 TRANSFER_SHADOW_CASTER_NORMALOFFSET(o);
    118.                 tristream.Append(o);
    119.                 v = IN[2];
    120.                 TRANSFER_SHADOW_CASTER_NORMALOFFSET(o);
    121.                 tristream.Append(o);
    122.                 tristream.RestartStrip();
    123.                 v = IN[0];
    124.                 TRANSFER_SHADOW_CASTER_NORMALOFFSET(o);
    125.                 tristream.Append(o);
    126.                 v = IN[1];
    127.                 TRANSFER_SHADOW_CASTER_NORMALOFFSET(o);
    128.                 tristream.Append(o);
    129.                 v = IN[0];
    130.                 v.vertex += float4(v.normal, 0.f);
    131.                 TRANSFER_SHADOW_CASTER_NORMALOFFSET(o);
    132.                 tristream.Append(o);
    133.                 tristream.RestartStrip();
    134.             }
    135.             float4 fragment(g2f i) : SV_Target
    136.             {
    137.                 SHADOW_CASTER_FRAGMENT(i)
    138.             }
    139.             ENDCG
    140.         }
    141.     }
    142. }
     
  5. Elias-Minor

    Elias-Minor

    Joined:
    Mar 12, 2015
    Posts:
    6
    Great, this helps a lot to understand. Thank you.