Một cách tiếp cận gần đây cho tán xạ dưới bề mặt


7

Tôi đọc "Một mô hình thực tế cho vận chuyển ánh sáng dưới bề mặt" và "Một kỹ thuật kết xuất phân cấp nhanh chóng cho các vật liệu mờ". Nếu tôi hiểu chính xác, cái trước không xem xét trường hợp khi một vật được thắp sáng phía sau và chúng ta có thể thấy ánh sáng đang đi qua nó.

Cái sau có thể đạt được điều này nhưng có một giai đoạn tiền xử lý không phù hợp với trình theo dõi đường dẫn CUDA của tôi và tôi muốn nó phải tự nhiên nhất có thể. Vì vậy, bạn có bất kỳ giấy tờ trong tâm trí không lỗi thời hoặc bạn sẽ đề nghị tôi giải quyết phương trình chuyển bức xạ đầy đủ?


1
Bạn đang tìm cách ước tính tán xạ dưới bề mặt trong trình theo dõi đường dẫn của bạn hoặc đánh giá chính xác nó bằng cách sử dụng tán xạ toàn thể tích?
RichieSams

Tôi đọc rằng mô phỏng tán xạ toàn thể tích là rất chậm. Nếu nó không chậm thì tôi muốn thực hiện nó. Mặc dù các xấp xỉ khuếch tán hoạt động nhanh hơn, chúng giả định rất nhiều thứ hoặc chúng cần các bước tiền xử lý xấu xí. Bạn đã thực hiện nó trước? Bất kỳ đề nghị sẽ là tuyệt vời!
Mustafa Işık

2
Nó có thể chậm, tùy thuộc vào việc thực hiện. Tôi đã thực hiện phương tiện tán xạ vũ lực, tán xạ đẳng hướng trong bộ theo dõi sở thích của tôi. Hình ảnh ví dụ: imgur.com/a/oy9F8 . (FPS / tổng số lần khung hình nằm ở góc trên bên trái). Sử dụng chức năng pha tán xạ ngược như Henyey-Greenstein có thể khiến nó hội tụ nhanh hơn đối với các vật liệu mờ hơn, nhưng tôi không chắc vì tôi đã không thử. Nếu không có gì khác, thực hiện tán xạ thể tích đầy đủ là một cách tuyệt vời để tìm hiểu những gì gần đúng đang cố gắng gần đúng.
RichieSams

Tôi sẽ cố gắng viết thư tối nay khi tôi về nhà. Trong lúc này, đây là liên kết đến đường dẫn của tôi. github.com/RichieSams/logio Nó không sẵn sàng sản xuất. Thay vào đó, nó chỉ để giúp tôi học toán đằng sau mọi thứ. Điều đó nói rằng, đó là nguồn mở trong Apache 2.0, vì vậy hãy tự sao chép và học hỏi từ nó.
RichieSams

1
Cuối cùng, đây là hai câu hỏi mà tôi hỏi ở đây về chủ đề này: computergraphics.stackexchange.com/questions/2482/... computergraphics.stackexchange.com/questions/2563/...
RichieSams

Câu trả lời:


8

Như đã đề cập trong các ý kiến, tôi rất muốn đề xuất bắt đầu với Phân tán toàn phần. Đây là hai lần:

  1. Vì bạn đang thực hiện theo dõi đường dẫn, việc thêm thể tích không quá khó.
  2. Hiểu đầy đủ về cách hoạt động của tán xạ thể tích đầy đủ sẽ là cơ sở tuyệt vời để hiểu các ước tính. Ngoài ra, nó có thể cung cấp "tài liệu tham khảo" tuyệt vời để xem liệu ước tính của bạn có hoạt động tốt / chính xác hay không.

Với ý nghĩ đó, dưới đây là phần giới thiệu cơ bản về cách triển khai Phân tán thể tích toàn phần trong trình theo dõi đường đi ngược.


Để bắt đầu, chúng ta hãy xem mã để theo dõi đường đi ngược chỉ có phản xạ, không truyền / khúc xạ:

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

Bằng tiếng Anh:

  1. Bắn một tia qua cảnh.
  2. Kiểm tra nếu chúng tôi nhấn bất cứ điều gì. Nếu không chúng tôi trả lại màu skybox và phá vỡ.
  3. Nếu đây là tia đầu tiên, hoặc chúng ta vừa bật ra khỏi bề mặt đầu cơ, hãy kiểm tra xem chúng ta có chạm đèn không. Nếu vậy, chúng tôi thêm sự phát xạ ánh sáng để tích lũy màu sắc của chúng tôi.
  4. Mẫu ánh sáng trực tiếp.
  5. Chọn một hướng mới cho tia tiếp theo. Chúng tôi có thể làm điều này thống nhất, hoặc mẫu quan trọng dựa trên BRDF.
  6. Đánh giá BRDF và tích lũy nó.
  7. Tạo một tia mới dựa trên hướng đã chọn của chúng tôi và nơi chúng tôi vừa đến.
  8. [Tùy chọn] Sử dụng Roulette Nga để chọn nếu chúng ta nên chấm dứt tia.
  9. Đi 1.

Để biết thêm chi tiết về Lấy mẫu ánh sáng trực tiếp, xem câu trả lời này .

BSDF

Để thêm truyền, trước tiên chúng tôi cần nâng cấp một số tài liệu BRDF của chúng tôi lên BSDF đầy đủ, với chức năng BTDF. Giải thích về BSDF

Ví dụ: BSDF cho một chất điện môi đặc trưng lý tưởng (nghĩa là thủy tinh) là:

class IdealSpecularDielectric : public BSDF {
public:
    IdealSpecularDielectric(float3 albedo, float ior)
        : BSDF(BSDFLobe::Specular, albedo), 
          m_ior(ior) {
    }

private:
    float m_ior;

public:
    float3 Eval(SurfaceInteraction &interaction) const override {
        return m_albedo;
    }

    void Sample(SurfaceInteraction &interaction, UniformSampler *sampler) const override {
        float VdotN = dot(interaction.OutputDirection, interaction.Normal);
        float IORo = m_ior;
        if (VdotN < 0.0f) {
            IORo = 1.0f;
            interaction.Normal = -interaction.Normal;
            VdotN = -VdotN;
        }

        float eta = interaction.IORi / IORo;
        float sinSquaredThetaT = SinSquaredThetaT(VdotN, eta);
        float fresnel = Fresnel(interaction.IORi, IORo, VdotN, sinSquaredThetaT);

        float rand = sampler->NextFloat();
        if (rand <= fresnel) {
            // Reflect
            interaction.InputDirection = reflect(interaction.OutputDirection, interaction.Normal);
            interaction.SampledLobe = BSDFLobe::SpecularReflection;
            interaction.IORo = interaction.IORi;
        } else {
            // Refract
            interaction.InputDirection = refract(interaction.OutputDirection, interaction.Normal, VdotN, eta, sinSquaredThetaT);
            interaction.SampledLobe = BSDFLobe::SpecularTransmission;
            interaction.IORo = IORo;
        }

        if (AnyNan(interaction.InputDirection)) {
            printf("nan");
        }
    }

    float Pdf(SurfaceInteraction &interaction) const override {
        return 1.0f;
    }
};

Phần thú vị của mã là Sample(). Đây là nơi một tia sẽ chọn phản xạ hoặc khúc xạ. Làm thế nào chúng ta làm điều này thực sự là tùy thuộc vào chúng ta, như thể hiện trong câu trả lời này . Tuy nhiên, một lựa chọn rõ ràng sẽ là lấy mẫu dựa trên các phương trình Fresnel .

Trong trường hợp của một điện môi Specular lý tưởng, chỉ có hai hướng đầu ra tiềm năng: khúc xạ hoàn hảo hoặc phản xạ hoàn hảo. Vì vậy, chúng tôi đánh giá Fresnel và chọn ngẫu nhiên để khúc xạ / phản xạ với tỷ lệ bằng với Fresnel.

Phương tiện truyền thông

Tiếp theo, chúng ta cần nói về phương tiện truyền thông, và cách chúng ảnh hưởng đến ánh sáng dội xung quanh. Như lời giải thích của Nathan Reed trong câu trả lời này :

Cách tôi muốn nghĩ về tán xạ âm lượng là một photon truyền qua môi trường có xác suất nhất định trên mỗi đơn vị độ dài tương tác (bị tán xạ hoặc bị hấp thụ). Miễn là nó không tương tác, nó chỉ đi theo một đường thẳng không bị cản trở và không mất năng lượng. Khoảng cách càng lớn, xác suất mà nó tương tác ở đâu đó trong khoảng cách đó càng lớn. Xác suất tương tác trên mỗi đơn vị độ dài là hệ số mà bạn thấy trong các phương trình. Chúng tôi thường có các hệ số riêng biệt để phân tán và xác suất hấp thụ, vì vậyσσ=σs+σa

Xác suất này trên mỗi đơn vị độ dài chính xác là nguồn gốc của luật Bia-Lambert. Cắt một đoạn tia thành các khoảng vô hạn, coi mỗi khoảng là một nơi độc lập có thể tương tác, sau đó tích hợp dọc theo tia; bạn nhận được phân phối theo cấp số nhân (với tham số tỷ lệ σσ) cho xác suất tương tác là một hàm của khoảng cách.

Về mặt kỹ thuật, bạn có thể chọn khoảng cách giữa các sự kiện theo ý muốn, miễn là bạn cân chính xác đường dẫn cho xác suất để một photon có thể thực hiện giữa hai sự kiện liền kề mà không tương tác với phương tiện. Nói cách khác, mỗi phân đoạn đường dẫn trong phương tiện đóng góp hệ số trọng số của , trong đó là độ dài của phân khúc.eσxx

Vì điều này, một lựa chọn tốt cho khoảng cách là lấy mẫu quan trọng từ phân bố mũ. Nói cách khác, bạn đặtx=(lnξ)/σ

Tóm tắt:

  1. Một tia đi qua một phương tiện có một số xác suất để:
    • Được hấp thụ
    • Bị phân tán
  2. Vì đây là Tích hợp Monte Carlo, chúng tôi có thể tự do chọn khoảng cách tương tác theo ý muốn. Tuy nhiên, một lựa chọn tốt là lấy mẫu quan trọng từ phân phối theo cấp số nhân tương tự như Bia-Lambert.

Tôi đã chọn thực hiện điều này với hệ số tán xạ và để Bia-Lambert chăm sóc hệ số hấp thụ.

class Medium {
public:
    Medium(float3 absorptionColor, float absorptionAtDistance) 
        : m_absorptionCoefficient(-log(absorptionColor) / absorptionAtDistance) {
        // This method for calculating the absorption coefficient is borrowed from Burley's 2015 Siggraph Course Notes "Extending the Disney BRDF to a BSDF with Integrated Subsurface Scattering"
        // It's much more intutive to specify a color and a distance, then back-calculate the coefficient
    }
    virtual ~Medium() {
    }

protected:
    const float3a m_absorptionCoefficient;

public:
    virtual float SampleDistance(UniformSampler *sampler, float tFar, float *weight, float *pdf) const = 0;

    virtual float3a SampleScatterDirection(UniformSampler *sampler, float3a &wo, float *pdf) const = 0;
    virtual float ScatterDirectionPdf(float3a &wi, float3a &wo) const = 0;

    virtual float3 Transmission(float distance) const = 0;
};

Môi trường không tán xạ là môi trường mà một photon truyền thẳng qua, nhưng nó bị suy giảm dọc đường theo Bia-Lambert:

class NonScatteringMedium : public Medium {
public:
    NonScatteringMedium(float3 color, float atDistance)
        : Medium(color, atDistance) {
    }

public:
    float SampleDistance(UniformSampler *sampler, float tFar, float *weight, float *pdf) const override {
        *pdf = 1.0f;
        return tFar;
    }

    float3a SampleScatterDirection(UniformSampler *sampler, float3a &wo, float *pdf) const override {
        return wo;
    }
    float ScatterDirectionPdf(float3a &wi, float3a &wo) const override {
        return 1.0f;
    }

    float3 Transmission(float distance) const override {
        return exp(-m_absorptionCoefficient * distance);
    }
};

Ví dụ không tán xạ

Môi trường tán xạ đẳng hướng cho phép tia có các sự kiện tán xạ (phản xạ) trong khi tia đi qua nó. Tia có thể được phản xạ theo bất kỳ hướng nào trong quả cầu xung quanh điểm tương tác (do đó là đẳng hướng).

Giải thích về sự tán xạ đẳng hướng

Khoảng cách giữa các phản xạ là ngẫu nhiên, dựa trên xác suất "phân tán" theo cấp số nhân.

class IsotropicScatteringMedium : public Medium {
public:
    IsotropicScatteringMedium(float3 absorptionColor, float absorptionAtDistance, float scatteringDistance)
        : Medium(absorptionColor, absorptionAtDistance),
          m_scatteringCoefficient(1 / scatteringDistance) {
    }

private:
    float m_scatteringCoefficient;

public:
    float SampleDistance(UniformSampler *sampler, float tFar, float *weight, float *pdf) const override {
        float distance = -logf(sampler->NextFloat()) / m_scatteringCoefficient;
        // If we sample a distance farther than the next intersecting surface, clamp to the surface distance
        if (distance >= tFar) {
            *pdf = 1.0f;
            return tFar;
        }

        *pdf = std::exp(-m_scatteringCoefficient * distance);
        return distance;
    }
    float3a SampleScatterDirection(UniformSampler *sampler, float3a &wo, float *pdf) const override {
        *pdf = 0.25f * M_1_PI; // 1 / (4 * PI)
        return UniformSampleSphere(sampler);
    }

    float ScatterDirectionPdf(float3a &wi, float3a &wo) const override {
        return 0.25f * M_1_PI; // 1 / (4 * PI)
    }
    float3 Transmission(float distance) const override {
        return exp(-m_absorptionCoefficient * distance);
    }
};

Ở khoảng cách tán xạ cao, vật liệu này hoạt động gần giống như NonScatteringMedium, bởi vì nó có xác suất tán xạ rất nhỏ trước khi truyền qua môi trường.

Khoảng cách tán xạ cao

Ở khoảng cách tán xạ thấp, vật liệu này hoạt động như sáp hoặc ngọc bích.

Khoảng cách tán xạ thấp

Khi khoảng cách tán xạ càng ngày càng thấp, chúng ta có cơ hội cao hơn và cao hơn để tán xạ khi đi qua phương tiện. Điều này trình bày một vài vấn đề:

  1. Số lượng nảy trên mỗi tia sẽ phát nổ.
  2. Nếu Russian Roulette giết chết tia sáng hoặc nếu bạn đi qua "maxBounces", bạn sẽ "mất" mọi đóng góp màu sắc từ bên trong phương tiện. Ví dụ trên Max bị trả lại

Do đó, bạn cần đặt maxBounces lên một số cao và dựa vào Roulette Nga để chấm dứt các tia trong trường hợp chung. Ngoài ra, IsotropicScatteringMedium cực kỳ kém hiệu quả khi đại diện cho các vật liệu chủ yếu mờ đục. Để có được hiệu suất tốt hơn, chúng ta nên sử dụng hàm pha không đẳng hướng, như Henyey-Greenstein hoặc Schlick . Những sai lệch sự tán xạ theo một hướng nhất định. Vì vậy, chúng ta có thể đặt chúng để có độ tán xạ ngược cao, do đó làm giảm bớt vấn đề tia "bị mất".

Để tất cả chúng cùng nhau

Vì vậy, với thông tin mới này, làm thế nào để chúng tôi sửa đổi nhà tích hợp để hiểu BSDF và phương tiện truyền thông?

Trước tiên, chúng ta cần bắt đầu theo dõi phương tiện chúng ta hiện đang ở và Chỉ số khúc xạ (IOR) của nó.

SurfaceInteraction interaction;
interaction.IORi = 1.0f; // Vacuum 
Medium *medium = nullptr; // nullptr == vacuum

Sau đó, chúng tôi chia bộ tích hợp thành hai phần: truyền và tương tác vật liệu.

void RenderPixel(uint x, uint y, UniformSampler *sampler) const {
    Ray ray = m_scene->Camera->CalculateRayFromPixel(x, y, sampler);

    float3 color(0.0f);
    float3 throughput(1.0f);
    SurfaceInteraction interaction;
    interaction.IORi = 1.0f; // Air
    Medium *medium = nullptr;
    bool hitSurface = false;

    // Bounce the ray around the scene
    uint bounces = 0;
    const uint maxBounces = 1500;
    for (; 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;
        }

        // We hit an object
        hitSurface = true;

        // Calculate any transmission
        if (medium != nullptr) {
            float weight = 1.0f;
            float pdf = 1.0f;
            float distance = medium->SampleDistance(sampler, ray.TFar, &weight, &pdf);
            float3 transmission = medium->Transmission(distance);
            throughput = throughput * weight * transmission;

            if (distance < ray.TFar) {
                // Create a scatter event
                hitSurface = false;

                ray.Origin = ray.Origin + ray.Direction * distance;

                // Reset the other ray properties
                float directionPdf;
                float3a wo = normalize(ray.Direction);
                ray.Direction = medium->SampleScatterDirection(sampler, wo, &directionPdf);
                ray.TNear = 0.001f;
                ray.TFar = infinity;
                ray.GeomID = INVALID_GEOMETRY_ID;
                ray.PrimID = INVALID_PRIMATIVE_ID;
                ray.InstID = INVALID_INSTANCE_ID;
                ray.Mask = 0xFFFFFFFF;
                ray.Time = 0.0f;
            }
        }

        if (hitSurface) {
            // 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);
            interaction.IORo = 0.0f;


            // Calculate the direct lighting
            color += throughput * SampleOneLight(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;

            // Update the current IOR and medium if we refracted
            if (interaction.SampledLobe == BSDFLobe::SpecularTransmission) {
                interaction.IORi = interaction.IORo;
                medium = material->medium;
            }

            // Shoot a new ray

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

            // Reset the other ray properties
            ray.Direction = interaction.InputDirection;
            if (AnyNan(ray.Direction))
                printf("bad");
            ray.TNear = 0.001f;
            ray.TFar = infinity;
            ray.GeomID = INVALID_GEOMETRY_ID;
            ray.PrimID = INVALID_PRIMATIVE_ID;
            ray.InstID = INVALID_INSTANCE_ID;
            ray.Mask = 0xFFFFFFFF;
            ray.Time = 0.0f;
        }

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

    if (bounces == maxBounces) {
        printf("Over max bounces");
    }

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

Bằng tiếng Anh:

  1. Bắn một tia qua cảnh.
  2. Kiểm tra nếu chúng tôi nhấn bất cứ điều gì. Nếu không chúng tôi trả lại màu skybox và phá vỡ.
  3. Kiểm tra nếu chúng ta hiện đang ở trong một phương tiện (không phải trong chân không).
    1. Lấy mẫu trung bình cho một khoảng cách.
    2. Đánh giá truyền tải của phương tiện và tích lũy thông lượng.
    3. Nếu khoảng cách tán xạ nhỏ hơn khoảng cách từ gốc tia tới bề mặt tiếp theo, hãy tạo sự kiện tán xạ.
    4. Lấy mẫu môi trường cho hướng phân tán.
  4. Kiểm tra xem chúng tôi có chạm vào bề mặt không (nghĩa là chúng tôi không có sự kiện phân tán).
    1. Nếu đây là tia đầu tiên, hoặc chúng ta vừa bật ra khỏi bề mặt đầu cơ, hãy kiểm tra xem chúng ta có chạm đèn không. Nếu vậy, chúng tôi thêm sự phát xạ ánh sáng để tích lũy màu sắc của chúng tôi.
    2. Mẫu ánh sáng trực tiếp.
    3. Chọn một hướng mới cho tia tiếp theo. Chúng tôi có thể làm điều này thống nhất, hoặc mẫu quan trọng dựa trên BRDF.
    4. Đánh giá BRDF và tích lũy nó.
    5. Nếu chúng tôi khúc xạ vào vật liệu, hãy cập nhật IOR và phương tiện cho lần nảy tiếp theo.
  5. Tạo một tia mới dựa trên hướng đã chọn của chúng tôi và nơi chúng tôi vừa đến.
  6. [Tùy chọn] Sử dụng Roulette Nga để chọn nếu chúng ta nên chấm dứt tia.
  7. Đi 1.

Cảm ơn bạn cho câu trả lời tuyệt vời này! Vấn đề là bất kể tôi cố gắng gì cho các hệ số, kết quả đầu ra của tôi trông giống như một chiếc cốc. Điều này có nghĩa là tôi đang làm phân tán phần sai? Dưới đây là chuỗi các kết quả đầu ra: imgur.com/a/gg2u1 Tôi chỉ thay đổi hệ số tán xạ trong khi vẫn giữ mức hấp thụ như nhau
Mustafa Işık

1
Bạn có chắc chắn rằng bạn không vô tình đặt hệ số bằng khoảng cách tán xạ không? Nó nên được phân tánCoe enough = (1 / scatteringDistance). Cũng hấp thụCoe enough = -log (hấp thụColor) / hấp thụAtDistance. Cuối cùng, việc bạn đưa ra hệ số như thế nào không quan trọng. Điều đó nói rằng, một hệ số thấp hơn sẽ có nghĩa là ít hấp thụ / tán xạ. Một hệ số cao hơn sẽ có nghĩa là ít hơn. Đối với các nghệ sĩ, việc nghĩ về khoảng cách sẽ dễ dàng hơn một chút, vì vậy chúng tôi tính toán lại các hệ số từ khoảng cách.
RichieSams

Không, phần cài đặt tham số là như nhau. Tôi không thể giải quyết vấn đề nhưng nếu tôi giải quyết nó, tôi sẽ bình luận ở đây.
Mustafa Işık

4

Đối với các trường hợp xấp xỉ khuếch tán được ưu tiên hơn theo dõi đường dẫn thể tích đầy đủ, phương pháp được xuất bản bởi Solid Angle khá hiệu quả: https://www.solidangle.com/research/s2013_bssrdf_slides.pdf

Nó được triển khai trong công cụ kết xuất Arnold, Blender's Ciking và pbrt, sau này là nguồn mở.

Tệp thực hiện nó trong PBRT có tại đây: https://github.com/mmp/pbrt-v3/blob/7095acfd8331cdefb03fe0bcae32c2fc9bd95980/src/core/bssrdf.cpp


Việc thực hiện PBRT có vẻ như khuếch tán chùm photon. Là khuếch tán chùm photon và những gì Solid Angle làm giống nhau? Tôi hỏi bởi vì tôi nghĩ PBD cũng lấy các mẫu điểm trên hình học làm bước tiền xử lý nhưng các slide Solid Angle không làm điều đó.
Mustafa Işık

1
Có hai điều cần phân biệt ở đây: Hàm tích hợp (BSSRDF) và phương thức tích hợp. Cách thứ nhất là các chức năng như lưỡng cực, đa cực, khuếch tán chùm photon, v.v ... Thứ hai là các phương pháp như octree phân cấp của Jensen hoặc theo dõi tia quan trọng của Solid Angle.
Stefan Werner
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.