LightEffect(プログラマ向け資料) - LHYAYOI/HujiTV GitHub Wiki
目次
1. StartUp
- Direction/SpotLightのみ対応の個別にボリュームを付与するスクリプトを作成
RendererにVolumetricLightShaftFeatureを追加しないと動作しないから注意!
2. Debug
1. まず基本設定を確認
- 使用中のCameraが参照する3D Rendererに、有効なLightShaftFeatureとシェーダーがあるか
- VolumeのLayer Mask、weight、Enable、Intensity、密度、Overrideが有効か。別Volumeに上書きされていないか
- SpotはLightShaftEmitterが必要。空間God RayではURP Main Directional Lightを使い、太陽のEmitterは不要
- 影にはLightとURPの双方の設定が必要。Shadow Distance外・カスケード境界・アトラス品質も確認
- Scene/Gameのカメラ、Renderer指定、Quality設定が意図したものか
2. 選別とタイルを確認
Tools → LightShaft → 品質とタイルのデバッグ(従来の Tools → Light Shaft → Quality Diagnostics も有効)を開きます
- Cameraを明示的に指定
- Spot/Fogの候補数と描画数を確認
- Selected volume gizmosで、選択された領域・Priority・フェード重みを確認。
- Tile debugをTotalCandidates / SpotCandidates / FogCandidatesへ切り替え
タイルは低解像度8×8ピクセル、数字はタイルで交差判定する候補数です
色は0=暗色、1=紫、2=青、3=緑、4〜5=黄、6〜9=橙、10以上=赤
全配置数、実際の散乱寄与数、GPU時間ではありません
投影境界ボックスを使うため、候補は保守的です、近クリップ面をまたぐ境界は全画面候補になります
デバッグ中は対象カメラのタイル生成を強制します
Profileには保存せず、Offまたはウィンドウ終了で解除します
体積散乱が有効なカメラが対象です。表示負荷を含むため、本計測ではオフにします
3. 時間蓄積の残像を調べる
Temporalは既定オフです、有効時はカメラ別のping-pong履歴を使い、代表散乱深度で再投影します。
履歴を3×3近傍の色範囲に制限し、深度不一致を棄却します
照明・霧・設定・選択フェード、カメラカット、投影・解像度の変化、長いフレーム間隔で履歴を無効化します
診断ウィンドウにAccumulatingまたはリセット理由が表示されます
カメラの微小な移動では再投影を継続します
独立した遮蔽物による影の変化をすべてCPUで追跡しているわけではありません
イベントが分かる場合はFeatureの ResetHistory(camera)、全カメラなら ResetHistory() を呼べます
比較時はTemporalをオフにし、単フレームの問題か履歴の問題かを分けます
履歴は1280×720・半解像度でカメラあたり約7.03 MiB
XRではTemporalとTileを使わず従来経路に戻り、整数ターゲット非対応環境ではTileを無効化します、検証済みのGPU環境はD3D12です。
4. 負荷を測る
診断ウィンドウでRecord pass timingsをオンにし、Unity ProfilerのGPU計測も有効にします
N/Aは未取得または未実行で、0 msではありません。値は直前に完了したフレームの呼び出し平均です
複数カメラでは混在するため、比較は1カメラで行います。
| パス | 内容 |
|---|---|
| Atmosphere | 霧+Spot+空間God Rayの積分。個別には分離できない |
| Composite | 合成+根元/深度境界の追加計算 |
| SkyMask / Radial / RadialFilter | 画面God Ray |
| Temporal | 履歴の再投影・混合 |
| Tiles | 候補ビットマスク生成 |
検証時はRTX 4060、1280×720、半解像度、50組で、根元補完ありの効果パス合計中央値がTileオフ0.573 ms/オン0.489 msでした
シーン全体のGPU時間ではなく、他環境の保証値でもありません
3. Code
基点は Assets/hatake/lightEffect/ です。
| ファイル | 役割 |
|---|---|
| scripts/LightShaftFeature.cs | 候補収集、シェーダーパラメーター、Render Graph、カメラ別状態 |
| scripts/LightShaftVolume.cs | 全体設定・品質・フェード・Temporal/TileのVolumeParameter |
| scripts/LightShaftEmitter.cs | Lightに付ける散乱強度・Priority・影の指定 |
| scripts/LocalFogVolume.cs | Box/Sphere局所霧、減算領域、Sun Boost、アクティブリスト |
| scripts/ShaftSelection.cs | 順位付け、固定枠、ヒステリシス、退場→入場フェード |
| shaders/ShaftIntervals.hlsl | 視線と円錐・Box・Sphereの交差、区間のステップ分割 |
| shaders/ShaftRaymarch.hlsl | 霧・Spot・空間God Rayの積分、代表深度 |
| shaders/ShaftComposite.hlsl | 深度を使う合成と根元・境界補完 |
| scripts/ShaftHistory.cs、shaders/ShaftTemporal.hlsl | 履歴RTHandleと再投影 |
| shaders/ShaftTiles.hlsl | タイルの候補ビットマスク生成 |
| scripts/ShaftTileDebug.cs、shaders/ShaftTileDebug.hlsl | 一時的なカメラ指定、ヒートマップ・数字・グリッド |
| scripts/ShaftProfiling.cs、ShaftBenchmarkPath.cs | GPU/CPUコマンド計測、固定カメラ経路 |
| scripts/ShaftPerformanceDemo.cs | 0〜50組の切替、固定経路反復、CSV |
| scripts/ShaftQualityPresets.cs | デモとEditorで共通の品質設定 |
4. 描画と選別の仕組み
Featureは透明物の描画前に実行します
深度から不透明面までの積分区間を作り、最大距離で制限します
霧・Spot・空間God Rayを低解像度で積分し、深度を考慮してフル解像度に合成します
透明物を正確に透過・屈折する霧ではありません
画面God Rayは別方式です
空の遮蔽マスク→太陽方向の放射状積分→低解像度フィルタを使います
画面外の太陽や特定の世界座標の見せ場には空間God Rayを使います
Sun Boostは画面God Rayを局所的に切り抜く機能ではありません
候補は視錐台・描画距離で絞り、Priority × 寄与量 × 画面占有の近似 × 近接度で評価します
表示中の候補にはヒステリシスを加えます。遮蔽物に完全に隠れているかを厳密にCPU判定する方式ではありません
固定枠の旧演出を0までフェードアウトしてから次をフェードインします
既定0.35秒は片側の時間です
光柱から外れたLightも通常照明・影は描き続けるので、4灯制限がシーン全体のライト負荷を4灯相当にするわけではありません
5. 変更時の注意
- 4/16の上限変更はC#配列、シェーダー配列、ビットマスク、ループ、検証を同時に更新します。
- パス番号0〜6をFeatureと両Shaderで一致させます。新しいテクスチャ/バッファはRender Graphの依存関係に明示します。
- SceneViewとGameの履歴・選別は独立させます。Feature破棄、履歴無効化、解像度変更でRTHandleを解放します。
- Volumeの新規パラメーターをUIから変更するときは
.Override()を使い、既存Profileでも反映させます。 - 光柱のCookie投影、Point Light、透明物への厳密な霧、Froxel、ReSTIRは未実装です。XR・モバイル・Playerビルドの最終確認は別途必要です。
- URP内部のSerializedProperty(RendererDataList、RendererFeatureMap、影設定)をセットアップで使用します。URP更新時はStage 7と対象カメラのRenderer割り当てを確認してください。