ヒーロー画像:太陽に照らされた長い列柱廊と、通路に落ちるくっきりとした安定した影

シャドウ(影)は、3Dシーンに実在感や説得力をもたらす重要なディテールのひとつですが、同時に破綻が目立ちやすい要素でもあります。今回のアップデートにより、太陽光のシャドウがより安定してクリーンになり、調整もはるかに簡単になりました。また、スポットライト、ポイントライト、エリアライトにも同様の改善が適用されています。

概要:

この記事の内容

なぜ影が重要なのか

シーンから影を取り除くと、すべてが浮いているように見えます。オブジェクトは地面とのつながりを失い、奥行きが分かりにくくなり、ライティングは平坦に見えます。適切な影は、物の位置、大きさ、そして光がどこから来ているのかを教えてくれます。

質の悪い影も同様に目立ちます。カメラの動きに合わせて這うようなエッジ、表面に現れる縞模様、あるいは影がそれを落とすオブジェクトから剥がれてしまう現象は、すべて即座に没入感を損ないます。今回のリリースは、まさにこれを解決するものです。

リアルタイムシャドウはどのように機能するのか?

現実の影は光が遮られることで生じますが、リアルタイムレンダラーは光を追跡しません。代わりに、シャドウマップと呼ばれる、より低コストで非常に効果的なトリックを使用します。

  1. 光源から見る。 光源の視点からシーンをレンダリングしますが、各ピクセルについて最も近いサーフェスまでの距離のみを保存します。その結果がシャドウマップです。
  2. カメラから見る。 画面上の各ピクセルについて、光源の視点から見た位置を計算し、その距離をシャドウマップに記録されたものと比較します。
  3. 判定する。 光源により近いものが記録されていた場合、そのピクセルは影の中にあります。そうでなければ、光が当たっています。

図:3ステップで見るシャドウマップ

問題は、シャドウマップが固定解像度のテクスチャであることです。光源から撮影されたシーンの低解像度写真と考えてください。ほぼすべてのシャドウ技術は、この限られた解像度を最大限に活用する方法なのです。

レイトレーシングやパストレーシングによる影については?

シャドウマップは近似であるため、なぜ単純に光を追跡しないのかと問うのは当然です。ハードウェアレイトレーシング対応のGPUではそれが可能です。各可視点から光源に向けてレイを飛ばし、何かが遮ればその点は影になります。テクスチャ解像度の限界がないため、ブロックノイズ、シャドウアクネ、ピーターパン現象は発生せず、ソフトシャドウも正確に得られます。パストレーシングはさらに一歩進み、シーン内で反射する多数のランダムな光の経路を追跡するため、シャドウ、反射、間接照明がすべて同じプロセスから生成されます。Evergineのパストレーサーのサンプルでその様子をご確認いただけます。

図:シャドウマップとレイトレーシングシャドウの比較

その代償はパフォーマンスです。クリーンな画像を得るには、フレームごとにピクセルあたり数本のレイが必要で、通常はその後デノイザーが適用されます。シーンには、オブジェクトの移動に応じて再構築が必要な加速構造が必要です。さらに、レイはあらゆる方向に散乱するため、三角形をテクスチャにラスタライズするよりもGPUメモリに大きな負荷がかかります。ハイエンドのデスクトップGPUでさえレイの使用は慎重に予算管理されており、ほとんどのスマートフォン、タブレット、ローエンドデバイスにはハードウェアレイトレーシングが全く搭載されていません。

これが、シャドウマップが依然としてリアルタイムシャドウの主力である理由です。低コストで予測可能であり、事実上あらゆるデバイスで動作します。レイトレーシングはハードウェアが許す場合の優れた選択肢ですが、それ以外のすべての環境でシーンを動かし続けるのがシャドウマップであり、だからこそ我々はシャドウマップへの投資を続けています。

太陽の問題とカスケード

ディレクショナルライトは太陽の代わりとなり、太陽はすべてを照らします。単一のシャドウマップで可視世界全体をカバーしようとすると、数百メートルに引き伸ばされたテクスチャは、ディテールが最も重要なプレイヤーの目前でさえブロック状の影を生み出します。

古典的な解決策はカスケードシャドウマップです。ビューをカメラからの距離に応じてスライスに分割します。手前の小さなスライス、その背後により大きなスライス、という具合です。各スライスが独自のシャドウマップを持つため、近くの影はシャープに、遠くの影は粗くなります。遠くのものは画面上で小さいため、ほとんど気になりません。

図:カメラの視錐台を4つのカスケードに分割し、それぞれを同じ解像度のシャドウマップにレンダリングする様子

Evergineはすでにカスケードを使用していました。今回のリリースは、その動作を改善することに焦点を当てています。

従来のアプローチが苦戦していた点

以下の3つの問題が繰り返し発生していました。

新機能

シマリングが解消されたカスケード

シャドウ空間は、カメラの向きではなく、光源の方向のみに依存するようになりました。各カスケードはシャドウマップのテクセルグリッドにスナップされ、そのサイズは約2%の小さなステップでのみ変化します。その結果、カメラの移動や回転によって、ワールドのどの部分をどのテクセルがカバーするかが変わらなくなり、シマリングは解消されました。

図:テクセルグリッドへのスナップ前後における、3フレームにわたる影のエッジの比較

シーンを理解するバイアス

バイアスがワールド空間で適用され、シャドウマップのテクセル単位で計測されるようになりました。2つの新しいプロパティShadowDepthBiasとShadowNormalBiasは、各カスケードのテクセルサイズとシャドウフィルターのソフトネスに応じて自動的にスケールします。単一の設定で、最も近いカスケードから最も遠いカスケードまで適切に動作するようになり、グレージング角でのシャドウアクネの縞模様や遠方での浮遊する影が解消されます。

図: バイアスが小さすぎる場合、バランスが取れた場合、大きすぎる場合

スポットライト、ポイントライト、エリアライト

テクセルベースのバイアスモデルは太陽光に限定されません。スポットライト、ポイントライト、エリアライトでも使用されるようになり、ShadowDepthBiasとShadowNormalBiasはすべてのライトタイプで同じ意味を持ちます。併せて2つの問題を修正しました:

図: ポイントライト周辺でキューブ面を重ねるガードバンド

調整可能なカスケード

ディレクショナルライトで、品質とパフォーマンスのトレードオフを調整できるようになりました:

図: 安定フィットモードとタイトフィットモード

注意: 1つのライトが複数のカメラでレンダリングされる場合、更新間隔は効果がありません。

デバッグ機能の改善

ライトのデバッグモードで、各カスケード (およびポイントライトの各キューブ面) の色に加え、8x8シャドウマップテクセルのチェッカーボードが表示されるようになり、画面上のシャドウ密度を正確に確認できます。スポットライトにも専用のDebugModeが追加されました。

関連する問題も修正しました: カスケード分割距離が正しい計算式を使用するようになり、ゼロのニアプレーンを持つ平行投影カメラで無効な分割が生成されなくなり、複数のシャドウキャストディレクショナルライトで複数のカメラをレンダリングしても、ライトが互いのシャドウマップを上書きしなくなりました。バックエンドは深度クランプを一貫して処理するため、カスケードの手前にあるオブジェクトがクリップされなくなりました。

違いを見る

スライダーをドラッグすると、同じシーンおよびカメラ位置における従来のシャドウシステムと新しいシャドウシステムを比較できます。

変更前:通路から見た列柱廊(従来のシャドウシステム) 変更後:通路から見た列柱廊(新しいシャドウシステム)
比較 1
変更前:テストシーン、ビュー2(従来のシャドウシステム) 変更後:テストシーン、ビュー2(新しいシャドウシステム)
比較 2
変更前:フェンスと柱の土台(従来のシャドウシステム) 変更後:フェンスと柱の土台(新しいシャドウシステム)
比較 3
変更前:テストシーン、ビュー4(従来のシャドウシステム) 変更後:テストシーン、ビュー4(新しいシャドウシステム)
比較 4
変更前:テストシーン、ビュー5(従来のシャドウシステム) 変更後:テストシーン、ビュー5(新しいシャドウシステム)
比較 5
変更前:列柱廊と遠方のオベリスク(従来のシャドウシステム) 変更後:列柱廊と遠方のオベリスク(新しいシャドウシステム)
比較 6

はじめに

すべての設定はエディターまたはコードから調整できます。以下の値は参考の開始点ですので、シーンに合わせて調整してください:

// Get the directional light of your sun entity
var sun = sunEntity.FindComponent<DirectionalLight>();

sun.IsShadowEnabled = true;
sun.ShadowDistance = 100;                   // How far from the camera shadows are rendered
sun.ShadowCascadeCount = 3;                 // Between 1 and 4

// Keep cascades stable, and fade shadows out smoothly
sun.CascadeFitMode = DirectionalLight.CascadeFitModes.Stable;
sun.ShadowFadeFraction = 0.1f;
sun.CascadeBlendFraction = 0.1f;

// Bias is measured in shadow map texels
sun.ShadowDepthBias = 1;
sun.ShadowNormalBias = 1;

これにより、3つの安定したカスケード、カスケード間のスムーズなブレンド、およびシャドウ距離での穏やかなフェードを備えた、影を落とす太陽光が有効になります。シャドウアクネが見られる場合はバイアスをわずかに上げ、影がキャスターから浮いて見える場合は下げてください。

以前のバージョンからのアップグレード

既存のプロジェクトに影響するいくつかの変更点があります:

ぜひお試しいただき、ご意見をお聞かせください

より安定したクリーンなシャドウをシーンに与える準備はできましたか? Evergineをアップデートし、ディレクショナルライトのあるシーンを開いて新しいオプションをお試しください。

皆様のご意見をお待ちしております。

José Antonio Collado Araque
著者
José Antonio Collado Araque
グラフィックスエンジニア - リサーチャー