影の実装がしたい!!
私はこれまでUIやモデルなどのグラフィック表現などを実装をしてきてゲームのグラフィック等に個人的に力を入れてきましたが、よりリアルな表現をしたいと思い影を実装したくなりました
というわけで、本記事では私が納得のいく影の実装を目指して努力した内容をつづろうと思います。(今回の記事では完結しないのでシリーズものになります)
まずは私が普段使っているDXライブラリでどう実装できそうか調べてみようと思います
影の実装は難しいのか
DXライブラリのリファレンスを調べてみたらMakeShadowMapという関数が見つかりました。これを使ったらうまいことできそうですね......。
公式のサンプルを参照しつつ実際に実装してみたのがこちらになります
なんとまぁ簡単にできちゃいました。いちよ公式の関数を用いて何をしたかだけ解説します。
<事前準備>
// シャドウマップのハンドルを生成
shadowMapHandle_ = MakeShadowMap(SHADOW_SCALE_X, SHADOW_SCALE_Y);
// シャドウマップが想定するライトの方向を設定
SetShadowMapLightDirection(shadowMapHandle_, GetLightDirection());
// シャドウマップに描画する範囲を設定
SetShadowMapDrawArea(shadowMapHandle_, SHADOW_MAP_MIN_AREA, SHADOW_MAP_MAX_AREA);
SHADOW_SCALEはどちらとも4096にしています。(どうやら値は2の累乗にする必要があるみたいです)この値を大きくすると影のクオリティがあがります。256とかにしたら影の角が丸くなってました。
<描画処理>
// シャドウマップへの描画の準備
ShadowMap_DrawSetup(shadowMapHandle_);
// ステージの描画
stage_->Draw();
// シャドウマップへの描画を終了
ShadowMap_DrawEnd();
// 描画に使用するシャドウマップを設定
SetUseShadowMap(0, shadowMapHandle_);
// ステージの描画
stage_->Draw();
// 描画に使用するシャドウマップの設定を解除
SetUseShadowMap(0, -1);
影を描画するモデルをShadowMap_DrawSetupからShadowMap_DrawEndの間で描画して、その後影を反映させるモデルを描画する流れになっています。なので、スカイドームは影を映す必要がないのでこのフローには含めていないです。
実装して思ったこと
今回DXライブラリの関数を用いることで簡単に影を実装することが出来ました。なので影を実装すること自体は難しくないですね。
ただ簡単に実装できる反面描画の負荷軽減は工夫する必要があると感じます。今回のサンプルはステージが一つのみでしたが複数のオブジェクトを描画する場合、影を実装するならそれだけの数分描画回数は2倍になるのでカリング処理や設計はしっかり考える必要があると思いました。
いちよ本記事の目的である影の実装については達成することが出来ました。
ただ、今回実装した陰には以下の問題点が挙げられます
・影が真っ黒!!
・桜の花部分がメッシュごと影を描画している!!
影が真っ暗な点は調べてみたら同じ境遇の人がいらっしゃったのでその人の記事を見ながら解決できそうです。(次回余裕があれば取り上げます)
ただ、モデルに含まれている板ポリゴンをそのまま陰にしている点については、その板ポリゴンのピクセルからアルファ値をみて影を描画するかを決めるようにしたら良いと思うのですがDXライブラリの機能では厳しいのではと思われます。
ただ、別の手法から影を描画させることでこの問題は解決できるのではと思われます。
調べてみたところ自作のシェーダで影を描画させる手法が公式のドキュメントにありました。
こちらの実行物を見たのですが私がやりたいとしてる影の表現にかなり近いと感じました。
というわけで次はこのサンプルを使って影の実装に挑戦しようと思います!
次回ね
次回予告
次回は公式のサンプルコードを読み解いて深度値を利用した影表現の方に挑戦していきたいと思います。深度値とは...って感じがしているのですがそこの勉強も含めて実装の方頑張りたいと思います!!
(ほんとはこの記事を書いてる時点で上の実装には取り掛かってたんですけどあまりにも難しくて人様に見せられるものが出来なかったので次回に持ち越すことにしました)
おわり!!!
