XNA 3.1 在清除之前保留深度缓冲区

发布于 2024-12-19 07:03:10 字数 1553 浏览 3 评论 0原文

我试图通过在切换渲染目标之前从深度缓冲区复制 IDirect3DSurface9 来解决 XNA 3.1 在切换渲染目标时自动清除深度缓冲区的问题,然后在稍后恢复深度缓冲区。

在代码中,getDepthBuffer方法是指向IDirect3DDevice9 GetDepthStencilBuffer函数的指针。指向该方法的指针似乎是正确的,但是当我尝试获取 IDirect3DSurface9 指针时,它返回异常(0x8876086C - D3DERR_INVALIDCALL)。 surfacePtr 指针最终指向 0x00000000。

知道为什么它不起作用吗?关于如何解决它有什么想法吗?

代码如下:

    public static unsafe Texture2D GetDepthStencilBuffer(GraphicsDevice g)
    {
        if (g.DepthStencilBuffer.Format != DepthFormat.Depth24Stencil8)
        {
            return null;
        }

        Texture2D t2d = new Texture2D(g, g.DepthStencilBuffer.Width, g.DepthStencilBuffer.Height, 1, TextureUsage.None, SurfaceFormat.Color);
        FieldInfo f = typeof(GraphicsDevice).GetField("pComPtr", BindingFlags.NonPublic | BindingFlags.GetField | BindingFlags.Instance);
        object o = f.GetValue(g);
        void* devicePtr = Pointer.Unbox(f.GetValue(g));
        void* getDepthPtr = AccessVTable(devicePtr, 160);
        void* surfacePtr;

        var getDepthBuffer = (GetDepthStencilBufferDelegate)Marshal.GetDelegateForFunctionPointer(new IntPtr(getDepthPtr), typeof(GetDepthStencilBufferDelegate));
        var rv = getDepthBuffer(&surfacePtr);

        SetData(t2d, 0, surfacePtr, g.DepthStencilBuffer.Width, g.DepthStencilBuffer.Height, (uint)(g.DepthStencilBuffer.Width / 4), D3DFORMAT.D24S8);
        Marshal.Release(new IntPtr(devicePtr));
        Marshal.Release(new IntPtr(getDepthPtr));
        Marshal.Release(new IntPtr(surfacePtr));
        return t2d;
    }

I'm trying to get around XNA 3.1's automatic clearing of the depth buffer when switching render targets by copying the IDirect3DSurface9 from the depth buffer before the render targets are switched, then restore the depth buffer at a later point.

In the code, the getDepthBuffer method is a pointer to the IDirect3DDevice9 GetDepthStencilBuffer function. The pointer to that method seems to be correct, but when I try to get the IDirect3DSurface9 pointer it returns an exception (0x8876086C - D3DERR_INVALIDCALL). The surfacePtr pointer ends up pointing to 0x00000000.

Any idea on why it is not working? And any ideas on how to fix it?

Heres the code:

    public static unsafe Texture2D GetDepthStencilBuffer(GraphicsDevice g)
    {
        if (g.DepthStencilBuffer.Format != DepthFormat.Depth24Stencil8)
        {
            return null;
        }

        Texture2D t2d = new Texture2D(g, g.DepthStencilBuffer.Width, g.DepthStencilBuffer.Height, 1, TextureUsage.None, SurfaceFormat.Color);
        FieldInfo f = typeof(GraphicsDevice).GetField("pComPtr", BindingFlags.NonPublic | BindingFlags.GetField | BindingFlags.Instance);
        object o = f.GetValue(g);
        void* devicePtr = Pointer.Unbox(f.GetValue(g));
        void* getDepthPtr = AccessVTable(devicePtr, 160);
        void* surfacePtr;

        var getDepthBuffer = (GetDepthStencilBufferDelegate)Marshal.GetDelegateForFunctionPointer(new IntPtr(getDepthPtr), typeof(GetDepthStencilBufferDelegate));
        var rv = getDepthBuffer(&surfacePtr);

        SetData(t2d, 0, surfacePtr, g.DepthStencilBuffer.Width, g.DepthStencilBuffer.Height, (uint)(g.DepthStencilBuffer.Width / 4), D3DFORMAT.D24S8);
        Marshal.Release(new IntPtr(devicePtr));
        Marshal.Release(new IntPtr(getDepthPtr));
        Marshal.Release(new IntPtr(surfacePtr));
        return t2d;
    }

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

久随 2024-12-26 07:03:10

XNA3.1 在更改渲染目标时不会清除深度模板缓冲区,但如果您不小心更改渲染目标,它会解决它(以便它无法用于深度测试)。

例如:

SetRenderTarget(someRenderTarget)
DrawStuff()
SetRenderTarget(null)
SetRenderTarget(someOtherRenderTarget)

将导致深度模板缓冲区被解析,但以下不会:

SetRenderTarget(someRenderTarget)
DrawStuff()
SetRenderTarget(someOtherRenderTarget)

我不确定为什么 XNA3.1(和早期版本)会发生这种情况,但自从弄清楚这一点以来,我一直能够保留相同的深度模板缓冲区可以通过许多渲染目标更改而存活,即使是清除操作,只要清除指定的 ClearOptions.Target 即可。

XNA3.1 will not clear your depth-stencil buffer upon changing render targets, it will however resolve it (so that it's unusable for depth tests) if you are not careful with your render target changes.

For example:

SetRenderTarget(someRenderTarget)
DrawStuff()
SetRenderTarget(null)
SetRenderTarget(someOtherRenderTarget)

Will cause the depth-stencil buffer to be resolved, but the following will not:

SetRenderTarget(someRenderTarget)
DrawStuff()
SetRenderTarget(someOtherRenderTarget)

I'm unsure why this happens with XNA3.1 (and earlier versions), but ever since figuring that out I've been able to keep the same depth-stencil buffer alive through many render target changes, even Clear operations as long as the clear specified ClearOptions.Target only.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文