超雑訳 Supplementary Document: Generalized Resampled Importance Sampling: Foundations of ReSTIR

こんこよ~。Pocolです。
今日は以前に読んだ,Generalized Resampled Importance Sampling: Foundations of ReSTIRの補足資料である
[Lin 2022] Daqi Lin, Markus Kettunen, Benedikt Bitterli, Jacopo Pantaleoni, Cem Yuksel, Chris Wyman, “Supplementary Document: Generalized Resampled Importance Sampling: Foundation of ReSTIR”, https://research.nvidia.com/publication/2022-07_generalized-resampled-importance-sampling-foundations-restir, 2022.
を読んでみます。
いつもながら,誤字・誤訳があるかと思いますので,ご指摘頂ける場合は正しい翻訳例と共に指摘して頂けるとありがたいです。

(さらに…)

FrameGraph関連の資料

実装用のネタ帳です。

● FrameGraph: Extensible Rendering Architecture in Frostbite
https://www.gdcvault.com/play/1024612/FrameGraph-Extensible-Rendering-Architecture-in

● Advanced Graphics Tech: Moving to DirectX12: Lessons Learned
https://www.gdcvault.com/play/1024656/Advanced-Graphics-Tech-Moving-to

● fg
https://github.com/acdemiralp/fg

● Why Talking About Render Graphs
https://logins.github.io/graphics/2021/05/31/RenderGraphs.html

● Task Graph Renderer At Activision
https://research.activision.com/publications/2023/06/Task-Graph-Renderer-at-Activision

● Organizing GPU Work with Directed Acyclic Graphs
https://levelup.gitconnected.com/organizing-gpu-work-with-directed-acyclic-graphs-f3fd5f2c2af3

● Render graphs and Vulkan – a deep dive
https://themaister.net/blog/2017/08/15/render-graphs-and-vulkan-a-deep-dive/

● Unreal Engine 5 – Render Dependency Graph
https://docs.unrealengine.com/5.3/en-US/render-dependency-graph-in-unreal-engine/

● GPU synchronization in Godot 4.3 is getting a major upgrade
https://godotengine.org/article/rendering-acyclic-graph/

● Render Graph 101
https://blog.traverseresearch.nl/render-graph-101-f42646255636

● An update to our Render Graph
https://blog.traverseresearch.nl/an-update-to-our-render-graph-17ca4154fd23

● EmbarkStudios kajiya-rg
https://github.com/EmbarkStudios/kajiya/tree/main/crates/lib/kajiya-rg

● Mastering Graphics Programming with Vulkan
https://github.com/PacktPublishing/Mastering-Graphics-Programming-with-Vulkan

● Render graphs
https://apoorvaj.io/render-graphs-1/

Virtual Texture関連の資料

Virtual Texture関連の私的メモです。

● Software Virtual Textures
https://mrelusive.com/publications/pubs_bytype.html
https://studiopixl.com/2022-04-27/sparse-virtual-textures

● Using Virtual Texturing to Handle Massive Texture Data
https://www.nvidia.com/content/GTC-2010/pdfs/2152_GTC2010.pdf

● Sparse Virtual Texturing
https://silverspaceship.com/src/svt/

● Advanced Virual Textures Topics
https://pdfs.semanticscholar.org/32f7/49c984e1ebd97e85f90d96b8ee5ed35c143a.pdf
https://dokumen.tips/documents/chapter02-mittring-advanced-virtual-texture-topics.html

● Virtual Texturing in Software and Hardware
https://mrelusive.com/publications/presentations/2012_siggraph/Virtual_Texturing_in_Software_and_Hardware_final.pdf

● Adaptive Virtual Texture Rendering in Far Cry 4
https://www.gdcvault.com/play/1021761/Adaptive-Virtual-Texture-Rendering-in

● Terrain Rendering in ‘Far Cry5’
https://www.gdcvault.com/play/1025480/Terrain-Rendering-in-Far-Cry

● Sampler Feedback
https://microsoft.github.io/DirectX-Specs/d3d/SamplerFeedback.html

1-Phase Occlusion Culling

完全に私的な実装メモです。
通常,オクルージョンカリングを実装する際は,GPU Zenやもんしょさんのサイトに載っているように2-Phaseでジオメトリ描画して実装するのが普通かと思います。
少し前ですが,GDC 2021の“Samurai Landscapes: Building and Rendering Tsushima Island on PS4”というセッションの,43:45あたりから,Occlusion-Cullingについての説明があり,Ghost of Tsushimaの実装では,前フレームの深度バッファと,それらから保守的(conservative)に作成したミップレベル,エピポラーサーチを用いて,現在フレームの深度バッファを復元し,1回のジオメトリ描画でオクルージョンカリングを実装する方法が紹介されています。
説明が分かりやすいので,アルゴリズムについては元動画を参照してください。
馬鹿まじめに線形探索をせずに,ミップマップを使って検索するのがアルゴリズムのキモみたいです。

一応実装コードが紹介されていますが,動画の品質が低すぎて全然良く見えませんw。
そこで,それっぽい感じに見えるコードを自分で推測しながら書いてみました。
推測で書いているのと,きちんと動作検証もしていないので,バグっている可能性があるので,まんまコピペで使用して不都合・不利益が発生しても何ら責任は負いませんのでご注意ください。
もし、「ここはこうじゃね?」とかアドバイスあればコメントください。

Depth Reprojection

// Forward-project last frame's depth to this frame's space
{
    float zPrev = pSrt->m_texIn[dispatchThreadId.xy];
    float zDepthPrev = DepthFromWorld(zPrev, pSrt->m_vecRecoryHypebolicDepth);

    float4 posClipPrev = float4(VecClipFromUv(uvThread), zDepthPrev, 1.0f);
    posClipPrev *= zPrev; // This ensure that zCur will end up in posClip.w;

    float4 posClip = mul(posClipPrev, pSrt->m_matClipPrevToClipCur);
    posClip.xyz /= posClip.w;

    float2 uv = UvFromVecClip(posClip.xy);

    if (all(uv >= pSrc->m_rectScissor.xy) && all(uv >= pSrc->m_rectScissor.zw))
    {
        // NOTE : z ends up in posClip.w so we can use that directly.
        float z = posClip.w;
        
        if (z < pSrt->m_zNear)
            z = pSrt->m_zFar;

        // NOTE : Add a small bias to resolve self-occlusion artifacts
        z += pSrt->m_dsBias;

        if (z > pSrt->m_zFar || zPrev >= pSrt->m_zFar)
            z = pSrt->m_zFar;

        float2 xy = floor(uv * pSrt->m_texture.m_dXy); // 多分、テクスチャサイズを乗算してウィンドウサイズに戻している。
  
        AtomicMax(pSrt->m_texOut[xy], z);
    }
}

{
     float4 posClip = float4(VecClipFromUv(uvThread), 0.0f, 1.0f);

     float4 posClipPrev = mul(posClip, pSrt->matClipCurToClipPrev);

     if (any(abs(posClipPrev.xy) >= abs(posClipPrev.w))
     {
          float2 uv = UvFromVecClip(posClipPrev.xy / posClipPrev.w);

          float z = pSrt->m_texIn->SampleLOD(pSrt->m_sampler, uv, 0) * pSrt->m_dsBias;

          AtomicMax(pSrt->m_texOut[dispatchThreadId.xy], z);
     }
}

Hole-Filling

float2 uv = (dispatchThreadId.xy + 0.5f.xx) * pSrt->m_texture.m_div;
float zMax = pSrt->m_texIn.SampleLOD(pSrt->m_sampler, uv, 0);

if (zMax == -FLT_MAX)
{
    float2 normalEpipole = normalize(pSrt->m_uvEpipole * uv);
    float2 dUvStep = pSrt->m_texture.m_div * normalEpipole;

    for(uint iMip = 1; iMip <= pSrt->m_iMipLast; ++iMip)
    {
        float2 uvSearch = uv - dUvStep;
        dUvStep *= 2.0;

        float z = pSrt->m_texIn.SampleLOD(pSrt->m_sampler, uvSearch, iMip);

        if (z != -FLT_MAX)
        {
            z = max(z, pSrt->m_texOut[dispatchThreadId.xy]);
            z *= pSrt->m_dsBias;
            z = min(z, pSrt->m_zFar);
            pSrt->m_texOut[dispatchThreadId.xy] = z;

            return;
        }
    }

    if (zMax < pSrt->m_zNear)
        zMax = pSrt->m_zFar;

    zMax = min(zMax, pSrt->m_zFar);

    pSrt->m_texOut[dispatchThreadId.xy] = zMax;
}

超雑訳 Supplementary Document for Moment Transparency

ちわっす。Pocolです。
前回読んだ,Moment Transparencyの補足資料をみていくことにします。
[Sharpe 2018] Brian Sharpe, “Supplementary Document for Moment Transparency”, HPG 18, https://dl.acm.org/doi/10.1145/3231578.3231585, 2018.

いつもながら、誤字・誤訳があるかと思いますので,ご指摘頂ける場合は正しい翻訳例と共に指摘して頂けるとありがたいです。

(さらに…)

超雑訳 Moment Transparency

こんぺこー。Pocolです。
引き続き,OIT関連の資料を見てみます。
今日は…
[Sharpe 2018] Brian Sharpe, “Moment Transparency”, HPG 2018, No.8, pp.1-4, 2018
を読んでみようと思います。
いつもながら、誤字・誤訳があるかと思いますので,ご指摘頂ける場合は正しい翻訳例と共に指摘して頂けるとありがたいです。
(さらに…)

超雑訳 Supplementary Document on Moment-Based Order-Independent Transparency

こんこよー。Pocolです。
今日は,前回読んだ Moment-Based OITの補足資料を読むことにします。
[Münstermann 2018], Cedrick Münstermann, Stefan Krumpen, Reinhard Klein, “Supplementary Document on Moment-Based Order-Independent Transparency”. https://momentsingraphics.de/I3D2018.html, 2018.


モーメントと量子化スキームのすべての選択を考慮に入れると,本文は透過率のための合計12の異なるモーメントベースの再構成を議論します。本稿では,バイアスと量子化変換のための最適戦略の簡潔な概要を提供します。さらに,本論文では議論されていない技術の変形に対する結果を提供します。すべてのテクニックのHLSLコードとビデオは個別に入手できます。

1 OPTIMAL BIASING

モーメントを使用する場合、丸めエラーの発生は避けられません。ベクトルモーメント\(b \in {\mathbb C}^{m+1}\)がノイズによって破壊された場合、それは最終的に無効になる可能性があり、すなわち、\(b = {\mathcal E}_Z({\mathbf b})\)のような深度分布\(Z\)が存在しない可能性があります。アルゴリズムでは,これはコレスキー分解が失敗するような負の固有値を持つ行列として現れます。その結果、不完全なピクセルを持つ引き延ばした領域ができてしまいます。
 モーメントシャドウマッピング [Peters and Klein 2015] で提案された解決法は,固定ベクトルバイアスモーメント\(b^{\star} \in {\mathbb R}^{m+1}\)に向かう線形補間を介してベクトルを許容領域に引き戻すことです。再構成への入力として使用されるバイアスおよび正規化されたベクトルは、次のようになります。

\begin{eqnarray}
(1 – \alpha) \cdot \frac{b}{b_0} + \alpha \cdot b^{\star}
\end{eqnarray}

三角モーメントの場合、\(b^{\star}\)の自然な選択は、\({b_0}^{\star}=1\)と他のすべてのエントリを0に設定することです [Peters and Klein 2015] 。これは深度領域の周期的シフトの下で不変な唯一の選択です。パワーモーメントに関して,最悪の場合に最も効果的なバイアスしたモーメントのベクトルを見つけるための洗練された最適化手順を提案しました[Peters et al. 2017]。結果は丸め誤差の正確な性質に依存し,それは量子化スキームに依存します。
 モーメントバイアス\(0 \lt \alpha \ll 1\)の強さは、結果にアーティファクトがなくなるまで、経験的に増やしていくのが最も良いです。これは、導入される丸め誤差の量に依存します。モーメントベースの再構成の他のアプリケーションでは、これはシーンではなく、選択された量子化スキームのみに依存します。論文で議論されているように、丸め誤差は多くのパスにわたって蓄積される可能性があるため、ここで採用されている加算レンダリングでは、これは当てはまりません。オーバードローが大きいほど、丸め誤差も大きくなります。実際には、これは単精度の浮動小数点数では問題ありませんが、ピクセルあたり16ビットでモーメントを保存する場合は,追加の処理が必要になります。
 表1は、上述したすべての技術におけるバイアスするモーメントの最適なベクトルです。モーメントバイアス\(\alpha\)に与えられた値は、オーバードローが少ない場合にうまく機能する値となります。モーメントあたり16ビットを使用する場合、オーバードローが大きいシーンでは値を大きくする必要がある可能性があります。

2 QUANTIZATION AT 16 BITS PER MOMENT

丸め誤差の発生を最小限に抑えるため、正規化されたモーメント・ベクトルを1モーメントあたり16ビットで保存する前に、アフィン変換\({\Theta_m}^{\star}\)を適用することが望ましいです。この変換は、出力値の有効範囲 [0, 1] [Peters and Klein 2015] に違反することなく、\(|{\rm det} {\Theta_m}^{\star}|\)を最大化するように選択されます。効率上の理由から、さらに奇数モーメントと偶数モーメントを別々に変換することが選択されます [Peters et al. 2017]。
 表2は、8つのパワーモーメントに対する我々の新しい量子化変換を含む、使用されたすべての量子化変換の概要を示しています。三角モーメントについては、このような量子化変換は適用しません。フーリエ基底は利用可能なメモリをそのまま有効に利用でき、実モーメントあたり16ビットの三角モーメントを用いた我々の手法の変形は、いずれにせよ特に興味深いトレードオフを提供するものではありません。

 これらの量子化変換のいずれかを使用する場合、、既存の正規化されモーメント\({\Theta_m}^{\star}( \frac{b}{b_0})\)の量子化されたベクトルに不透明度\(\alpha_l\)を持つ深度\(z_l\)の新しいフラグメントを取り入れる正しい方法は、次のようになります。

\begin{eqnarray}
\frac{b_0 \cdot {\Theta_m}^{\star} \left( \frac{b}{b_0} \right) – {\rm ln}(1 – \alpha_l) \cdot {\Theta_m}^{\star} ({\mathbf b}(z_l)) }{ b_0 – {\rm ln}(1 – \alpha_l) }
\end{eqnarray}

3 ADDITIONAL RESULT

以下では、議論したテクニックの他のバリエーションについて、いくつかの追加結果とタイミングを示します。

3.1 Results With Eight Power Moments

本稿では、8つのべき乗モーメントを持つモーメントベースOITの結果は示しません。なぜかというと、6つのべき乗モーメントまたは3つの三角モーメントを持つ変形がより有用であると考えるからです。図2に示すように、8つのパワーモーメントは6つのパワーモーメントよりも若干の品質向上が見られますが、3つの三角モーメントよりも明らかに悪いです。表3から、8つのパワーモーメントの実行時間コストは3つの三角モーメントに近いことがわかります。したがって、コストと品質という点ではこれらの手法の間に入りますが、品質の向上はコストの増加に比べて相対的に小さいです。もう一つの欠点は、交差点を扱えないことです(図1参照)。

3.2 Efficiency of Rasterizer Ordered Views

表3はまた、予想外の興味深い実装の詳細にも光を当てています。モーメントベースのOITにラスタライザーの順序付きビューを使用するオーバーヘッドを決定するために、単精度浮動小数点数を使用するバリアントをこのように実装しました。驚くべきことに、我々のテストハードウェアで得られたフレーム時間は、ハードウェアアクセラレーションによる加算ブレンディングで得られたフレーム時間よりも実際に短くなっています。この現象について決定的な説明はありませんが、シェーダープログラムが非常に短いため、Rasteizer Ordered Viewを使用することによるオーバーヘッドが少ないと予想されることに注意してください。

3.3 Multi-Layer Alpha Blending with Low Dynamic Range

ほとんどの最新のアセットと同様に、評価に使用するアセットでは、外観を適切に再現するには、カラーチャネルあたり8ビット以上のレンダリングが必要です。そのため、すべての手法で一貫してカラーチャネルあたり16ビットのレンダーターゲットを使用しています。しかし,多層アルファブレンディングは低ダイナミックレンジを用いた技法として最初に提案されたものであり,従って筆者らの実装は元の技法より遅いです。表3に、カラーチャネルあたり8ビットのみを使用するマルチレイヤーアルファブレンディングのバリエーションと透過率のタイミングを示します。このバリエーションでは、シーンに対して正しいイメージが作成されないことに注意してください。
この方法で帯域幅要件を削減することによって達成される高速化は重要です。4層の多層アルファブレンディングは, 224ビットに格納された6つのパワーモーメントを持つ筆者らの手法に近いランタイムを持ちます。しかし,筆者らの手法はより良い品質を提供し,実質的に低いオーバーヘッドで高ダイナミックレンジレンダリングを処理しました。

REFERENCES

  • Christoph Peters and Reinhard Klein. 2015. Moment Shadow Mapping. In Proceedings of the 19th ACM SIGGRAPH Symposium on Interactive 3D Graphics and Games (i3D’15). ACM, 7–14. https://doi.org/10.1145/2699276.2699277
  • Christoph Peters, Cedrick Münstermann, Nico Wetzstein, and Reinhard Klein. 2017. Improved Moment Shadow Maps for Translucent Occluders, Soft Shadows and Single Scattering. Journal of Computer Graphics Techniques (JCGT) 6, 1 (2017), 17–67. http://jcgt.org/published/0006/01/03/

超雑訳 Moment-Based Order-Independent Transparency

こんらみ。Pocolです。
今日は,Alan Wake 2で採用されているという…
[Münstermann 2018] Cedrick Münstermann, Stefan Krumpen, Reinhard Klein, Christophe Peters, “Moment-Based Order-Independent Transparency”, I3D 2018.
を読んでみようと思います。
いつもながら誤字・誤訳があるかと思いますので,ご指摘頂ける場合は正しい翻訳例と共に指摘して頂けるとありがたいです。


(さらに…)

GPUで実行するテレイン上へのプロシージャルな配置の話

先日、Twitter(現X)を見ていたら,Unity engine上でテレイン上に配置する奴のツイート(リポスト)が来たので,忘れないようにメモとして残しておこうと思います。

1つ目は,GPU Run-time Procedural Placement on Terrain というやつです。
Horizon Zero-Dawnの資料を元に実装しているっぽく、どこぞの会社とおなじようなものっぽいです。

2つ目は、上記記事の続編と思われる Efficient GPU Rendering for Dynamic Instances in Game Development です。

いわゆるテレインを使用するオープンワールドゲームを作る際には役に立つかと思います。