goo blog サービス終了のお知らせ 

暇人の反省会というなの暇つぶし

写真とかがメイン(のはず)。とりあえず、楽しんでいただければ光栄です。

Zソート...

2011年02月07日 00時20分51秒 | その他どうでもいいこと
モデラーとか作っていると、範囲を3Dで表示するために半透明のオブジェクトを良く描画します。

DirectXはZバッファ法です。
Zバッファ法では、ピクセルに点が描画されるとき、同時にその時点での一定のルールに沿った値(通常はカメラからの距離)も保存しておき、次から同じ場所に書き込まれるときは、その値と比較して描画するかしないかを決めています。
これがあるために、重なったポリゴンはちゃんと手前だけが描画されるわけです。

それとは別の方式にZソート法というものがありんす。
こちらは奥にあるポリゴンから手前に向けて描画するという方式のもので、ポリゴンのZ値に応じてソートしてから描画するものです。

現在ではZソート法は余り効率がよろしくないので、リアルタイムで処理する必要があるゲームにおいては滅多なことでは使われません。
Zソート自体はオブジェクトをまるまるクリップする場合や、複雑なピクセルシェーダーによる処理負担を軽減させるために使うことはあるのですが、描画処理それそのもののために使われることは非常に珍しいです。

然し。
Zバッファ法では透過オブジェクトの描画はそのままではうまくいきません。
透明のオブジェクトであっても、Z値は書き込まれるため、先に半透明の物体が手前に表示されてしまうと、その後ろにオブジェクトが描画されてもそこはクリップされてしまうのです。
だから半透明な窓の中には何も描画されていなかった...なんてことが普通に起きます。

それを避ける方法は単純に、透過オブジェクトを後から描画すれば言いというだけ。
しかし、それでも問題が起きます。
今度は透過オブジェクトが重なる場合、先に手前の透過オブジェクトが描画されてしまうと、当然のことながらその奥の透過オブジェクトが描画できません。

じゃぁ、どうするのか。
ここでZソート法です。
透過オブジェクトをZソートするわけです。
奥の透過オブジェクトから描画していけば重なりが表現できます。

しかしさらに問題があります。
それが全体が透明なオブジェクの描画です。
つまり、これまでのZソートはメッシュ単位で行っていました。。
出ないと何万個もあろうかというポリゴン全てをソートしなければならなくなるためです。
しかし、これではオブジェクト(メッシュ)内のZソートが出来ません。
そのため、全部透明なオブジェクトとかではうまいこと透過できません。
オブジェクト内のポリゴンの描画順序によって、薄い部分(重ならなかったところ)と濃い部分(重なった部分)が混在します。
同じように透過オブジェクト同士が重なった部分がうまく表現できません。
いったいどうすればいいのか。


そんな時にはこれ。
Direct3DのSetRenderingStateの項目にはこんなのがあります。

SetRenderState(D3DRS_ZWRITEENABLE, FALSE);

これは、「Zバッファの比較は行う」が「Zバッファへの書き込みは行わない」というものです。
つまり、先にZバッファに書き込みをした不透明オブジェクトの後に、このレンダリングステートを設定したアルファぶれんディングを行えば万事解決するわけです。

.
.
.

で、Zソートってなんだったんでしょうか?(苦笑
私の5時間を返してくださいMSDN。(涙
MSDNの説明は見づらいんですよね。
すっかりZバッファは有効化無効化しか出来ないのかと思っていました。
疲れた...。

おまけ↓
モデルは初めてのメタセコというサイトで見かけたサンプルモデルです。
そろそろ自分でもモデリングしなきゃなぁーと思いつつ腰が上がらない今日この頃。


またアニメ調エンジンを改造してます。
距離によるエッジ処理を高精度化したので前髪とかの処理が比較的はっきりしました。

エッジを滑らかにする方法を色々考えたんですが、やっぱりアンチエイリアジングに頼るしかなさそうです。
あれはソフトウェア的に実装するより、ハードウェアにやってもらったほうが処理が早いので、諦めました。
エッジをぼかしてみたりしたんですけど、どうしても眠い絵になるだけで綺麗にはならないんですよね。
なんか良い方法があったら実装しようとは思いますけど、とりあえずはここまでですね。

最新の画像もっと見る

コメントを投稿