я используя двигатель который использует 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_Create
а также Texture_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_A8R8G8B8
а также D3DPOOL_MANAGED
?
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.
Других решений пока нет …