compute_deferred_lighting

compute_deferred_lighting

English | 日本語

compute_deferred_lighting

概要

Deferred Lightingは、geometryを先にG-bufferへ描き、保存した表面情報に対して後段で光源を評価する描画方式です。このサンプルではComputeEffectPipelineがGeometry Buffer、Deferred Lighting、tone mappingを接続し、最大128個のLocal Lightをpixel単位で評価します。シーンのgeometryは光源数にかかわらず一度だけ描画されるため、geometryの複雑さと光源評価の複雑さを分けて観察できます。

Local Lightには、全方向へ放射するtype: "point"と、指定方向の円錐内へ放射するtype: "cone"があります。このサンプルは多数灯の負荷を比較しやすくするため、動く光源をすべてpointとして明示します。typeは必須です。coneを使う場合はdirectioninnerAngleouterAngleも必須で、不完全なconeがpointへ置き換えられることはありません。

光源のpositiondirectionはWorld座標系で指定します。DeferredLightingPassは、その描画frameのCameraFrameを使い、位置をcamera-relativeなview-space位置へ、方向を平行移動を含まないview-space方向へ変換します。このため、アプリケーションがprojection配列やview matrixを別々に構築する必要はありません。

光源とフレームの接続

point Local Lightは次のように作ります。

const lights = [{
  type: "point",
  position: [0.0, 2.0, -4.0],
  color: [1.0, 0.45, 0.12],
  radius: 9.0,
  intensity: 3.2
}];

同じframeのcameraFrameをG-buffer生成と照明計算へ渡します。サンプルではShadow、SSAO、SSR、DoF、Bloom、Toon、Edgeを無効にし、多数のLocal LightとG-bufferの関係だけを確認できる構成にしています。

app.start({
  onBeforeDraw: ({ cameraFrame }) => {
    pipeline.renderScene(app.space, cameraFrame, app.clearColor, {
      shadowEnabled: false
    });
  },

  onAfterDraw3d: ({ cameraFrame }) => {
    app.getGPU().endPass();
    const finalColor = pipeline.encode(app.getGPU().commandEncoder, {
      cameraFrame,
      shadowEnabled: false,
      ssaoEnabled: false,
      ssrEnabled: false,
      lights,
      lightCount: 64,
      lightingView: "lighting"
    });
    app.screen.beginPresentPass({ clearColor: app.clearColor });
    copyPass.draw(finalColor);
    app.screen.clearDepthBuffer();
  }
});

lightCountは配列の先頭から評価する灯数です。配列長を超える値やconstructorのmaxLightsを超える値は例外になります。各pixelがすべてのactive lightを走査する基準実装なので、灯数を増やすと計算量も増えます。さらに多くの光源が必要なアプリケーションでは、tiled lightingやclustered lightingを検討します。

実行方法と確認点

compute_deferred_lighting.htmlをWebGPU対応ブラウザで開きます。VまたはCommandPaletteでlighting / albedo / normal / depthを切り替えると、照明結果とG-buffer入力を分けて調べられます。

12、またはCommandPaletteのLightsで、有効灯数を16, 32, 64, 96, 128から選べます。Spaceキーでlight animationを止めると、同じ光源配置のままdebug viewや灯数を比較できます。light数を増やしたときにgeometryの形は変わらず、照明計算の負荷と重なりだけが増えることを確認してください。