mmd-for-unity-proj / mmd-for-unity

MikuMikuDance for Unity
BSD 3-Clause "New" or "Revised" License
415 stars 83 forks source link

透過材質の描画改善 #30

Closed eral closed 10 years ago

eral commented 10 years ago

透過材質の描画改善

透過する材質の描画を改善しました。 大きく分けて下記の3つの対応が行われています。

個別に解説します。

エッジ付き材質が半透明ソートを無視する不具合の修正

シェーダー付けでレンダーキューの指定が出来ます。 エッジ無し透過シェーダーはTransparentキューなのに対し、エッジ有り透過シェーダーはTransparent+1キューと1テンポ遅延させていました。 これに依り半透明ソートが崩れている様に思いましたので、全てTransparentキューにしました。 多分こちらの方が化ける事が少ない様に思います。

マテリアルの透過判定を最適化

その材質を透過として扱う必要が有るかどうかを判定するには、下記を考慮しなければいけません。

Unityでは1つのシェーダーに非透明と透過を混在させる事が出来ません(と思う…)ので、エッジ周りの透過も考慮する必要があります。 故に下記も考慮しなければいけません。

これらの考慮事項に対応しました。 これで透過判定の誤爆率は大分減るかと思います。

ただし、高速化の為に幾つか簡略化していますのでそれに依る誤爆が発生する可能性は有ります。 高速化の為に行った簡略化は下記と為ります。

個別に解説します。

UV参照に於けるテクセルを全領域行わない

3角形ポリゴンが与えられた場合、其処からは3つのUV座標が取得出来、それらはテクスチャ上で3角形を構成します。 本来ならその3角形に掛かる全てのテクセルについて透過を確認する必要が有ります。 テクスチャ解像度とテクスチャ上の3角形の大きさ(≠3角形ポリゴンの大きさ)に依っては確認するべきテクセルは相当数に上ります。 現在の実装では全テクセルの確認を行っておらず、下記の代表する7点のテクセルのみ確認しています。

UVモーフは0から1迄の値を持ちます。 0の時と1の時に参照する領域は多くの場合違っており、00.001でも違っている可能性があります。 0から1迄の全てのレベルは使用される可能性が有る為、それらで参照するテクセルは全て確認しなければいけません。 現在の実装では6角形での確認は行っておらず、中間レベルを全て無視して01のそれぞれ2つの3角形のみで確認しています。

UVモーフで範囲外レベルを考慮しない

グループモーフを組み合わせればモーフのレベルは1を超える事が出来ます。 しかし現在の実装では、作用するグループモーフを持っていたとしても1を超えた領域は確認しません。

UVモーフを複数持つ場合の組み合わせ計算の無視

複数のUVモーフが同一頂点に対して作用する場合、合算して作用します。 U方向に+0.5するモーフとV方向に+0.5するモーフが有る場合、組み合わせればU+0.5,V+0.5領域を参照出来ますが、現在の実装では確認しません。

カスタムレンダーキュー対応

シェーダー付けでレンダーキューの指定が出来る事は前述しましたが、スクリプト上ではマテリアル単位で設定出来ます。 マテリアル全てに厳密な描画順を設定する事で半透明ソートに依存せず、MMDと同じ登録順で描画する事に対応しました。 ただし後述する欠点の為に変換直後は無効化されています。 有効にするにはMMDEngineのInspectorに在るRender QueueチェックボックスをONにします。

利点

モデル単体で見るとMMDの描画順と完全に一致する為、化ける事はまず発生しなくなります。 化身バレッタ式セルシアナさんを正面から見た場合、半透明ソートでは眉毛と睫毛が欠けますがカスタムレンダーキューではそれも改善されます。

欠点

半透明ソートが効かなくなる為、モデル外の半透明オブジェクトと喧嘩する場合が有ります。 化身バレッタ式セルシアナさんの手前に半透明のCubeを置いた場合、半透明ソートでは正常に映りますがカスタムレンダーキューでは前後関係がおかしく見えます

テストモデル

GRGSIBERIA commented 10 years ago

プルリクありがとうございます.変更によって影響の出るモデルが少なそうなのでマージします.