Search Unity

Rendering on top of everything, without ZTest Always?

Discussion in 'Shaders' started by Michael-N3rkmind, Jun 23, 2017.

  1. Michael-N3rkmind

    Michael-N3rkmind

    Joined:
    Aug 16, 2015
    Posts:
    24
    Hey Forum! Thanks for having a look at this thread :)

    I've got a gun that I want to display on top of everything, so he does not clip through walls.
    I want to take a shader approach to that problem ( And not running another camera )

    The problem I have with my current shader is that when I set it on ZTest Always, with a Queue = Overlay, is that I see the insides of the gun.

    I'm wondering, there has to be a way to have a ZTest LEqual only on my shader, and a ZTest Always for all the other objects not using this shader.

    I'd appreciate your help! Thank you!

    **This is without ZTest Always**
    Unity 5.6.1f1 Personal (64bit) - scene.unity - GunShader - PC, Mac & Linux Standalone DX11.jpg
    **This is with ZTest Always**
    Unity 5.6.1f1 Personal (64bit) - scene.unity - GunShader - PC, Mac & Linux Standalone DX11_2.jpg
     
  2. Peter77

    Peter77

    QA Jesus

    Joined:
    Jun 12, 2013
    Posts:
    6,609
    I don't know whether the following idea is a good way of doing it, but I can imagine rendering the weapon in two passes could fix this issue.

    1st pass only writes to the depth buffer (see SV_Depth semantic). This is to clear the depth values where the weapon is rendered to. I'm not sure whether this works with Unity's _DepthTexture and _DepthNormalTexture built-in textures, maybe that's where the depth macros come into play.

    2nd pass renders the weapon as usual (ZWrite=On, ZTest=LEqual). Since the 1st pass cleared the depth buffer behind the weapon, ZTest=LEqual should work and prevent the sorting issue from that screenshot you posted.

    Hope it makes sense.
     
    Beennn likes this.
  3. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,342
    There have been several threads on first person weapons on the forum, including one or two that have working shaders posted.

    First person weapons are always something of a problem if you don't let them exist in the "world" as they are. Lots of modern games will play a special animation when you're close to a wall to either drop the gun, or pull it back, so that it doesn't go through the wall rather than use any other trick.

    Doing the two pass clear depth and render @Peter77 suggested will work, but shadows are a problem. When not sticking the gun through a wall, it'll be fine, but when you do then the shadowing on the part of the gun inside the wall will just use the shadow from the wall, which means it'll look like it's unshadowed all of a sudden. If you fix it in the camera depth texture (what receives directional shadows in Unity) so that it does the two passes, now you'll just have the gun in shadow once it's inside the wall, which is just as bad.

    A better solution is to not go through the wall at all by either "squishing" the gun, or by scaling it down. Squishing (scaling the clip space z) is actually quite easy, but made more difficult by surface shaders not having a way to do this, so you have to hand modify a surface shader's generated shader or write a custom shader from "scratch". However the problem with this method is, even though the gun will render nicely, it'll also screw up shadows. Best case is the shelf shadowing either goes away or looks terrible since the mesh is now super thin, but more likely it'll still cast the shadow as if it's unscaled, which means no or weird self shadowing, and casting a shadow that appears to stuck through the wall. You could of course disable shadow casting, but again, no self shadowing.

    So a real solution probably requires rendering the shadows for the gun manually, like the old Blacksmith Unity demo character shadows worked.
     
  4. Kwajo7

    Kwajo7

    Joined:
    Oct 24, 2017
    Posts:
    3
    I came here looking to make an effect where there's a transparent overlay on the screen wherever the player is occluded. I eventually figured it out, but for anyone else here for the same thing, I posted how I did it on another thread.