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.
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:
Draw the terrain using some ground texture
Draw other objects
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
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.
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…
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.
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).
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.)
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.