オンラインでいくつかの記事を読んだ後、レイトレーシングでアンチエイリアシングがどのように機能するかについて私は自信がないと自信を持って言えます。
私が理解しているのは、単一のピクセル/光線が1ではなく4つのサブピクセルと4つの光線に分割されていることです。
誰かがこれがどのように行われるのかを説明できますか?
foreach pixel : p{acc = 0; foreach subsample : s { acc+=sample_scene(s);} store(p, acc);}
オンラインでいくつかの記事を読んだ後、レイトレーシングでアンチエイリアシングがどのように機能するかについて私は自信がないと自信を持って言えます。
私が理解しているのは、単一のピクセル/光線が1ではなく4つのサブピクセルと4つの光線に分割されていることです。
誰かがこれがどのように行われるのかを説明できますか?
foreach pixel : p{acc = 0; foreach subsample : s { acc+=sample_scene(s);} store(p, acc);}
回答:
レイトレーシングでAAを実行するには、2つの異なる方法があると言っても安全だと思います。
1:最終画像と深度画像がある場合、ゲームで使用されているほとんどすべての既存の技術(FXAAなど)を適用できます。これらは最終画像に直接作用し、レイトレーシングとは関係ありません
2:2番目の方法は、ピクセルごとに複数の光線を考慮して、結果を平均化することです。非常に単純なバージョンの場合、次のように考えてください。
この方法には他にもバリエーションがあります。たとえば、ジオメトリの端にあるピクセルのサンプル数を調整できます。つまり、一部のピクセルでは4つのサンプルしか使用できず、他のピクセルでは16になります。
上記のコメント内のリンクを確認してください。
Raxvanは、深度などの情報を使用してアンチエイリアシングを行うものを含め、「従来の」アンチエイリアシング手法がレイトレーシングで機能することを完全に正しいと考えています。たとえば、レイトレーシングで一時的なアンチエイリアシングを行うこともできます。
ジュリアンは、スーパーサンプリングの説明であるRaxvanの2番目の項目を拡張し、実際にそれを行う方法を示しました。また、ピクセル内のサンプルの位置をランダム化できるが、その後、多くの信号処理国に入ることに言及しましたより深く、そして間違いなくそうです!
そうした場合でも、エイリアスを取得できます。サンプリングレートを上げているので、それをしないよりはましです。したがって、より高い周波数のデータ(詳細は小さい)を処理できますが、エイリアシングを引き起こす可能性があります。
rand()またはstd :: uniform_int_distributionから取得するような「通常の」乱数を使用する場合、白色光が他のすべての色(周波数)で構成される方法など、すべての周波数が含まれるため「ホワイトノイズ」と呼ばれます) 光の。
ホワイトノイズを使用してピクセル内のサンプルをランダム化すると、サンプルがまとまってしまうという問題が発生します。たとえば、ピクセルで100個のサンプルを平均しても、それらがすべてピクセルの左上隅にある場合、ピクセルの他の部分に関する情報は取得されないため、最終的なピクセルの色はどの色にする必要があるかに関する情報が欠落しています。
より良いアプローチは、高周波成分のみを含むブルーノイズと呼ばれるものを使用することです(青色光が高周波光である方法など)。
ブルーノイズの利点は、均一なサンプリンググリッドで得られるように、ピクセル全体を均一にカバーできることですが、それでもある程度のランダム性が得られるため、エイリアシングがノイズに変わり、見栄えが良くなります。
残念ながら、ブルーノイズは計算に非常にコストがかかる可能性があり、最良の方法はすべて特許を取得しているようです(一体何でしょう!)、しかしこれを行う1つの方法はpixarによって発明されていますサンプルポイントの偶数グリッドを作成し、各サンプルポイントをランダムにオフセットします(サンプリンググリッドの幅と高さのプラスまたはマイナス間のランダムな量など)。このようにして、かなり安価にブルーノイズのサンプリングを行うことができます。
これは層化サンプリングの形式であり、ポアソンディスクサンプリングもその形式であり、ブルーノイズを生成する方法でもあることに注意してください。https: //www.jasondavies.com/poisson-disc/
もっと深く知りたい場合は、おそらくこの質問と回答も確認してください。
ピクセル内で複数のランダムサンプルを使用するアンチエイリアシングの基本的な理由は何ですか?
最後に、このようなものは、フォトリアリスティックなレイトレーシングを行う一般的な方法であるモンテカルロパストレーシングの領域に迷い込み始めています。それについてもっと知りたいなら、これを読んでください!
http://blog.demofox.org/2016/09/21/path-tracing-getting-started-with-diffuse-and-emissive/
かなり典型的なレイトレーシングのメインループを考えてみましょう。
struct Ray
{
vec3 origin;
vec3 direction;
};
RGBColor* image = CreateImageBuffer(width, height);
for (int j=0; j < height; ++i)
{
for (int i=0; i < width; ++i)
{
float x = 2.0 * (float)i / (float)max(width, height) - 1.0;
float y = 2.0 * (float)j / (float)max(width, height) - 1.0;
vec3 dir = normalize(vec3(x, y, -tanHalfFov));
Ray r = { cameraPosition, dir };
image[width * j + i] = ComputeColor(r);
}
}
4つのサンプルMSAAを実行するための1つの可能な変更は次のとおりです。
float jitterMatrix[4 * 2] = {
-1.0/4.0, 3.0/4.0,
3.0/4.0, 1.0/3.0,
-3.0/4.0, -1.0/4.0,
1.0/4.0, -3.0/4.0,
};
for (int j=0; j < height; ++i)
{
for (int i=0; i < width; ++i)
{
// Init the pixel to 100% black (no light).
image[width * j + i] = RGBColor(0.0);
// Accumulate light for N samples.
for (int sample = 0; sample < 4; ++sample)
{
float x = 2.0 * (i + jitterMatrix[2*sample]) / (float)max(width, height) - 1.0;
float y = 2.0 * (i + jitterMatrix[2*sample+1]) / (float)max(width, height) - 1.0;
vec3 dir = normalize(vec3(x, y, -tanHalfFov) + jitter);
Ray r = { cameraPosition, dir };
image[width * j + i] += ComputeColor(r);
}
// Get the average.
image[width * j + i] /= 4.0;
}
}
もう1つの可能性は、(上記のマトリックスベースの代わりに)ランダムジッタを行うことですが、すぐに信号処理の領域に入り、適切なノイズ関数を選択する方法を知るには多くの読み取りが必要になります。
アイデアは同じままです:ピクセルを小さな正方形の領域を表すと考え、ピクセルの中心を通過する光線を1つだけ照射する代わりに、ピクセル領域全体をカバーする多くの光線を照射します。光線の分布が密であればあるほど、より良い信号が得られます。
PS:上記のコードをその場で書いたので、いくつかのエラーが発生することを期待しています。基本的な考え方を示すことのみを目的としています。