D3D11中的锁定矩形

问题描述 投票:1回答:1

我正在尝试从在线教程中实现像素完美碰撞检测算法,但是它是使用d3d9编写的。我正在d3d11中编写游戏,所以我想知道转换它的最佳方法。原始代码使用了锁定的rects,研究后发现我不在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;
} 
c++ directx collision-detection directx-11 directxtk
1个回答
0
投票

如果要在CPU上进行碰撞,最好的选择是两次创建纹理。第一次正常,另一次作为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);

当然,如果您想最小化磁盘带宽,则可以使用CopyTexture从磁盘上创建纹理,然后从其创建DEFAULT副本。

此时,您可以通过Map访问CPU内存中的实际纹理数据。 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资源中捕获CPU上的纹理数据,因为它更易于使用,但是如果需要,您可以将其保留在STAGING内存中。

© www.soinside.com 2019 - 2024. All rights reserved.