Bagaimana Anti Aliasing Diimplementasikan dalam Ray Tracing?

12

Setelah membaca beberapa artikel online, saya yakin dapat mengatakan bahwa saya tidak mengerti bagaimana Anti-Aliasing bekerja ketika Ray Tracing .

Yang saya mengerti adalah A Single Pixel / Ray dibagi menjadi 4 sub-pixel dan 4 sinar daripada 1 .

Bisakah seseorang tolong jelaskan bagaimana hal ini dilakukan (sebaiknya dengan kode)?

Arjan Singh
sumber
2
Bisakah saya menyarankan Anda melihat "supersampling" en.wikipedia.org/wiki/Supersampling dan mungkin juga en.wikipedia.org/wiki/Distributed_ray_tracing ?
Simon F
2
Saya juga dapat merekomendasikan membaca bab PBRT ini pbrt.org/chapters/pbrt_chapter7.pdf dan membaca makalah ini lgdv.cs.fau.de/get/785 (yang menjelaskan teknik yang berbeda dari yang diterapkan dalam pbrt).
Tom van Bussel
1
foreach pixel : p{acc = 0; foreach subsample : s { acc+=sample_scene(s);} store(p, acc);}
ratchet freak

Jawaban:

11

Saya pikir aman untuk mengatakan bahwa ada dua cara berbeda untuk melakukan AA dalam raytracing:

1: jika Anda memiliki gambar akhir dan gambar kedalaman, dimungkinkan untuk menerapkan hampir semua teknik yang ada yang digunakan dalam game (FXAA, dll.) Itu bekerja langsung pada gambar akhir dan tidak terkait dengan raytracing

2: metode kedua adalah dengan memperhitungkan lebih dari satu sinar untuk setiap piksel dan kemudian rata-rata hasilnya. Untuk versi yang sangat sederhana pikirkan seperti ini:

  • Anda membuat gambar berukuran 1024x1024, satu ray untuk setiap piksel (misalnya)
  • setelah rendering, Anda skala gambar ke 512x512 (masing-masing 4 piksel rata-rata menjadi satu) dan Anda dapat melihat bahwa ujung-ujungnya lebih halus. Dengan cara ini Anda telah menggunakan 4 sinar untuk setiap piksel secara efektif dalam gambar akhir ukuran 512x512.

Ada variasi lain pada metode ini. Misalnya Anda dapat menyesuaikan jumlah sampel untuk piksel yang tepat di tepi geometri yang berarti bahwa untuk beberapa piksel Anda hanya akan memiliki 4 sampel, dan untuk yang lain 16.

Periksa tautan di komentar di atas.

Raxvan
sumber
Jadi pada dasarnya saya membuat gambar ke ukuran besar dan ketika menyimpannya ke gambar, turunkan ke ukuran lebih rendah? Itu sepertinya cukup sederhana :)! Apakah ini metode super sampling?
Arjan Singh
1
@Arjan Singh ya itu en.wikipedia.org/wiki/Supersampling , tapi ini yang paling lambat, raytracing memungkinkan Anda melakukan supersampling adaptif dengan mudah, yang bisa bekerja jauh lebih baik
Raxvan
12

Raxvan sepenuhnya benar bahwa teknik anti aliasing "tradisional" akan bekerja dalam raytracing, termasuk yang menggunakan informasi seperti kedalaman untuk melakukan antialiasing. Anda bahkan dapat melakukan anti aliasing sementara dalam penelusuran ray misalnya.

Julien memperluas item kedua Raxvan yang merupakan penjelasan tentang super sampling, dan menunjukkan bagaimana Anda benar-benar melakukan itu, juga menyebutkan bahwa Anda dapat mengacak lokasi sampel dalam piksel tetapi kemudian Anda memasuki negara pemrosesan sinyal yang banyak lebih dalam, dan itu pasti!

NN

Jika Anda melakukan itu, Anda masih bisa mendapatkan alias. Itu lebih baik daripada TIDAK melakukannya, karena Anda meningkatkan laju sampling Anda, sehingga akan dapat menangani data frekuensi yang lebih tinggi (alias detail lebih kecil), tetapi masih dapat menyebabkan alias.

N

Ketika Anda hanya menggunakan angka acak "biasa" seperti yang Anda dapatkan dari rand () atau std :: uniform_int_distribution, itu disebut "white noise" karena berisi semua frekuensi, seperti bagaimana cahaya putih terdiri dari semua warna lain (frekuensi ) cahaya.

Menggunakan white noise untuk mengacak sampel dalam piksel memiliki masalah yang kadang-kadang sampel Anda akan mengumpul. Misalnya, jika Anda rata-rata 100 sampel dalam piksel, tetapi semuanya SEMUA berakhir di sudut kiri atas piksel, Anda tidak akan mendapatkan informasi APA PUN tentang bagian lain dari piksel, sehingga warna piksel akhir yang dihasilkan Anda akan ada informasi yang hilang tentang warna apa yang seharusnya.

Pendekatan yang lebih baik adalah dengan menggunakan sesuatu yang disebut blue noise yang hanya berisi komponen frekuensi tinggi (seperti bagaimana cahaya biru adalah frekuensi tinggi).

Keuntungan dari noise biru adalah Anda mendapatkan cakupan yang merata di atas piksel, seperti yang Anda dapatkan dengan grid pengambilan sampel yang seragam, tetapi, Anda masih mendapatkan beberapa keacakan, yang mengubah alias menjadi noise dan memberi Anda gambar yang tampak lebih baik.

Sayangnya, noise biru bisa sangat mahal untuk dihitung, dan metode terbaik semua tampaknya dipatenkan (apa-apaan ini ?!), tetapi satu cara untuk melakukan ini, ditemukan oleh pixar (dan dipatenkan juga saya pikir tetapi tidak 100% yakin) adalah untuk membuat kisi-kisi titik sampel yang rata, kemudian secara acak mengimbangi setiap titik sampel dengan jumlah kecil - seperti jumlah acak antara plus atau minus setengah lebar dan tinggi dari kisi-kisi sampel. Dengan cara ini Anda mendapatkan semacam sampling noise biru untuk cukup murah.

Perhatikan bahwa ini adalah bentuk pengambilan sampel bertingkat, dan pengambilan sampel disk poisson adalah bentuk itu juga, yang juga merupakan cara menghasilkan blue noise: https://www.jasondavies.com/poisson-disc/

Jika Anda tertarik untuk masuk lebih dalam, Anda mungkin juga ingin memeriksa pertanyaan dan jawaban ini!

Apa alasan mendasar anti aliasing menggunakan beberapa sampel acak dalam satu piksel?

Terakhir, hal ini mulai menyimpang ke ranah pelacakan jalur monte carlo yang merupakan metode umum untuk melakukan raytracing fotorealistik. jika Anda tertarik untuk mempelajari lebih lanjut tentang itu, bacalah ini!

http://blog.demofox.org/2016/09/21/path-tracing-getting-started-with-diffuse-and-emissive/

Alan Wolfe
sumber
7

Misalkan loop utama raytracing yang cukup khas:

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);
    }
}

Salah satu modifikasi yang memungkinkan untuk melakukan 4 sampel MSAA adalah:

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;
    }
}

Kemungkinan lain adalah melakukan jitter acak (bukan berbasis matriks di atas), tetapi Anda kemudian segera memasuki bidang pemrosesan sinyal dan perlu banyak membaca untuk mengetahui cara memilih fungsi noise yang baik.

Idenya tetap sama: pertimbangkan pixel untuk mewakili area persegi kecil, dan alih-alih menembak hanya satu sinar yang melewati pusat pixel, tembak banyak sinar yang menutupi seluruh area pixel. Semakin padat distribusi ray, semakin baik sinyal yang Anda dapatkan.

PS: Saya menulis kode di atas dengan cepat, jadi saya berharap beberapa kesalahan di dalamnya. Itu hanya dimaksudkan untuk menunjukkan ide dasar.

Julien Guertault
sumber
Jawaban Hebat! Apa manfaat menggunakan metode ini yang bertentangan dengan metode yang digunakan @Raxvan? Apakah saya akan mendapatkan hasil yang sama dengan merender ke ukuran besar dan kemudian menurunkan skala ke ukuran yang lebih kecil?
Arjan Singh
Pada dasarnya, dengan penelusuran sinar, Anda tidak perlu membuat gambar yang lebih besar lalu memperkecilnya. Itu berarti Anda memiliki lebih banyak fleksibilitas: Anda dapat memiliki banyak sampel, Anda dapat memvariasikan jumlah sampel tergantung pada wilayah, dan hanya, Anda tidak perlu menambahkan langkah skala ulang.
Julien Guertault
2
Pada topik jittering, ini ternyata menjadi topik yang cukup kompleks. Berikut ini adalah makalah yang bagus menganalisis keadaan mutakhir beberapa tahun yang lalu graphics.pixar.com/library/MultiJitteredSampling/paper.pdf
Mikkel Gjoel
Contoh kode di atas menggunakan 4 Contoh MSAA, jika saya ingin melakukan 8x MSAA seperti apa matriksnya? Apa yang perlu saya ubah dalam matriks jitter yang ditunjukkan di atas?
Arjan Singh