【发布时间】:2017-03-11 13:47:48
【问题描述】:
我正在实现一个带有反射的递归光线追踪器。光线追踪器目前正在反射阴影区域,我不知道为什么。当反射代码被注释掉时,光线追踪器的阴影部分按预期工作,所以我认为这不是问题。
Vec Camera::shade(Vec accumulator,
Ray ray,
vector<Surface*>surfaces,
vector<Light*>lights,
int recursion_depth) {
if (recursion_depth == 0) return Vec(0,0,0);
double closestIntersection = numeric_limits<double>::max();
Surface* cs;
for(unsigned int i=0; i < surfaces.size(); i++){
Surface* s = surfaces[i];
double intersection = s->intersection(ray);
if (intersection > EPSILON && intersection < closestIntersection) {
closestIntersection = intersection;
cs = s;
}
}
if (closestIntersection < numeric_limits<double>::max()) {
Point intersectionPoint = ray.origin + ray.dir*closestIntersection;
Vec intersectionNormal = cs->calculateIntersectionNormal(intersectionPoint);
Material materialToUse = cs->material;
for (unsigned int j=0; j<lights.size(); j++) {
Light* light = lights[j];
Vec dirToLight = (light->origin - intersectionPoint).norm();
Vec dirToCamera = (this->eye - intersectionPoint).norm();
bool visible = true;
for (unsigned int k=0; k<surfaces.size(); k++) {
Surface* s = surfaces[k];
double t = s->intersection(Ray(intersectionPoint, dirToLight));
if (t > EPSILON && t < closestIntersection) {
visible = false;
break;
}
}
if (visible) {
accumulator = accumulator + this->color(dirToLight, intersectionNormal,
intersectionPoint, dirToCamera, light, materialToUse);
}
}
//Reflective ray
//Vec r = d − 2(d · n)n
if (materialToUse.isReflective()) {
Vec d = ray.dir;
Vec r_v = d-intersectionNormal*2*intersectionNormal.dot(d);
Ray r(intersectionPoint+intersectionNormal*EPSILON, r_v);
//km is the ideal specular component of the material, and mult is component-wise multiplication
return this->shade(accumulator, r, surfaces, lights, recursion_depth--).mult(materialToUse.km);
}
else
return accumulator;
}
else
return accumulator;
}
Vec Camera::color(Vec dirToLight,
Vec intersectionNormal,
Point intersectionPoint,
Vec dirToCamera,
Light* light,
Material material) {
//kd I max(0, n · l) + ks I max(0, n · h)p
Vec I(light->r, light->g, light->b);
double dist = (intersectionPoint-light->origin).magnitude();
I = I/(dist*dist);
Vec h = (dirToLight + dirToCamera)/((dirToLight + dirToCamera).magnitude());
Vec kd = material.kd;
Vec ks = material.ks;
Vec diffuse = kd*I*fmax(0.0, intersectionNormal.dot(dirToLight));
Vec specular = ks*I*pow(fmax(0.0, intersectionNormal.dot(h)), material.r);
return diffuse+specular;
}
我已经提供了我的输出和预期的输出。照明看起来有点不同 b/c 我的最初是一个 .exr 文件,另一个是 .png,但我在输出中绘制了箭头,其中表面应该反射阴影,但事实并非如此。
【问题讨论】:
-
您能否将示例中的几何渲染减少到两个或三个对象和一个灯光?图像的复杂程度有点难以诊断。
-
另外,如您所说,其中一个示例图像应该带有“反射代码注释掉”吗?我问是因为两者似乎都有反射。
-
@DanielA.Thompson 这两个图像都是使用反射代码创建的。上图是我的输出,下图是预期输出。 (我提到注释掉反射代码的唯一原因是为了澄清影子代码可以正常工作,因此在某种程度上是反射代码引入了错误。)
-
好的。
recursion_depth使用什么初始值?如果你增加它,问题会消失吗? -
recursion_depth是 20。增加到 100,并没有消失。
标签: c++ graphics 3d raytracing