compute_shadow_map

compute_shadow_map

English | 日本語

compute_shadow_map

概要

このサンプルは、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が入力を生成し、SsaoPassDeferredLightingPassが後段で読む現在の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 ComputeGPU RenderGPU TotalGPU 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 はコアの SpotShadowMapPassComputeSpotShadowPass で扱います。spot light では光源位置、照射方向、FOV、inner / outer angle、near、farから透視投影のlight view-projection matrixを作り、coneの外側を徐々に暗くします。このサンプルはdirectional lightの低水準構成を確認するためのものなので、spot light shadowの実行確認は ComputeEffectPipelineshadow.type: "spot" を使うアプリケーション側で行います。

実行方法

操作と確認ポイント

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は次段階の検討対象です。