সুস্পষ্ট আলোক স্যাম্পলিং সহ প্রগতিশীল পাথ ট্রেসিং


14

আমি বিআরডিএফ অংশের জন্য গুরুত্বপূর্ণ নমুনা দেওয়ার পিছনে যুক্তিটি বুঝতে পারি। যাইহোক, যখন আলোর উত্সগুলি স্পষ্টভাবে নমুনা নেওয়ার কথা আসে, তখন সমস্ত বিভ্রান্ত হয়। উদাহরণস্বরূপ, আমার দৃশ্যে যদি আমার এক পয়েন্ট আলোর উত্স থাকে এবং আমি যদি প্রত্যক্ষভাবে প্রতিটি ফ্রেমে এটি নমুনা করি তবে আমি কি এটিকে মন্টি কার্লো ইন্টিগ্রেশনের জন্য আরও একটি নমুনা হিসাবে গণনা করব? এটি হ'ল, আমি কোসাইন-ওজনযুক্ত বিতরণ এবং অন্যটি বিন্দু থেকে নমুনা নিই। এটি মোট দুটি নমুনা বা একটি মাত্র? এছাড়াও, আমি কি সরাসরি নমুনা থেকে আসা তেজকে কোনও পদে বিভক্ত করব?

উত্তর:


19

পাথ ট্রেসিংয়ের একাধিক ক্ষেত্র রয়েছে যা নমুনাযুক্ত হয়ে উঠতে পারে। এছাড়াও, সেই ক্ষেত্রগুলির প্রত্যেকটি একাধিক গুরুত্ব স্যাম্পলিং ব্যবহার করতে পারে, যা প্রথম ভ্যাচ এবং গুইবার 1995 এর কাগজে প্রস্তাবিত হয়েছিল । আরও ভাল ব্যাখ্যা করতে, আসুন পিছনের পথের ট্রেসারটি দেখুন:

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);
    SurfaceInteraction interaction;

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

        // The ray missed. Return the background color
        if (ray.GeomID == INVALID_GEOMETRY_ID) {
            color += throughput * m_scene->BackgroundColor;
            break;
        }

        // 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 emission
        if (light != nullptr) {
            color += throughput * light->Le();
        }

        interaction.Position = ray.Origin + ray.Direction * ray.TFar;
        interaction.Normal = normalize(m_scene->InterpolateNormal(ray.GeomID, ray.PrimID, ray.U, ray.V));
        interaction.OutputDirection = normalize(-ray.Direction);


        // Get the new ray direction
        // Choose the direction based on the bsdf        
        material->bsdf->Sample(interaction, sampler);
        float pdf = material->bsdf->Pdf(interaction);

        // Accumulate the weight
        throughput = throughput * material->bsdf->Eval(interaction) / pdf;

        // Shoot a new ray

        // Set the origin at the intersection point
        ray.Origin = interaction.Position;

        // Reset the other ray properties
        ray.Direction = interaction.InputDirection;
        ray.TNear = 0.001f;
        ray.TFar = infinity;


        // Russian Roulette
        if (bounces > 3) {
            float p = std::max(throughput.x, std::max(throughput.y, throughput.z));
            if (sampler->NextFloat() > p) {
                break;
            }

            throughput *= 1 / p;
        }
    }

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

ইংরেজীতে:

  1. দৃশ্যের মাধ্যমে একটি রশ্মি অঙ্কুর
  2. আমরা কিছু আঘাত করে কিনা তা পরীক্ষা করে দেখুন। যদি না হয় আমরা স্কাইবক্সের রঙ এবং বিরতি ফিরিয়ে দেব।
  3. আমরা কোন আলো মারি কিনা তা পরীক্ষা করে দেখুন। যদি তা হয় তবে আমরা আমাদের রঙ জমে হালকা নির্গমন যুক্ত করি
  4. পরবর্তী রশ্মির জন্য একটি নতুন দিক চয়ন করুন। আমরা বিআরডিএফ এর উপর ভিত্তি করে এটি অভিন্ন বা গুরুত্বের নমুনাটি করতে পারি
  5. বিআরডিএফকে মূল্যায়ন করুন এবং এটি জমা করুন। মন্টি কার্লো অ্যালগরিদম অনুসরণ করতে এখানে আমাদের আমাদের নির্বাচিত দিকের পিডিএফ দ্বারা ভাগ করতে হবে।
  6. আমাদের নির্বাচিত দিকের উপর ভিত্তি করে একটি নতুন রশ্মি তৈরি করুন এবং আমরা সবেমাত্র এসেছি
  7. [Ptionচ্ছিক] আমাদের যদি রশ্মি বন্ধ করা উচিত কিনা তা চয়ন করতে রাশিয়ান রুলেট ব্যবহার করুন
  8. গোটো ঘ

এই কোডটি সহ, কেবলমাত্র রঙটি পাই যদি শেষ পর্যন্ত রশ্মি একটি আলোতে আঘাত করে। এগুলির পাশাপাশি, এটি নিয়মিত আলোর উত্সগুলিকে সমর্থন করে না, কারণ তাদের কোনও অঞ্চল নেই।

এটি ঠিক করতে, আমরা প্রতিটি বাউন্সে সরাসরি লাইট নমুনা করি। আমাদের কয়েকটি ছোট পরিবর্তন করতে হবে:

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);
    SurfaceInteraction interaction;

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

        // The ray missed. Return the background color
        if (ray.GeomID == INVALID_GEOMETRY_ID) {
            color += throughput * m_scene->BackgroundColor;
            break;
        }

        // 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 this is the first bounce or if we just had a specular bounce,
        // we need to add the emmisive light
        if ((bounces == 0 || (interaction.SampledLobe & BSDFLobe::Specular) != 0) && light != nullptr) {
            color += throughput * light->Le();
        }

        interaction.Position = ray.Origin + ray.Direction * ray.TFar;
        interaction.Normal = normalize(m_scene->InterpolateNormal(ray.GeomID, ray.PrimID, ray.U, ray.V));
        interaction.OutputDirection = normalize(-ray.Direction);


        // Calculate the direct lighting
        color += throughput * SampleLights(sampler, interaction, material->bsdf, light);


        // Get the new ray direction
        // Choose the direction based on the bsdf        
        material->bsdf->Sample(interaction, sampler);
        float pdf = material->bsdf->Pdf(interaction);

        // Accumulate the weight
        throughput = throughput * material->bsdf->Eval(interaction) / pdf;

        // Shoot a new ray

        // Set the origin at the intersection point
        ray.Origin = interaction.Position;

        // Reset the other ray properties
        ray.Direction = interaction.InputDirection;
        ray.TNear = 0.001f;
        ray.TFar = infinity;


        // Russian Roulette
        if (bounces > 3) {
            float p = std::max(throughput.x, std::max(throughput.y, throughput.z));
            if (sampler->NextFloat() > p) {
                break;
            }

            throughput *= 1 / p;
        }
    }

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

প্রথমে আমরা "রঙ + = থ্রুপুট * স্যাম্পললাইট (...)" যুক্ত করি। আমি স্যাম্পললাইট () সম্পর্কে কিছুটা বিশদে যাব। তবে, মূলত, এটি সমস্ত লাইটের মধ্যে ছড়িয়ে পড়ে এবং বিএসডিএফ দ্বারা তত্পর হয়ে রঙে তাদের অবদানটি ফিরিয়ে দেয়।

এটি দুর্দান্ত, তবে এটি সঠিক করতে আমাদের আরও একটি পরিবর্তন করা দরকার; বিশেষত, যখন আমরা একটি আলো আঘাত করি তখন কী হয়। পুরানো কোডে, আমরা রঙের জমে আলোর নিঃসরণ যুক্ত করেছি। তবে এখন আমরা প্রতিটি বাউন্সে সরাসরি আলোকে নমুনা করি, তাই আমরা যদি আলোর নিঃসরণ যুক্ত করি তবে আমরা "ডাবল ডিপ" করব। সুতরাং, সঠিক জিনিসটি হ'ল ... কিছুই নয়; আমরা আলোর নিঃসরণ জমে এড়িয়ে চলি।

তবে দুটি কর্নার কেস রয়েছে:

  1. প্রথম রশ্মি
  2. পুরোপুরি স্পেকুলার বাউন্স (ওরফে মিরর)

যদি প্রথম রশ্মি আলোকে আঘাত করে তবে আপনার উচিত আলোর নির্গমন সরাসরি দেখা উচিত। সুতরাং আমরা যদি এটি এড়িয়ে চলে যাই তবে সমস্ত আলোকসজ্জা কালো হিসাবে প্রদর্শিত হবে যদিও তাদের চারপাশের পৃষ্ঠতলগুলি আলোকিত হয়।

আপনি যখন পুরোপুরি স্পেকুলার পৃষ্ঠগুলিতে আঘাত করেন আপনি সরাসরি কোনও আলোর নমুনা করতে পারবেন না, কারণ একটি ইনপুট রশ্মির কেবল একটি আউটপুট থাকে। আচ্ছা, প্রযুক্তিগতভাবে, আমরা ইনপুট রশ্মিটি হালকা আঘাত করতে চলেছে কিনা তা পরীক্ষা করে দেখতে পারি , তবে এর কোনও মানে নেই; মূল পাথ ট্রেসিং লুপ যেভাবেই করতে চলেছে। অতএব, আমরা যদি একটি স্পেসুলার পৃষ্ঠকে আঘাত করার ঠিক পরে একটি হালকা আঘাত করি তবে আমাদের রঙটি সংগ্রহ করতে হবে। যদি আমরা না করি তবে লাইটগুলি আয়নাতে কালো হবে।

এখন, আসুন স্যাম্পললাইটগুলি () সন্ধান করুন:

float3 SampleLights(UniformSampler *sampler, SurfaceInteraction interaction, BSDF *bsdf, Light *hitLight) const {
    std::size_t numLights = m_scene->NumLights();

    float3 L(0.0f);
    for (uint i = 0; i < numLights; ++i) {
        Light *light = &m_scene->Lights[i];

        // Don't let a light contribute light to itself
        if (light == hitLight) {
            continue;
        }

        L = L + EstimateDirect(light, sampler, interaction, bsdf);
    }

    return L;
}

ইংরেজীতে:

  1. সমস্ত লাইট মাধ্যমে লুপ
  2. আমরা যদি এটি আঘাত করি তবে আলোটি এড়িয়ে যান
    • ডাবল ডুব দেবেন না
  3. সমস্ত আলো থেকে সরাসরি আলো একত্রিত করুন
  4. সরাসরি আলো ফিরিয়ে দিন

পরিশেষে, () কেবল ) মূল্যায়নBSDF(p,ωi,ωo)Li(p,ωi)

নিয়মিত আলোর উত্সগুলির জন্য, এটি এত সহজ:

float3 EstimateDirect(Light *light, UniformSampler *sampler, SurfaceInteraction &interaction, BSDF *bsdf) const {
    // Only sample if the BRDF is non-specular 
    if ((bsdf->SupportedLobes & ~BSDFLobe::Specular) != 0) {
        return float3(0.0f);
    }

    interaction.InputDirection = normalize(light->Origin - interaction.Position);
    return bsdf->Eval(interaction) * light->Li;
}

তবে, আমরা যদি আলোর ক্ষেত্রফল পেতে চাই তবে আমাদের প্রথমে আলোর একটি বিন্দুর নমুনা নেওয়া দরকার। সুতরাং, সম্পূর্ণ সংজ্ঞাটি হ'ল:

float3 EstimateDirect(Light *light, UniformSampler *sampler, SurfaceInteraction &interaction, BSDF *bsdf) const {
    float3 directLighting = float3(0.0f);

    // Only sample if the BRDF is non-specular 
    if ((bsdf->SupportedLobes & ~BSDFLobe::Specular) != 0) {
        float pdf;
        float3 Li = light->SampleLi(sampler, m_scene, interaction, &pdf);

        // Make sure the pdf isn't zero and the radiance isn't black
        if (pdf != 0.0f && !all(Li)) {
            directLighting += bsdf->Eval(interaction) * Li / pdf;
        }
    }

    return directLighting;
}

আমরা হালকা-> নমুনা প্রয়োগ করতে পারি তবে আমরা চাই; আমরা বিন্দুটি অভিন্ন বা গুরুত্বের নমুনাটি চয়ন করতে পারি। উভয় ক্ষেত্রেই, আমরা বিন্দুটি বেছে নেওয়ার পিডিএফ দ্বারা রেডিজিটিটি ভাগ করি। আবার মন্টি কার্লোর প্রয়োজনীয়তা পূরণ করতে fy

বিআরডিএফ যদি সর্বোচ্চ নির্ভরশীল হয় তবে আলোর উপর এলোমেলো পয়েন্টের পরিবর্তে বিআরডিএফ-এর ভিত্তিতে একটি পয়েন্ট বেছে নেওয়া আরও ভাল। তবে আমরা কীভাবে নির্বাচন করব? নমুনা আলোর উপর ভিত্তি করে, বা বিআরডিএফ ভিত্তিক?

কেন না উভয়? একাধিক গুরুত্ব স্যাম্পলিং প্রবেশ করান। সংক্ষেপে, আমরা একাধিকবার, বিভিন্ন নমুনা কৌশল ব্যবহার করে, তারপরে পিডিএফ-এর উপর ভিত্তি করে ওজন ব্যবহার করে তাদের একসাথে গড় করুন। কোডটি হ'ল:BSDF(p,ωi,ωo)Li(p,ωi)

float3 EstimateDirect(Light *light, UniformSampler *sampler, SurfaceInteraction &interaction, BSDF *bsdf) const {
    float3 directLighting = float3(0.0f);
    float3 f;
    float lightPdf, scatteringPdf;


    // Sample lighting with multiple importance sampling
    // Only sample if the BRDF is non-specular 
    if ((bsdf->SupportedLobes & ~BSDFLobe::Specular) != 0) {
        float3 Li = light->SampleLi(sampler, m_scene, interaction, &lightPdf);

        // Make sure the pdf isn't zero and the radiance isn't black
        if (lightPdf != 0.0f && !all(Li)) {
            // Calculate the brdf value
            f = bsdf->Eval(interaction);
            scatteringPdf = bsdf->Pdf(interaction);

            if (scatteringPdf != 0.0f && !all(f)) {
                float weight = PowerHeuristic(1, lightPdf, 1, scatteringPdf);
                directLighting += f * Li * weight / lightPdf;
            }
        }
    }


    // Sample brdf with multiple importance sampling
    bsdf->Sample(interaction, sampler);
    f = bsdf->Eval(interaction);
    scatteringPdf = bsdf->Pdf(interaction);
    if (scatteringPdf != 0.0f && !all(f)) {
        lightPdf = light->PdfLi(m_scene, interaction);
        if (lightPdf == 0.0f) {
            // We didn't hit anything, so ignore the brdf sample
            return directLighting;
        }

        float weight = PowerHeuristic(1, scatteringPdf, 1, lightPdf);
        float3 Li = light->Le();
        directLighting += f * Li * weight / scatteringPdf;
    }

    return directLighting;
}

ইংরেজীতে:

  1. প্রথমত, আমরা আলোর নমুনা করি
    • এটি ইন্টারঅ্যাকশন আপডেট করে I
    • আলোর জন্য আমাদের লি দেয়
    • এবং আলোর উপর পয়েন্ট চয়ন করার পিডিএফ
  2. দেখুন যে পিডিএফটি বৈধ এবং তেজস্বী শূন্য নয় is
  3. নমুনাযুক্ত ইনপুট দিকনির্দেশ ব্যবহার করে BSDF মূল্যায়ন করুন
  4. নমুনাযুক্ত ইনপুট দিকনির্দেশ দেওয়া বিএসডিএফের জন্য পিডিএফ গণনা করুন
    • মূলত, এই নমুনাটি কতটা সম্ভব, যদি আমরা আলোর পরিবর্তে বিএসডিএফ ব্যবহার করে নমুনা বোধ করি
  5. লাইট পিডিএফ এবং বিএসডিএফ পিডিএফ ব্যবহার করে ওজন গণনা করুন
    • ভিচ এবং গুইবাস ওজন গণনা করার জন্য কয়েকটি পৃথক পদ্ধতি নির্ধারণ করে। পরীক্ষামূলকভাবে, তারা বেশিরভাগ ক্ষেত্রে সর্বাধিক ক্ষেত্রে সবচেয়ে ভাল কাজ করার জন্য 2 এর শক্তি দিয়ে পাওয়ার হিউরিস্টিককে খুঁজে পেয়েছিল। আমি আপনাকে আরও বিশদ জন্য কাগজ রেফারেন্স। বাস্তবায়ন নীচে
  6. সরাসরি আলোক গণনার সাথে ওজনকে গুণিত করুন এবং হালকা পিডিএফ দ্বারা ভাগ করুন। (মন্টি কার্লোর জন্য) এবং সরাসরি আলো জমে যুক্ত করুন।
  7. তারপরে, আমরা বিআরডিএফ নমুনা করি
    • এটি ইন্টারঅ্যাকশন আপডেট করে I
  8. বিআরডিএফকে মূল্যায়ন করুন
  9. বিআরডিএফের উপর ভিত্তি করে এই দিকটি বেছে নেওয়ার জন্য পিডিএফ পান
  10. স্যাম্পলড ইনপুট দিকনির্দেশ দিয়ে হালকা পিডিএফ গণনা করুন
    • এটিই আগের আয়না। এই দিকটি কতটা সম্ভব, যদি আমরা আলোকে নমুনা দিতাম
  11. যদি আলোকপিডিএফ == 0.0f হয়, তবে রশ্মি আলোটি মিস করেছে, তাই কেবলমাত্র আলোকের নমুনা থেকে সরাসরি আলো ফিরিয়ে দিন।
  12. অন্যথায়, ওজন গণনা করুন, এবং জমে BSDF সরাসরি আলো যোগ করুন
  13. শেষ অবধি, জমে থাকা সরাসরি আলো ফিরিয়ে দিন

inline float PowerHeuristic(uint numf, float fPdf, uint numg, float gPdf) {
    float f = numf * fPdf;
    float g = numg * gPdf;

    return (f * f) / (f * f + g * g);
}

এই ক্রিয়াকলাপগুলিতে আপনি করতে পারেন এমন অনেকগুলি অপ্টিমাইজেশন / উন্নতি রয়েছে, তবে সেগুলি বোঝার সহজ করার জন্য আমি তাদের এড়িয়ে গেছি। আপনি যদি চান, আমি এই উন্নতি কিছু ভাগ করতে পারেন।

স্যাম্পলিং ওয়ান লাইট

স্যাম্পললাইটগুলিতে () আমরা সমস্ত লাইট লুপ করি এবং তাদের অবদান পাই। অল্প সংখ্যক লাইটের জন্য, এটি ঠিক আছে, তবে কয়েকশ বা হাজার হাজার আলোতে এটি ব্যয়বহুল হয়। সৌভাগ্যক্রমে, আমরা মন্টি কার্লো ইন্টিগ্রেশন একটি দৈত্য গড়ের বিষয়টি কাজে লাগাতে পারি। উদাহরণ:

আসুন সংজ্ঞা দিন

h(x)=f(x)+g(x)

বর্তমানে, আমরা দ্বারা অনুমান করছি :h(x)

h(x)=1Ni=1Nf(xi)+g(xi)

তবে, এবং উভয়ই গণনা ব্যয়বহুল, সুতরাং পরিবর্তে আমরা এটি করি:f(x)g(x)

h(x)=1Ni=1Nr(ζ,x)pdf

যেখানে একটি অভিন্ন র্যান্ডম ভেরিয়েবল এবং হিসাবে :ζr(ζ,x)

r(ζ,x)={f(x),0.0ζ<0.5g(x),0.5ζ<1.0

এই ক্ষেত্রে কারণ পিডিএফ 1 সংহত করতে হবে, এবং সেখান থেকে পছন্দ করে নিন 2 ফাংশন আছে।pdf=12

ইংরেজীতে:

  1. মূল্যায়নের জন্য এলোমেলোভাবে বা বেছে নিন ।g ( x )f(x)g(x)
  2. ফলাফলটি দ্বারা ভাগ করুন (যেহেতু দুটি আইটেম রয়েছে)12
  3. গড়

এন বড় হওয়ার সাথে সাথে অনুমানটি সঠিক সমাধানে রূপান্তরিত হবে।

আমরা হালকা স্যাম্পলিংয়ে একই নীতিটি প্রয়োগ করতে পারি। প্রতিটি আলোকে নমুনা দেওয়ার পরিবর্তে, আমরা এলোমেলোভাবে একটি বাছাই করি এবং লাইটের সংখ্যা দ্বারা ফলাফলকে গুণ করি (এটি ভগ্নাংশ পিডিএফ দ্বারা বিভাজন হিসাবে সমান):

float3 SampleOneLight(UniformSampler *sampler, SurfaceInteraction interaction, BSDF *bsdf, Light *hitLight) const {
    std::size_t numLights = m_scene->NumLights();

    // Return black if there are no lights
    // And don't let a light contribute light to itself
    // Aka, if we hit a light
    // This is the special case where there is only 1 light
    if (numLights == 0 || numLights == 1 && hitLight != nullptr) {
        return float3(0.0f);
    }

    // Don't let a light contribute light to itself
    // Choose another one
    Light *light;
    do {
        light = m_scene->RandomOneLight(sampler);
    } while (light == hitLight);

    return numLights * EstimateDirect(light, sampler, interaction, bsdf);
}

এই কোডটিতে, সমস্ত লাইটের বাছাইয়ের সমান সুযোগ রয়েছে। তবে, আমরা চাইলে নমুনাকে গুরুত্ব দিতে পারি। উদাহরণস্বরূপ, আমরা বড় লাইটগুলি বাছাই করার একটি উচ্চতর সুযোগ বা হিট পৃষ্ঠের কাছাকাছি আলো দিতে পারি। আপনি শুধু PDF, যা আর হবে দ্বারা ফলাফলের ভাগ আছে।1numLights

একাধিক তাত্পর্য "নতুন রে" দিকনির্দেশনা নমুনা

বর্তমান কোডটি কেবল BSDF এর উপর ভিত্তি করে "নতুন রে" দিকের নমুনাকে গুরুত্ব দেয়। আমরা যদি আলোর অবস্থানের ভিত্তিতে নমুনাকেও গুরুত্ব দিতে চাই?

আমরা উপরে যা শিখেছি তা গ্রহণ করে একটি পদ্ধতি হ'ল দুটি "নতুন" রশ্মি অঙ্কন করা এবং তাদের পিডিএফ-এর উপর ভিত্তি করে প্রতিটি ওজন করা। তবে এটি উভয়ই গণনামূলকভাবে ব্যয়বহুল এবং পুনরাবৃত্তি ছাড়াই কার্যকর করা শক্ত।

এটি কাটিয়ে উঠতে, আমরা কেবলমাত্র একটি আলো স্যাম্পলিং করে শিখেছি একই নীতিগুলি প্রয়োগ করতে পারি। এটি, এলোমেলোভাবে নমুনার জন্য একটি চয়ন করুন, এবং এটি বেছে নেওয়ার পিডিএফ দ্বারা ভাগ করুন।

// Get the new ray direction

// Randomly (uniform) choose whether to sample based on the BSDF or the Lights
float p = sampler->NextFloat();

Light *light = m_scene->RandomLight();

if (p < 0.5f) {
    // Choose the direction based on the bsdf 
    material->bsdf->Sample(interaction, sampler);
    float bsdfPdf = material->bsdf->Pdf(interaction);

    float lightPdf = light->PdfLi(m_scene, interaction);
    float weight = PowerHeuristic(1, bsdfPdf, 1, lightPdf);

    // Accumulate the throughput
    throughput = throughput * weight * material->bsdf->Eval(interaction) / bsdfPdf;

} else {
    // Choose the direction based on a light
    float lightPdf;
    light->SampleLi(sampler, m_scene, interaction, &lightPdf);

    float bsdfPdf = material->bsdf->Pdf(interaction);
    float weight = PowerHeuristic(1, lightPdf, 1, bsdfPdf);

    // Accumulate the throughput
    throughput = throughput * weight * material->bsdf->Eval(interaction) / lightPdf;
}

এগুলি সবই বলেছিল, আমরা কি আলোর উপর ভিত্তি করে "নিউ রে" দিকের নমুনাকে গুরুত্ব দিতে চাই ? জন্য সরাসরি আলো, radiosity উভয় পৃষ্ঠের BSDF, এবং হালকা দিক দ্বারা প্রভাবিত হয়। কিন্তু পরোক্ষ আলোকসজ্জার জন্য, রেডিয়োসিটিটি প্রায় একচেটিয়াভাবে পূর্বের পৃষ্ঠের হিট বিএসডিএফ দ্বারা সংজ্ঞায়িত করা হয়। সুতরাং, হালকা গুরুত্বের নমুনা যুক্ত করা আমাদের কিছু দেয় না।

সুতরাং, বিএসডিএফের সাথে "নতুন দিকনির্দেশ" কেবলমাত্র নমুনাকে গুরুত্ব দেওয়া সাধারণ তবে সরাসরি আলোকে একাধিক গুরুত্ব স্যাম্পলিং প্রয়োগ করুন।


সুস্পষ্ট উত্তরের জন্য আপনাকে ধন্যবাদ! আমি বুঝতে পারি যে আমরা যদি কোনও স্পষ্ট আলোর নমুনা ছাড়াই কোনও পাথ ট্রেসার ব্যবহার করি তবে আমরা কখনই কোনও পয়েন্ট আলোর উত্সকে আঘাত করতে পারি না। সুতরাং, আমরা মূলত এর অবদান যুক্ত করতে পারি। অন্যদিকে, আমরা যদি কোনও অঞ্চল আলোর উত্সকে নমুনা করি তবে আমাদের অবশ্যই তা নিশ্চিত করতে হবে যে ডাবল ডিপ এড়াতে পরোক্ষ আলো দিয়ে আমরা এটি আবার আঘাত না করা উচিত
মোস্তফা আইয়েক

একদম ঠিক! আপনার কি কোনও অংশ রয়েছে যার বিষয়ে আপনার স্পষ্টতা দরকার? বা যথেষ্ট বিশদ নেই?
রিচিস্যামস

এছাড়াও, একাধিক গুরুত্বের নমুনা কেবল প্রত্যক্ষ আলো গণনার জন্য ব্যবহৃত হয়? হয়তো আমি মিস করেছি তবে এর আর একটি উদাহরণ আমি দেখতে পাইনি। যদি আমি আমার পাথ ট্রেসারগুলিতে বাউন্স প্রতি মাত্র একটি রশ্মি অঙ্কুর করি তবে মনে হয় পরোক্ষ আলো গণনার জন্য আমি এটি করতে পারি না।
মোস্তফা Işık

2
আপনি গুরুত্ব স্যাম্পলিং ব্যবহার করে যে কোনও জায়গায় একাধিক গুরুত্ব স্যাম্পলিং প্রয়োগ করা যেতে পারে। একাধিক গুরুত্বের নমুনা দেওয়ার ক্ষমতাটি হ'ল আমরা একাধিক নমুনা কৌশলগুলির সুবিধার একত্রিত করতে পারি। উদাহরণস্বরূপ, কিছু ক্ষেত্রে, হালকা গুরুত্বের নমুনা বিএসডিএফ নমুনার চেয়ে ভাল হবে। অন্য ক্ষেত্রে, বিপরীত। এমআইএস উভয় বিশ্বের সেরা একত্রিত হবে। তবে, বিএসডিএফ স্যাম্পলিংয়ের সময়টি যদি 100% আরও ভাল হয় তবে এমআইএসের জটিলতা যুক্ত করার কোনও কারণ নেই। আমি এই পয়েন্টটি প্রসারিত করতে উত্তরে কিছু বিভাগ যুক্ত করেছি
রিচিস্যামস

1
দেখে মনে হচ্ছে আমরা আগত আলোকস্রোতের উত্সকে প্রত্যক্ষ ও পরোক্ষ হিসাবে দুটি ভাগে বিভক্ত করেছি। আমরা প্রত্যক্ষ অংশের জন্য লাইটগুলি স্পষ্টভাবে নমুনা করি এবং এই অংশটি স্যাম্পল করার সময়, লাইটের পাশাপাশি বিএসডিএফগুলির নমুনাকে গুরুত্ব দেওয়া যুক্তিসঙ্গত। অপ্রত্যক্ষ অংশের জন্য, তবে আমাদের কোন ধারণা নেই যে কোন দিকটি আমাদের সম্ভাব্য উচ্চতর আলোকিত মান প্রদান করতে পারে কারণ এটি আমাদের নিজেরাই যে সমস্যাটি সমাধান করতে চাই is তবে, আমরা বলতে পারি কোসাইন পদ এবং বিএসডিএফ অনুসারে কোন দিকটি আরও বেশি অবদান রাখতে পারে। এই আমি বুঝতে পেরেছি। আমি ভুল হলে আমাকে সংশোধন করুন এবং আপনার দুর্দান্ত উত্তরের জন্য আপনাকে ধন্যবাদ।
মোস্তফা Işık
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.