在direct 3d中支援直接渲染到貼圖,使用手動的方式,還需要建立自己建立depth stencil。在d3dx中提供了ID3DXRenderToSurface接口簡化了render to surface的操作,不再需要自己維護depth stencil。以下是渲染到貼圖的基本步驟:
聲明必要的接口:
CComPtr<ID3DXRenderToSurface> m_renderToSurface;
D3DVIEWPORT9 m_viewport;
CComPtr<IDirect3DTexture9> m_fullScreenTexture;
CComPtr<IDirect3DSurface9> m_fullScreenTextureSurf;
初始化階段
// 建立全屏渲染貼圖
FAILED_THROW_D3DEXCEPTION(D3DXCreateTexture(
pd3dDevice,
pBackBufferSurfaceDesc->Width,
pBackBufferSurfaceDesc->Height,
1,
0, //D3DUSAGE_RENDERTARGET,
D3DFMT_A8R8G8B8,
D3DPOOL_DEFAULT,
&m_fullScreenTexture));
FAILED_THROW_D3DEXCEPTION(m_fullScreenTexture->GetSurfaceLevel(0, &m_fullScreenTextureSurf));
// 建立 RenderToSurface
D3DSURFACE_DESC desc;
FAILED_THROW_D3DEXCEPTION(m_fullScreenTextureSurf->GetDesc(&desc));
FAILED_THROW_D3DEXCEPTION(D3DXCreateRenderToSurface(
pd3dDevice,
desc.Width,
desc.Height,
desc.Format,
TRUE,
D3DFMT_D16,
&m_renderToSurface));
// 儲存一下viewport
pd3dDevice->GetViewport(&m_viewport);
// 清理一下render target,防止alpha綁定問題
HRESULT hr;
V(m_renderToSurface->BeginScene(m_fullScreenTextureSurf, &m_viewport));
V(pd3dDevice->Clear(0, NULL, D3DCLEAR_TARGET, 0x00, 1.0f, 0));
V(m_renderToSurface->EndScene(0));
物體渲染到貼圖
// 将模型渲染到貼圖的surface上
if(SUCCEEDED(m_renderToSurface->BeginScene(m_fullScreenTextureSurf, &m_viewport)))
{
V(pd3dDevice->Clear(0, NULL, D3DCLEAR_TARGET|D3DCLEAR_ZBUFFER, D3DCOLOR_ARGB(0, 66, 75, 121), 1.0f, 0));
...
V(m_renderToSurface->EndScene(0));
}
再将整個貼圖渲染到螢幕
// 将目标貼圖渲染到螢幕上
if(SUCCEEDED(pd3dDevice->BeginScene()))
{
V(pd3dDevice->Clear(0, NULL, D3DCLEAR_TARGET|D3DCLEAR_ZBUFFER, D3DCOLOR_ARGB(0, 66, 75, 121), 1.0f, 0));
// 聲明一個方形的矩形頂點格式
struct VERTEX
{
FLOAT x, y, z, w;
FLOAT u, v;
} vertices[] =
{
{ m_viewport.X, m_viewport.Y, 0.5f, 1.0f, 0.0f, 0.0f, },
{ m_viewport.X + m_viewport.Width, m_viewport.Y, 0.5f, 1.0f, 1.0f, 0.0f, },
{ m_viewport.X, m_viewport.Y + m_viewport.Height, 0.5f, 1.0f, 0.0f, 1.0f, },
{ m_viewport.X + m_viewport.Width, m_viewport.Y + m_viewport.Height, 0.5f, 1.0f, 1.0f, 1.0f, },
};
// 将貼圖以矩形的方式直接渲染到螢幕
V(pd3dDevice->SetFVF(D3DFVF_XYZRHW | D3DFVF_TEX1));
V(pd3dDevice->SetTexture(0, m_fullScreenTexture));
V(pd3dDevice->SetTextureStageState( 0, D3DTSS_COLOROP, D3DTOP_SELECTARG1));
V(pd3dDevice->SetTextureStageState( 0, D3DTSS_COLORARG1, D3DTA_TEXTURE ));
V(pd3dDevice->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, _countof(vertices) - 2, vertices, sizeof(vertices[0])));
V(pd3dDevice->EndScene());
}
總結:
渲染到貼圖有很多實際作用,如實作畫中畫,但常用的是用來實作景深的一種手段,現将場景渲染到貼圖并儲存對應的深度值,在将貼圖渲染到螢幕的時候,對貼圖進行抖動模糊,并根據深度來決定模糊插值,進而實作模拟“景深”的一種手段。
但是渲染到貼圖本身也有很多缺陷,其性能會下降大緻2/3,且最為重要的是“不支援multisample”,目前普遍的解決方法(針對dx9)就是使用IDirect3DDevice9::CreateRenderTarget和IDirect3DDevice9::StretchRect