描画に関係しないシステム的な部分。ロードのインターフェイス。(空デカール)あと、実行ファイル及び、プロジェクトファイルが入っています。■やっていること影が汚くなる原因を考えましょう。ピクセル単位で深度値の判定を間違える場合があることです。これを回避するために、バイアスをかませたり、裏面の深度マップを使う方法が考えられています。これらの方法には欠点があり、バイアスをかけた場合には、影の形がずれます。裏面の深度マップを使う方法では、やはり裏面の部分の判定時にちらつきが出てしまいます。2番目に置かれたポリゴンの深度の平均を取るアイデアが提唱されています。(誤差も大きくなるので)大変なので、さらに一ひねりした方法を考えました。レンダリングしようとするピクセルから遠いほうの深度を深度判定に用いる」という方法です。この方法によって、現在手広く出回っているグラフィックチップでも、よりよい影の判定が可能になります。ちなみに、手前から2番目にあるポリゴンを描画するのは、実は簡単です。2番目に置かれたポリゴンの深度が分かります。緑の部分は、赤い部分の深度値を判定に用います。この方法にも欠点があります。それは、車のウイングのような薄い部分を描画するときには、やはりちらつきが出てしまうことです。これに関しては、よい解決方法が思い浮かばなかったので、放置しています。一つの影が汚くなる原因は、テクスチャーの解像度です。ライトの方向とカメラの方向は違うので、影バッファが影を生成するための情報は十分ではありません。影マップ特有の量子化ノイズを除去します。この結果、半影ができます。レンダリング回数が増えてしまうので、今回は簡易的なテクスチャをずらす方法でレンダリングします。この方法でも、ノイズを取りきれない部分もありますので、さらに改良を加えていく楽しみが残っています。結果的に、レンダリング工程は次のようになります。1パス目に、表面の深度をレンダリングします。同時に、色のα成分にも深度を格納します。この色は、1番手前のポリゴンと2番目のポリゴンとどちらが近いのかを判定するために用います。2パス目に、裏面の深度をレンダリングします。このときも、色成分に深度を格納します。赤色成分に深度を保存します。深度バッファは、1パス目と2パス目で違うバッファを使いますが、フレームバッファは同じバッファを使います。3パス目から6パス目は、上下左右に少しずつずらしながら、影になる部分を加算合成で合成します。このとき、3パス目は深度を書き込みますが、以降は3パス目の深度情報を使って(深度バッファを書き込まないで)レンダリングします。前面だけの判定で済むようにしたからです。一枚のフルスクリーンポリゴンで処理するので、今回行なう処理よりもはるかに効率が良くなっています。最後の7パス目は、求まった影の部分をシーンから減算して影になる部分を求めます。なじませるようにしました。■深度作成のパス最初の工程は、深度バッファの作成になります。この工程では、表示する面を表と裏を切り替えて深度バッファを更新します。同時に、D3DRS_COLORWRITEENABLEを使って、アルファ成分と赤成分だけに書き込みをします。いうのは、独自に設定したタイプで、DrawModelの中では、次のような場合分けが行なわれています。}モデルを表示するシェーダは次のとおりです。座標変換は、普通に座標変換して、深度をいろ情報として出力します。c16.yピクセルシェーダでは、単純に入力された色をフレームバッファに出力します。v0■影作成のパス次に、深度バッファの値と、描画しようとするポリゴンの深度を比較して、どの部分が影になるか算出します。方法としては、レンダリング用の1つのターゲットを用意して、そのテクスチャにテスト結果を加算合成します。それぞれのテストでは、深度バッファの値を少しずらします。(ここが遅延シェーディング的な考え方をしている部分です)。使って、同じ深度でも仮想的に手前に来るように処理しました。);実際に深度バッファの座標をずらすのは、射影空間からテクスチャ座標系への変換で行ないます。それぞれの工程に応じて、16箱サンプリングと同様のずらし方で斜めにずらします。mScaleBias;頂点シェーダでは、最初の工程と同様に座標や色を作成し、テクスチャ座標を追加の情報として座標変換します。表と裏で遠いほうがどちらになるかを判定し、判定した深度バッファによる影の判定の結果を採用します。-v0の命令で、深度マップの色による深度と、色レジスタに入力された現在の深度の差をとります。t0命令で、各係数に関する差の2乗を作ります。これで、符号によらない判定ができるようになります。0.5は、後のcnd命令で比較のために使用する値です。cnd命令で使用するのは、α成分ですから、その後の命令で、α成分に赤色成分を代入します。c0見て分かるように、内積計算を使って、α成分に代入しました。赤色の成分だけが抽出できます。その後に、いよいよ比較命令を使って深度バッファを選びます。裏面の深度バッファによる判定を採用します。小さければ、その逆です。最後に、得られた影の情報をスケーリングして、影の濃さが飽和しないように調整します。c1■最終的な合成のパス最後の工程では、得られた影の部分を乗算して、最終的なレンダリング結果を作ります。呼び出しの部分では、先ほど作成したレンダリング結果をテクスチャにして普通にレンダリングします。lpD3DDev->SetPixelShader(0);頂点シェーダでは、普通にレンダリングします。色の成分0に平行光源の拡散光を入れ、色の成分1に環境色の強さを入れます。テクスチャ座標に関しては、普通のテクスチャと、影の部分を記したマップの2つを設定します。一度環境色の強さを足すことによって、一番暗い部分の濃さを環境色の濃さに抑えます。後は、モデルの色を求めて影の濃さを乗算すると、最終的な絵が出来上がります。陰をつける■最後にまだ、車の後ろの部分が陰になるときに縞が見えてしまいますね。これ以上は、オブジェクトごとに影マップを作らないと厳しいなぁ。今回の方法は、7パス使うので、現在のハードウェアでは現実的でない方法です。深度を作成する部分や影を抽出する部分が1パスになるので、もう少し現実的になるでしょうか。遠い面を判定に使うのは我ながら面白いアイデアだと思うので、他の応用例を考えてみたいと思います。もどるimagire@gmail.com。