0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

OpenQMC使ってみた

Last updated at Posted at 2025-11-24
Page 1 of 22

OpenQMC使ってみた

これはレイトレ合宿11で公開したスライドです


OpenQMC

logo-light.png


OpenQMCとは

  • 準モンテカルロ法で使う低食い違い数列とそれを使った疑似乱数を扱うライブラリ
  • 10月に突然AcademySoftwareFoundationから公開される
    • GitHubの履歴は2023年から始まっている
  • FramestoreのレンダラーFreakで使われているらしい
  • グラフィックスアプリケーションで使いやすくデザイン!

ライセンスについて

  • LICENSE は Apache License 2.0
  • もう一つ LICENSE-NVIDIA というファイルがある
    • OpenQMCを使っている限りは特許を主張しないという覚書

特徴

  • ヘッダーオンリー
    • C++14
  • CPU、GPU対応
  • SSE、AVX、NEON対応

特徴

  • 3種類の数列
    • Progressive Multi-Jittered
    • Sobol
    • Lattice
  • 4次元のサンプルを生成
  • それぞれにブルーノイズのバリアントがある
    • ディザリングなどに

特徴

  • ドキュメントが充実
    • というかREADMEが充実
  • サンプルも充実
    • レイトレのサンプルコード、あります!
  • というわけでとっつきは良いはず

使ってみる(抜粋)

まず最初にキャッシュのスペースを確保して初期化

    auto qmcCache = std::vector<char>(oqmc::PmjSampler::cacheSize);
    auto qmcCacheData = qmcCache.data();
    oqmc::PmjSampler::initialiseCache(qmcCacheData);

使ってみる(抜粋)

ルートのドメインを作成して必要な分を分岐させる

    for (int iy = 0; iy < height; iy++) {
        for (int ix = 0; ix < width; ix++) {
            for(int isp = 0; isp < sampleCount; isp++) {
                enum {
                    kCameraDomain,
                    kFilterDomain,
                    kSubpixelDomain
                };
                const auto pixelDomain = oqmc::PmjSampler(ix, iy, frameIndex, isp, qmcCacheData);
                const auto cameraDomain = pixelDomain.newDomain(kCameraDomain);
                const auto filterDomain = pixelDomain.newDomain(kFilterDomain);
                const auto subpixelDomain = pixelDomain.newDomain(kSubpixelDomain);

使ってみる(抜粋)

ほしい数だけ各ドメインからサンプリング(最大4個)

                float ssSample[2];
                subpixelDomain.drawSample<2>(ssSample);
                float sx = (ix + ssSample[0]) / width * 2.0 - 1.0;
                float sy = (iy + ssSample[1]) / height * 2.0 - 1.0;

                float lensSample[2];
                cameraDomain.drawSample<2>(lensSample);
                Ray ray = Camera::getThinLensRay(&camera, sx, sy, lensSample[0], lensSample[1]);

実験1:DOF

  • 簡単なDOFのテストシーンで実験

結果 (DOF)

  • 32spp ランダム(xoshiro256)

dof032_rnd.png


結果 (DOF)

  • 32spp Sobol

dof032_sbl.png


結果 (DOF)

  • 32spp PMJ

dof032_pmj.png


結果 (DOF)

  • 32spp 比較

dofall.png


実験2:ソフトフィルター

  • すりガラスのようなレンズフィルターを再現したい
    • 要するにブルームがのるフィルター
  • 実装はレンズの出口でGGXでレイを散乱させる
    • 薄レンズとGGXで合計4個の乱数を消費

結果 (ソフトフィルター)

  • 32spp ランダム

soft032_rnd.png


結果 (ソフトフィルター)

  • 32spp Sobol

soft032_sbl.png


結果 (ソフトフィルター)

  • 32spp PMJ

soft032_pmj.png


結果 (ソフトフィルター)

  • 32spp 比較

softall.png


まとめ

  • 簡単に使えて意外と効果がある
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?