Skip to content

第09回 影表現の基礎

前回: 第08回 内積とフレネル、外積と法線マップ / 次回: 第10回 スキンメッシュ基礎

光が届かない場所を どう描くか

影はライティングの 説得力を支える要素

暗くするだけではなく 空間関係を伝える

前回の振り返り

角度によって変わる見え方を扱いました

  • 第08回では、視線方向と法線の内積から リムライトやフレネル効果を作りました
  • 法線マップでは、表面の細かな向きをテクスチャーとして扱い ライティングに使う法線を変化させました
  • つまり前回は、面の向き見る方向 を使って 質感を制御しました
  • 今回は、光が物体に遮られるかどうかを判定し、 影として表現する方法を扱います

今回の授業で扱うこと

影が描画される仕組みを理解する

  • 影の役割
  • Cast Shadow と Receive Shadow
  • Depth と Depth Buffer
  • Depth Buffer と Shadow Map の関係
  • ライト空間での深度比較
  • Shadow Bias とよくあるアーティファクト
  • ソフトシャドウの考え方
  • 影を調整するときに、どの設定を見ればよいか

今回の授業内容

シャドウマップの基礎

  • 影があると何が伝わるのか
  • 深度バッファの役割
  • シャドウマップの2パス描画
  • 深度比較による影判定
  • Bias、Normal Bias、Shadow Acne
  • Shadow Distance、Resolution、Cascade
  • Shader Graph と影
  • 授業内課題

なぜ影が重要なのか

空間の関係を読みやすくする

  • 影があると、物体が床に接しているのか 空中に浮いているのかが分かりやすくなります
  • 影の向きから、ライトの位置や方向も推測できます
  • 影の濃さ、ぼけ方、長さは、時間帯や空気感にも影響します
  • ゲームでは、リアルさだけでなく プレイヤーが足場、敵、攻撃範囲を読むための情報としても使われます
  • 影は見た目の装飾ではなく、空間理解を助ける情報です

影を作る2つの役割

Cast と Receive

役割意味
Cast Shadowほかの場所に影を落とす
Receive Shadowほかの物体からの影を受ける
  • 影を落とす物体と、影を受ける物体は別の役割を持ちます
  • Unity では Mesh Renderer や Light、Render Pipeline の設定で 影の有無や品質を調整します
  • 「影が出ない」ときは、ライト、物体、マテリアル、Render Pipeline の どこで無効になっているかを切り分ける必要があります

リアルタイム影の難しさ

光線をすべて追跡するのは重い

  • 現実の影は、光が物体に遮られることで発生します
  • 現実をそのまま再現するなら、光源から出る大量の光線を追跡し、 どこに届くかを調べる必要があります
  • しかし処理時間の限られたリアルタイム描画では、 毎フレームすべての光線を計算するのは現実的ではありません
  • そこでゲームでは、比較的軽く影を表現できる Shadow Map が広く使われています

深度とは

カメラから見た奥行き

Z-depth map の例
Z-depth map の例 この画像では、カメラに近いほど白く、 遠いほど黒く表示されている 出典: Wikimedia Commons / Creativonly / Public domain

  • Depth は、カメラから見た奥行きを表す値です
  • 3D空間の物体を画面に描くとき、 カメラに近い面は手前にあり、 カメラから遠い面は奥にいくことになります
  • 奥にある面で手前の面を上書きしてしまうと 3D の描画は破綻してしまいます
  • そこで深度を比較して、カメラから見て手前に ある面を優先して描画する仕組みが必要に なります

Depth Buffer

ピクセルごとの奥行きを保存する

Depth Buffer の概念図
画面上の重なりは、ピクセルごとの深度比較で解決される

  • Depth Buffer は、画面の各ピクセルに対応した 深度を保存するバッファです
  • 新しいピクセルを描画する際は、その深度を Depth Buffer に保存済みの深度と比較します
  • 新しいピクセルの方が手前なら描画を行い、 Depth Buffer も新しい深度に更新します
  • 新しいピクセルのほうが奥なら、 既に描かれた手前の物体に隠れているため 描画をスキップします

Z Test と Z Write

深度を比較し、必要なら書き込む

  • 深度比較は Z Test、深度を書き込む処理は Z Write と呼ばれます
  • 一般的には、現在のピクセルが保存済みの深度より手前なら 描画を行いますが、他の比較方法もあります
  • 不透明オブジェクトでは通常 Z Write 有効で描画を行いますが、 半透明オブジェクトでは見た目の都合で無効にすることがあります
  • 第04回で扱った透明表現の描画順問題は、 Depth Buffer とも関係しています

Shadow Map との関係

カメラの代わりにライトから深度を見る

  • 通常の Depth Buffer は、カメラから見た奥行きを保存します
  • Shadow Map は、同じ考え方をライト視点に置き換えたものです
  • ライトから見て手前にある面には光が届き、 それより奥にある面は何かに遮られていると判断できます
  • つまり Shadow Map は、ライトから見た Depth Buffer のようなものです

シャドウマップの考え方

ライトをカメラのように扱う

Shadow Map の深度ビュー
画像右上がライトから撮影された距離 オブジェクト描画時にライト空間内の深度と比較して シャドウの有無を判定する

  • シャドウマップは、ライトから見たシーンの 深度をテクスチャーとして保存したものです
  • ライトから見えている場所には光が届きますが 物体に隠れている場所には光が届かないため 影になります
  • 「ライトから見て最初に見えた深度」と 「現在描画しているピクセルの深度」を比較 することで、対象のピクセルが影になるかを 判定できます

深度比較による影判定

現在の点がライトから見えるか

  • Shadow Map には、ライトから見て最も手前にある面の深度が入ります
  • 現在描画しているピクセルが、その深度より奥にある場合、 手前の物体に遮られていると判断できます
  • 反対に、Shadow Map の深度と同じか手前であれば ライトから見えているので影にはなりません
  • 判定は単純ですが、解像度や数値誤差による問題がつきもので 安定した影を作るためには調整が必要になります

Shadow Map の2パス描画

影用の情報を先に作る

  1. ライトから見たシーンの深度だけを Shadow Map に保存する
  2. 通常のカメラからシーンを描画する
  3. 各ピクセルをライト空間に変換し、Shadow Map に保存された深度と比較する
  4. 奥にあれば、何かに遮られているので影として暗くする
  • この手順のためには 「ライトから見た深度を保存する描画パス」と 「カメラから描画する描画パス」の2つの描画パスが必要になります

ライト空間

比較するために座標系をそろえる

  • カメラから描画しているピクセルの位置は、通常はワールド空間や クリップ空間などで扱われています
  • 一方、Shadow Map はライトから見た深度なので、 比較するには現在ピクセルをライトから見た座標へ変換する必要があります
  • この「ライトから見た座標系」をライト空間と呼びます
  • ライト空間で見た深度を比較することで、 そのピクセルに光が届くかどうかを判定できます

Shadow Acne

表面に細かな自己影が出る問題

  • Shadow Map の深度はテクスチャーに保存されるため 精度にも分解能にも限界があり、完全に連続した値にもなりません
  • 現在描画している面と、Shadow Map に保存された面が同じでも、 数値誤差によって「少し奥にある」と判定されることがあります
  • その結果、本来影にならない表面に しま模様のような自己影が出ることがあります
  • この現象は Shadow Acne と呼ばれます Acne は ニキビの意味で、表面に細かい影ができる様子から名付けられています

Shadow Bias

深度比較に余裕を持たせる

Bias が小さすぎる例
バイアスが小さすぎると精度エラーによる自己影が出る
Bias が大きすぎる例
バイアスが大きすぎると影が浮いて見える

  • Bias は、影判定で使う深度を少しずらし、 自己影が出にくくなるようにする値です
  • 小さすぎると Shadow Acne が残ります
  • 大きすぎると、影が物体から離れて見えます この現象は Peter Panning と呼ばれます
  • 影が汚い場合は、まず Bias と Normal Bias を 少しずつ調整します

Normal Bias

法線方向にずらして自己影を減らす

  • Normal Bias は、影を落とす面を法線方向へ少し押し出すように扱う調整です
  • 斜めの面や細かい形状では、通常の Bias だけでは 自己影を消しにくいことがあります
  • Normal Bias を上げると Shadow Acne は減りますが、 細い影が消えたり、接地影が弱くなったりします
  • Bias 系の値は一般に「正解の数値」がありません ライト、スケール、カメラ距離、解像度に合わせて都度調整が必要です

Shadow Resolution

Shadow Map の解像度

  • Shadow Map はテクスチャーなので、解像度が足りないと 影の輪郭がギザギザになります
  • 解像度を上げると影は細かくなりますが、 メモリ使用量と描画負荷も上がります
  • 影をきれいにしたいときは、ただ解像度を上げるだけでなく ライトの範囲、Shadow Distance、カメラ距離も見直します
  • 広い範囲を1枚の Shadow Map に詰め込むほど、 1ピクセルあたりの影の精度は下がります

Shadow Distance

遠くの影をどこまで描くか

  • Shadow Distance は、カメラからどの距離まで影を描くかを決める設定です
  • 遠くまで影を描くほど、Shadow Map の限られた解像度を 広い範囲に使うことになります
  • そのため Shadow Distance が長すぎると、 近くの影まで粗く見えることがあります
  • ゲームでは、遠くの影を省略したり、 距離に応じて品質を変えたりして負荷と見た目を調整します

ハードシャドウとソフトシャドウ

影の輪郭の違い

ハードシャドウの例
ソフトシャドウの例
ハードシャドウとソフトシャドウの比較

  • Hard Shadow は輪郭がくっきりした影 Soft Shadow は輪郭をぼかした影です
  • Shadow Map は「影か、影ではないか」の 二値判定のため、通常は硬い影になります
  • Shadow Map を複数回サンプリングして 周囲の結果を平均し、影の輪郭を柔らかく するのが Soft Shadow の一般的な実現方法です
  • サンプル数を増やすほど滑らかになりますが、 その分描画負荷も高くなります

Cascade Shadow

距離ごとに Shadow Map を分ける

Cascade Shadow の設定
Cascade Shadow の解像度が低い例
Cascade Shadow の解像度を改善した例
カスケードシャドウの設定パネルと設定例 シャドウマップ1枚では影が荒くなる

  • 1枚の Shadow Map だけでは広範囲の影を フォローしきれず、近くの影が粗くなります
  • Cascade Shadow はカメラからの距離に応じて 複数の Shadow Map を使い分ける方法です
  • 近くは高精度、遠くは低精度にすることで 見た目と負荷のバランスを取りやすくなります
  • ただしカスケードの境界が見えることもある ため、分割数や距離の調整が必要になります

Contact Shadow

接地部分の影を補う

Contact Shadow 調整前
Contact Shadow 調整後
SSAOでの影の強化例 接地感が増す

  • Shadow Map の解像度や距離の制限で接地影が 十分に表現できない場合の補強手法です
  • Unity の URP では未対応ですが、SSAO で 似た効果を実現できます
  • 実在感を強化する強力な手法ですが、 強すぎるとノイズ感が出て不自然になるため 調整が必要です

Shader Graph で意識すること

影を受ける、影を落とす

  • Lit 系の Shader Graph では、レンダーパイプラインのライト計算により 影を受けることができます Unlit 系では、基本的にライトや影の影響を受けません
  • 影を落とすかどうかは、シェーダーだけでなく Renderer の Cast Shadows 設定にも関係します
  • 透明や Alpha Clip を使うマテリアルでは、 影の形もアルファに合わせたいのかを確認する必要があります

Alpha Clip と影

透明部分を影に含めない

  • 葉っぱやフェンスのようなマテリアルでは、 四角いポリゴン全体ではなく、アルファで切り抜いた形の影が必要です
  • Alpha Clip を使うと、一定以下のアルファを描画しないため、 影用の描画でも切り抜き形状に近い影を作れます
  • しきい値が高すぎると影が欠けたり細くなったりし、 低すぎると本来透明にしたい部分まで影が残ります
  • 第04回で扱った透明表現は、影の見え方にも関係します

法線マップと影

細かい凹凸は影を落とさない

  • 法線マップは、ライティングに使う法線方向を変える技術です
  • しかし実際のメッシュ形状を変えているわけではないため、 法線マップの細かな凹凸そのものが Shadow Map に影を落とすわけではありません
  • 近くで見る細かな陰影は法線マップで表現し、 大きな遮蔽や接地影は Shadow Map で表現します
  • 必要に応じて、Height Map、Parallax、Displacement などの表現も使い分けます

実習

影の設定を確認する

影が出る条件と 品質調整を試す

実習1

影が出る最小構成を作る

  1. 床用の Plane と、影を落とす Cube または Sphere を配置する
  2. Directional Light を配置する
  3. オブジェクトの Mesh Renderer で Cast Shadows を確認する
  4. 床側の Renderer とマテリアルが影を受ける設定になっているか確認する
  5. ライトの向きを変え、影の方向が変わることを確認する

実習2

Bias を調整する

  1. ライトの Shadow 設定を開く
  2. Bias を小さくして Shadow Acne が出るか確認する
  3. Bias を大きくして影が物体から離れるか確認する
  4. Normal Bias を調整して、斜めの面の自己影がどう変わるか確認する
  5. 不自然にならない範囲を探す

実習3

Shadow Distance と Resolution を比較する

  1. カメラの近くと遠くにオブジェクトを配置する
  2. Shadow Distance を短くして、遠くの影が消えることを確認する
  3. Shadow Distance を長くして、近くの影の精度が変わるか確認する
  4. Shadow Resolution を変更して、輪郭のギザギザを比較する
  5. 見た目と負荷のバランスを考える

実習4

Alpha Clip の影を確認する

  1. 葉っぱやフェンスのようなアルファ付きテクスチャーを用意する
  2. Shader Graph で Alpha Clip を有効にする
  3. しきい値をプロパティ化する
  4. 表示される形と影の形が一致するか確認する
  5. しきい値を変えて、見た目と影がどう変わるか観察する

授業内課題

影の設定を調整し 接地感のあるシーンを 作成してください

より良いビジュアルを 作ってね

課題の条件

以下を満たしてください

  • 影を落とすオブジェクトと、影を受ける床または壁がある
  • Directional Light、Point Light、Spot Light のいずれかで影を出している
  • Bias または Normal Bias を調整し、極端な自己影や影の浮きを避けている
  • Shadow Distance または Shadow Resolution を変更して比較している
  • Alpha Clip を使う場合は、切り抜き形状に近い影になっている
  • スクリーンショットで、影による接地感が確認できる

この回の到達目標

  • Cast Shadow と Receive Shadow の違いを説明できる
  • Shadow Map がライトから見た深度テクスチャーであることを説明できる
  • ライト空間での深度比較によって影を判定する考え方を説明できる
  • Shadow Acne、Peter Panning、Bias の関係を説明できる
  • Shadow Distance、Resolution、Cascade が影の品質に与える影響を説明できる

今回のまとめ

影はライトから見えるかどうかで決まる

  • Shadow Map は、ライトから見たシーンの深度を保存したテクスチャーです
  • カメラから描画するときに、現在ピクセルのライト空間深度と Shadow Map の深度を比較して影を判定します
  • Shadow Map は近似なので、Bias、Resolution、Shadow Distance の調整が必要です
  • ソフトシャドウは、影判定を複数回サンプリングして輪郭を柔らかく見せる考え方です
  • 影は質感だけでなく、物体の位置関係と接地感を伝える重要な表現です

おつかれさまでした!

次回予告 第10回 スキンメッシュ基礎

ボーンとウェイトで キャラクターを動かす