【问题标题】:Copying render target data to D3DPOOL_MANAGED?将渲染目标数据复制到 D3DPOOL_MANAGED?
【发布时间】:2013-04-25 03:54:40
【问题描述】:

我是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 方法)...

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

我已经尝试过以下方法:

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

【问题讨论】:

  • 你可以用D3DFMT_A8R8G8B8创建你的渲染目标,只有设备的backbuffer应该用D3DFMT_X8R8G8B8创建。此外,此渲染目标通常可用于渲染,但不能用于锁定操作。您需要锁还是只想将渲染目标渲染到后台缓冲区?
  • 如果我使用D3DFMT_A8R8G8B8 创建它,那么我仍然需要一种方法将其剥离到新的D3DPOOL_MANAGED 纹理中,因为我将不再使用rendertarget 对象并希望释放它使用的任何资源。引擎将纹理和渲染目标视为单独的对象,其中渲染目标存储/消耗更多资源......并且对于渲染,我的应用程序使用纹理对象数组,因此渲染目标仅在初始化期间用于创建新纹理(在像素着色器中) ) 添加到这个D3DPOOL_MANAGED 纹理数组中。
  • 就锁定渲染目标而言...只要我仍然可以(以某种方式)将其数据克隆到新创建的D3DPOOL_MANAGED 纹理中,那么不,它不需要锁定支持。 . 否则,是的。知道如何安全地将这些数据克隆到新纹理中吗?另外,上面的代码对你有用吗?对我来说,它似乎可以正确地将图像保存到磁盘,但不知何故无法在我的应用程序中呈现。
  • 我不知道,为什么你的代码不起作用。您是否尝试过使用StretchRect 来复制您的渲染目标?在我的一个应用程序中,我使用它来获取渲染目标的数据,它运行良好。
  • 根据MSDN documentation(驱动程序支持部分),您不能使用StretchRect 从RT 纹理转到普通纹理。只有屏幕外的普通纹理才能进入常规纹理,甚至不允许从 RT 复制到屏幕外的纯纹理。

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


【解决方案1】:

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。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-04-30
    • 1970-01-01
    • 2015-05-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多