Search Unity

vertex displacement shader and ssao not working together

Discussion in 'Shaders' started by warby, Mar 26, 2012.

  1. warby

    warby

    Joined:
    Mar 23, 2009
    Posts:
    162
    hi

    we are using a bunch of vertex shaders in our game that applies sinus curves to vert positions so that all kinds of foliage can sway in the wind.

    when i turn on the build in screen space ambient occlusion too the "darkend" areas remain static where the grass originally was before it started displacing.

    what do i need to change on the shader (or ssao image effect) to make these 2 effects play along together nicely ?



    ... the ssao grabs what exactly from the frame buffer to perform its magic ? the normals ? also the depth right ? could it be that my displacement/wobble/shader doesnt update one of them in the framebuffer and needs some extra code to do it:




    Code (csharp):
    1.  
    2.  
    3.         Shader "ese_wobble_masked_pixellit"
    4.     {
    5.         Properties
    6.         {
    7.     _MainTex("_MainTex", 2D) = "white" {}
    8.     _frequency("_frequency", Float) = 1
    9.     _speed("_speed", Float) = 1
    10.     _scale_x("_scale_x", Float) = 0.1
    11.     _scale_y("_scale_y", Float) = 0.1
    12.     _scale_z("_scale_z", Float) = 1
    13.     _alpha_threshold("_alpha_threshold", Range(0.01,0.99) ) = 0.5
    14.    
    15.         }
    16.        
    17.         SubShader
    18.         {
    19.             Tags
    20.             {
    21.     "Queue"="Geometry"
    22.     "IgnoreProjector"="True"
    23.     "RenderType"="TransparentCutout"
    24.    
    25.             }
    26.    
    27.            
    28.     Cull Off
    29.     ZWrite On
    30.     ZTest LEqual
    31.     ColorMask RGBA
    32.     Fog{
    33.     }
    34.    
    35.    
    36.             CGPROGRAM
    37.     #pragma surface surf Lambert  addshadow vertex:vert nolightmap noforwardadd
    38.     #pragma target 2.0
    39.    
    40.    
    41.     sampler2D _MainTex;
    42.     float _frequency;
    43.     float _speed;
    44.     float _scale_x;
    45.     float _scale_y;
    46.     float _scale_z;
    47.     float _alpha_threshold;
    48.    
    49.                
    50.                 struct Input {
    51.                     float2 uv_MainTex;
    52.                     float4 color : COLOR;
    53.    
    54.                 };
    55.    
    56.                 void vert (inout appdata_full v, out Input o) {
    57.                     float4 Splat2=v.texcoord1.y;
    58.                     float4 Splat1=v.texcoord1.x;
    59.                     float4 Multiply4=_Time * _speed.xxxx;
    60.                     float4 Add2=v.vertex + Multiply4;
    61.                     float4 Splat3=Add2.z;
    62.                     float4 Multiply3=Splat3 * _frequency.xxxx;
    63.                     float4 Add4=Splat1 + Multiply3;
    64.                     float4 Sin1=sin(Add4);
    65.                     float4 Multiply0=_scale_x.xxxx * Sin1;
    66.                     float4 Multiply2=_scale_y.xxxx * Sin1;
    67.                     float4 Multiply5=_scale_z.xxxx * Sin1;
    68.                     float4 Assemble0=float4(Multiply0.x, Multiply2.y, Multiply5.z, 0);
    69.                     float4 Multiply7=Splat2 * Assemble0;
    70.                     float4 Add1=Multiply7 + v.vertex;
    71.                     float4 VertexOutputMaster0_1_NoInput = float4(0,0,0,0);
    72.                     float4 VertexOutputMaster0_2_NoInput = float4(0,0,0,0);
    73.                     float4 VertexOutputMaster0_3_NoInput = float4(0,0,0,0);
    74.                     v.vertex = Add1;
    75.                 }
    76.                
    77.    
    78.                 void surf (Input IN, inout SurfaceOutput o) {
    79.                     o.Normal = float3(0.0,0.0,1.0);
    80.                     o.Alpha = 1.0;
    81.                     o.Albedo = 0.0;
    82.                     o.Emission = 0.0;
    83.                     o.Gloss = 0.0;
    84.                     o.Specular = 0.0;
    85.                    
    86.                     float4 Tex2D0=tex2D(_MainTex,(IN.uv_MainTex.xyxy).xy);
    87.                     float4 Multiply0=Tex2D0 * IN.color;
    88.                     float4 Subtract0=Tex2D0.aaaa - _alpha_threshold.xxxx;
    89.                     clip( Subtract0 );
    90.                     o.Albedo = Multiply0;
    91.                 }
    92.             ENDCG
    93.         }
    94.         Fallback "Transparent/Cutout/VertexLit"
    95.     }
    96.  
     
  2. larsbertram1

    larsbertram1

    Joined:
    Oct 7, 2008
    Posts:
    6,902
    hi,

    are you using forward rendering mode?
     
  3. brn

    brn

    Joined:
    Feb 8, 2011
    Posts:
    320
    The SSAO uses a depth normal buffer to calculate its intensity. My guess would be that the data being written to the Depth buffer is being done by a shader pass that isn't being transformed in the same way as your color pass, ect. You could try adding this to your shader.

    addshadow

    like this

    #pragma surface surf Lambert addshadow vertex:vert nolightmap noforwardadd addshadow

    Its purpose is as follows "addshadow - Add shadow caster collector passes. Commonly used with custom vertex modification, so that shadow casting also gets any procedural vertex animation."

    It might help, I havent tested it.

    Cheers
    Brn
     
    MaxPirat likes this.
  4. RTshaders

    RTshaders

    Joined:
    Mar 20, 2009
    Posts:
    57
    I got the problem too but I fixed it.Here is my way.

    Tags
    {
    "Queue"="Geometry"

    "IgnoreProjector"="True"

    "RenderType"="TransparentCutout"
    }


    Corret above to below

    Tags

    {

    "Queue"="AlphaTest"

    "IgnoreProjector"="True"

    "RenderType"="TreeLeaf"



    }


    Btw,"RenderType"="TreeLeaf" or "RenderType"="Grass",both works.
     
    Last edited: Mar 27, 2012
  5. larsbertram1

    larsbertram1

    Joined:
    Oct 7, 2008
    Posts:
    6,902
    hi there,

    as far as i can say, you are not able to write your own vertex displacement / lighting function without getting some artifacts on either real time shadows (using a custom lighting function which only supports forward lighting rendered in deferred rendering mode) or ssao (custom displacement function in forward rendering mode) or even both.
    you will have to use the built in vertex displacement functions and assign the according "Render Type" in order to make the shader work correctly under all circumstances: e.g.: bending function: "AnimateVertex" (from "TerrainEngine.cginc") and "Render Type = Tree Leaves".
    The easiest way to do so would be just to use the built in "tree creator leaves fast optimized" shader and prepare your models in an appropriate way by adding vertex colors and a second uv in order to control bending.
    unfortunately setting up the second uv channel seems to be not the easiest task so i would advice to model your grass using the tree creator.

    please correct me if i am wrong. but i have done quite some work on trying to get custom bending / lighting work correctly – without any success so far.



    btw: even the original grass shader (grass rendered as quad not billboard) produces artifacts as fas as ssao is concerned (using forward rendering mode):

    $grass.jpg
     
    Last edited: Mar 27, 2012
    DezBoyle likes this.
  6. ToreTank

    ToreTank

    Joined:
    Jun 23, 2008
    Posts:
    165
    We struggled with the same issue when trying to do vertex displacement in forward mode, and use it with depth-aware post effects. Addshadow makes the real-time shadows work correctly, it seems, but it doesn't fix the depth buffer writes. While there is the option of manually drawing the depth buffer, it seems like the simplest solution is to patch the shaders Unity uses when doing the depth passes.

    Here's what seems to work:
    *For your custom shader, give it a unique RenderType
    *Copy the Camera-DepthNormalTexture and Camera-DepthTexture shaders from the builtin shader bundle. I think these shaders must be placed inside Resources to work in a build.
    *Add subshaders that match the custom shader RenderType, and replicate the displacement there

    I put together a small demo project as proof of concept - it seems to work in both editor and windows standalone, but I haven't tried webplayer or mac standalone yet.

    A couple of screenshots showing before and after patched depth pass shaders (the sphere is using a slightly modified version of the normal extrusion example found here):




    I have not been able to test this extensively, so feedback and errors are much appreciated :)
     
  7. Tim-C

    Tim-C

    Unity Technologies

    Joined:
    Feb 6, 2010
    Posts:
    2,225
    Hi,

    This is an issue with how we render the 'depth/normals' map for forward rendering. Internally we use a shader replace that does not take vertex displacement and custom normal information into account. What this means is that when we render this map the objects are in their 'default' position.

    Currently there are not any super nice workarounds for this. The best is to render your own custom depth-normal map using a shader replace call, and not render one from the camera normally (See the shader replace example from the Unity web site on how to do this... you could use custom tags for your object types).

    ToreTank has raised a bug about this and we will get to this when we can. The biggest issue is that to handle this in the correct way we need to add new shader permutations, and modify the render pipeline a bit. This increases build size (shader cache) and is not a super nice solution, but it's the best solution.
     
  8. brn

    brn

    Joined:
    Feb 8, 2011
    Posts:
    320
    Thanks stramit ToreTank for submitting the bug.

    Im scared to think how complex the back end of unity's shader system is to manage. With all the new permutations being added to the existing ones . Its a credit to you guys that it holds together as well as it does. I do find myself having a moment every once and a while when I hit a show stopping shader bug. But I'm sure I would have many more white hairs on my head if I had to write every permutation for every hardware and lighting condition a shader is likely to encounter.

    Cheers for the top work, with a little nudge for more documentation :)
     
  9. Tim-C

    Tim-C

    Unity Technologies

    Joined:
    Feb 6, 2010
    Posts:
    2,225
    When you encounter bugs please raise them and let me know their # via pm. It's not a guarantee they will be fixed for the next release, but it means they are 'more' on the radar.

    While the backend of our shader system is quite complex we have a really nice suit of automated graphical tests across all platforms. Really helps us not end up with a broken graphics pipeline as you can imagine :)
     
  10. larsbertram1

    larsbertram1

    Joined:
    Oct 7, 2008
    Posts:
    6,902
    @ToreTank: thanks a lot – i always though that i must have been missing something when trying to write vertex animated shaders working in deffered mode but only supporting forward lighting. now writing a vertex animated foliage shader is already done!

    lars
     
  11. sgoodrow

    sgoodrow

    Joined:
    Sep 28, 2012
    Posts:
    150
    My apologies for the slight necro-post but I think the question is relevant and this thread has some useful information in it already.

    I have been experimenting with ToreTank's approach, adding custom rendertype shaders to the built-in camera depth texture shader (and overriding it by placing it in resources) but have one question: Is the _Time parameter known to be the same in a depth pass as it was in the main pass for a given frame?

    I have a simple waving quad shader which functions almost identically to the built-in terrain grass shader except it uses the _Time parameter. Unfortunately the waving seems to be out of sync in the depth texture.