シャドウ
ディレクショナルライトのシャドウ

Unity のライトは、あるオブジェクトからそれ自体の一部や近くにある他のゲームオブジェクトに 影 (シャドウ) を作ることができます。シャドウによって、ゲームオブジェクトのスケールや位置が明確になるため、シーンに奥行きと現実感が生まれます。シャドウがないと、オブジェクトは 「平坦」に見えてしまいます。

ゲームオブジェクトがシャドウを投影しているシーン
ゲームオブジェクトがシャドウを投影しているシーン

シャドウのしくみ

光源が1つしかない単純なシーンを想像してください。光源から発せられたレイ(光線)は、光源から直線的に進み、やがてシーン内にあるゲームオブジェクトにぶつかります。レイがオブジェクトにぶつかると、それ以上は進めなくなるので、その先を照らすことはありません (つまり、レイは最初にぶつかったオブジェクトで跳ね返り、通過しません)。ゲームオブジェクトが作りだすシャドウは、単にライトが届かないために照らされない領域のことなのです。

別の見方として、ライトと同位置にあるカメラをイメージしてください。影になるシーンの領域は、カメラで見ることのできない領域と正確に同じになります。

同じシーンの「ライトの視界」
同じシーンの「ライトの視界」

実際、まさにこれが、Unity がライトによるシャドウの位置を決定する方法なのです。ライトはカメラと同じ原理を使って、その視点からシーンを内部的に「レンダリング」します。シーンカメラによって使用されているように、深度バッファーシステムがライトに最も近いサーフェスを追跡します。視点の直線上にあるサーフェスは照らされますが、他のすべては影になります。この場合の深度マップは シャドウマップ と呼ばれています(シャドウマッピングの詳細は Wikipedia Page を参照してください)。

シャドウを有効にする

インスペクターの Shadow Type プロパティーを使って個々のライトに対するシャドウを有効にし定義します。

プロパティー 機能
Shadow Type Hard Shadows を選ぶと、エッジのくっきりしたシャドウを生成します。Hard shadows は Soft Shadows に比べて特に現実的なわけではありませんが、処理が少なく多くの場合で許容できます。Soft shadows は、シャドウマップからギザギザのエイリアシングを減少させる傾向もあります。
Strength シャドウの濃さを決定します。一般に、ライトは大気によって拡散され、他のゲームオブジェクトに反射します。そのため通常は、シャドウの Strength を最高に設定することはありません。
Resolution 前出のシャドウマップの「カメラ」のレンダリング解像度を設定します。シャドウのエッジがとてもはっきり見える場合は、この値を上げるとよい場合があります。
Bias シャドウの位置と鮮明さの微調整を行います。詳しくは後述の シャドウマップと Bias プロパティー を参照してください。
Normal Bias シャドウの位置と鮮明さの微調整を行います。詳しくは後述の シャドウマップと Bias プロパティー を参照してください。
Shadow Near Plane シャドウをレンダリングするときに、ニアクリップ面の値を選択できます。ライトとの距離がこの距離より短いオブジェクトはシャドウを作りません。

シーンの各 メッシュレンダラーCast ShadowsReceive Shadows プロパティーを持ち、必要に応じて有効にする必要があります。

Cast Shadows のドロップダウンで On を選択すると、メッシュからのシャドウの投影を有効にします。Two Sided を選択すると、メッシュのどちらのサーフェスからでもシャドウを投影することができます (そのため、バックフェースカリングは投影目的では無視されます)。Shadows Only は非表示のゲームオブジェクトからシャドウを投影できます。

シャドウマッピングと Bias プロパティー

指定されたライトのシャドウはシーンの最終的なレンダリング中に決定されます。シーンがメインカメラのビューにレンダリングされるとき、ビュー内の各ピクセル位置はライトの座標システムに変換されます。それから、ライトからのピクセル距離がシャドウマップの対応するピクセルと比較されます。ピクセルがシャドウマップのピクセルよりも離れている場合、別のゲームオブジェクトによってライトから隠されると推測され、そのピクセルは照らされません。

正常なシャドウ
正常なシャドウ

ライトが直接照らすサーフェスに、部分的に影があるように見えることがあります。正確にシャドウマップで指定された距離でなければならないピクセルが、ずっと遠くにあるように計算されてしまう場合があるためです(シャドウフィルタリングやシャドウマップに低解像度画像を使用した結果)。その結果として、実際には照らされるべきピクセルが影になって模様を作る、「シャドウアクネ」と言われる現象が発生します。

不自然なシャドウを作るシャドウアクネ
不自然なシャドウを作るシャドウアクネ

シャドウアクネを避けるために、シャドウマップの距離に Bias 値を加え、数値の境目にあるピクセルが確実に比較にとおるようにします。または、シャドウマップにレンダリングする間に、ゲームオブジェクトが法線に沿って少し差し込まれるようにします。これらの値は、シャドウが有効の時に Light インスペクターウィンドウの BiasNormal Bias プロパティーによって設定されます。

Bias 値をあまり高く設定しないでください。なぜなら、ゲームオブジェクトが作るシャドウ近くの領域は時々誤って照らされることがあるからです。この結果、オブジェクトから離れたシャドウとなり、ゲームオブジェクトがまるで空中に浮かんでいるように見えます。

あまりにも Bias 値を高くすると、シャドウがオブジェクトから「離れている」ように見えます
あまりにも Bias 値を高くすると、シャドウがオブジェクトから「離れている」ように見えます

同様に、Normal Bias 値をあまり高く設定すると、ゲームオブジェクトに対し、シャドウの幅が狭くなりすぎてしまいます。

Normal Bias 値を高くし過ぎると、シャドウの幅がとても狭くなります
Normal Bias 値を高くし過ぎると、シャドウの幅がとても狭くなります

ある状況では、Normal Bias が「ライトブリーディング」と呼ばれる、望ましくないエフェクトの原因になることがあります。ライトブリーディングとは、ライトが近くのジオメトリから影になる領域に漏れてしまうことです。可能なソリューションはゲームオブジェクトの Mesh Renderer を開き、 Cast Shadows プロパティーを Two Sided にします。これによって、問題を解決できる場合があります。ただし、よりリソース負荷が高くなり、シーンをレンダリングするときにパフォーマンスオーバーヘッドが増加します。

ライトの Bias 値には、望まないエフェクトが発生しないように微調整が必要な場合があります。一般に、計算するよりも目測で値をとる方が簡単です。

さらに、シャドウアクネを避けるために、シャドウパンケーキ ( ディレクショナルライトのシャドウ: シャドウパンケーキ を参照) という技術を使用します。一般的に、この方法は効果的です。しかし、とても大きな三角形には、視覚的なアーティファクトが発生します。

プロパティーの Shadow Near Plane Offset 値が低いと、シャドウに穴が開いたように見えます
プロパティーの Shadow Near Plane Offset 値が低いと、シャドウに穴が開いたように見えます

プロパティーの Shadow Near Plane Offset 値を適切に調整すると、この問題は解決されます。この値をあまり高く設定すると、シャドウアクネが発生します。

正常なシャドウ
正常なシャドウ
シャドウ
ディレクショナルライトのシャドウ