古い質問に対する新しい回答ですが、私はこれに出くわし、この問題に遭遇したときに他の誰かがそれに出くわした場合に備えて回答を提供すると思いました。これは、私のラッパーとその関数の簡素化されたバージョンを使用したソリューションです。
レンダラーに複数のレイヤーがあり、そのうちの 1 つがジオメトリ レイヤーであるゲームがあります。レンダリングするときは、すべてのレイヤーを繰り返し処理し、それらの Draw 関数を呼び出します。各レイヤーには、RenderTarget ラッパーの独自のインスタンスがあります。レイヤーが描画すると、そのレンダー ターゲットが「アクティブ化」され、バッファーがアルファにクリアされ、シーンが描画されてから、そのレンダー ターゲットが「非アクティブ化」されます。すべてのレイヤーがレンダー ターゲットに描画された後、これらのレンダー ターゲットのすべてがバックバッファーに結合され、最終的なイメージが生成されます。
GeometryLayer::Draw
* このレイヤーが使用するレンダー ターゲットをアクティブにする
* 必要なレンダリング ステートを設定する
* バッファーをクリアする
* ジオメトリ
を描画する * このレイヤーが使用するレンダー ターゲットを非アクティブにする
void GeometryLayer::Draw( const math::mat4& viewProjection )
{
m_pRenderTarget->Activate();
pDevice->SetRenderState(D3DRS_ALPHABLENDENABLE,TRUE);
pDevice->SetRenderState(D3DRS_SRCBLEND,D3DBLEND_SRCALPHA);
pDevice->SetRenderState(D3DRS_DESTBLEND,D3DBLEND_INVSRCALPHA);
pDevice->Clear(0,0,D3DCLEAR_TARGET,m_clearColor,1.0,0);
pDevice->BeginScene();
pDevice->Clear(0,0,D3DCLEAR_ZBUFFER,0,1.0,0);
for(auto it = m->visibleGeometry.begin(); it != m->visibleGeometry.end(); ++it)
it->second->Draw(viewProjection);
pDevice->EndScene();
m_pRenderTarget->Deactivate();
}
私の RenderTarget ラッパーには、描画先のテクスチャを生成するために D3DXCreateTexture で使用される IDirect3DTexture9* (m_pTexture) が含まれています。また、テクスチャによって提供される IDirect3DSurface9* (m_pSurface) も含まれています。また、別の IDirect3DSurface9* (m_pMSAASurface) も含まれています。
私の RenderTarget の初期化には、マルチサンプリングを有効にするオプションがあります。このオプションがオフの場合、m_pMSAASurface は nullptr に初期化されます。このオプションをオンにすると、IDirect3DDevice9::CreateRenderTarget 関数を使用して m_pMSAASurface が作成され、現在のマルチサンプリング設定が 4 番目と 5 番目の引数として指定されます。
RenderTarget::Init
* テクスチャを作成します
* テクスチャからサーフェスを取得します (サーフェスの参照カウントに追加します)
* MSAA の場合、msaa 対応のサーフェスを作成します
void RenderTarget::Init(const int width,const int height,const bool enableMSAA)
{
m_bEnableMSAA = enableMSAA;
D3DXCreateTexture(pDevice,
width,
height,
1,
D3DUSAGE_RENDERTARGET,
D3DFMT_A8R8G8B8,
D3DPOOL_DEFAULT,
&m_pTexture;
);
m_pTexture->GetSurfaceLevel(0,&m_pSurface);
if(enableMSAA)
{
Renderer::GetInstance()->GetDevice()->CreateRenderTarget(
width,
height,
D3DFMT_A8R8G8B8,
d3dpp.MultiSampleType,
d3dpp.MultiSampleQuality,
false,
&m_pMSAAsurface,
NULL
);
}
}
この MSAA 設定がオフの場合、RenderTarget::Activate は m_pSurface をレンダー ターゲットとして設定します。この MSAA 設定がオンの場合、RenderTarget::Activate は m_pMSAASurface をレンダー ターゲットとして設定し、マルチサンプリング レンダー ステートを有効にします。
RenderTarget::Activate
* 現在のレンダー ターゲットを格納します (そのサーフェスの参照カウントに追加します)
* MSAA でない場合、サーフェスを新しいレンダー ターゲットとして
設定します * MSAA の場合、msaa サーフェスを新しいレンダー ターゲットとして設定し、msaa レンダリング ステートを有効にします
void RenderTarget::Activate()
{
pDevice->GetRenderTarget(0,&m_pOldSurface);
if(!m_bEnableMSAA)
{
pDevice->SetRenderTarget(0,m_pSurface);
}
else
{
pDevice->SetRenderTarget(0,m_pMSAAsurface);
pDevice->SetRenderState(D3DRS_MULTISAMPLEANTIALIAS,true);
}
}
この MSAA 設定がオフの場合、RenderTarget::Deactivate は単に元のレンダー ターゲットを復元します。この MSAA 設定がオンの場合、RenderTarget::Deactivate は元のレンダー ターゲットも復元しますが、m_pMSAASurface を m_pSurface にコピーします。
RenderTarget::Deactivate
* MSAA の場合、MSAA レンダリング ステートを無効にする
* 以前のレンダー ターゲットを復元する
* 以前のレンダー ターゲットの参照カウントを削除する
void RenderTarget::Deactivate()
{
if(m_bEnableMSAA)
{
pDevice->SetRenderState(D3DRS_MULTISAMPLEANTIALIAS,false);
pDevice->StretchRect(m_pMSAAsurface,NULL,m_pSurface,NULL,D3DTEXF_NONE);
}
pDevice->SetRenderTarget(0,m_pOldSurface);
m_pOldSurface->Release();
m->pOldSurface = nullptr;
}
後でレンダラーがジオメトリ レイヤーに RenderTarget テクスチャを要求して、他のレイヤーと組み合わせると、そのテクスチャには m_pMSAASurface からコピーされた画像が含まれます。アルファ チャネルを容易にするフォーマットを使用していると仮定すると、このテクスチャは、複数のレイヤーのレンダー ターゲットで行っているように、他のテクスチャとブレンドできます。