首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >单向路径追踪器输出太暗

单向路径追踪器输出太暗
EN

Stack Overflow用户
提问于 2022-10-31 19:44:52
回答 1查看 68关注 0票数 -1

我正在写一个运行在Windows上的CPU射线追踪器。不幸的是,目前的输出似乎太黑暗,就像我错过了全局照明。

这是一个室内房间,灯光来自两个窗户。只有一个方向光。反弹的次数设置为8。

在这里,我的路径跟踪器输出:

搅拌机周期输出:

虽然直接照明是好的,但它感觉我错过了全球照明。但是为什么呢?

下面是示例代码:

代码语言:javascript
复制
RGBColor pathTracing(const Math::Ray& ray, nbUint32 depth)
{
    // Find intersection using intel's Embree
    Intersector::IntersectionInfo isectInfo;
    m_intersector->intersect(ray, isectInfo);

    // Check if an intersection occured
    if (isectInfo.object == nullptr)
    {
        return BlackRGBColor;
    }

    // Get intersection properties
    const auto isectProps = buildIntersectionProperties(ray, isectInfo, m_currentScene);

    // The scene model
    const auto& model = m_currentScene->getModel();

    // Read the material
    const DatabaseMaterialPtr material = model->getMaterialPtr_FromEntity(isectInfo.object->getMaterialId());

    // Compute direct lighning
    RGBColor directCont = BlackRGBColor;
    {
        for (const EntityIdentifier& lightId : m_currentScene->getLights())
        {
            // Generate light sample
            const auto light = Entity::EntityDatabaseSingleton::instance()->getEntity<Light::BaseLight>(lightId);
            const auto sampleToLight = light->generateSampleToLight(isectProps.P);

            const nbFloat32 NoL = glm::dot(isectProps.BsdfProps.N, sampleToLight.L);
            if (NoL <= 0.0f)
                continue;

            // Compute occlusion
            Math::Ray shadowRay(isectProps.deltaP, sampleToLight.L, sampleToLight.length);
            const nbFloat32 occlusionStrength = m_intersector->occlusion(shadowRay);

            if (occlusionStrength != 1.0f)
            {
                // Build the bsdf sample struture
                Material::BaseMaterial::SampleBsdfData bsdfSample;
                bsdfSample.L = sampleToLight.L;
                bsdfSample.V = isectProps.V;
                bsdfSample.NoL = NoL;
                bsdfSample.geoProps = &isectProps.BsdfProps;

                // Sample the brdf to get the scale
                auto sampledBrdf = material.sampleBsdf(bsdfSample);

                // Multiply by light radiance
                sampledBrdf *= light->getColor();

                // Multiply by visibility
                sampledBrdf *= (1.0f - occlusionStrength);

                // Finally add light contribution
                directCont += sampledBrdf;
            }
        }
    }


    // Compute indirect lighning
    RGBColor indirectCont;
    if (++depth <= m_settings.m_maxDepth)
    {
        BaseMaterial::SpawnRayResult newRayData;
        newRayData = material->spawnRay(/* some parameters*/);

        // Build the bsdf sample struture
        Material::BaseMaterial::SampleBsdfData bsdfSample;
        bsdfSample.L = newRayData.ray.getDirection();
        bsdfSample.V = isectProps.V;
        bsdfSample.NoL = glm::dot(newRayData.ray.getDirection(), isectProps.BsdfProps.N);
        bsdfSample.geoProps = &isectProps.BsdfProps;

        // Indirect raytracing
        const Spectrum sampledBrdf = material->sampleBsdf(bsdfSample);
        const Spectrum sampledRadiance = sampledBrdf * pathTracing(newRayData.ray, depth);//recursion

        static const float normalizationFactor = 2.0f * Math::Pi.getValue();
        indirectCont = sampledRadiance * normalizationFactor;
    }

    return directCont + indirectCont;
}

这里有更多的代码片段。

sampleBsdf方法

代码语言:javascript
复制
RGBColor BaseMaterial::sampleBsdf(const SampleBsdfData& data) const
{
    DistributionFunction::SampleInput distSampleInput;
    distSampleInput.L = data.L;
    distSampleInput.V = data.V;
    distSampleInput.N = data.geoProps->N;
    distSampleInput.T = data.geoProps->T;
    distSampleInput.B = data.geoProps->B;
    distSampleInput.H = glm::normalize(data.L + data.V);

    distSampleInput.HoN = std::abs(glm::dot(data.geoProps->N, distSampleInput.H));
    distSampleInput.NoV = std::abs(glm::dot(data.geoProps->N, data.V));
    distSampleInput.NoL = data.NoL;


    return sampleBrdf(distSampleInput) * distSampleInput.NoL;
}

sampleBrdf方法

代码语言:javascript
复制
inline nbFloat32 lambert(const SampleInput& input)
{
    return Math::InvPi.getValue();
}

nbFloat32 blinnPhong(const SampleInput& input, nbFloat32 shininess)
{
    const nbFloat32 HoN = std::min(input.HoN, 0.999f);
    nbFloat32 normalizationFactor = (shininess + 8.0f) * Math::InvPi8.getValue();
    normalizationFactor = glm::clamp(normalizationFactor, 0.0f, 1.0f);

    return std::pow(HoN, shininess) * normalizationFactor;
}

#define NO_FRESNEL_VALUE 0.4f

nbFloat32 DefaultDielectric::sampleFresnel(nbFloat32 HoN) const
{
    if (m_fresnelEnabled)
    {
        // Schlick approximation.
        return glm::clamp(m_fresnel0 + (1.0f - m_fresnel0) * pow(1.0f - HoN, 5.0f), 0.0f, 1.0f);
    }

    return NO_FRESNEL_VALUE;
}

RGBColor DefaultDielectric::sampleBrdf(DistributionFunction::SampleInput& distSampleInput) const
{
    nbFloat32 fresnelFactor = sampleFresnel(distSampleInput.HoN);

    // Diffuse
    nbFloat32 diffuseFactor = lambert(distSampleInput) * (1.0f - fresnelFactor);
    auto diffuseLightning = m_diffuse * diffuseFactor;

    // Specular
    nbFloat32 specularFactor = blinnPhong(distSampleInput, m_glossiness) * fresnelFactor;
    auto specLightning = m_specular * specularFactor;

    return m_opacity * (diffuseLightning + specLightning);
}
EN

回答 1

Stack Overflow用户

发布于 2022-11-01 01:11:53

用1.0/2.2f的因子进行伽马校正是有帮助的,但渲染仍然缺乏全局照明。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/74268416

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档