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. Dismiss Notice

Modifying Fragment Depth Values in Shader

Discussion in 'Shaders' started by Poya, Jul 3, 2011.

  1. Poya

    Poya

    Joined:
    Jul 3, 2011
    Posts:
    51
    Sorry if this has been asked and answered before but I can't seem to find a definitive answer to this by searching on the forums. Is there any way to modify / adjust / set the depth value of fragments in the fragment shader in Unity? Comments here and there suggest that it is not...can anybody confirm this?

    Some more context: I've written a basic grass shader which assumes the grass is formed from several layers of grass texture stacked on top of each other, and an alpha map containing dots which represent the grass blades. Since I'm actually rendering 1 layer (i.e the grass planes are extruded in the shader), I need to be able to modify the depth values so that the grass blades look correct next to other objects in the scene.
     
  2. Farfarer

    Farfarer

    Joined:
    Aug 17, 2010
    Posts:
    2,249
    Is it possible to change the vertex positions in the vertex shader then render downwards rather than upwards in your fragment shader?

    So rather than rendering grass incrementally upwards from the base plane, start "below" the base plane and render up to it?
     
    Limofeus likes this.
  3. Poya

    Poya

    Joined:
    Jul 3, 2011
    Posts:
    51
    Thank you very much for that Farfarer, I hadn't actually thought in that direction.

    I tried it and it works...somewhat...the problem is that in order to avoid having to render the ground separately, I was just adding a fraction of the ground texture color to the grass fragments wherever there is a gap (i.e. the alpha at that fragment isn't already 1.0). This gives an incorrect look when I extrude the whole train up and use alpha blending with the rest of the scene.

    So here what I should really be doing:

    1) Draw the terrain using some ground texture
    2) Draw other objects
    3) Draw the grass using vertex extruding and alpha blending, and don't include the ground texture component as explained above. This means I need to generate the grass mesh and can't just replace the terrain shader. This is probably a good idea anyway.


    I'm still interested to know if modifying depth values is an option or if it'll ever be
     
  4. aubergine

    aubergine

    Joined:
    Sep 12, 2009
    Posts:
    2,864
    From the unity help docs:

    What exactly do you mean by depth anyways?

    EDIT:
    If i understand correctly, you want to extrude the terrain mesh up 8-10 times and texture each layer with a grass texture?
    Dont do the extrusion in a shader, do it with Mesh class, so atleast you can have more control on the polygons you are working with. Only do the simple texturing within the shader.
     
    Last edited: Jul 7, 2011
  5. Poya

    Poya

    Joined:
    Jul 3, 2011
    Posts:
    51
    I mean setting the value of the z-buffer at each fragment in the fragment shader.

    In Cg it looks like you can do this by actually defining a depth component in your output. So your shader can actually return a result like this:

    struct PixelOut
    {
    half4 Color : COLOR;
    half Depth : DEPTH;
    };

    Unity's compiler doesn't seem to allow this.

    Extruding the vertices outside the shader is definitely an option but 1) I'm just replacing the unity's terrain shader and I don't think I can get the terrain to render multiple times in the same frame 2) even if I made a grass to be its own mesh, performance-wise I would think rendering the whole thing in one pass and doing everything in the shader would be better than 8-10 passes...
     
  6. xevius

    xevius

    Joined:
    Nov 2, 2010
    Posts:
    9
    *bump*
     
  7. Ippokratis

    Ippokratis

    Joined:
    Oct 13, 2008
    Posts:
    1,521
  8. Kurodo

    Kurodo

    Joined:
    Dec 16, 2013
    Posts:
    1
    This is not a good way to accomplish this task, hitting the CPU with the task of extruding the geometry is never going to be faster (actually way slower) than doing the same thing on the GPU and I don't see what extra control this gives you that you can't easily accomplish on the GPU.

    The classic pre DX11 way to do this is to render the geometry in multiple passes and extrude the vertex position along the vertex normal by some constant dist * pass number. If done in the vertex shader you shouldn't need to alter the depth in the pixel shader.
     
  9. jcowles

    jcowles

    Joined:
    May 25, 2016
    Posts:
    11
    The struct works fine for me, the key is to make sure you have ZWrite On and the fragment shader function itself must have no semantics (I think it has SV_Target by default).
     
  10. jvo3dc

    jvo3dc

    Joined:
    Oct 11, 2013
    Posts:
    1,520
    Yes, a struct like that works fine in Unity. (ZWrite On is not required, you could use it for Z-testing only.) The main problem is the performance impact. If you output the depth from the pixel shader, you disable early z-rejection. Which essentially means you'll always shade all pixels, visible or not. So if you output depth, you should render this material before the rest of the scene. (It can occlude other pixels, but it can't be occluded itself.)
     
  11. jjxtra

    jjxtra

    Joined:
    Aug 30, 2013
    Posts:
    1,453
    Use a frag with SV_Depth instead of SV_Target semantics that returns float (0 - 1). Make sure ZWrite is On. Return the new depth value in the fragment.
     
    apkdev likes this.