XNA 3.1 Сохранение буфера глубины до его очистки - PullRequest
0 голосов
/ 01 декабря 2011

Я пытаюсь обойти автоматическую очистку буфера глубины в XNA 3.1 при переключении целей рендеринга путем копирования IDirect3DSurface9 из буфера глубины до переключения целей рендеринга, а затем восстановления буфера глубины на более позднем этапе.

В коде метод 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;
    }

1 Ответ

1 голос
/ 12 января 2012

XNA3.1 не очистит ваш буфер глубины-трафарета при изменении целей рендеринга, однако разрешит его (так что он непригоден для тестов глубины), если вы не будете осторожны с изменениями целей рендеринга.

Например:

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

Будет вызывать разрешение буфера глубины трафарета, но следующее не будет:

SetRenderTarget(someRenderTarget)
DrawStuff()
SetRenderTarget(someOtherRenderTarget)

Я не уверен, почему это происходит с XNA3.1 (и более ранними версиями), но с тех пор, как я понял это, я смог сохранить тот же буфер глубины-трафарета живым благодаря многим изменениям цели рендеринга, даже операциям очистки как Пока очистка указала только ClearOptions.Target.

...