Код русской рулетки правильный?

8

Я использую www.scratchapixel.com среди других ресурсов, чтобы помочь мне узнать, как реализовать рендерер. Я смотрю на следующий код с этой страницы, где рассматривается пакет фотонов, движущихся через материал. Для каждого фотонного пакета вес инициализируется равным . - вероятность поглощения.вес1dвес

Непонятная часть для меня - это когда вычитается из . Я вижу, что это имеет смысл, когда пакет имеет полный вес потому что - это не поглощенная доля фотонов. Например, если вероятность поглощения составляет тогда и фотонов остаются. Я не вижу, как это имеет смысл на последующих итерациях. Например, на второй итерации поэтому половина фотонов поглощается на этой итерации, а не треть.dвесвес11-dвес33%весзнак равно1-0,33знак равно0,6767%весзнак равно0,67-0,33знак равно0,34

int photons = 10000; 
... 
int m = 5; // there's 1 over 6 chances for the packet to be absorbed 
for (int i = 0; i < nphotons; ++i) { 
    float w = 1; // set the weight to 1 
    Vec3f P(0, 0, 0); 
    Vec3f V(0, 0, 1); 
    while (1) { 
        ... 
        float dw = sigma_a / sigma_t; 
        absorption += dw; 
        w -= dw; 
        if (w < 0.001) { // perform russian roulette if weight is small 
            if (drand48() < 1.0 / m) { 
                break; // we kill the packet 
            } 
            else 
                w *= m; // adjust weight 
        } 
    } 
} 
PeteUK
источник

Ответы:

4

Я думаю, что вы правы, и вычитание является ошибкой. Код должен скорее умножать долю фотонов, не поглощенных в весе. Что-то вроде:

float fraction_absorbed = sigma_a / sigma_t;
absorption += w * fraction_absorbed;
w *= (1.0f - fraction_absorbed);

Это делает absorptionобщую долю фотонов, поглощенных до сих пор, и wдолю оставшихся фотонов.

Натан Рид
источник
2
В качестве дополнения: Ответ на этот другой вопрос содержит пример кода для русской рулетки. computergraphics.stackexchange.com/questions/2316/…
RichieSams