[メモ]Blue Noiseとリアルタイムレイトレーシング

Blue Noiseのリアルタイムレイトレーシングへの適用についてのメモです

参照

[Ulichney93] Void-and-cluster method for dither array generation.

クリックして1993-void-cluster.pdfにアクセス

[Christoph Peters]
Blog
Free blue noise textures
The problem with 3D blue noise
GitHub
https://github.com/MomentsInGraphics/BlueNoise

[Iliyan 2016] Blue-noise Dithered Sampling

クリックしてdither_abstract.pdfにアクセス

[Mitchell 1991] Spectrally Optimal Sampling for Distribution Ray Tracing
http://delivery.acm.org/10.1145/130000/122736/p157-mitchell.pdf?ip=39.110.237.146&id=122736&acc=ACTIVE%20SERVICE&key=D494438A622BF6CC%2ED494438A622BF6CC%2E4D4702B0C3E38B35%2E4D4702B0C3E38B35&__acm__=1561000223_60c10848f9f813f1ce2a9163884c3c60


[2019/06/21追記]

参照
[Heitz 2019]
A Low-Discrepancy Sampler that Distributes Monte Carlo Errors as a Blue Noise in Screen Space
https://eheitzresearch.wordpress.com/762-2/

A Low-Discrepancy Sampler that Distributes Monte Carlo Errors as a Blue Noise in Screen Spaceを読んでみた

想定するSampling

PixelごとにD次元のN個のサンプリングを想定。
疑似乱数列の代わりにこれを用いることで、Monte Carlo積分の誤差がスクリーン空間でBlue Noiseの特性になるように分布するように最適化する。NはSobol列の制限で、2のべき乗数に限定されるので実際に必要とされるサンプル数と同じか大きくなる。

Scramble用のキー

PixelごとにD個(次元数)の整数を用意する。Sobol列の値の整数表現(Bitごとに、1/2,1/4,1/8….)をxorするためのもの。これによる値のxor操作は、Sobolの分布特性を壊さない。

Rankingのキー

Pixelごとに一つの整数を用意する。これは、そのPixelのSobol列のインデックスをxorするためのもの。Sobol列の特性として、ある2のべき乗の数にアラインしたその数のサブセット、(2なら[0,1][2,3], 4なら[0,1,2,3][4,5,6,7])は低食い違い特性を保持している。したがって、インデックスにxorを適用してもその特性は保持される。

値の評価

n個目のサンプルを評価するときは、nをRankingのキーでxorして得られたインデックスを用いて、Sobol列をサンプリングして、その整数表現をScrambleのキーでxorした後実際の値を得る。

128×128のタイルを実現するために必要なデータセット

  • SamplePoint: N(最大サンプル回数)xD(次元数)個のSobol列
  • ScrambingKey: 128x128xD(次元数)の整数
  • RankingKey: 128×128の整数

キーの最適化

このままでは、ただScramblingされたSobol列のサンプリングになってしまいます。目的は、MC積分によって計算される積分のエラーの差を隣接ピクセルで最大化することで、そのために、ScramblingのキーとRankのキーを最適化します。

仮想の被積分関数のセットを定義します。この論文のアイデアでは、典型的なレンダリングの被積分関数のセットの代理として、D-1次元の正規化された方向ベクトルと1次元の位相で定義されるoriented Heaviside関数を用います。(これについては詳細が不明)
ランダムに選択した、65536個のoriented Heaviside関数を用意します。個々のPixelで、この関数をSobol列でN回評価してMC積分を行い、解析的に解いた積分値との誤差を計算します。これを65536回行い、個々のPixelごとに65536個のエラーの数列を計算します。

これを用いてNサンプル使った場合のScramblingのキーを最適化(誤差がBlue Noiseになるように変更)します。方法は、Blue NoiseのVoid-and-cluster methodを使いますが、エネルギーを計算する式(Void-Clusterの評価値を計算する式)は、Gaussian Kernelの距離関数と共に、先ほど計算したエラーの差の二次モーメントを用います。こうすることで、隣接するピクセルの保持するエラーの差が最大化されることになります。

次に、Rankingキーの最適化を行います。こちらは、Nサンプル以下のみを使用した場合にも適用される最適化です。RankingのXorに使うKeyの各ビットは、そのBitの大きさの長さのSobol列をSwapする効果があります。つまり、各Bitには、受け持つSobol列の範囲があるので、各Bitの範囲の先頭までと、最後の要素までのサブセットのエラーをそれぞれ計算して、その2次モーメントの合計を誤差関数に反映させて、Blue Noiseの最適化を掛けます。これを再帰的にN,N/2…. 1まで行うことで、各Bitが受け持つ範囲でのRankingキーの最適化が行われます。

追記終わり


BlueNoiseの性質について

値の分布がUniformであること
値の空間的分布において低周波成分が少ないこと
異方性を持たないこと
空間的にタイリングしても上記の性質を失わないこと

Blue Noiseの作り方

 [Ulichney93]が示した通り、一様乱数とVoid-and-cluster methodを使って作ります。簡単に説明すると、高い値が集まっている場所”Cluster”のPixelと、低い値が集まっている場所”Void”のPixelを入れ替える操作を繰り返し行うことで生成できます。ClusterやVoidは、簡単なGaussian KernelのConvolutionによって見つけることができ、Filter Kernelを空間的にWrapさせることで、タイリングしてもBlue Noiseの性質を保つことができるようになります。
 ちなみにこの手法は United States Patent 5,535,020で保護されていたそうですが、2013年に期限切れとなっているようです。この辺りは[Christoph Peters]のブログに書いてありますが、氏も専門家ではないとおっしゃっているので、専門家の判断を仰ぐのが良いかと思います。

Blue NoiseとDenoising

 Blue Noiseの空間的分布に低周波成分が少ないということは、フィルタリングによって値を均一化しようとしたときに、必要となるFilter径が小さくて済む、もしくは小さなFilter径で良好な結果が得られるということだと思います。言い換えれば、Filter径が小さくて良いということは、オリジナルの信号が持つ低周波成分を維持することができ、画像のディテールを保持してFilteringできるということだと思います。
 2D画像のDitheringの場合は、Blue Noiseの信号がそのまま2D画像のパターンとして発現するので、Blue Noiseの持つ空間的な性質は、そのまま画像の空間に反映されることになると思います。

Blue Noiseとレイトレーシング

 特にリアルタイムレイトーレシングでは、限られたサンプル数から良好なレンダリング結果を得るためにDenoisingは必須といえると思います。上記の2DのDitheringと同様に、レンダリング結果が、スクリーン空間上で低周波成分ノイズの少ない状態にできれば、小さなFilter径で良好なDenoisingが可能となると思います。
 レイトレーシングの場合は、一般的に1Pixelもしくは1Ray当たりに複数回の乱数による選択が行われ、それがレンダリング結果として画像に反映されることになります。例えば、Bounce Ray構築のために2回乱数を生成し、それを元にベクトルを生成する場合などです。この場合には、必要な次元数に応じてVoid-and-cluster methodを適用したSamplingを使う方が理に適っています。これは、[Iliyan 2016]Blue-noise Dithered Samplingで示されています。

Anisotropic 3D Blue Noise

 2D Blue Noiseの空間的な拡張である3D Blue Noiseは、Voxel版のBlue Noiseと言えるでしょう。保持している性質も2Dと同じです。
 レイトレーシングでは、同様の処理を投機的に複数回繰り返すことがあります。例えば、Bounce Rayを複数回飛ばす場合は、個々のRay方向が隣接するピクセルで相似性が少ないことも重要ですし、同一Pixel上の一連のRayの方向の相似性が少ないことも重要です。このような場合は、3D Blue Noiseは有用かもしれません。しかし[Christoph Peters]氏のBlogで触れられている通り、3D Blue Noiseの1枚のSliceは2D Blue Noiseとしての性質を十分に満たしていません。フーリエ変換した結果を見てもわかる通り、3D Blue Noiseの1枚のSliceは、2D Blue Noiseよりも低周波成分が明らかに多いです。あくまで、3つの次元を同等に扱って満たされる性質となります。これは、1D Blue Noiseと2D Blue Noiseの関係性と似ています。この点においては注意が必要です。そして、リアルタイムレイトレーシングのコンテキストでは、レンダリングされた2D画像の結果の低周波成分が少ないことが重要です。
 Blue Noiseの生成過程のVoid-and-cluster methodで用いるConvolutionのKernelは異方性があっても期待通りの動作をします。したがって、スクリーン空間のX,Y軸に大きくKernelをとり、時間軸もしくは回数軸であるZ軸に小さなKernelをとることもできます。このようにして生成した異方性のある3D Blue Noiseは、Kernelの設定次第で、XY軸において、ほぼ2D Blue Noiseと同様の性質を保ちつつ、Z軸方向に、小さい範囲ではありますが相似性を避けるように生成することができると思います。これがリアルタイムレイトレーシングのコンテキストにおいて有用であるかは、もう少し考察が必要だと思います。

Cosine Weighted Blue Noise

 Blue Noiseのリアルタイムレイトレーシングにおける適用について考えてみます。例えば、2次元ベクトルの2D Blue Noiseを乱数として使ってCosine Weightedな半球上に分布するベクトルを生成すると、Blue Noiseの性質は半球上にCosine Weightedで投影したことにより変化してしまいます。具体的には、天頂付近はPDFが高いのでBlue Noise的には、”Cluster”が強くなり、水平付近では”Void”が強くなるでしょう。正しくBlue Noiseのコンセプトに従うのであれば、これらは望ましくありません。
 Blue Noiseを生成するVoid-and-cluster methodは、系の中が一様な分布である必要が無いのは自明です。したがってCosine WeightedなVector列を生成し、そのベクトルの距離を用いてVoid-and-cluster methodを適用すれば、Cosine Weightedな3次元VectorのBlue Noise化されたデータセットが生成できると思います。同様にSpecularのImportance Samplingにも適用可能かと思います。例えばGGXのPDFでも同じことができると思います。問題はRoughnessによる組み合わせが多すぎるので、この点に関しては更に工夫が必要だと思います。