将渲染目标数据复制到D3DPOOL_MANAGED?

时间:2013-05-01 05:35:31

标签: c++ copy directx textures render-to-texture

我是using an engine,它使用DirectX9。

使用以下方法创建它的渲染目标:

D3DXCreateTexture(
    pD3DDevice, width, height, 1, 
    D3DUSAGE_RENDERTARGET, D3DFMT_X8R8G8B8, 
    D3DPOOL_DEFAULT, &pRT
)


所有其他纹理都是这样创建的:

D3DXCreateTexture(
    pD3DDevice, width, height,
    1, 0, D3DFMT_A8R8G8B8,
    D3DPOOL_MANAGED, &pTex
)

值得注意的是后备缓冲区也是D3DFMT_X8R8G8B8所以我不确定为什么纹理会以不同的方式创建...但我想“如果没有破坏,请不要修复它” 对吗?所有纹理似乎都可以加载/渲染。 有关此引擎如何运作的更多详细信息,here is it's main graphics module's code (主要注意Target_CreateTexture_Create方法)...

但是,在尝试将渲染目标纹理转换为常规纹理时,我在尝试坚持这些规则时遇到了很多麻烦。引擎没有内置功能,渲染目标被视为纹理中的单独对象......反过来,这限制了我实际 USE 任何需要渲染目标的能力(即,像素着色器等)。最终结果是我需要找到一种方法将此渲染目标数据复制到如上所述创建的纹理中,引擎可以使用该纹理而不会发生任何冲突。

我尝试过以下内容:

inline PVOID LockedBits(LPDIRECT3DSURFACE9 surface, UINT w, UINT h, INT* size)
{
    D3DLOCKED_RECT lr;
    RECT rc = {0, 0, w, h};
    surface->LockRect(&lr, &rc, 0);
    if(size) *size = (w*h) * 4;
    return lr.pBits;
}
inline PVOID LockedBits(LPDIRECT3DTEXTURE9 texture, UINT w, UINT h, INT* size)
{
    D3DLOCKED_RECT lr;
    RECT rc = {0, 0, w, h};
    texture->LockRect(0, &lr, &rc, 0);
    if(size) *size = (w*h) * 4;
    return lr.pBits;
}

LPDIRECT3DTEXTURE9 CloneTextureFromTarget(LPDIRECT3DDEVICE9 device, LPDIRECT3DTEXTURE9 target, UINT w, UINT h)
{
    D3DDISPLAYMODE dm;
    device->GetDisplayMode(0, &dm);

    // Create source and destination surfaces and copy rendertarget
    LPDIRECT3DSURFACE9 dstSurf = NULL, srcSurf = NULL;
    device->CreateOffscreenPlainSurface(w, h, dm.Format, D3DPOOL_SYSTEMMEM, &dstSurf, NULL);
    target->GetSurfaceLevel(0, &srcSurf);
    device->GetRenderTargetData(srcSurf, dstSurf);
    SafeRelease(&srcSurf);

    // Create destination texture
    LPDIRECT3DTEXTURE9 dstTexture = NULL;
    D3DXCreateTexture(device, w, h, 1, 0, D3DFMT_A8R8G8B8, D3DPOOL_MANAGED, &dstTexture);

    // Get bits for destination surface and texture
    INT dwSrc, dwDst;
    PVOID pBitsSrc = LockedBits(dstSurf, w, h, &dwSrc);
    PVOID pBitsDst = LockedBits(dstTexture, w, h, &dwDst);

    // Copy bits from surface to texture
    RtlCopyMemory(pBitsSrc, pBitsDst, dwSrc);
    dstTexture->UnlockRect(0);
    dstSurf->UnlockRect();
    SafeRelease(&dstSurf);

    /* Just to double-check if it worked... */
    D3DXSaveTextureToFileA("C:\\outSrc.png", D3DXIFF_PNG, target, NULL);
    D3DXSaveTextureToFileA("C:\\outDst.png", D3DXIFF_PNG, dstTexture, NULL);

    // Return the result
    return dstTexture;
}

此代码的结果是两个纹理都正确保存到磁盘并按预期出现,但拒绝正确呈现...

我做错了吗? 将这些数据完美复制到使用D3DFMT_A8R8G8B8D3DPOOL_MANAGED创建的新纹理的最佳方法是什么?

1 个答案:

答案 0 :(得分:0)

TBH更改您的复制方法如下:

char* pSrc = (char*)pBitsSrc;
char* pDst = (char*)pBitsDst;
int p = 0;
int pMax = w * h;
while( p < pMax )
{
    // Copy B
    *pDst = *pSrc;
    pDst++;
    pSrc++;
    // Copy G
    *pDst = *pSrc;
    pDst++;
    pSrc++;
    // Copy R
    *pDst = *pSrc;
    pDst++;
    pSrc++;
    // Set A
    *pDst = 0xff;
    pDst++;
    pSrc++;
    p++;
}

或者失败,只是将目标纹理创建为D3DFMT_X8R8G8B8。

相关问题