ロシアンルーレットは本当に答えですか?


21

パストレースの一部の実装では、ロシアンルーレットと呼ばれるアプローチを使用して、一部のパスをカリングし、他のパス間でその寄与を共有することを確認しました。

貢献の特定のしきい値を下回るまでパスをたどり、それを放棄するのではなく、別のしきい値が使用され、そのしきい値を下回る貢献のパスはわずかな確率で終了することを理解しています。他のパスは、終端されたパスからの失われたエネルギーを共有することに対応する量だけ寄与が増加します。これがテクニックによって導入されたバイアスを修正することなのか、それともバイアスを回避するためにテクニック全体が必要かどうかは、私にはわかりません。

  • ロシアンルーレットは公平な結果をもたらしますか?
  • ロシアンルーレットは公平な結果を得るために必要ですか?

つまり、小さなしきい値を使用し、そのしきい値を下回る瞬間にパスを終了するだけで、より偏った結果またはより偏りのない結果が得られますか?

任意の数のサンプルが与えられた場合、両方のアプローチは不偏の結果の画像に収束しますか?

ロシアンルーレットアプローチを使用する根本的な理由を理解したいと考えています。速度や品質に大きな違いはありますか?


総エネルギーを保存するために、他の光線にエネルギーが再分配されることを理解しています。ただし、レイがしきい値に達した後にランダムに決定された寿命を持つのではなく、固定されたしきい値を下回るとレイが終了した場合、この再配布はまだ実行できませんか?

逆に、エネルギーを再分配せずにレイを終了することによって失われるエネルギーが最終的に失われる場合(再分配されるレイも最終的に終了するため)、これは状況をどのように改善しますか?

回答:


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回など)の後、最終的な色への寄与量は非常にわずかです。

そのため、コンピューティングリソースを節約するために、多くのパストレーサーにはバウンスの数に厳しい制限があります。これはバイアスを追加します。

とはいえ、その厳しい制限値を選択するのは困難です。いくつかのシーンは、2回のバウンス後に見栄えがよくなります。その他(送信またはSSSの場合など)は、最大10または20かかります。 ディズニーのビッグヒーロー6から2バウンス ディズニーのビッグヒーロー6から9バウンス

低すぎる値を選択すると、画像に視覚的な偏りが生じます。しかし、あまりに高い値を選択すると、計算のエネルギーと時間が無駄になります。

これを解決する1つの方法は、既に述べたように、減衰のしきい値に達した後にパスを終了することです。これもバイアスを追加します。

しきい値後クランプ、だろう仕事が、再び、どのように我々は、しきい値を選ぶのですか?選択したサイズが大きすぎると、画像に視覚的な偏りが生じ、小さすぎるため、リソースが無駄になります。

ロシアンルーレットは、これらの問題を公平に解決しようとします。まず、コードは次のとおりです。

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

ロシアンルーレット技術自体は、システムバイアスを導入せずにパスを終了する方法です。原理はかなり単純です。特定の頂点で、エネルギーを任意に0に置き換える確率が10%あり、無限に繰り返すと、エネルギーが10%少なくなります。エネルギーブーストはそれを補います。パスの終了により失われたエネルギーを補償しなかった場合、ロシアンルーレットにバイアスがかかりますが、バイアスを回避するにはテクニック全体が有用な方法です。

「貢献度が小さな固定値よりも小さいパスを終了する」手法に偏りがあることを証明しようとする敵である場合、ライトを使用してシーンを構築し、パスが常にその値よりも小さくなるようにします。おそらく、私は低照度カメラをシミュレートしています。

しかし、もちろん、固定値を調整可能なパラメーターとしてユーザーに公開することもできます。そのため、シーンが暗い場合は、さらに値を落とすことができます。それでは、その例を無視してみましょう。

放物面反射器によって収集される非常に低エネルギーの多くの経路によって照らされる物体を考えるとどうなりますか?低エネルギー経路は、必ずしも完全に無視できる方法で無差別に跳ね返るわけではありません。同様に、一定のバウンス回数でパスを遮断するなどの理由も当てはまります。オブジェクトに当たる前に一連の20個のミラーで跳ね返るパスでシーンを構築できます。

別の見方:パスが一定のイプシロンを下回った後にパスの寄与を0に設定した場合、そのエネルギー損失をどのように修正しますか?単に総エネルギーを少しだけ減らすわけではありません。あなたが無視しているエネルギーの量については何も知りません。なぜなら、あなたは他の要因である入射エネルギーを知る前に、ある寄与閾値で遮断しているからです。


8

他のいくつかの答えを拡張するだけで、ロシアンルーレットが偏った結果をもたらさないという証拠は非常に簡単です。

F

F=F1++FN

各用語を次のように置き換えます。

F={1pF確率で p0さもないと

次に:

E[F]=p×1pE[F]+1p×0=E[F]

pF

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.