代码之家  ›  专栏  ›  技术社区  ›  Patrick Oscity

什么会导致Phong镜面着色产生色域溢出?

  •  3
  • Patrick Oscity  · 技术社区  · 14 年前

    我目前在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;
    }
    

    球体内.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;
    }
    

    你知道错误可能在哪里引起吗?导致这种结果的可能因素有哪些?

    事先谢谢, 帕特里克。

    1 回复  |  直到 13 年前
        1
  •  2
  •   Patrick Oscity    14 年前

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