3
我目前在C++中實現了一個基本的raytracer。到目前爲止工作得非常好,無光澤材料(具有環境和漫反射brdf)迄今爲止按預期工作。什麼會導致Phong鏡面陰影產生色域溢出?
添加鏡面高光會導致完整的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;
}
你有想法,可能會導致錯誤嗎?導致這種結果的可能因素是什麼?
在此先感謝, 帕特里克。
反射表面上的色域點對我來說並不特別令人驚訝。從側面指向它的典型銀球應具有比明亮更明亮的鏡面高光。 – msw 2010-03-05 03:41:17
是的,這是事實,但通常情況下,如果我增加指數,點應該變小。但它沒有:( – 2010-03-05 11:52:21
我被'反射'標籤愚弄,darn,預期.net反射 – Axarydax 2010-03-05 12:56:45