1

我正在使用使用 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如此,所以我不确定为什么纹理的创建方式不同......但我想“如果它没有坏,就不要修复它”,对吧?所有纹理似乎都可以很好地加载/渲染。有关此引擎如何运行的更多详细信息,这是它的主要图形模块的代码
(主要注意Target_CreateandTexture_Create方法)...

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

我尝试过类似以下的方法:

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_A8R8G8B8and创建的新纹理中的最佳方法是什么D3DPOOL_MANAGED

4

1 回答 1

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。

于 2013-05-09T17:48:38.457 回答