compute_shadow_map
English | 日本語

概要
このサンプルは、directional light 1灯のshadow mapを検証します。webg/ShadowMapPass.jsが光源視点からsceneをdepth textureへ描き、GeometryBufferPassがcamera視点のalbedo、normal、depthを作ります。その後、webg/ComputeShadowPass.jsがcamera側の位置をworld-spaceへ戻し、light spaceへ投影してshadow mapと比較します。
shadow map生成をRender Pass、影の評価と合成をCompute Passへ分けています。三角形のrasterizeとdepth testはRender Pipelineへ任せ、Compute Shaderは生成済みdepthを使ったbias、PCF、debug表示に集中します。これはGeometryBufferPassが入力を生成し、SsaoPassやDeferredLightingPassが後段で読む現在のwebg 2の構成と同じ責務分割です。
ShadowMapPassはwebgコアの実装です。static Shapeとskinned ShapeをSpaceから収集し、depth-only Render Passで描きます。skinned Shapeでは標準Shapeの2本のvertex bufferとSkeletonのmatrix paletteを読み、通常描画やGeometryBufferPassと同じbone姿勢をshadow mapへ反映します。alpha testはまだ未対応であり、暗黙に別の処理へ置き換えません。
FrameTimerはshadow depthとG-bufferのRender Pass、shadow評価のCompute Passをtimestamp queryで計測します。CommandPaletteとHelp panelにはGPU Compute、GPU Render、GPU Total、GPU Loadを表示します。GPU Loadは計測対象のGPU合計時間をframe間隔で割った目安です。最終的なfullscreen copyは計測対象外です。
処理フロー
Space
-> ShadowMapPass
-> directional light depth
Space
-> GeometryBufferPass
-> camera albedo / normal / depth
camera G-buffer + light depth
-> ComputeShadowPass
-> shadowed color
-> FullscreenPass
-> canvas
directional lightには正射影を使います。光源方向、注視中心、光源までの距離、正射影範囲、near、farからlight view-projection matrixを作ります。影が途中で切れる場合は、最初に正射影範囲へsceneが収まっているかを確認します。
spot light shadow はコアの SpotShadowMapPass と ComputeSpotShadowPass で扱います。spot light では光源位置、照射方向、FOV、inner / outer angle、near、farから透視投影のlight view-projection matrixを作り、coneの外側を徐々に暗くします。このサンプルはdirectional lightの低水準構成を確認するためのものなので、spot light shadowの実行確認は ComputeEffectPipeline の shadow.type: "spot" を使うアプリケーション側で行います。
実行方法
- 実行ファイルは ./compute_shadow_map.html です
- WebGPU対応ブラウザで開きます
- cameraはdrag、矢印キー、wheelで操作できます
操作と確認ポイント
Vはcomposite / shadow / albedo / normal / depthを切り替えます1と2はconstant depth biasを減少・増加します3はPCF radiusを0、1、2へ切り替えますSpaceは緑色のskinned shadow casterの移動、回転、曲げを停止・再開します- CommandPaletteとHelp panelでGPU時間とGPU Loadが更新されることを確認します
shadow表示はvisibilityを白、遮蔽を黒で表示します。物体表面に細かな自己影が出る場合はbias不足、影が物体から離れて見える場合はbias過大を疑います。PCF radius 0は1 sample、1は3×3、2は5×5で比較するため、境界の変化と追加sample数を確認できます。
画面手前側を移動する緑色の円柱は両端を平面で閉じ、5本のboneで連続的に曲がりながらNode自体も回転します。端面は側面と頂点を分け、各端のboneへ固定しているため、曲げても側面から分離しません。本体の移動、回転、曲げと床へ落ちる影の輪郭が同時に変化することを確認します。ShadowMapPassはSkeletonごとにbone palette用BufferとBind Groupを再利用し、毎frameは現在のmatrix paletteだけを更新します。static Shapeは同じpipelineを使いますが、skinning無効flagと正式なdummy vertex bindingを渡すため、誤ってbone変形を適用しません。
この版はstatic/skinned opaque Shape、単一directional light、固定解像度1024×1024のshadow mapを対象にしています。spot lightはコアAPIとして追加済みですが、このサンプルでは扱いません。Cascaded Shadow Maps、point light、alpha test、light frustumの自動fitは次段階の検討対象です。