รูเล็ตรัสเซียเป็นคำตอบจริงๆหรือไม่?


21

ฉันได้เห็นแล้วว่าในการติดตั้ง Path Tracing การใช้แนวทางที่เรียกว่า Russian Roulette นั้นใช้ในการกำจัดเส้นทางบางส่วนและแบ่งปันผลงานของพวกเขาในเส้นทางอื่น ๆ

ฉันเข้าใจว่าแทนที่จะติดตามเส้นทางจนกว่ามันจะลดลงต่ำกว่าค่าการสนับสนุนที่กำหนดไว้และจากนั้นให้ทิ้งการใช้เกณฑ์ที่แตกต่างกันและเส้นทางที่การบริจาคต่ำกว่าเกณฑ์นั้นจะถูกยกเลิกด้วยความน่าจะเป็นเพียงเล็กน้อยเท่านั้น เส้นทางอื่นมีส่วนร่วมของพวกเขาเพิ่มขึ้นตามจำนวนที่สอดคล้องกับการแบ่งปันพลังงานที่หายไปจากเส้นทางที่ถูกยกเลิก ฉันยังไม่ชัดเจนว่าจะเป็นการแก้ไขอคติที่ได้รับการแนะนำโดยเทคนิคหรือไม่หรือจำเป็นต้องใช้เทคนิคทั้งหมดเพื่อหลีกเลี่ยงอคติ

  • รูเล็ตรัสเซียให้ผลที่ไม่เอนเอียงหรือไม่?
  • รูเล็ตรัสเซียจำเป็นสำหรับผลที่เป็นกลางหรือไม่?

นั่นคือจะใช้ขีด จำกัด เล็ก ๆ และยกเลิกเส้นทางทันทีที่มันลดลงต่ำกว่าขีด จำกัด นั้นจะให้ผลลัพธ์ที่เอนเอียงหรือมีอคติน้อยลงหรือไม่

เมื่อพิจารณาจากตัวอย่างจำนวนมากโดยพลการทั้งสองจะเข้าหากันบนภาพผลลัพธ์ที่เป็นกลางหรือไม่?

ฉันกำลังมองหาที่จะเข้าใจเหตุผลพื้นฐานสำหรับการใช้วิธีรูเล็ตรัสเซีย ความเร็วหรือคุณภาพแตกต่างกันอย่างมีนัยสำคัญหรือไม่?


ฉันเข้าใจว่าพลังงานถูกกระจายไปในรังสีอื่นเพื่อรักษาพลังงานทั้งหมด อย่างไรก็ตามการแจกจ่ายนี้ยังไม่สามารถทำได้ถ้ารังสีนั้นสิ้นสุดลงเมื่อลดลงต่ำกว่าขีด จำกัด คงที่แทนที่จะมีช่วงชีวิตที่กำหนดแบบสุ่มหลังจากถึงขีด จำกัด นั้นหรือไม่?

ในทางกลับกันถ้าพลังงานที่จะสูญเสียไปโดยการยุติรังสีโดยไม่ต้องกระจายพลังงานนั้นก็จะหายไปในที่สุด (เช่นเดียวกับรังสีที่มันถูกแจกจ่ายไปก็ถูกยกเลิกด้วย) ในที่สุดสิ่งนี้จะปรับปรุงสถานการณ์ได้อย่างไร

คำตอบ:


26

เพื่อที่จะเข้าใจรูเล็ตรัสเซียมาดูที่เส้นทางย้อนกลับพื้นฐาน:

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

IE เราเด้งไปรอบ ๆ ฉากสะสมสีและลดทอนแสงเมื่อเราไป เพื่อที่จะไม่เอนเอียงทางคณิตศาสตร์อย่างสมบูรณ์การตีกลับควรไปที่อินฟินิตี้ แต่นี่เป็นสิ่งที่ไม่สมจริงและตามที่คุณสังเกตเห็นไม่จำเป็นต้องใช้สายตา สำหรับฉากส่วนใหญ่หลังจากที่มีการตีกลับมาเป็นจำนวนมากให้บอกว่า 10 จำนวนของการมีส่วนร่วมกับสีสุดท้ายนั้นน้อยมาก

ดังนั้นเพื่อประหยัดทรัพยากรในการคำนวณ Tracers เส้นทางจำนวนมากมีการ จำกัด จำนวนการตีกลับอย่างหนัก นี่เป็นการเพิ่มอคติ

ที่กล่าวว่ามันยากที่จะเลือกสิ่งที่ขีด จำกัด ที่ควรจะเป็น บางฉากดูดีหลังจากการตีกลับ 2 ครั้ง อื่น ๆ (พูดด้วยการส่งหรือ SSS) อาจใช้เวลานานถึง 10 หรือ 20 2 ตีกลับจาก Big Hero ของดิสนีย์ 6 9 Bounces จาก Big Hero ของดิสนีย์ 6

หากเราเลือกต่ำเกินไปภาพจะลำเอียงอย่างเห็นได้ชัด แต่ถ้าเราเลือกสูงเกินไปเราจะสูญเสียพลังงานและเวลาในการคำนวณ

วิธีหนึ่งในการแก้ไขปัญหานี้ตามที่คุณระบุไว้คือการยุติเส้นทางหลังจากที่เราถึงเกณฑ์การลดทอนแล้ว สิ่งนี้ยังเพิ่มอคติ

การยึดตามขีด จำกัด จะทำงานได้ แต่อีกครั้งเราจะเลือกขีด จำกัด ได้อย่างไร หากเราเลือกขนาดใหญ่เกินไปภาพจะมีอคติอย่างเห็นได้ชัดเล็กเกินไปและเราสิ้นเปลืองทรัพยากร

Russian Roulette พยายามแก้ไขปัญหาเหล่านี้อย่างเป็นกลาง ก่อนอื่นนี่คือรหัส:

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

รูเล็ตรัสเซียสุ่มยุติเส้นทางด้วยความน่าจะเป็นที่ตรงกันข้ามกับปริมาณงาน ดังนั้นเส้นทางที่มีปริมาณงานต่ำซึ่งไม่ได้ช่วยอะไรมากในฉากมีแนวโน้มที่จะถูกยกเลิก

ถ้าเราหยุดตรงนั้นเรายังคงลำเอียง เรา 'สูญเสีย' พลังงานของเส้นทางที่เรายุติแบบสุ่ม เพื่อเพิ่มความเป็นกลางเราเพิ่มพลังงานของเส้นทางที่ไม่สิ้นสุดโดยความน่าจะเป็นที่จะถูกยกเลิก สิ่งนี้รวมถึงการสุ่มทำให้รูเล็ตรัสเซียไม่เอนเอียง

ในการตอบคำถามสุดท้ายของคุณ:

  1. รูเล็ตรัสเซียให้ผลที่ไม่เอนเอียงหรือไม่?
    • ใช่
  2. รูเล็ตรัสเซียจำเป็นสำหรับผลที่เป็นกลางหรือไม่?
    • ขึ้นอยู่กับสิ่งที่คุณหมายถึงโดยเป็นกลาง ถ้าคุณหมายถึงทางคณิตศาสตร์แล้วใช่ อย่างไรก็ตามถ้าคุณหมายถึงภาพแล้วไม่ คุณเพียงแค่ต้องเลือกความลึกเส้นทางสูงสุดและเกณฑ์การตัดยอดอย่างระมัดระวังมาก เรื่องนี้น่าเบื่อมากเพราะมันสามารถเปลี่ยนจากฉากหนึ่งไปอีกฉากหนึ่ง
  3. คุณสามารถใช้ความน่าจะเป็นคงที่ (ตัดออก) แล้วกระจายพลังงานที่หายไป นี่เป็นกลางหรือไม่?
    • หากคุณใช้ความน่าจะเป็นคงที่คุณจะเพิ่มอคติ โดยการกระจายพลังงาน 'ที่หายไป' คุณจะลดอคติ แต่ก็ยังมีอคติทางคณิตศาสตร์อยู่ หากจะเป็นกลางอย่างสมบูรณ์จะต้องสุ่ม
  4. หากพลังงานที่จะสูญเสียไปโดยการยุติรังสีโดยไม่ต้องแจกจ่ายพลังงานนั้นก็จะหายไปในที่สุด (เช่นเดียวกับรังสีที่มันถูกแจกจ่ายไปก็ถูกยกเลิกด้วย) ในที่สุดสิ่งนี้จะปรับปรุงสถานการณ์ได้อย่างไร
    • รูเล็ตรัสเซียจะหยุดการตีกลับเท่านั้น ไม่ลบตัวอย่างทั้งหมด นอกจากนี้พลังงานที่ 'สูญเสีย' จะถูกคำนวณในการสะท้อนจนถึงการสิ้นสุด ดังนั้นวิธีเดียวที่พลังงานจะ 'หายไปในที่สุด' ก็คือการมีห้องสีดำสนิท

ในท้ายที่สุดรูเล็ตรัสเซียเป็นอัลกอริทึมที่ง่ายมากที่ใช้ทรัพยากรการคำนวณพิเศษจำนวนเล็กน้อย ในการแลกเปลี่ยนมันสามารถบันทึกทรัพยากรการคำนวณจำนวนมาก ดังนั้นฉันไม่เห็นเหตุผลที่จะไม่ใช้มันจริงๆ


ฉันไม่แน่ใจto be completely unbiased it must be randomจริงๆ ฉันคิดว่าคุณยังสามารถรับผลลัพธ์ทางคณิตศาสตร์ได้โดยใช้การสุ่มตัวอย่างแบบเศษส่วนแทนที่จะใช้รหัสผ่าน / วางที่รูเล็ตรัสเซียกำหนด
v.oddou

9

เทคนิครูเล็ตรัสเซียนั้นเป็นวิธีการยกเลิกเส้นทางโดยไม่ต้องมีอคติอย่างเป็นระบบ หลักการนั้นค่อนข้างตรงไปตรงมา: ถ้าในจุดสุดยอดหนึ่งคุณมีโอกาส 10% ที่จะเปลี่ยนพลังงานด้วย 0 โดยพลการและถ้าคุณทำเช่นนั้นโดยไม่ จำกัด จำนวนครั้งคุณจะเห็นพลังงานน้อยลง 10% การเพิ่มพลังงานเพียงแค่ชดเชยสิ่งนั้น หากคุณไม่ได้ชดเชยพลังงานที่สูญเสียไปเนื่องจากการยุติเส้นทางรูเล็ตรัสเซียก็จะลำเอียง แต่เทคนิคทั้งหมดเป็นวิธีที่มีประโยชน์ในการหลีกเลี่ยงอคติ

ถ้าฉันเป็นปฏิปักษ์มองที่จะพิสูจน์ว่า "ยุติเส้นทางที่มีผลงานน้อยกว่าค่าคงที่บางเล็ก" เทคนิคจะลำเอียงผมจะสร้างฉากที่มีไฟสลัวเพื่อว่าเส้นทางที่เอื้ออยู่เสมอน้อยกว่าค่าที่ บางทีฉันจำลองกล้องที่มีแสงน้อย

แต่แน่นอนคุณสามารถเปิดเผยค่าคงที่เป็นพารามิเตอร์ที่ปรับแต่งได้กับผู้ใช้เสมอเพื่อให้ผู้ใช้สามารถวางมันได้แม้ในฉากที่มีแสงน้อย งั้นลองมองข้ามตัวอย่างนั้นสักครู่

เกิดอะไรขึ้นถ้าผมคิดว่าวัตถุที่ถูกส่องสว่างโดยมากของเส้นทางพลังงานต่ำมากที่จะเก็บรวบรวมโดยหนึ่งกระจกโค้ง ? เส้นทางพลังงานต่ำไม่จำเป็นต้องเด้ง ๆ ไปเรื่อย ๆ ในลักษณะที่คุณสามารถละเลยได้อย่างสมบูรณ์ การใช้เหตุผลในทำนองเดียวกันเช่นตัดเส้นทางหลังจากมีการตีกลับจำนวนคงที่: คุณสามารถสร้างฉากด้วยเส้นทางที่สะท้อนชุดของกระจก 20 ชุดก่อนที่จะชนวัตถุ

อีกวิธีในการดู: หากคุณตั้งค่าการมีส่วนร่วมของเส้นทางเป็น 0 หลังจากที่มันลดลงต่ำกว่า epsilon คงที่คุณจะแก้ไขการสูญเสียพลังงานได้อย่างไร คุณไม่ได้ลดพลังงานโดยรวมลงเพียงเล็กน้อย คุณไม่รู้อะไรเลยเกี่ยวกับพลังงานที่คุณถูกทอดทิ้งเพราะคุณกำลังตัดค่าใช้จ่ายบางส่วนก่อนที่คุณจะรู้ปัจจัยอื่น ๆ : พลังงานที่ตกกระทบ


8

เพียงเพื่อขยายคำตอบอื่น ๆ การพิสูจน์ว่ารูเล็ตรัสเซียไม่ได้ให้ผลลัพธ์แบบชีวมวลนั้นง่ายมาก

F

F=F1++Fยังไม่มีข้อความ

แทนที่แต่ละคำด้วย:

Fผม'={1พีผมFผมด้วยความน่าจะเป็น พีผม0มิฉะนั้น

แล้ว:

E[Fผม']=พีผม×1พีผมE[Fผม]+(1-พีผม)×0=E[Fผม]

พีผมF

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.