Apakah Russian Roulette benar-benar jawabannya?

21

Saya telah melihat bahwa dalam beberapa implementasi Path Tracing, sebuah pendekatan yang disebut Russian Roulette digunakan untuk menyisihkan beberapa jalur dan berbagi kontribusinya di antara jalur lainnya.

Saya memahami bahwa alih-alih mengikuti jalur sampai turun di bawah nilai ambang batas kontribusi tertentu, dan kemudian mengabaikannya, ambang batas yang berbeda digunakan dan jalur yang kontribusinya di bawah ambang batas itu hanya diakhiri dengan kemungkinan kecil. Jalur lain memiliki kontribusi mereka meningkat dengan jumlah yang sesuai untuk berbagi energi yang hilang dari jalur yang diakhiri. Tidak jelas bagi saya apakah ini untuk memperbaiki bias yang diperkenalkan oleh teknik, atau apakah seluruh teknik itu sendiri diperlukan untuk menghindari bias.

  • Apakah Russian Roulette memberikan hasil yang tidak bias?
  • Apakah Roulette Rusia diperlukan untuk hasil yang tidak bias?

Yaitu, akan menggunakan ambang kecil dan hanya mengakhiri jalan saat turun di bawah ambang itu memberikan hasil yang lebih bias atau kurang bias?

Dengan jumlah sampel yang besar dan sewenang-wenang, akankah kedua pendekatan bertemu pada gambar yang dihasilkan tidak bias?

Saya ingin memahami alasan mendasar untuk menggunakan pendekatan Roulette Rusia. Apakah ada perbedaan signifikan dalam kecepatan atau kualitas?


Saya mengerti bahwa energi didistribusikan kembali di antara sinar-sinar lain untuk menghemat energi total. Namun, bisakah redistribusi ini masih tidak dapat dilakukan jika sinar diakhiri karena jatuh di bawah ambang batas tetap, daripada memiliki rentang hidup yang ditentukan secara acak setelah mencapai ambang batas itu?

Sebaliknya, jika energi yang akan hilang dengan menghentikan sinar tanpa mendistribusikan kembali energinya pada akhirnya akan hilang pula (karena sinar yang disalurkan kembali juga akhirnya dihentikan), bagaimana cara ini memperbaiki situasi?

trichoplax
sumber

Jawaban:

26

Untuk memahami Roulette Rusia, mari kita lihat pelacak jalur mundur yang sangat mendasar:

void RenderPixel(uint x, uint y, UniformSampler *sampler) {
    Ray ray = m_scene->Camera.CalculateRayFromPixel(x, y, sampler);

    float3 color(0.0f);
    float3 throughput(1.0f);

    // Bounce the ray around the scene
    for (uint bounces = 0; bounces < 10; ++bounces) {
        m_scene->Intersect(ray);

        // The ray missed. Return the background color
        if (ray.geomID == RTC_INVALID_GEOMETRY_ID) {
            color += throughput * float3(0.846f, 0.933f, 0.949f);
            break;
        }

        // We hit an object

        // Fetch the material
        Material *material = m_scene->GetMaterial(ray.geomID);
        // The object might be emissive. If so, it will have a corresponding light
        // Otherwise, GetLight will return nullptr
        Light *light = m_scene->GetLight(ray.geomID);

        // If we hit a light, add the emmisive light
        if (light != nullptr) {
            color += throughput * light->Le();
        }

        float3 normal = normalize(ray.Ng);
        float3 wo = normalize(-ray.dir);
        float3 surfacePos = ray.org + ray.dir * ray.tfar;

        // Get the new ray direction
        // Choose the direction based on the material
        float3 wi = material->Sample(wo, normal, sampler);
        float pdf = material->Pdf(wi, normal);

        // Accumulate the brdf attenuation
        throughput = throughput * material->Eval(wi, wo, normal) / pdf;


        // Shoot a new ray

        // Set the origin at the intersection point
        ray.org = surfacePos;

        // Reset the other ray properties
        ray.dir = wi;
        ray.tnear = 0.001f;
        ray.tfar = embree::inf;
        ray.geomID = RTC_INVALID_GEOMETRY_ID;
        ray.primID = RTC_INVALID_GEOMETRY_ID;
        ray.instID = RTC_INVALID_GEOMETRY_ID;
        ray.mask = 0xFFFFFFFF;
        ray.time = 0.0f;
    }

    m_scene->Camera.FrameBuffer.SplatPixel(x, y, color);
}

YAITU. kami melompat-lompat di sekitar tempat kejadian, mengumpulkan warna dan redaman cahaya saat kami pergi. Agar benar-benar tidak bias secara matematis, pantulan harus menuju tak terhingga. Tapi ini tidak realistis, dan seperti yang Anda catat, tidak perlu secara visual; untuk sebagian besar adegan, setelah sejumlah pantulan, katakanlah 10, jumlah kontribusi terhadap warna akhir sangat sangat minim.

Jadi untuk menghemat sumber daya komputasi, banyak pelacak jalur memiliki batasan keras untuk jumlah bouncing. Ini menambah bias.

Yang mengatakan, sulit untuk memilih apa batas yang seharusnya. Beberapa adegan tampak hebat setelah 2 memantul; yang lain (katakanlah dengan transmisi atau SSS) dapat memakan waktu hingga 10 atau 20. 2 Bouncing dari Pahlawan Besar Disney 6 9 Memantul dari Pahlawan Besar Disney 6

Jika kita memilih terlalu rendah, gambar akan terlihat bias. Tetapi jika kita memilih terlalu tinggi, kita membuang-buang energi dan waktu perhitungan.

Salah satu cara untuk memecahkan ini, seperti yang Anda catat, adalah mengakhiri jalur setelah kami mencapai ambang pelemahan. Ini juga menambah bias.

Menjepit setelah ambang batas, akan berhasil , tetapi sekali lagi, bagaimana kita memilih ambang batas? Jika kita memilih terlalu besar, gambar akan terlihat bias, terlalu kecil, dan kita membuang-buang sumber daya.

Roulette Rusia berupaya menyelesaikan masalah ini dengan cara yang tidak bias. Pertama, ini kodenya:

void RenderPixel(uint x, uint y, UniformSampler *sampler) {
    Ray ray = m_scene->Camera.CalculateRayFromPixel(x, y, sampler);

    float3 color(0.0f);
    float3 throughput(1.0f);

    // Bounce the ray around the scene
    for (uint bounces = 0; bounces < 10; ++bounces) {
        m_scene->Intersect(ray);

        // The ray missed. Return the background color
        if (ray.geomID == RTC_INVALID_GEOMETRY_ID) {
            color += throughput * float3(0.846f, 0.933f, 0.949f);
            break;
        }

        // We hit an object

        // Fetch the material
        Material *material = m_scene->GetMaterial(ray.geomID);
        // The object might be emissive. If so, it will have a corresponding light
        // Otherwise, GetLight will return nullptr
        Light *light = m_scene->GetLight(ray.geomID);

        // If we hit a light, add the emmisive light
        if (light != nullptr) {
            color += throughput * light->Le();
        }

        float3 normal = normalize(ray.Ng);
        float3 wo = normalize(-ray.dir);
        float3 surfacePos = ray.org + ray.dir * ray.tfar;

        // Get the new ray direction
        // Choose the direction based on the material
        float3 wi = material->Sample(wo, normal, sampler);
        float pdf = material->Pdf(wi, normal);

        // Accumulate the brdf attenuation
        throughput = throughput * material->Eval(wi, wo, normal) / pdf;


        // Russian Roulette
        // Randomly terminate a path with a probability inversely equal to the throughput
        float p = std::max(throughput.x, std::max(throughput.y, throughput.z));
        if (sampler->NextFloat() > p) {
            break;
        }

        // Add the energy we 'lose' by randomly terminating paths
        throughput *= 1 / p;


        // Shoot a new ray

        // Set the origin at the intersection point
        ray.org = surfacePos;

        // Reset the other ray properties
        ray.dir = wi;
        ray.tnear = 0.001f;
        ray.tfar = embree::inf;
        ray.geomID = RTC_INVALID_GEOMETRY_ID;
        ray.primID = RTC_INVALID_GEOMETRY_ID;
        ray.instID = RTC_INVALID_GEOMETRY_ID;
        ray.mask = 0xFFFFFFFF;
        ray.time = 0.0f;
    }

    m_scene->Camera.FrameBuffer.SplatPixel(x, y, color);
}

Roulette Rusia mengakhiri jalur secara acak dengan probabilitas berbanding terbalik dengan throughput. Jadi jalur dengan throughput rendah yang tidak akan berkontribusi banyak ke tempat kejadian lebih mungkin untuk diakhiri.

Jika kita berhenti di situ, kita masih bias. Kita 'kehilangan' energi dari jalan yang kita hentikan secara acak. Untuk membuatnya tidak bias, kami meningkatkan energi jalur non-terminasi dengan probabilitas mereka untuk dihentikan. Ini, bersama dengan menjadi acak, membuat Roulette Rusia tidak bias.

Untuk menjawab pertanyaan terakhir Anda:

  1. Apakah Russian Roulette memberikan hasil yang tidak bias?
    • iya nih
  2. Apakah Roulette Rusia diperlukan untuk hasil yang tidak bias?
    • Tergantung pada apa yang Anda maksud dengan tidak bias. Jika Anda maksud secara matematis, maka ya. Namun, jika maksud Anda secara visual, maka tidak. Anda hanya harus memilih Anda kedalaman jalur maks dan ambang batas cutoff dengan sangat hati-hati. Ini bisa sangat membosankan karena bisa berubah dari satu adegan ke adegan lainnya.
  3. Bisakah Anda menggunakan probabilitas tetap (cut-off), dan kemudian mendistribusikan kembali energi 'hilang'. Apakah ini tidak bias?
    • Jika Anda menggunakan probabilitas tetap, Anda menambahkan bias. Dengan mendistribusikan kembali energi 'hilang', Anda mengurangi bias, tetapi masih bias secara matematis. Agar sama sekali tidak bias, itu harus acak.
  4. Jika energi yang akan hilang dengan menghentikan sinar tanpa mendistribusikan energi, akhirnya akan hilang pula (karena sinar yang didistribusikan juga akhirnya diakhiri), bagaimana cara ini memperbaiki situasi?
    • Roulette Rusia hanya menghentikan pantulannya. Itu tidak menghapus sampel sepenuhnya. Juga, energi 'hilang' diperhitungkan dalam bouncing hingga penghentian. Jadi satu-satunya cara agar energi 'akhirnya hilang' adalah memiliki ruang yang sepenuhnya hitam.

Pada akhirnya, Russian Roulette adalah algoritma yang sangat sederhana yang menggunakan sejumlah kecil sumber daya komputasi ekstra. Sebagai gantinya, ini dapat menghemat sejumlah besar sumber daya komputasi. Karena itu, saya tidak dapat benar-benar melihat alasan untuk tidak menggunakannya.

RichieSams
sumber
Sejujurnya aku tidak sepenuhnya yakin tentang itu to be completely unbiased it must be random. Saya pikir Anda masih bisa mendapatkan hasil matematika-ok dengan menggunakan sampel fraksional weigthing, daripada lulus biner / menjatuhkan bahwa roulette Rusia memaksakan, hanya saja roulette akan konvergen lebih cepat karena mengoperasikan sampel kepentingan yang sangat penting.
v.oddou
9

Teknik roulette Rusia itu sendiri adalah cara mengakhiri jalur tanpa memperkenalkan bias sistemik. Prinsipnya cukup mudah: jika pada titik tertentu Anda memiliki peluang 10% untuk secara sewenang-wenang mengganti energi dengan 0, dan jika Anda melakukannya berkali-kali, Anda akan melihat energi 10% lebih sedikit. Peningkatan energi hanya mengimbangi itu. Jika Anda tidak mengkompensasi energi yang hilang karena pemutusan jalur, maka roulette Rusia akan menjadi bias, tetapi seluruh teknik adalah metode yang berguna untuk menghindari bias.

Jika saya seorang musuh yang ingin membuktikan bahwa teknik "terminasi jalur yang kontribusinya kurang dari nilai tetap kecil" bias, saya akan membuat adegan dengan cahaya yang sangat redup sehingga jalur yang berkontribusi selalu lebih kecil dari nilai itu. Mungkin saya mensimulasikan kamera rendah cahaya.

Tapi tentu saja Anda selalu dapat mengekspos nilai tetap sebagai parameter yang dapat diubah-ubah kepada pengguna, sehingga mereka dapat menjatuhkannya lebih jauh jika adegan mereka kurang cahaya. Jadi mari kita abaikan contoh itu sebentar.

Apa yang terjadi jika saya menganggap objek yang diterangi oleh banyak jalur berenergi sangat rendah yang dikumpulkan oleh a reflektor parabola ? Jalur energi rendah tidak harus terpental secara membabi buta dengan cara yang bisa Anda abaikan sepenuhnya. Alasan yang sama berlaku untuk, misalnya, memotong jalur setelah sejumlah terpental: Anda dapat membuat adegan dengan jalur yang memantulkan serangkaian 20 cermin sebelum mengenai suatu objek.

Cara lain untuk melihatnya: jika Anda menetapkan kontribusi jalur ke 0 setelah jatuh di bawah beberapa epsilon tetap, bagaimana Anda memperbaiki kehilangan energi itu? Anda tidak hanya mengurangi energi total dengan sebagian kecil. Anda tidak tahu apa-apa tentang berapa banyak energi yang Anda abaikan, karena Anda memotong pada ambang batas kontribusi sebelum Anda tahu faktor lain: energi kejadian.

John Calsbeek
sumber
8

Hanya untuk memperluas pada beberapa jawaban lain, bukti bahwa Roulette Rusia tidak memberikan hasil yang bias sangat sederhana.

F

F=F1++FN

Ganti setiap istilah dengan:

Fsaya={1halsayaFsayadengan probabilitas halsaya0jika tidak

Kemudian:

E[Fsaya]=halsaya×1halsayaE[Fsaya]+(1-halsaya)×0=E[Fsaya]

halsayaF

Nama samaran
sumber