Я пишу приложение для 3D-моделирования в D3D9, которое я хотел бы сделать максимально совместимым. Это означает использование нескольких аппаратно-зависимых функций, то есть мультисэмплинг. Однако, хотя рендеринг в реальном времени не обязательно должен быть безупречным, мне нужно обеспечить привлекательные снимки экрана, которые без мультисэмплинга выглядят довольно сглаженными и плохими.
Для создания снимков экрана я создаю временную поверхность в памяти, визуализирую сцену на ней один раз, затем сохраняю ее в файл. Моей первой мыслью о том, как я могу добиться захвата сглаживания, было создание моей трафаретной поверхности вне экрана как мультисэмпла, но, конечно, DX не допустит этого, так как само устройство было инициализировано с D3DMULTISAMPLE_NONE.
Для начала, вот пример того, как именно я создаю снимок экрана. Я знаю, что было бы проще просто сохранить буферный буфер уже отрендеренного фрейма, однако мне нужна возможность сохранять изображения с размерами, отличными от фактического окна рендеринга - вот почему я делаю это таким образом. Проверка ошибок, код для восстановления состояния и освобождение ресурса здесь опущены для краткости. m_d3ddev - это мой LPDIRECT3DDEVICE9.
//Get the current pp
LPDIRECT3DSWAPCHAIN9 sc;
D3DPRESENT_PARAMETERS pp;
m_d3ddev->GetSwapChain(0, &sc);
sc->GetPresentParameters(&pp);
//Create a new surface to which we'll render
LPDIRECT3DSURFACE9 ScreenShotSurface= NULL;
LPDIRECT3DSURFACE9 newDepthStencil = NULL;
LPDIRECT3DTEXTURE9 pRenderTexture = NULL;
m_d3ddev->CreateDepthStencilSurface(_Width, _Height, pp.AutoDepthStencilFormat, pp.MultiSampleType, pp.MultiSampleQuality, FALSE, &newDepthStencil, NULL );
m_d3ddev->SetDepthStencilSurface( newDepthStencil );
m_d3ddev->CreateTexture(_Width, _Height, 1, D3DUSAGE_RENDERTARGET, pp.BackBufferFormat, D3DPOOL_DEFAULT, &pRenderTexture, NULL);
pRenderTexture->GetSurfaceLevel(0,&ScreenShotSurface);
//Render the scene to the new surface
m_d3ddev->SetRenderTarget(0, ScreenShotSurface);
RenderFrame();
//Save the surface to a file
D3DXSaveSurfaceToFile(_OutFile, D3DXIFF_JPG, ScreenShotSurface, NULL, NULL);
Вы можете увидеть вызов CreateDepthStencilSurface (), в котором я надеялся заменить pp.MultiSampleType, например, D3DMULTISAMPLE_4_SAMPLES
, но это не сработало.
Моей следующей мыслью было создание совершенно другого LPDIRECT3DDEVICE9 как D3DDEVTYPE_REF
, который всегда поддерживает D3DMULTISAMPLE_4_SAMPLES
(независимо от видеокарты). Однако все мои ресурсы (сетки, текстуры) были загружены в m_d3ddev, мое устройство HAL, поэтому я не мог использовать их для рендеринга сцены под устройством REF. Обратите внимание, что ресурсы могут быть разделены между устройствами под Direct3d9ex (Vista), но я работаю над XP. Поскольку ресурсов довольно много, перезагрузка всего для визуализации этого одного кадра, а затем их выгрузка слишком неэффективны по времени для моего приложения.
Я рассмотрел другие варианты сглаживания изображения после захвата (например, фильтр размытия 3x3), но все они дали довольно дрянные результаты, поэтому я действительно хотел бы попытаться получить сглаженную сцену прямо из D3D, если возможно. ...
Любая мудрость или указатели будут с благодарностью оценены ...
Спасибо!