compute_deferred_lighting
English | 日本語
概要
Deferred Lighting は、geometry を先に G-buffer へ描き、その後で light を pixel 単位に評価する描画構成です。このサンプルでは GeometryBufferPass が albedo、view-space normal、depth を出力し、DeferredLightingPass が最大 128 個の point light を読みながら各 pixel の lighting を計算します
DeferredLightingPass をコアへ切り出した目的は、G-buffer を使う多数ライト評価で毎回繰り返される処理を sample 外へ整理することです。アプリケーション側は scene をどう動かすか、light をどう並べるか、どの view mode を選ぶかに集中し、pass 側は light 配列の検証、world-space から view-space への変換、uniform 更新、storage texture への出力を担当します。この分離により、Geometry Pass、deferred lighting、canvas copy の3段階が main.js から追いやすくなります
使いどころは、G-buffer を使った lighting の最も素直な基準実装を確認したいときです。各 pixel が全 light を走査するため仕組みは読みやすい一方、計算量は light 数に比例して増えます。実用的に大量の light を扱う場合は tiled lighting や clustered lighting へ進む必要がありますが、その前段として入力契約と処理順を確認するには扱いやすい構成です
const deferredPass = new DeferredLightingPass(app.getGPU(), {
label: "compute-deferred",
width: app.screen.getWidth(),
height: app.screen.getHeight(),
maxLights: 128
});
deferredPass.encode(app.getGPU().commandEncoder, gbuffer.getBindingResources(), {
projection,
viewMatrix,
lights,
lightCount: 64,
view: "lighting"
});
この例で projection は createGBufferProjectionParams() が返す 4 要素、viewMatrix は createViewMatrix(app.eye) の結果、lights は { position, color, radius, intensity } を持つ配列です。DeferredLightingPass は G-buffer の生成や canvas への最終 copy は所有しないため、frame の順序はアプリケーション側で明示します
実行方法
- 実行ファイルは ./compute_deferred_lighting.html です
- WebGPU に対応したブラウザで開き、必要に応じて help panel と CommandPalette と合わせて確認してください
確認ポイント
V で lighting / albedo / normal / depth を切り替えます。lighting が壊れた場合でも、albedo、normal、depth を分けて見れば、G-buffer 生成の問題か light 計算の問題かを切り分けられます
1 と 2 で有効な light 数を 16, 32, 64, 96, 128 の順に変更できます。Space で light animation を止めると、同じ G-buffer と light 数で負荷や見え方を比べやすくなります
注意点として、この実装は全 light 走査の素直な構成です。light 数を増やしたときに Compute の負荷が増えること、G-buffer は一度だけ描けばよいこと、debug view が原因切り分けに有効であることを確認するための基準実装として使ってください