Search Unity

Transparent shader with culling off and correct face sorting, possible?

Discussion in 'Shaders' started by bitinn, Jul 30, 2019.

  1. bitinn

    bitinn

    Joined:
    Aug 20, 2016
    Posts:
    542
    Say I have a cube, each side using a texture with holes (eg. alpha = 0), and I want to see through holes and see the backfaces.

    So I am using a transparent shader with culling off and an extra depth pass to allow correct face sorting.

    Problem is because it's just a cube, writing to depth cause back faces to be blocked by front faces, ignoring the holes in the texture.

    Is it possible to have both the holes and correct sorting?
    What trickery should I do in the depth pass to take these holes into account?
     
  2. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    7,157
    Could use a 4 pass shader.

    1. Cull Front, ZWrite only pass.
    2. Cull Front, Draw normally.
    3. Cull Back, ZWrite Only pass.
    4. Cull Back, Draw normally.

    Or use alpha testing.
     
    bitinn likes this.
  3. bitinn

    bitinn

    Joined:
    Aug 20, 2016
    Posts:
    542
    OK good to know I do need 4 passes here. I will make do with alpha testing for now.

    A tangentially related question: I saw you had discussions on depth pre-pass before, do you happen to know any drawbacks using the depth pre-pass result for z-testing? eg. don't clear the depth pre-pass and reuse it.

    (I am writing a custom SRP similar to LWRP hence I have control on this; AFAIK LWRP doesn't reuse the depth pre-pass in z-testing.)
     
    Last edited: Jul 31, 2019
  4. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    7,157
    On mobile a depth pre pass doesn't really save anything for rendering since many mobile GPUs do tiled based deferred rendering which effectively does a depth pre pass in hardware. So you're doubling the draw calls for zero benefit.

    If you plan on having something like a camera depth texture to sample from, and you want to use MSAA, this also becomes a bit of an issue. Mainly, when making a copy of the depth to a texture usually requires some kind of custom MSAA resolve pass. Usually you'd want to pick the closest depth from the subsample data, but the default hardware resolve uses an average which you don't want. More cheaply you could always grab the first subsample depth, but that'll skew the depth data slightly. A proper MSAA resolve can sometimes be more expensive than just rendering the scene twice!

    Rendering only to depth is really fast on modern desktop GPUs, but it still requires some time on the CPU to issue the API commands to do the drawing. It's possible you spend more time issuing API commands than you save in render time from the reduced over shading.

    Otherwise I don't know of any issues.
     
  5. bitinn

    bitinn

    Joined:
    Aug 20, 2016
    Posts:
    542
    If I do need a camera depth texture for post processing, it is not possible to just read the depth result from current render target, right? I have to do a depth pre-pass, right?

    (post processing and screen space shadow are the reason for my depth pre-pass, perhaps there are alternative solutions I am not aware of?)
     
  6. bitinn

    bitinn

    Joined:
    Aug 20, 2016
    Posts:
    542
    Actually, and I haven't tested it, if I do the following:

    GetTemporaryRT(colorID, ...)
    GetTemporaryRT(depthID, ...)
    SetRenderTarget(colorID, depthID, ...)
    DrawRenderers(...)

    Then I should be able pass on that Depth buffer to any subsequent shader/compute shader.

    Then there isn't a strong need for me to do a depth pre-pass besides the screen-space shadow.

    I need to test this out.
     
  7. bitinn

    bitinn

    Joined:
    Aug 20, 2016
    Posts:
    542
    Update: ok, with random write enabled, the depth render texture from opaque pass can be used with compute shader. I assume it would work with fragment shader post processing too.

    That's all good.