XNA Creators Club Online
Page 1 of 1 (13 items)
Sort Posts: Previous Next

Depth Buffer access, why redraw the scene?

Last post 03/07/2009 0:46 by siferion. 12 replies.
  • 30/06/2009 20:43

    Depth Buffer access, why redraw the scene?

    Greetings...


    I got a question while dealing with Depth Buffers.

    Why we need redraw the entire scene to get a Z texture? By what I seen, the default Render Target already has a Depth Buffer (probably a DX surface of some sort), so would be faster just flush it right to a Texture2D than redraw a fake one, repeating calculations already done by the built in RenderTarget.
    Also the need in draw everything with a DB shader just to get a texture and after redraw don't makes sense, since the ZBuffer is already calculated.

    Does someone knows how to simply get a texture2D right from the DepthBuffer without redraw and test everything again?


    Thank you in advance.






  • 30/06/2009 20:59 In reply to

    Re: Depth Buffer access, why redraw the scene?

    There is no way to get the depth buffer as a texture to the best of my knowledge. I believe this was a design decision made due to differences in how hardware handles such things. You could always write out depth information to the alpha channel of your render target, though you lose some precision there and it only helps if you are not using the alpha channel.
    www.dadoogames.com
    Curling 2010 - in playtest soon, this month or next, this year for sure (maybe)
  • 30/06/2009 22:40 In reply to

    Re: Depth Buffer access, why redraw the scene?

    Can't do it.  You'll have to render depth to a texture yourself.

    This is because XNA on the PC is built upon Direct3D9, which doesn't allow you this sort of access natively (since it wasn't a requirement of the API spec to have depth buffers in some sort of shader-readable format).  The 360's a different situation since it's a fixed platform, but you wouldn't be able to maintain compatibility with the PC.
    Matt Pettineo | DirectX/XNA MVP


    Ride into The Danger Zone | PIX With XNA Tutorial
  • 01/07/2009 1:42 In reply to

    Re: Depth Buffer access, why redraw the scene?

    This is the trouble, in DX we can create textures from Surfaces... A backbuffer or depthbuffer is a Surface, I inserted a break point to watch all the components of Graphics Device and inside the DepthStencilBuffer in a Non-Public Member there is a pointer to a IDirect3DSurface... It exists and is already there.

    Probably other XNA objects like Texture2D, ResolveTexture2D are also related to such method.
     
    I tried to derive an object from DepthStencilBuffer but got no access to it, I seen some samples in C++ where a guy could retrieve the ComPtr content, but I fear that such approach will not work when porting to the 360.

    Any other ideas?
  • 01/07/2009 12:36 In reply to

    Re: Depth Buffer access, why redraw the scene?

    Why not just use multiple render targets, your second render target could be in the SurfaceFormat.Single for the added accuracy of a 32-bit element. I'm sure that works equally as well on both PC and XBox360 and requires very minimal modifications to your existing shaders to output that depth value.

    As I understand it though, the depth-stencil buffer doesn't store it's information as pixels you can read back and have a depth value. Even if you get the surface via some hack, you still would need to decode the data into a usable depth value.
  • 01/07/2009 15:18 In reply to

    Re: Depth Buffer access, why redraw the scene?

    creasso:
    This is the trouble, in DX we can create textures from Surfaces... A backbuffer or depthbuffer is a Surface, I inserted a break point to watch all the components of Graphics Device and inside the DepthStencilBuffer in a Non-Public Member there is a pointer to a IDirect3DSurface... It exists and is already there.


    Yes but it's not a surface you can actually do anything with.  You can't make a texture out of it for sampling, or even Lock it to access the data on the CPU.  The only thing you can do with an IDirect3DSurface9 that was created by IDirect3DDevice9::CreateDepthStencilSurface is set it as the current depth buffer for the device, or retrieve some basic info about it.

    Even if you could sample the data from a depth-stencil surface, there's no guarantee it would be in a format that your app would know how to interpret.  This is because Direct3D9 imposed no restrictions on how devices could store their depth/stencil information.

    creasso:

    Probably other XNA objects like Texture2D, ResolveTexture2D are also related to such method.
     
    I tried to derive an object from DepthStencilBuffer but got no access to it, I seen some samples in C++ where a guy could retrieve the ComPtr content, but I fear that such approach will not work when porting to the 360.


    Indeed, managed XNA objects like Texture2D and RenderTarget2D will often have one or more pointers to COM interfaces for native Direct3D9 resources...on the PC anyway.  But trying to do anything with those is extremely risky even on the PC, since XNA uses a virtualized GraphicsDevice.


    Matt Pettineo | DirectX/XNA MVP


    Ride into The Danger Zone | PIX With XNA Tutorial
  • 01/07/2009 15:23 In reply to

    Re: Depth Buffer access, why redraw the scene?

    This is exactly what I'm talking about: How to avoid 1 render call on all visible objects and the depth test just to get an information that is already there.

    I did look first on the Depth Texture Sample, but to follow that steps we'll need:

    1 - Test for formats, sizes and everything.
    2 - Create the Render Target
    3 - Create the DepthStencil to the new RT
    4 - Perform a LessEqual test
    5 - Change the shaders to bake depth, or change all object shaders at runtime to use a bakedepth.fx just to the draw call, and after, give then back the colorshader to do the scene rendering. Maybe the same shader with 2 techniques could help here, I'll need visit JWatte posts to watch some HLSL ^^.
    6 - Swap render target
    7 - Do a Draw Call just to bake Depth.
    8 - Get the result Texture and feed the shaders that will use the information.
    9 - Swap RT Back
    10 - Render everything again.

    Or if we could access the DepthStencil Info:

    1 - Copy the Surface that is inside GraphicsDevice.DepthStencilBuffer
    2 - Read the depth info surface like a Texture2D and feed the shaders that will use the information.
    3 - Render.

    I really would love if the XNA team could gift us with a ResolveDepth( ) method like the ResolveBackBuffer( ) since looks like they are the only ones that has access to the DSB Surface.

    Oh... And thank you by the answers ;)

  • 01/07/2009 15:27 In reply to

    Re: Depth Buffer access, why redraw the scene?

    You cannot have a ResolveDepth API, because DirectX9 does not support this functionality.

    This is not a limitation of the XNA Framework specifically, but of the underlying native graphics API and driver model.

    Sure, the hardware has the depth data in some internal format, but this is different on every card, and there is no consistent way for an app to access that data.
    XNA Framework Developer - blog - homepage
  • 01/07/2009 16:35 In reply to

    Re: Depth Buffer access, why redraw the scene?

    Thank you by the explanation, Shawn.


    Well, when I told about a ResolveDepth( ), I meant get the surface content like you do with the BackBuffer "also a surface" with one of the allowed DX color formats I guess.

    Nice to know that is difficult because is difficult to predict how the hardware stored the info (so my question is answered, thanks), but:

    - And if we know exactly the hardware? XBox 360.
    - Checking the DepthStencilBuffer properties, I seen that one of then is "SurfaceFormat" so, I suppose that when this info comes to the XNA GraphicsDevice it was already interpreted to a DX Color Format, regardless how it was stored in hardware.

    You know that D3DX has the D3DXSaveSurfaceToFile( ) method that get any surface and generates an image from it, so when I crossed the DX help with XNA I began to get ideas.

    Please don't get me wrong, is my noobish logic: Surface=>MemorywithColorFormat=>Texture.





     
  • 01/07/2009 16:45 In reply to

    Re: Depth Buffer access, why redraw the scene?

    creasso:
    And if we know exactly the hardware? XBox 360.


    The Xbox hardware is capable of using depth data as a texture, although with some caveats. We chose not to expose this functionality in the XNA Framework, though, because it was not consistent enough across different platforms.

    creasso:
    Checking the DepthStencilBuffer properties, I seen that one of then is "SurfaceFormat" so, I suppose that when this info comes to the XNA GraphicsDevice it was already interpreted to a DX Color Format, regardless how it was stored in hardware.


    DirectX9 defines surface formats for depth data, so you can specify how many bits of precision and stencil you want. But it does not provide any way to read this data back to the CPU or to use it as a texture. The only thing you can do with a depth buffer is to use it for depth testing. I appreciate you might not like that, but that's the way it is...
    XNA Framework Developer - blog - homepage
  • 01/07/2009 16:52 In reply to

    Re: Depth Buffer access, why redraw the scene?

    Shawn Hargreaves:


    The Xbox hardware is capable of using depth data as a texture, although with some caveats. We chose not to expose this functionality in the XNA Framework, though, because it was not consistent enough across different platforms.



    So how about I send you guys some $$$'s, and you add a nice "ResolveDepthStencilBufferOnXbox360ForMJPOnly" method?  If you want you can make the second parameter a string that takes a super-secret password, so that only I can use it.  :P
    Matt Pettineo | DirectX/XNA MVP


    Ride into The Danger Zone | PIX With XNA Tutorial
  • 01/07/2009 18:05 In reply to

    Re: Depth Buffer access, why redraw the scene?

    Nice spoiler! And thank you for share... :D I'll keep this info near to the case in someday I got my fingers on the Pro XDK where maybe this is exposed.

    I understand that we'll look to features by different viewpoints, you like library provider team member will target consistency, while I'm just interested in put my game up fast, so don't get my comments like criticism, I love XNA.

    While keep the Windows compatibility is probably an important goal, you can also consider that many XNA users picked it just because is the most accessible chance to deploy to a next gen console. So, get some stuff that will just work on 360 will be good to many of us. ;)

    Thank you by the answers.
  • 03/07/2009 0:46 In reply to

    Re: Depth Buffer access, why redraw the scene?

    I think you misunderstood what I suggested. I was suggesting you output multiple pixels in the same pixel shader. COLOR0 = first target, COLOR1 = second target, ect. From my experience most computers support at least 3 so 2 shouldn't be a problem (one for your color, other for the depth). Isonormalized depth (depth in the range of 0.0f to 1.0f) will also help you move a lot of your depth based stuff into a scaler quantity and in turn make it easier to manage and work with later. To normalize your depths you could use: depth = vertex position z / (max depth - min depth) before passing the vertex position through the projection matrix (world and view only), or you can pass throught he projection and not factor the max and min depths which would result in some odd jumps in values that show as bands between depths that have a lot of object and ones that dont.
Page 1 of 1 (13 items) Previous Next