Я использую движок, использующий 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
, поэтому я не уверен, почему текстуры создаются по-другому... но я полагаю, "если он не сломан, не чините его", правильно? Все текстуры загружаются/отрисовываются нормально. Для получения более подробной информации о том, как работает этот движок, здесь его основной графический модуль code.
(в основном обратите внимание на методы 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
?
D3DFMT_A8R8G8B8
, только задний буфер устройства должен быть создан с помощьюD3DFMT_X8R8G8B8
. Более того, этот rendertarget обычно можно использовать для рендеринга, но не для блокирующих операций. Нужна ли вам блокировка или вы хотите отрендерить цель рендеринга только в резервный буфер? - person Gnietschow   schedule 01.05.2013D3DFMT_A8R8G8B8
, мне все равно потребуется средство для его удаления в новую текстуруD3DPOOL_MANAGED
, поскольку я больше не буду использовать объект rendertarget и хотел бы освободить любые ресурсы, которые он использует. Движок обрабатывает текстуры и цели рендеринга как отдельные объекты, где цели рендеринга хранят/потребляют больше ресурсов... А для рендеринга мое приложение использует массив объектов текстуры, поэтому цель рендеринга просто используется во время инициализации для создания новых текстур (в пиксельном шейдере). ), чтобы добавить к этому массивуD3DPOOL_MANAGED
текстур. - person RectangleEquals   schedule 01.05.2013D3DPOOL_MANAGED
, тогда нет, поддержка блокировки не требуется... В противном случае да, требуется. Любая идея, как я могу безопасно клонировать эти данные в новую текстуру? Кроме того, приведенный выше код работает для вас? Для меня кажется, что изображение правильно сохраняется на диск, но почему-то не отображается в моем приложении. - person RectangleEquals   schedule 01.05.2013StretchRect
, чтобы скопировать ваш rendertarget? В одном из моих приложений я использовал его для получения данных цели рендеринга, и он работал хорошо. - person Gnietschow   schedule 01.05.2013StretchRect
для перехода от текстуры RT к обычной текстуре. В обычную текстуру могут переходить только закадровые плоские текстуры, а копирование из RT в закадровый плайн даже не позволяет. - person RectangleEquals   schedule 02.05.2013