<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>RenderingSandbox on ながむしメモ</title><link>https://nagakagachi.github.io/lab/webgpu/experiments/rendering-sandbox/</link><description>Recent content in RenderingSandbox on ながむしメモ</description><generator>Hugo</generator><language>ja-JP</language><lastBuildDate>Sun, 01 Nov 2026 23:13:33 +0900</lastBuildDate><atom:link href="https://nagakagachi.github.io/lab/webgpu/experiments/rendering-sandbox/index.xml" rel="self" type="application/rss+xml"/><item><title>RenderingSandbox v04</title><link>https://nagakagachi.github.io/lab/webgpu/experiments/rendering-sandbox/v04/</link><pubDate>Sun, 01 Nov 2026 00:00:00 +0900</pubDate><guid>https://nagakagachi.github.io/lab/webgpu/experiments/rendering-sandbox/v04/</guid><description>&lt;p&gt;Rust・wgpu・eguiへ移行した版です。WebGPUとWindows DX12で共通の描画処理を使います。WebGLは対象外です。&lt;/p&gt;&#10;&lt;p&gt;GPU Frameは最初のGPUパスからegui描画末尾までの区間時間をmsで示します。非同期で取得した平滑値で、CPU処理・画面表示待ちは含みません。停止中は最終計測値を保持し、非対応環境では計測非対応と表示します。&lt;/p&gt;&#10;&lt;h2 id="rustへの移行"&gt;Rustへの移行&lt;/h2&gt;&#10;&lt;p&gt;描画処理と設定UIをRustへ移し、ブラウザ版はWasm＋WebGPU、Windows版はDX12で動かします。UIにはeguiを使い、起動とイベント処理はwinitが担当します。ブラウザ側のJavaScriptはWasmの読み込みだけです。&lt;/p&gt;&#10;&lt;p&gt;地形のHeight Clipmap、GPUカリングとIndirect Draw、4段CSM、Sky・2次SH・Octahedral Specular IBL、HDR描画とPreExposure、ACES Tonemappingを引き継ぎます。樹木の配置・LODと、枝葉・幹の共有IB＋Storage VBによる描画もRust側で扱います。&lt;/p&gt;&#10;&lt;p&gt;画面内でRendererとModelerを切り替えます。Modelerでは樹形・枝葉クラス・形状バリエーション・LODを確認できます。WASDで前後左右、Q/Eで上下、ドラッグで回転します。Shiftで移動を加速します。&lt;/p&gt;&#10;&lt;h2 id="gpu時間の計測"&gt;GPU時間の計測&lt;/h2&gt;&#10;&lt;p&gt;GPUタイムスタンプに対応する環境ではGPU Frameとパス別の時間を表示します。4組の読戻しバッファを順に使い、結果を非同期取得します。全て使用中ならそのフレームの計測を省略し、描画を待たせません。&lt;/p&gt;&#10;&lt;p&gt;GPU FrameにはHeight・Skyの更新、カリング、各描画パス、eguiの描画を含みます。転送処理・CPU時間・Present待ちは含みません。パス別表示ではHeight・Sky更新の内訳をまだ分離していません。連続描画は既定でONです。表示更新に合わせて毎フレーム描画します。OFFでは静止時の描画を止め、最後の計測値を保持します。3Dビューは16:9を維持します。&lt;/p&gt;&#10;&lt;h2 id="移行時の差と検証範囲"&gt;移行時の差と検証範囲&lt;/h2&gt;&#10;&lt;p&gt;v03は変更せず比較用に残します。モデル生成の演算精度や代表形状の選択順に差があるため、ピクセル単位で同一の絵を保証する移植ではありません。Modelerの全クラス同時比較は未対応です。&lt;/p&gt;&#10;&lt;p&gt;Windows DX12での描画検証、Wasmビルド、データ構造とシェーダの検査を実施しています。長時間動作や実機スマートフォンは未検証です。&lt;/p&gt;&#10;&lt;p&gt;3Dの描画解像度は「描画」から選びます。既定のAutoは表示領域とDPIに追従し、1920×1080を上限とします。720p・1080p・1440p・2160pの固定指定も可能です。いずれも16:9で、eguiの解像度は変更しません。&lt;/p&gt;&#10;&lt;h2 id="ソース"&gt;ソース&lt;/h2&gt;&#10;&lt;p&gt;&lt;a href="https://github.com/nagakagachi/nagakagachi.github.io/tree/main/rendering-sandbox/v04"&gt;共通レンダラ・Modeler・WGSL（GitHub）&lt;/a&gt; · &lt;a href="https://github.com/nagakagachi/nagakagachi.github.io/blob/main/rendering-sandbox/README.md"&gt;ビルドと実行手順&lt;/a&gt;&lt;/p&gt;</description></item><item><title>RenderingSandbox v05</title><link>https://nagakagachi.github.io/lab/webgpu/experiments/rendering-sandbox/v05/</link><pubDate>Sun, 01 Nov 2026 00:00:00 +0900</pubDate><guid>https://nagakagachi.github.io/lab/webgpu/experiments/rendering-sandbox/v05/</guid><description>&lt;p&gt;CSMで不足する近距離のコンタクトと、CSMが届かない遠距離の影を、メインビューの深度を使うScreen Space Shadowで補います。距離対応と旧来の固定レイを切り替え、品質とコストを比較できます。&lt;/p&gt;&#10;&lt;h2 id="screen-space-shadow"&gt;Screen Space Shadow&lt;/h2&gt;&#10;&lt;p&gt;ZPrePass → Screen Shadow Trace → CSM → Forward HDR → PostProcess → eguiの順です。WebGPUでは同じQueueに順に送信し、独立した非同期Computeで動かしているとは扱いません。&lt;/p&gt;&#10;&lt;p&gt;Traceは各対象画素からDirectional Lightへワールド空間でサンプルを配置し、毎回投影して深度を参照します。既定ONのInterleaved Gradient Noise（IGN）で、画素ごとにサンプル列の位相を1ステップ幅内でずらし、規則的な縞やブロック状の誤差を分散します。光源方向やステップ数は変えません。フレーム番号を使わない静的ジッターで、OFFでは従来の区間中央サンプルへ戻せます。Infinity-far Reversed Zの深度から位置を復元し、交差判定はビューZのm単位の厚みで行います。始点バイアスは光源方向の距離です。法線バッファは追加しません。&lt;/p&gt;&#10;&lt;p&gt;既定はフル解像度・16ステップ・レイ長64m・基準厚み0.2m・始点バイアス0.02mです。等倍/縦横1/2/縦横1/4と4/8/16ステップを選択できます。1080pで縦横1/4・8ステップなら、論理的な深度参照数の上限は約1.04M/Frameです。始点の深度取得は別に1回/対象画素あり、空の除外・交差や画面外での終了により実際の回数は変わります。&lt;/p&gt;&#10;&lt;h2 id="サンプル位置と合成の処理"&gt;サンプル位置と合成の処理&lt;/h2&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#e6edf3;background-color:#0d1117;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-wgsl" data-lang="wgsl"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#ff7b72"&gt;let&lt;/span&gt;&lt;span style="color:#6e7681"&gt; &lt;/span&gt;phase&lt;span style="color:#6e7681"&gt; &lt;/span&gt;&lt;span style="color:#ff7b72;font-weight:bold"&gt;=&lt;/span&gt;&lt;span style="color:#6e7681"&gt; &lt;/span&gt;select(&lt;span style="color:#a5d6ff"&gt;0.5&lt;/span&gt;,&lt;span style="color:#6e7681"&gt; &lt;/span&gt;interleavedGradientNoise(originPixel),&lt;span style="color:#6e7681"&gt; &lt;/span&gt;ss.display.w&lt;span style="color:#6e7681"&gt; &lt;/span&gt;&lt;span style="color:#ff7b72;font-weight:bold"&gt;!=&lt;/span&gt;&lt;span style="color:#6e7681"&gt; &lt;/span&gt;&lt;span style="color:#a5d6ff"&gt;0u&lt;/span&gt;);&lt;span style="color:#6e7681"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#ff7b72"&gt;let&lt;/span&gt;&lt;span style="color:#6e7681"&gt; &lt;/span&gt;distance&lt;span style="color:#6e7681"&gt; &lt;/span&gt;&lt;span style="color:#ff7b72;font-weight:bold"&gt;=&lt;/span&gt;&lt;span style="color:#6e7681"&gt; &lt;/span&gt;ss.trace.z&lt;span style="color:#6e7681"&gt; &lt;/span&gt;&lt;span style="color:#ff7b72;font-weight:bold"&gt;+&lt;/span&gt;&lt;span style="color:#6e7681"&gt; &lt;/span&gt;mix(lo,&lt;span style="color:#6e7681"&gt; &lt;/span&gt;hi,&lt;span style="color:#6e7681"&gt; &lt;/span&gt;phase);&lt;span style="color:#6e7681"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;各画素のIGNで区間内の位置を決め、始点バイアスを加えます。lo/hiは初期の細かい区間か、後半の二次配置の区間です。ノイズテクスチャは追加せず、静止時は同じ位置を使います。&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#e6edf3;background-color:#0d1117;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-wgsl" data-lang="wgsl"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#ff7b72"&gt;let&lt;/span&gt;&lt;span style="color:#6e7681"&gt; &lt;/span&gt;contact&lt;span style="color:#6e7681"&gt; &lt;/span&gt;&lt;span style="color:#ff7b72;font-weight:bold"&gt;=&lt;/span&gt;&lt;span style="color:#6e7681"&gt; &lt;/span&gt;min(csm,&lt;span style="color:#6e7681"&gt; &lt;/span&gt;value.y);&lt;span style="color:#6e7681"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#ff7b72"&gt;return&lt;/span&gt;&lt;span style="color:#6e7681"&gt; &lt;/span&gt;mix(contact,&lt;span style="color:#6e7681"&gt; &lt;/span&gt;value.x,&lt;span style="color:#6e7681"&gt; &lt;/span&gt;weight);&lt;span style="color:#6e7681"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;value.yは短距離のコンタクト、value.xはレイ全体の可視率です。Forwardの直射光へ適用する前に、CSMと合成します。weightはCSM終端の90%から1へ遷移し、遠方ではレイ全体の可視率を使います。&lt;/p&gt;&#10;&lt;h2 id="距離に応じたサンプリング"&gt;距離に応じたサンプリング&lt;/h2&gt;&#10;&lt;p&gt;距離対応は既定ONです。視点からの線形深度をzとして、scale=max(1,z/基準距離)で後半のレイを拡張します。既定の基準距離は128m、最大レイ長は8192mです。例えばz=128mまでは64m、z=1024mで512m、z=8192mで4096mのレイになります。&lt;/p&gt;&#10;&lt;p&gt;最初4ステップは、視点距離に関係なく0.25m間隔を維持します。最初から遠景用の大きな間隔で進んで、近い遮蔽物を飛び越えるのを抑えるためです。残り12ステップは、初期区間の終端からレイ終端までを二次分布で配置します。ステップ数自体は増やしません。IGNは各区間の中でサンプル位置をずらします。&lt;/p&gt;&#10;&lt;p&gt;厚みも距離に応じて緩和します。後半の判定幅は「基準厚み×scale＋区間幅×係数」を最大厚みで制限します。既定の係数は0.5、最大厚みは256mです。最初の細かい区間には基準厚みだけを使い、近景の接触部を遠景用の大きな許容幅で潰さないようにします。厚みは深度表面の背後にどれだけ侵入しても交差とみなすか、という近似です。緩和しすぎると別の物体や斜面を誤って遮蔽物と判断します。&lt;/p&gt;&#10;&lt;p&gt;距離対応OFFでは、従来の等間隔レイ・固定厚みへ戻ります。初期ステップ数、初期間隔、基準距離、最大レイ長、最大厚み、区間幅の係数をUIで変更できます。&lt;/p&gt;&#10;&lt;h2 id="csmとの合成"&gt;CSMとの合成&lt;/h2&gt;&#10;&lt;p&gt;1本のレイから、全体の可視率と最初の細かい区間だけの可視率を同時に得ます。CSM範囲内はmin(CSM,contact)で細かいコンタクトを補完し、CSM終端距離の90%から全体の可視率へ補間して、遠景の影へ切り替えます。直射光だけへ適用し、SkyLightには掛けません。&lt;/p&gt;&#10;&lt;p&gt;全体の可視率は既存マスクのR、コンタクトはAへ格納します。追加テクスチャや2本目のレイは使いません。「近景にも長距離成分を合成」は全体の可視率を近景でも適用する比較モードです。CSMがOFFの場合も全体の可視率を使います。&lt;/p&gt;&#10;&lt;h2 id="可視化と比較"&gt;可視化と比較&lt;/h2&gt;&#10;&lt;p&gt;パラメータUIは「ライト」と「シャドウ」を分けています。「シャドウ」の下に「ディレクショナルシャドウ」（CSM・バイアス・PCF・キャスターカリング）と「Screen Space Shadow」を置いています。&lt;/p&gt;&#10;&lt;p&gt;可視率マスク、コンタクトマスク、深度参照数、終了理由をメイン画面へ表示できます。終了理由は赤が交差、緑が未交差、青が画面外/投影範囲外、灰が旧固定モードで除外したCSM範囲内、黒が空です。CSMのみ/Screen Space Shadowのみ/合成の比較も可能です。合成切替ではTraceを継続するため、GPU負荷を比較するときはScreen Space Shadow自体をOFFにしてください。&lt;/p&gt;</description></item><item><title>RenderingSandbox v02</title><link>https://nagakagachi.github.io/lab/webgpu/experiments/rendering-sandbox/v02/</link><pubDate>Wed, 28 Oct 2026 00:00:00 +0900</pubDate><guid>https://nagakagachi.github.io/lab/webgpu/experiments/rendering-sandbox/v02/</guid><description>&lt;p&gt;学習用にAgentCodingで生成したデモです&lt;/p&gt;&#10;&lt;p&gt;&lt;a href="../"&gt;版一覧&lt;/a&gt; · &lt;a href="../v01/"&gt;前の版：v01&lt;/a&gt;&lt;/p&gt;&#10;&lt;p&gt;地形を使ってCSMとPBR、天空IBLを確認するレンダリング実験です。v02では2048×2048のAtlasに4カスケードのShadow Mapを描画し、直接光のGGX鏡面反射と、Octahedral Mapを使ったSpecular IBLを追加しています。&lt;/p&gt;&#10;&lt;!-- demo --&gt;&#10;&lt;h2 id="操作"&gt;操作&lt;/h2&gt;&#10;&lt;p&gt;「実行」で開始します。WASDで前後左右、Q/Eで上下、Shiftで加速、ドラッグ・矢印キーで視点を回転します。ホイールでも前後へ移動できます。&lt;/p&gt;&#10;&lt;p&gt;設定パネルは3Dビュー程度の高さで内部スクロールします。上から描画・カメラ・地形・ライト／シャドウ・Sky・デバッグの順です。&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;地形のRoughness・Metallicと固定RGBアルベドで材質を変更できます。RGBは0〜1のリニア反射率です&lt;/li&gt;&#10;&lt;li&gt;直接光とSpecular IBLは個別にOFFにできます。SkyLight強度はDiffuseとSpecularの両方に掛かります&lt;/li&gt;&#10;&lt;li&gt;カメラの露出はEV100、−10〜15です。値を1増やすと光量は半分になります&lt;/li&gt;&#10;&lt;li&gt;シャドウ距離はCSM全体の最遠距離です。既定は4096 mで、4段の分割位置を自動で求めます&lt;/li&gt;&#10;&lt;li&gt;「太陽を動かす」で方位角を毎フレーム変更し、天空・SH・GGX Prefilterを同じフレームで更新します。OFFでは静止画を連続描画しません&lt;/li&gt;&#10;&lt;li&gt;「GGX Octahedral Map」と「GGX Mip」で、Prefiltered Mapの各Mipを表示できます。元のSky Mapと同時にONにすると左右へ並びます&lt;/li&gt;&#10;&lt;li&gt;Sky枠に大気遠近法とSkyLightの設定をまとめています&lt;/li&gt;&#10;&lt;li&gt;デバッグの「メインビュー表示」でメイン深度を全画面表示、「シャドウAtlas（RawDepth）」でシャドウマップを小窓表示できます&lt;/li&gt;&#10;&lt;li&gt;デバッグの「CSMテクセルグリッド」は各段の光源投影上に1・4・16テクセル間隔の格子を表示します。CSM色分けと併用でき、段の切替で世界空間の密度が変わる様子を確認できます。範囲外は暗いグレーです&lt;/li&gt;&#10;&lt;li&gt;CSM色分けは参照するシャドウ段、Height Clipmap色分けは標高段、HeightMapグリッドは16×16標高テクセル単位を示します&lt;/li&gt;&#10;&lt;li&gt;「カリング・配置を固定」で可視リストと標高窓・シャドウ投影を固定できます。検証中は太陽アニメーションも止まります&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;h2 id="描画パス"&gt;描画パス&lt;/h2&gt;&#10;&lt;p&gt;必要な標高更新、天空生成、SH投影、GGX Prefilter、各視点のGPUカリングの後、次の順で描画します。&lt;/p&gt;&#10;&lt;table&gt;&#10;&#9;&lt;thead&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;パス&lt;/th&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;処理&lt;/th&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&lt;/thead&gt;&#10;&#9;&lt;tbody&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;ZPrePass&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;メイン視点の深度を確定&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;ShadowPass&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;Atlas内の4領域へカスケードごとのZOnly描画&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;ForwardShadingPass&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;GGX＋Lambertの直接光、Diffuse／Specular IBL、大気遠近法、天球をHDR出力&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;環境マップのデバッグ表示&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;通常表示時は天空・GGXテクスチャをHDRカラーへ重ねる&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;最終表示&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;通常時はPostProcessPassでACES FilmicとsRGB符号化を適用。メイン深度表示時は深度テクスチャを直接表示&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;シャドウAtlasのデバッグ表示&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;ONの場合は最終表示へ小窓を重ねる&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&lt;/tbody&gt;&#10;&lt;/table&gt;&#10;&lt;p&gt;ZOnlyはZPrePassとShadowPassで同じ原本を使います。Forwardは深度ReadOnly・Equal比較です。位置計算は&lt;code&gt;terrain-geometry.wgsl&lt;/code&gt;で共有し、不透明PSにはdiscard・深度出力・Storage書き込みを置きません。&lt;/p&gt;&#10;&lt;h2 id="cascaded-shadow-maps"&gt;Cascaded Shadow Maps&lt;/h2&gt;&#10;&lt;h3 id="分割とatlas"&gt;分割とAtlas&lt;/h3&gt;&#10;&lt;p&gt;Shadow Mapは2048×2048の&lt;code&gt;depth32float&lt;/code&gt;を1枚、容量16 MiBです。2×2に分け、それぞれ1024×1024の4カスケードを配置します。clear=0、書込greater、参照greater-equalのReversed Zです。&lt;/p&gt;&#10;&lt;p&gt;視点のnear=1 mと指定距離の間を、対数分割75%・一様分割25%で分けます。各分割の受光フラスタムの外接球を求め、光源の正射影の中心をシャドウテクセル単位でスナップします。球の半径はカメラの回転に依存しないため、回転時に投影サイズが伸縮するのを抑えます。&lt;/p&gt;&#10;&lt;p&gt;各カスケードの距離範囲の末尾10%は隣のカスケードもサンプリングしてブレンドします。次のカスケードの投影範囲にも、このブレンド領域を含めます。PCFは1・3×3・5×5を選べます。各サンプルのUVを、対象カスケードの領域の端から半テクセル内側までに制限し、Atlasの隣の領域を参照しません。&lt;/p&gt;&#10;&lt;h3 id="shadowcastervolumeculling"&gt;ShadowCasterVolumeCulling&lt;/h3&gt;&#10;&lt;p&gt;ShadowCasterVolumeCullingを使用しています。受光フラスタムを光源方向へ押し出したShadow Caster Volumeを求め、その体積と光源の正射影フラスタムの両方に対して、GPUでタイルのAABBを判定します。&lt;/p&gt;&#10;&lt;p&gt;メイン視点の可視リストをシャドウへ流用すると、画面外から入る影が消えます。一方、球を囲む光源ボックスだけでは、受光領域へ影を落とせないタイルも残ります。そこで分割ごとの受光フラスタムから、光源側へ押し出しても有効な面とシルエット辺の側面を求め、追加のカリング平面として渡します。光源側へ伸びる体積を使うので、メインビューでは見えないキャスターも残します。&lt;/p&gt;&#10;&lt;p&gt;&lt;img src="shadow-caster-volume-culling.svg" alt="1カスケードを上から見た模式図。緑は受光フラスタムを光源方向へ押し出した領域。視野外のAは影が届くため残し、光源フラスタム内のBは影が届かないため除外する"&gt;&lt;/p&gt;</description></item><item><title>RenderingSandbox v01</title><link>https://nagakagachi.github.io/lab/webgpu/experiments/rendering-sandbox/v01/</link><pubDate>Tue, 27 Oct 2026 00:00:00 +0900</pubDate><guid>https://nagakagachi.github.io/lab/webgpu/experiments/rendering-sandbox/v01/</guid><description>&lt;p&gt;学習用にAgentCodingで生成したデモです&lt;/p&gt;&#10;&lt;p&gt;&lt;a href="../"&gt;版一覧&lt;/a&gt; · &lt;a href="../v00/"&gt;前の版：v00&lt;/a&gt;&lt;/p&gt;&#10;&lt;p&gt;地形・シャドウ・天球を組み合わせたHDRレンダリングの実験環境です。地球の大気散乱、2次SHによるスカイライト、大気遠近法を扱い、PreExposureを適用したHDRカラーを最後にトーンマッピングして表示します。&lt;/p&gt;&#10;&lt;!-- demo --&gt;&#10;&lt;h2 id="操作と表示"&gt;操作と表示&lt;/h2&gt;&#10;&lt;p&gt;「実行」で開始します。ビューをクリックし、WASDで前後左右、Q/Eで上下、Shiftで加速、ドラッグ・矢印キーで視点を回転します。ホイールでも前後へ移動できます。&lt;/p&gt;&#10;&lt;p&gt;設定はビュー横のパネルにまとめています。横並びでは実行ボタンと3Dビューを合わせた高さを上限としてパネル内をスクロールできます。狭い画面ではビュー下へ移り、設定欄の高さを制限します。地形シードなどは「地形」で変更し、生成ボタンで適用します。ライトの方位角0°は+Z、90°は+X、仰角は水平からの角度です。&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;「大気遠近法」で、遠景の減衰と散乱光の有無を比較できます&lt;/li&gt;&#10;&lt;li&gt;「カメラ」の露出 EV100は−10〜15で調整できます。EVが1増えると光量は半分になります。垂直画角は30〜110°で変更できます&lt;/li&gt;&#10;&lt;li&gt;「地形」のアルベドを固定値にすると、RGB各成分のリニア反射率を調整できます&lt;/li&gt;&#10;&lt;li&gt;「ライト・シャドウ」の直接光をOFFにすると、天空を維持したまま地形への直射光だけを無効にできます&lt;/li&gt;&#10;&lt;li&gt;「SkyLight」の強度は地表の拡散環境光へ作用します&lt;/li&gt;&#10;&lt;li&gt;「診断」のSky Octahedral MapをONにすると、SkyLightの入力テクスチャをビュー左上へ表示します&lt;/li&gt;&#10;&lt;li&gt;「診断」のHeight Clipmap色分けとHeightMapグリッドで、標高キャッシュの参照段と解像度を確認できます&lt;/li&gt;&#10;&lt;li&gt;「診断」の法線・タイル色・シャドウ可視率で形状やカリングを確認できます。可視率は白が受光、黒が遮蔽です&lt;/li&gt;&#10;&lt;li&gt;「カリング・配置を固定」では、可視リストと地形配置を固定したままカメラを移動できます&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p&gt;メトリクスの「実行状況」には可視タイル数や更新状況、「構成情報」には適用中の条件とGPUリソースを表示します。&lt;/p&gt;&#10;&lt;h2 id="描画パス"&gt;描画パス&lt;/h2&gt;&#10;&lt;table&gt;&#10;&#9;&lt;thead&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;パス&lt;/th&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;出力・役割&lt;/th&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&lt;/thead&gt;&#10;&#9;&lt;tbody&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;ZPrePass&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;メインビューの深度を確定&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;ShadowPass&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;ライト視点のShadow Mapを生成&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;ForwardShadingPass&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;直接光・SkyLight・大気遠近法と天球を、PreExposure済みの線形HDRへ出力&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;PostProcessPass&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;HDRカラーを読み、トーンマッピング・表示色変換を適用&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&lt;/tbody&gt;&#10;&lt;/table&gt;&#10;&lt;p&gt;デバッグ表示がONの場合だけ、ForwardShadingPassとPostProcessPassの間にSkyMapDebugPassを発行します。&lt;/p&gt;&#10;&lt;p&gt;これらの前に、必要な標高キャッシュ更新、天空環境の生成・SH投影、Main/ShadowのカリングをComputeで行います。ZPrePassをShadowPassより前に置くのは、将来SSAOなどがメイン深度を参照する構成を想定しているためです。この版ではSSAOや非同期Computeは実装していません。&lt;/p&gt;&#10;&lt;p&gt;不透明物の描画契約は&lt;code&gt;render-passes.ts&lt;/code&gt;の&lt;code&gt;OpaqueRenderable&lt;/code&gt;です。今後追加するモデルも、深度用のZOnlyバリエーションとForwardバリエーションをこの契約へ登録します。背景の天球は別の&lt;code&gt;BackgroundRenderable&lt;/code&gt;として扱います。&lt;/p&gt;&#10;&lt;h2 id="地形とgpuカリング"&gt;地形とGPUカリング&lt;/h2&gt;&#10;&lt;p&gt;地形は&lt;a href="../../terrain-rendering00/"&gt;TerrainRendering00&lt;/a&gt;のタイルClipmap方式を引き継いでいます。64×64セルのタイルを共有IBで描画し、VBは持ちません。標高はComputeで生成し、1024²を基本としたFP16のHeight Clipmapに保持します。&lt;/p&gt;&#10;&lt;p&gt;カリングはメインビューとライト視点で独立して行います。それぞれにScene Uniform・可視タイルIDリスト・Indirect引数を持ち、各視点のフラスタムと地形の保守的AABBで判定します。メインで不可視のタイルも、ライトの描画範囲にあればシャドウキャスターとして残します。&lt;/p&gt;&#10;&lt;p&gt;可視リストの領域予約はsubgroupで集約し、未対応環境ではworkgroup scanを使います。描画はGPU上の可視リストとIndirect引数を参照し、CPUへ可視数を読み戻して描画を制御する構成にはしていません。メトリクス用の読み戻しだけを非同期で行います。&lt;/p&gt;&#10;&lt;h3 id="セルスナップと三角形分割の安定性"&gt;セルスナップと三角形分割の安定性&lt;/h3&gt;&#10;&lt;p&gt;共有タイルIBの対角線はセルごとに交互となるため、各LODは2セル単位でスナップします。1セル移動で同じ世界セルの対角線が反転する現象を防ぎます。接続帯は外周8行を使い、同じ粗格子点へ集約する頂点に共通の変形・標高混合率を与えます。通常部の格子と三角形分割は固定されますが、LOD接続帯の切り替わりによる形状変化は残ります。&lt;/p&gt;&#10;&lt;h3 id="height-clipmapの色分け"&gt;Height Clipmapの色分け&lt;/h3&gt;&#10;&lt;p&gt;「診断」のHeight Clipmap色分けで、描画に参照している標高キャッシュの段を表示します。段0〜6は赤・橙・黄緑・緑・水色・青紫・赤紫です。メッシュLOD0と1は同じ標高段0を使うため同じ色になります。接続帯では標高と同じ重みで隣の段の色へ補間します。標高窓全体の範囲ではなく、地形描画がどの段を参照しているかの可視化です。&lt;/p&gt;&#10;&lt;p&gt;照明・アルベド・大気遠近法は適用せず、カメラ露出とトーンマッピングは共通の経路を通します。この表示は法線・タイル色・シャドウ可視率より優先されます。ワイヤーフレームは重ねられます。&lt;/p&gt;&#10;&lt;h3 id="heightmapのテクセルグリッド"&gt;HeightMapのテクセルグリッド&lt;/h3&gt;&#10;&lt;p&gt;「診断」のHeightMapグリッドで、各標高段の16×16テクセルを1マスとした世界XZ平面上の格子を表示します。段0〜6の格子間隔は16・32・64・128・256・512・1024 mです。Height Clipmap色分けと併用でき、単独ではグレー地に格子を表示します。接続帯は参照する2段の格子を標高と同じ重みで混合します。ワールド原点に固定するため、トロイダル更新で格子の位相は動きません。線は画面上の微分でアンチエイリアスし、細かくなりすぎる遠方では減衰させます。メッシュのワイヤーフレームとは異なり、標高データ側の解像度を示します。&lt;/p&gt;&#10;&lt;h2 id="深度プリパスとシャドウマップ"&gt;深度プリパスとシャドウマップ&lt;/h2&gt;&#10;&lt;h3 id="zonlyバリエーション"&gt;ZOnlyバリエーション&lt;/h3&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#e6edf3;background-color:#0d1117;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-wgsl" data-lang="wgsl"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#ff7b72"&gt;return&lt;/span&gt;&lt;span style="color:#6e7681"&gt; &lt;/span&gt;terrainVertex(id,&lt;span style="color:#6e7681"&gt; &lt;/span&gt;instance).clip;&lt;span style="color:#6e7681"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;terrain-geometry.wgsl&lt;/code&gt;にある位置・標高・LOD接続の計算を、ZOnlyとForwardで共有します。ZOnlyは位置だけを出力し、法線の取得やPSを持ちません。メインとライトでは同じZOnly Pipelineを使い、視点のUniformと可視リストを切り替えます。&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#e6edf3;background-color:#0d1117;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ts" data-lang="ts"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;depthStencil&lt;span style="color:#ff7b72;font-weight:bold"&gt;:&lt;/span&gt; { format&lt;span style="color:#ff7b72;font-weight:bold"&gt;:&lt;/span&gt; &lt;span style="color:#a5d6ff"&gt;&amp;#39;depth32float&amp;#39;&lt;/span&gt;, depthWriteEnabled: &lt;span style="color:#ff7b72"&gt;false&lt;/span&gt;, depthCompare&lt;span style="color:#ff7b72;font-weight:bold"&gt;:&lt;/span&gt; &lt;span style="color:#a5d6ff"&gt;&amp;#39;equal&amp;#39;&lt;/span&gt; }&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;ForwardはZPrePassの深度をReadOnlyで参照し、Equal比較で描画します。頂点位置の計算を一致させ、両バリエーションの位置出力に&lt;code&gt;invariant&lt;/code&gt;を付けています。不透明PSにはdiscard/clip・深度出力・Storage書き込みを置きません。&lt;/p&gt;</description></item><item><title>RenderingSandbox v00</title><link>https://nagakagachi.github.io/lab/webgpu/experiments/rendering-sandbox/v00/</link><pubDate>Mon, 26 Oct 2026 00:00:00 +0900</pubDate><guid>https://nagakagachi.github.io/lab/webgpu/experiments/rendering-sandbox/v00/</guid><description>&lt;p&gt;学習用にAgentCodingで生成したデモです&lt;/p&gt;&#10;&lt;p&gt;&lt;a href="../"&gt;版一覧&lt;/a&gt; · &lt;a href="../v01/"&gt;次の版：v01&lt;/a&gt;&lt;/p&gt;&#10;&lt;p&gt;公開初版を保存したv00です。この版の実装は固定し、新しい開発は別の版で行います。&lt;/p&gt;&#10;&lt;p&gt;TerrainRendering00をベースにしたレンダリング実験環境です。現在はプロシージャル地形に、ZPrePass・ShadowPass・ForwardShadingPassを適用し、ピクセルレイの天球と1次SHのDiffuse SkyLightを加えています。今後、配置物や新しいシャドウ技法、GIを追加していく実験環境の初版です。&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;「実行」で開始。ビューをクリックし、WASDで前後左右、Q/Eで上下、Shiftで加速、ドラッグ・矢印キーで回転します&lt;/li&gt;&#10;&lt;li&gt;ライトは方位角と仰角で変更できます。方位角0°は+Z、90°は+X、仰角は水平からの角度です&lt;/li&gt;&#10;&lt;li&gt;シャドウON/OFFで影を比較できます。「シャドウ可視率表示」は白が受光、黒が遮蔽です。法線表示はこれより優先します&lt;/li&gt;&#10;&lt;li&gt;Shadow Mapは2048²の1枚です。投影半幅の初期値は2kmで、光源平面の4km四方をカバーします。範囲外は影なしで表示します&lt;/li&gt;&#10;&lt;li&gt;深度バイアス・法線バイアス・PCFを調整できます。PCFの各tapにもハードウェアの線形比較フィルタが掛かります&lt;/li&gt;&#10;&lt;li&gt;SkyLight Diffuseの強度で、天球から投影したSH拡散光を調整できます。法線方向によって値が変わり、影内だけでなく全体へ適用します。背景の空の明るさとは独立した調整です&lt;/li&gt;&#10;&lt;li&gt;タイル色分け・ワイヤーフレーム・セルスナップ・密度・カバー半径はTerrainRendering00と同じです&lt;/li&gt;&#10;&lt;li&gt;フリーズはMain/Shadowの両可視リスト、地形配置、標高キャッシュ、光源投影を固定します。カメラだけを動かして、カリング結果を観察できます&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p&gt;操作はWebGPU対応ブラウザとキーボード・マウスを使うPC向けです。衝突判定はありません。静止中は連続描画せず、カメラやライト操作時に再描画します。&lt;/p&gt;&#10;&lt;!-- demo --&gt;&#10;&lt;h2 id="passの構成"&gt;Passの構成&lt;/h2&gt;&#10;&lt;p&gt;空の変更時にOctahedral生成・SH投影 → 標高の差分生成 → Main/Shadowの独立カリング → ZPrePass → ShadowPass → ForwardShadingPassの順に発行します。&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#e6edf3;background-color:#0d1117;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ts" data-lang="ts"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#ff7b72"&gt;object&lt;/span&gt;.drawDepth(prepass, &lt;span style="color:#a5d6ff"&gt;&amp;#39;main&amp;#39;&lt;/span&gt;);&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#ff7b72"&gt;object&lt;/span&gt;.drawDepth(shadow, &lt;span style="color:#a5d6ff"&gt;&amp;#39;shadow&amp;#39;&lt;/span&gt;);&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#ff7b72"&gt;object&lt;/span&gt;.drawForward(forward);&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;background&lt;span style="color:#ff7b72;font-weight:bold"&gt;?&lt;/span&gt;.draw(forward);&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;ZPrePassでメイン深度を先に確定し、将来のSSAOなどがこの深度を参照できる順序にしています。現時点ではSSAOや非同期Computeを追加していません。&lt;/p&gt;&#10;&lt;p&gt;Passの発行は&lt;code&gt;render-passes.ts&lt;/code&gt;、地形の描画・資源の管理は&lt;code&gt;main.ts&lt;/code&gt;が担当します。今後の不透明モデルも&lt;code&gt;OpaqueRenderable&lt;/code&gt;へ登録し、位置専用のZOnlyバリエーションとForwardバリエーションを用意する枠組みです。モデル読み込みはまだ実装していません。背景の天球は不透明物とは別の描画契約で登録します。&lt;/p&gt;&#10;&lt;h2 id="共通の位置計算とzonly"&gt;共通の位置計算とZOnly&lt;/h2&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#e6edf3;background-color:#0d1117;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-wgsl" data-lang="wgsl"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#ff7b72"&gt;return&lt;/span&gt;&lt;span style="color:#6e7681"&gt; &lt;/span&gt;terrainVertex(id,&lt;span style="color:#6e7681"&gt; &lt;/span&gt;instance).clip;&lt;span style="color:#6e7681"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;terrain-geometry.wgsl&lt;/code&gt;の位置・標高・LOD接続計算を、ZOnlyとForwardへ同じソースとして組み込みます。&lt;code&gt;terrain-zonly.wgsl&lt;/code&gt;は位置だけを返し、法線取得やPSはありません。メインとシャドウは同じZOnly Pipelineを使い、group(0)の視点と可視リストだけを変更します。&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#e6edf3;background-color:#0d1117;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ts" data-lang="ts"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;depthStencil&lt;span style="color:#ff7b72;font-weight:bold"&gt;:&lt;/span&gt; { format&lt;span style="color:#ff7b72;font-weight:bold"&gt;:&lt;/span&gt; &lt;span style="color:#a5d6ff"&gt;&amp;#39;depth32float&amp;#39;&lt;/span&gt;, depthWriteEnabled: &lt;span style="color:#ff7b72"&gt;false&lt;/span&gt;, depthCompare&lt;span style="color:#ff7b72;font-weight:bold"&gt;:&lt;/span&gt; &lt;span style="color:#a5d6ff"&gt;&amp;#39;equal&amp;#39;&lt;/span&gt; }&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;ZPrePassが深度を書き、ForwardはReadOnlyの深度AttachmentへEqual比較で描画します。両方の位置出力に&lt;code&gt;invariant&lt;/code&gt;を指定し、同じ頂点位置計算を使います。不透明PSでdiscard/clip、深度出力、Storage書込を行いません。将来、頂点変形を追加するときもZOnlyとForwardで同じ位置を出す必要があります。&lt;/p&gt;&#10;&lt;h2 id="シャドウ用のカリング"&gt;シャドウ用のカリング&lt;/h2&gt;&#10;&lt;p&gt;メイン用とシャドウ用で480バイトのScene Uniform、6,400バイトの可視タイルリスト、20バイトのIndirect引数を別々に保持します。ライトの正射影行列から6平面を取り、地形の保守的AABBで判定します。メインで見えない地形も、光源側の範囲に入ればキャスターとして描画します。&lt;/p&gt;&#10;&lt;p&gt;候補タイル・LOD・標高キャッシュは共通です。シャドウのために別のLOD地形を生成しないので、受け手とキャスターの形状が一致します。subgroup集約、未対応時のworkgroup scanも維持しています。表示用の可視数だけを非同期で読み、描画にCPU読戻しは使いません。&lt;/p&gt;&#10;&lt;h2 id="directional-lightと影の参照"&gt;Directional Lightと影の参照&lt;/h2&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#e6edf3;background-color:#0d1117;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-wgsl" data-lang="wgsl"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#ff7b72"&gt;let&lt;/span&gt;&lt;span style="color:#6e7681"&gt; &lt;/span&gt;direct&lt;span style="color:#6e7681"&gt; &lt;/span&gt;&lt;span style="color:#ff7b72;font-weight:bold"&gt;=&lt;/span&gt;&lt;span style="color:#6e7681"&gt; &lt;/span&gt;lighting.light.w&lt;span style="color:#6e7681"&gt; &lt;/span&gt;&lt;span style="color:#ff7b72;font-weight:bold"&gt;*&lt;/span&gt;&lt;span style="color:#6e7681"&gt; &lt;/span&gt;max(dot(n,&lt;span style="color:#6e7681"&gt; &lt;/span&gt;lighting.light.xyz),&lt;span style="color:#6e7681"&gt; &lt;/span&gt;&lt;span style="color:#a5d6ff"&gt;0.0&lt;/span&gt;)&lt;span style="color:#6e7681"&gt; &lt;/span&gt;&lt;span style="color:#ff7b72;font-weight:bold"&gt;*&lt;/span&gt;&lt;span style="color:#6e7681"&gt; &lt;/span&gt;visibility&lt;span style="color:#6e7681"&gt; &lt;/span&gt;&lt;span style="color:#ff7b72;font-weight:bold"&gt;/&lt;/span&gt;&lt;span style="color:#6e7681"&gt; &lt;/span&gt;&lt;span style="color:#a5d6ff"&gt;3.14159265&lt;/span&gt;;&lt;span style="color:#6e7681"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;今回のライティングは正規化Lambertの直射光と、仮のSkyLight Diffuseです。直射光だけにShadow Mapの可視率を掛けます。地形の標高に応じた無彩色アルベドに適用し、最後に近似ガンマ変換します。&lt;/p&gt;</description></item></channel></rss>