Заперто в D3D11 - PullRequest
       122

Заперто в D3D11

1 голос
/ 24 апреля 2020

Я пытаюсь реализовать идеальный по пикселям алгоритм обнаружения столкновений из онлайн-учебника, но он написан с использованием d3d9. Я пишу свою игру в d3d11, поэтому я хотел бы знать, как лучше ее конвертировать. Исходный код, использующий заблокированные ректы, которые c, ч после исследования я обнаружил, не были в D3D11. Кстати, я использую DirectX TK, поэтому мне нужно преобразовать ShaderResourceView в текстуру. Вот оригинальный код:

int Bird::PixelPerfectCollision(Vector2* birdPoints, Vector2* pipePoints, Renderer& renderer)
{
    // Creation of the bounding rectangles from the SPRITE values 
    // Remember that coordinates start in the upper left corner of the screen 
    //bird
    RECT rect1; 
    rect1.left = (long)birdPoints[4].x;
    rect1.top = (long)birdPoints[0].y;
    rect1.right = (long)birdPoints[2].x;
    rect1.bottom = (long)birdPoints[3].y;
    //pipe
    RECT rect2; 
    rect2.left = (long)pipePoints[0].x;
    rect2.top = (long)pipePoints[0].y;
    rect2.right = (long)pipePoints[1].x;
    rect2.bottom = (long)pipePoints[2].y;
    // Intersection of the bounding rectangles 
    // Up to here the code is just bounding box collision detection 
    RECT dest;

    if (IntersectRect(&dest, &rect1, &rect2))
    {
        ComPtr<ID3D11ShaderResourceView> birdTexSRV = renderer.GetBirdTexture();
        ComPtr<ID3D11ShaderResourceView> pipeTexSRV = renderer.GetPipeTexture();

        // Loking of the textures 
        // In this case the SPRITE object holds the texture to draw 
        // We will access it and invoke the LockRect method of LPDIRECT3DTEXTURE9 
        // The pixels will be saved in each D3DLOCKED_RECT object 
        Microsoft::WRL::ComPtr<ID3D11Resource> resource;
        birdTexSRV->GetResource(resource.GetAddressOf());

        ComPtr<IDirect3DTexture9> birdTex;
        DX::ThrowIfFailed(resource.As(&birdTex));

        D3DLOCKED_RECT rectS1;
        HRESULT hResult = birdTex->LockRect(0, &rectS1, NULL, NULL);

        if (FAILED(hResult))
        {
            MessageBox(0, L"Failed", L"Info", 0);
            return 0;
        }
        Microsoft::WRL::ComPtr<ID3D11Resource> resource;
        pipeTexSRV->GetResource(resource.GetAddressOf());

        ComPtr<IDirect3DTexture9> pipeTex;
        DX::ThrowIfFailed(resource.As(&pipeTex));

        D3DLOCKED_RECT rectS2;
        hResult = pipeTex -> LockRect(0, &rectS2, NULL, NULL);

        if (FAILED(hResult))
        {
            MessageBox(0, L"Failed", L"Info", 0);
            return 0;
        }
        // Get the pointer to the color values 
        // From now on, we will read that pointer as an array
        D3DCOLOR* pixelsS1 = (D3DCOLOR*)rectS1.pBits;
        D3DCOLOR* pixelsS2 = (D3DCOLOR*)rectS2.pBits;
        // We will check the area of the intersected rect (dest) 
        // In this rectangle, we have to check that in the same spot: 
        // A pixel from each texture collide 
        for (int rx = dest.left; rx < dest.right; rx++)
        {
            for (int ry = dest.top; ry < dest.bottom; ry++)
            {
                // Translation from the "dest" rect to sprite1 coordinates 
                int s1x = rx - screenPos.x;
                int s1y = ry - screenPos.y;
                // Translation from the "dest" rect to sprite2 coordinates
                int s2x = rx - pipePoints[0].x; 
                int s2y = ry - pipePoints[0].y;
                // Check the alpha value of each texture pixel 
                // The alpha value is the leftmost byte
                BYTE a = (pixelsS1[s1y * 128 + s1x] & 0xFF000000) >> 24;
                BYTE b = (pixelsS2[s2y * 480 + s2x] & 0xFF000000) >> 24;
                // If both pixels are opaque, we found a collision 
                // We have to unlock the textures and return 
                if (a == 255 && b == 255)
                {
                    birdTex->UnlockRect(0); pipeTex->UnlockRect(0);
                    return 1;
                }
            }
        }
        // If we reached here, it means that we did not find a collision
        birdTex->UnlockRect(0);
        pipeTex->UnlockRect(0);
        return 0;

        return true;
    }
    return 0;
} 

1 Ответ

0 голосов
/ 26 апреля 2020

Если вы хотите столкнуться с процессором, лучше всего дважды создавать текстуры. Первый раз как обычно, а в другой раз как ресурс STAGING. Используйте версию загрузчика Ex и предоставьте ее D3D11_USAGE_STAGING.

ComPtr<ID3D11Resource> birdTexCPU;

...

hr = CreateWICTextureFromFileEx(device, "birdtex.png", 0, 
   D3D11_USAGE_STAGING, 0, D3D11_CPU_ACCESS_READ, 0,
   WIC_LOADER_DEFAULT,
   birdTexCPU.ReleaseAndGetAddressOf(), nullptr);

Конечно, вы можете просто создать текстуру с диска в качестве STAGING, а затем создать копию DEFAULT из нее, используя CopyTexture если вы хотите минимизировать пропускную способность диска.

В этот момент вы можете получить доступ к фактическим данным текстуры в памяти процессора через Map. DirectX Tool Kit имеет вспомогательный класс для того, чтобы он всегда вызывал Unmap.

#include "DirectXHelpers.h"

...

{
    DirectX::MapGuard texdata(context, birdTexCPU.Get(), 0, D3D11_MAP_READ, 0);

    // You have a pointer now from texdata.get();

}

Вы должны захватывать данные текстуры на ЦП в некоторой стандартной памяти вместо На данный момент ресурс Direct3D 11 проще в использовании, но вы можете оставить его в памяти STAGING, если хотите.

...