2

私はD3D9で3Dモデリングアプリケーションを作成しており、可能な限り広く互換性を持たせたいと考えています。これは、ハードウェアに依存する機能、つまりマルチサンプリングをほとんど使用しないことを意味します。ただし、リアルタイムレンダリングは完璧である必要はありませんが、見栄えの良い画面キャプチャを提供する必要があります。マルチサンプリングを行わないと、エイリアシングが発生し、見栄えが悪くなります。

画面キャプチャを作成するには、メモリ内に一時的なサーフェスを作成し、シーンを1回レンダリングしてから、ファイルに保存します。アンチエイリアスキャプチャを実現する方法について最初に考えたのは、オフスクリーンのステンシルサーフェスをマルチサンプルとして作成することでしたが、デバイス自体がD3DMULTISAMPLE_NONEで初期化されていたため、もちろんDXではそれができませんでした。

まず、スクリーンキャプチャを作成する方法のサンプルを次に示します。すでにレンダリングされたフレームのバックバッファを保存する方が簡単なことはわかっていますが、実際のレンダリングウィンドウとは異なるサイズの画像を保存する機能が必要です。そのため、この方法で保存します。エラーチェック、状態を復元するためのコード、およびリソースの解放は、簡潔にするためにここでは省略されています。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をieD3DMULTISAMPLE_4_SAMPLESに置き換えることができると期待していた場所ですが、機能しませんでした。

私の次の考えは、(ビデオカードに関係なく)D3DDEVTYPE_REF常にサポートする、まったく異なるLPDIRECT3DDEVICE9を作成することでした。D3DMULTISAMPLE_4_SAMPLESただし、すべてのリソース(メッシュ、テクスチャ)がHALデバイスであるm_d3ddevにロードされているため、REFデバイスでシーンをレンダリングするためにそれらを使用することはできませんでした。Direct3d9ex(Vista)ではデバイス間でリソースを共有できますが、私はXPで作業していることに注意してください。非常に多くのリソースがあるため、この1つのフレームをレンダリングするためにすべてをリロードしてからアンロードすることは、私のアプリケーションにとって時間効率が悪すぎます。

キャプチャ後に画像をアンチエイリアスするための他のオプション(つまり、3x3ブラーフィルター)を調べましたが、それらはすべてかなりひどい結果を生成したので、可能であれば、D3Dからアンチエイリアスされたシーンを取得してみてください。

どんな知恵や指針も大歓迎です...

ありがとう!

4

3 に答える 3

3

より大きなバッファにレンダリングしてスケールダウンするか、ジッタのあるバッファを組み合わせることによるスーパーサンプリングがおそらく最善の策です。複数のジッターバッファを組み合わせると、特定の数のサンプルに対して最高の品質が得られます(通常のグリッドよりも、同じ数のサンプルを複数の解像度でレンダリングしてスケールダウンすることで得られます)が、複数のレンダリングパスのオーバーヘッドが発生します。ただし、レンダリングターゲットのサポートされる最大サイズに制限されないという利点があり、ほぼ任意のレベルのAAを選択できます(ただし、多くのジッターバッファーを組み合わせる場合は、精度の問題に注意する必要があります)。

opengl.orgの記事「AntialiasingwithAccumulationBuffer」では、ジッタのあるサンプリング用に射影行列を変更する方法について説明しています(OpenGLですが、計算は基本的に同じです)。AlexanderKellerとWolfgangHeidrichによる論文「InterleavedSampling」は、さらに多くのレンダリングパスを犠牲にして、より良いサンプリングパターンを提供する手法の拡張について説明しています。リンクを提供しないことについて申し訳ありません-新しいユーザーとして、私は回答ごとに1つのリンクしか投稿できません。Googleはあなたのためにそれらを見つける必要があります。

レンダリングのルートをより大きなバッファとダウンサンプリングに移動したいが、最大許容レンダリングターゲットサイズによって制限されたくない場合は、ここで説明するように、中心から外れた投影行列を使用してタイル画像を生成できます。

于 2009-07-16T01:01:59.213 に答える
1

幅と高さの2倍(つまり、サイズの4倍)のテクスチャにいつでもレンダリングして、それをスーパーサンプリングすることができます。

確かに、カードがバックバッファの4倍のサイズのテクスチャを作成できない場合でも問題が発生します...

編集:頭に浮かぶ別の方法があります。

ビューマトリックスに小さなジッターを付けてフレームをn回繰り返すと、必要な数の画像を生成でき、後でそれらを合計して、非常に高度なアンチエイリアス処理された画像を形成できます。ボーナスは、画像をレンダリングできるすべてのマシンで動作することです。明らかに、それは遅いです。それでも、256xAAは、これを行うと本当に見栄えがします。

于 2009-07-14T08:13:33.997 に答える
0

この記事http://msdn.microsoft.com/en-us/library/bb172266(VS.85).aspxは、レンダリング状態フラグD3DRS_MULTISAMPLEANTIALIASを使用してこれを制御できることを示唆しているようです。アンチエイリアスを有効にしてデバイスを作成できますが、このレンダリング状態フラグを使用して、画面レンダリングではオフにし、オフスクリーンレンダリングではオンにしますか?

私はこれを自分で試したことはありません。

于 2009-07-15T07:19:47.607 に答える