【问题标题】:What can cause Phong specular shading to produce gamut overflows?什么会导致 Phong 镜面反射着色产生色域溢出?
【发布时间】:2011-05-18 14:04:37
【问题描述】:

我目前正在用 C++ 实现一个基本的光线追踪器。到目前为止效果很好,哑光材质(带有环境和漫反射 brdf)到目前为止可以正常工作。

添加镜面高光会产生完整的Phong Model,而这正是我试图做的。

不幸的是,我遇到了色域溢出,镜面反射常数 ks 和指数有各种值。以下是一些示例。

// Sphere material definition:
ka    = 0.9;
kd    = 1.0;
ks    = 0.3;
exp   = 1.0;
color = rgb(1.0, 1.0, 0.98);

图片:http://dl.dropbox.com/u/614366/cornell_1.png

// Sphere material definition:
ka    = 0.9;
kd    = 1.0;
ks    = 0.3;
exp   = 20.0;                  // only changed exp
color = rgb(1.0, 1.0, 0.98);

图片:http://dl.dropbox.com/u/614366/cornell_2.png

// Sphere material definition:
ka    = 0.9;
kd    = 1.0;
ks    = 0.1;                  // only changes here
exp   = 0.1;                  // and here
color = rgb(1.0, 1.0, 0.98);

图片:http://dl.dropbox.com/u/614366/cornell_3.png

这里是一些相关的代码摘录:

在 raycast.cpp 中

namespace {
    const float floatmax = std::numeric_limits<float>::max();
}

rgb
RayCast::trace ( const Ray& ray ) const
{
    HitRecord rec(scene_ptr_);
    float tmax = floatmax;
    float tmin = 0.0;

    if ( scene_ptr_->shapes.hit(ray,tmin,tmax,rec) )
    {
        rec.ray = ray;
        return rec.material_ptr->shade(rec);
    }

    return scene_ptr_->bgcolor;
}

在 phong.cpp 中

rgb
Phong::shade ( HitRecord& hitrec ) const
{
    Vector wo = - hitrec.ray.dir();

    rgb L = ambient_brdf_ptr_->rho(hitrec,wo) *
        hitrec.scene_ptr->ambient_ptr->L(hitrec);

    int num_lights = hitrec.scene_ptr->lights.size();

    for (int i = 0; i < num_lights; ++i)
    {
        Vector wi     = hitrec.scene_ptr->lights[i]->get_direction(hitrec);
        float  ndotwi = dot(hitrec.normal, wi);

        if ( ndotwi > 0.0 )
        {
            L += ( diffuse_brdf_ptr_->f (hitrec, wo, wi)  +
                   specular_brdf_ptr_->f(hitrec, wo, wi)
                 ) * hitrec.scene_ptr->lights[i]->L(hitrec) * ndotwi;
        }
    }

    return L;
}

在 specular.cpp 中

namespace {
    const rgb black(0.0,0.0,0.0);
}

rgb
Specular::f ( const HitRecord& hitrec, const Vector& wo, const Vector& wi ) const
{
    rgb L(0,0,0);
    float ndotwi = dot(hitrec.normal, wi);

    Vector r = -wi + 2.0 * hitrec.normal * ndotwi;
    float rdotwo = dot(r, wo);

    // reflection detected
    if ( rdotwo > 0.0 )
        L = ks_ * pow(rdotwo, exp_);

    return L;
}

rgb
Specular::rho ( const HitRecord& hitrec, const Vector& wo ) const
{
    return black;
}

在 sphere.cpp 中

bool
Sphere::hit ( const Ray& ray, interval_t tmin, interval_t tmax, HitRecord& hitrec ) const
{
    Vector org = ray.origin() - center_;
    Vector dir = ray.dir();
    float a = dot(dir, dir);
    float b = dot(dir, org) * 2;
    float c = dot(org, org) - pow(radius_, 2);
    float discriminant = pow(b,2) - 4*a*c;

    if ( discriminant > 0 )
    {
        discriminant = sqrt(discriminant);
        double t = ( -b - discriminant ) / ( 2*a );

        if ( t < tmin )
            t = ( -b + discriminant ) / ( 2*a );

        if ( t > tmin and t < tmax )
        {
            // hit detected
            hitrec.t            = t;
            hitrec.hit          = true;
            hitrec.normal       = unify( t*ray.dir() + org );
            hitrec.material_ptr = material_ptr_;
            hitrec.hitpoint     = ray.origin() + t * ray.dir();
            hitrec.ray          = ray;

            return true;
        }
    }

    return false;
}

您是否知道可能导致错误的位置?导致这种结果的可能因素是什么?

提前致谢, 帕特里克。

【问题讨论】:

  • 反射表面上的色域外斑点对我来说并不特别令人惊讶。具有从侧面指向它的点的规范银球应该具有比明亮更亮的镜面高光。
  • 是的,这是真的,但通常情况下,如果我增加指数,斑点应该会变小。但它没有:(
  • 我被'reflection'标签愚弄了,该死,预期的.net反射

标签: c++ reflection overflow raytracing


【解决方案1】:

问题的解决方法是你必须统一 wo 向量(在 Phong::shade 中)。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-01-20
    • 2014-03-26
    • 2021-01-05
    • 2018-07-09
    • 1970-01-01
    • 2011-06-09
    • 2017-08-29
    • 2014-07-30
    相关资源
    最近更新 更多