Facepunch / garrysmod-requests

Feature requests for Garry's Mod
84 stars 24 forks source link

Ability to copy Depth and/or Share depth buffers with Render Targets #2308

Open WardenPotato opened 7 months ago

WardenPotato commented 7 months ago

The depth buffer is an essential part of creating graphics effects and doing render work, sadly Render Targets are unable to share depth with MATERIAL_RT_DEPTH_SHARED if any form of Anti Aliasing is enabled.

It is also not currently possible to copy the main depth buffer to a Render Target with its own stencil-depth buffer.

This behaviour can be observed here: https://github.com/lua9520/source-engine-2018-hl2_src/blob/master/materialsystem/ctexture.cpp#L1713 https://github.com/lua9520/source-engine-2018-hl2_src/blob/master/materialsystem/shaderapidx9/shaderapidx8.cpp#L8058

Currently a huge amount of existing addons and code in gmod relies on MATERIAL_RT_DEPTH_SHARED always sharing depth instead of being dependant on AA, i have added this caveat to the wiki but it was not known to people before this and considered "render targets randomly breaking"

A real world example of the limitations this causes can also be observed at: https://github.com/TTT-2/TTT2/issues/1411

So to recap the 2 biggest limitations with RT's currently are:

  1. Not being able to share depth if AA is on
  2. Not being able to copy the depth buffer of one RT to another RT

Proposed solution:

  1. Allow the sharing of the depth buffer regardless of AA setting as this assumption has been made for all existing RT code out there.
  2. Something similar to render.CopyTexture but it instead being render.CopyDepth/render.CopyStencil
A1steaksa commented 7 months ago

I'd personally like to see a calling convention like this

render.CopyColor( fromRenderTarget, toRenderTarget )
render.CopyDepth( fromRenderTarget, toRenderTarget )
render.CopyStencil( fromRenderTarget, toRenderTarget )
WardenPotato commented 6 months ago

After doing a bit of digging in the engine it might be that copying the depth buffer to a texture is quite simple if i got nothing wrong pRenderContext->CopyRenderTargetToTextureEx(destinationTexture, -1, NULL, NULL); Inside of CShaderAPIDx8::CopyRenderTargetToTextureEx it appears that -1 is taken as a depth copy request. In the glua api render.CopyRenderTargetToTexture doesnt seem to accept passing a int nRenderTargetID, instead its just always the top of the RT stack which isnt allowed to go below 0

A1steaksa commented 6 months ago

It would also be nice to be able to read/write those buffers as tables or strings of numbers.

That may not be practical to do, though, depending on where in the rendering pipeline this all lives.

meetric1 commented 6 months ago

@WardenPotato CopyRenderTargetToTextureEx with the second parameter as -1 crashes the game. May be an Xbox only thing.

meetric1 commented 6 months ago

From the looks of it (according to some stackoverflow forum research) the only good way to apply depth is to use the DEPTH output in pixel shaders. Problem is I don't see any way of actually getting the depth information once its stored in the depth texture

WardenPotato commented 3 months ago

i think that changing this line to

else if ( type == RENDER_TARGET_WITH_DEPTH || type == RENDER_TARGET_ONLY_DEPTH || (g_pShaderAPI->DoRenderTargetsNeedSeparateDepthBuffer() && type != RENDER_TARGET_FORCE_SHARED ))

and this line to

bool bShouldForce = g_pShaderAPI->DoRenderTargetsNeedSeparateDepthBuffer() && m_nOriginalRenderTargetType != RENDER_TARGET_FORCE_SHARED;

and this line to

if ( m_nOriginalRenderTargetType == RENDER_TARGET || m_nOriginalRenderTargetType == RENDER_TARGET_FORCE_SHARED )

should allow us to actually use the depth buffer instead of it forcibly opting out when AA is on

phoen1xf commented 3 months ago

🙏