Russian Roulette có thực sự là câu trả lời không?


21

Tôi đã thấy rằng trong một số triển khai Truy tìm đường dẫn, một cách tiếp cận có tên Russian Roulette được sử dụng để loại bỏ một số đường dẫn và chia sẻ đóng góp của chúng trong các đường dẫn khác.

Tôi hiểu rằng thay vì đi theo một con đường cho đến khi nó giảm xuống dưới một giá trị đóng góp ngưỡng nhất định và sau đó từ bỏ nó, một ngưỡng khác được sử dụng và các đường dẫn có đóng góp dưới ngưỡng đó chỉ bị chấm dứt với một xác suất nhỏ. Các đường dẫn khác có đóng góp của chúng tăng thêm một lượng tương ứng với việc chia sẻ năng lượng bị mất từ ​​đường dẫn bị chấm dứt. Tôi không rõ liệu điều này có phải là sửa lỗi sai lệch được giới thiệu bởi kỹ thuật hay không, hay liệu toàn bộ kỹ thuật có cần thiết để tránh sai lệch hay không.

  • Russian Roulette có cho kết quả không thiên vị không?
  • Russian Roulette có cần thiết cho một kết quả không thiên vị không?

Đó là, việc sử dụng một ngưỡng nhỏ và chỉ cần chấm dứt một con đường vào thời điểm nó giảm xuống dưới ngưỡng đó sẽ cho kết quả sai lệch hơn hoặc ít sai lệch hơn?

Cho một số lượng lớn mẫu tùy ý, cả hai cách tiếp cận sẽ hội tụ vào một hình ảnh kết quả không thiên vị?

Tôi đang tìm hiểu lý do cơ bản của việc sử dụng phương pháp Roulette Nga. Có sự khác biệt đáng kể về tốc độ hoặc chất lượng?


Tôi hiểu rằng năng lượng được phân phối lại giữa các tia khác để bảo toàn tổng năng lượng. Tuy nhiên, việc phân phối lại này có thể vẫn chưa được thực hiện nếu tia bị chấm dứt khi giảm xuống dưới ngưỡng cố định, thay vì có tuổi thọ được xác định ngẫu nhiên sau khi đạt đến ngưỡng đó?

Ngược lại, nếu năng lượng sẽ bị mất bằng cách chấm dứt một tia mà không phân phối lại thì cuối cùng năng lượng cũng bị mất (vì các tia được phân phối lại cuối cùng cũng bị chấm dứt), làm thế nào để cải thiện tình hình này?

Câu trả lời:


26

Để hiểu về Roulette Nga, chúng ta hãy xem xét một công cụ tìm đường lùi rất cơ bản:

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

I E. chúng tôi tung lên xung quanh khung cảnh, tích lũy màu sắc và suy giảm ánh sáng khi chúng tôi đi. Để hoàn toàn không thiên vị về mặt toán học, các lần thoát phải đi đến vô cùng. Nhưng điều này là không thực tế, và như bạn đã lưu ý, không cần thiết về mặt trực quan; đối với hầu hết các cảnh, sau một số lần thoát nhất định, giả sử là 10, số tiền đóng góp cho màu cuối cùng là rất rất nhỏ.

Vì vậy, để tiết kiệm tài nguyên máy tính, nhiều công cụ theo dõi đường dẫn có giới hạn cứng đối với số lần thoát. Điều này thêm sự thiên vị.

Điều đó nói rằng, thật khó để chọn giới hạn cứng đó là gì. Một số cảnh trông tuyệt vời sau 2 lần nảy; những người khác (nói với truyền hoặc SSS) có thể mất tới 10 hoặc 20. 2 Bounce từ Big Hero 6 của Disney 9 Bounce từ Big Hero 6 của Disney

Nếu chúng ta chọn quá thấp, hình ảnh sẽ bị sai lệch rõ ràng. Nhưng nếu chúng ta chọn quá cao, chúng ta sẽ lãng phí năng lượng và thời gian tính toán.

Một cách để giải quyết điều này, như bạn đã lưu ý, là chấm dứt con đường sau khi chúng ta đạt đến ngưỡng suy giảm nào đó. Điều này cũng thêm sự thiên vị.

Kẹp sau một ngưỡng, sẽ hoạt động , nhưng một lần nữa, làm thế nào để chúng ta chọn ngưỡng? Nếu chúng ta chọn quá lớn, hình ảnh sẽ bị sai lệch rõ ràng, quá nhỏ và chúng ta đang lãng phí tài nguyên.

Russian Roulette cố gắng giải quyết những vấn đề này một cách không thiên vị. Đầu tiên, đây là mã:

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

Russian Roulette chấm dứt ngẫu nhiên một con đường với xác suất nghịch đảo với thông lượng. Vì vậy, các đường dẫn có thông lượng thấp sẽ không đóng góp nhiều cho cảnh có nhiều khả năng bị chấm dứt.

Nếu chúng ta dừng lại ở đó, chúng ta vẫn thiên vị. Chúng ta 'mất' năng lượng của con đường chúng ta chấm dứt ngẫu nhiên. Để làm cho nó không thiên vị, chúng tôi tăng cường năng lượng của các đường dẫn không bị chấm dứt bởi xác suất của chúng bị chấm dứt. Điều này, cùng với việc là ngẫu nhiên, làm cho Roulette Nga không thiên vị.

Để trả lời câu hỏi cuối cùng của bạn:

  1. Russian Roulette có cho kết quả không thiên vị không?
    • Vâng
  2. Russian Roulette có cần thiết cho một kết quả không thiên vị không?
    • Phụ thuộc vào những gì bạn có nghĩa là không thiên vị. Nếu bạn có ý nghĩa toán học, thì có. Tuy nhiên, nếu bạn có nghĩa là trực quan, thì không. Bạn chỉ cần chọn cho bạn độ sâu đường dẫn tối đa và ngưỡng cắt rất rất cẩn thận. Điều này có thể rất tẻ nhạt vì nó có thể thay đổi từ cảnh này sang cảnh khác.
  3. Bạn có thể sử dụng một xác suất cố định (cắt bỏ), và sau đó phân phối lại năng lượng 'mất'. Đây có phải là thiên vị?
    • Nếu bạn sử dụng một xác suất cố định, bạn đang thêm sai lệch. Bằng cách phân phối lại năng lượng 'mất', bạn giảm bớt sự thiên vị, nhưng nó vẫn thiên về toán học. Để hoàn toàn không thiên vị, nó phải là ngẫu nhiên.
  4. Nếu năng lượng sẽ bị mất bằng cách chấm dứt một tia mà không phân phối lại thì cuối cùng năng lượng cũng bị mất (vì các tia được phân phối lại cuối cùng cũng bị chấm dứt), làm thế nào để cải thiện tình hình này?
    • Russian Roulette chỉ dừng lại nảy. Nó không loại bỏ hoàn toàn mẫu. Ngoài ra, năng lượng 'mất' được tính trong các lần nảy cho đến khi chấm dứt. Vì vậy, cách duy nhất để năng lượng "cuối cùng bị mất" sẽ là có một căn phòng hoàn toàn tối đen.

Cuối cùng, Russian Roulette là một thuật toán rất đơn giản sử dụng một lượng rất nhỏ tài nguyên tính toán bổ sung. Đổi lại, nó có thể tiết kiệm một lượng lớn tài nguyên tính toán. Vì vậy, tôi thực sự không thể thấy một lý do để không sử dụng nó.


Thành thật mà nói tôi không hoàn toàn chắc chắn về to be completely unbiased it must be random. Tôi nghĩ rằng bạn vẫn có thể nhận được kết quả toán học bằng cách sử dụng các mẫu vật phân đoạn, thay vì truyền / thả nhị phân mà roulette Nga áp đặt, chỉ là roulette sẽ hội tụ nhanh hơn vì nó vận hành lấy mẫu quan trọng hoàn hảo.
v.oddou

9

Kỹ thuật roulette Nga tự nó là một cách chấm dứt các con đường mà không đưa ra sự thiên vị hệ thống. Nguyên tắc khá đơn giản: nếu ở một đỉnh cụ thể, bạn có 10% cơ hội tùy ý thay thế năng lượng bằng 0 và nếu bạn làm điều đó với số lần vô hạn, bạn sẽ thấy năng lượng ít hơn 10%. Việc tăng năng lượng chỉ bù đắp cho điều đó. Nếu bạn không bù năng lượng bị mất do chấm dứt đường dẫn, thì roulette Nga sẽ bị sai lệch, nhưng toàn bộ kỹ thuật là một phương pháp hữu ích để tránh sai lệch.

Nếu tôi là một kẻ thù đang tìm cách chứng minh rằng kỹ thuật "chấm dứt các đường dẫn có đóng góp nhỏ hơn một số giá trị cố định nhỏ" bị sai lệch, tôi sẽ xây dựng một cảnh có ánh sáng mờ đến mức các đường dẫn đóng góp luôn nhỏ hơn giá trị đó. Có lẽ tôi đang mô phỏng một camera ánh sáng yếu.

Nhưng tất nhiên, bạn luôn có thể hiển thị giá trị cố định dưới dạng tham số có thể điều chỉnh cho người dùng, vì vậy họ có thể giảm giá trị hơn nữa nếu cảnh của họ xảy ra ánh sáng yếu. Vì vậy, hãy bỏ qua ví dụ đó trong một phút.

Điều gì xảy ra nếu tôi xem xét một vật thể được chiếu sáng bởi rất nhiều đường năng lượng rất thấp được thu thập bởi một gương phản xạ parabol ? Con đường năng lượng thấp không nhất thiết phải nảy xung quanh một cách bừa bãi theo cách mà bạn hoàn toàn có thể bỏ bê. Lý luận tương tự áp dụng cho, ví dụ, cắt các đường dẫn sau một số lần thoát cố định: bạn có thể tạo một cảnh với một đường dẫn bật ra một loạt 20 gương trước khi chạm vào một đối tượng.

Một cách khác để xem xét nó: nếu bạn đặt mức đóng góp của một đường dẫn thành 0 sau khi nó giảm xuống dưới một số epsilon cố định, làm thế nào để bạn khắc phục sự mất năng lượng đó? Bạn không chỉ đơn giản là giảm tổng năng lượng bằng một phần nhỏ. Bạn không biết bất cứ điều gì về việc bạn đang bỏ bê bao nhiêu năng lượng, bởi vì bạn đang cắt ở một số ngưỡng đóng góp trước khi bạn biết yếu tố khác: năng lượng sự cố.


8

Chỉ cần mở rộng một số câu trả lời khác, bằng chứng cho thấy Russian Roulette không đưa ra kết quả biassed là rất đơn giản.

F

F= =F1++FN

Thay thế mỗi thuật ngữ bằng:

Ftôi'= ={1ptôiFtôivới xác suất ptôi0nếu không thì

Sau đó:

E[Ftôi']= =ptôi×1ptôiE[Ftôi]+(1-ptôi)×0= =E[Ftôi]

ptôiF

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.