正如您所看到的,球体有一些黑点并且不光滑。知道这个错误可能来自哪里吗?
计算颜色,在这里我创建了所有光线的反弹。我将 epsilon 应用于光线:
vec3 ComputeColor(const Ray& ray, const world& scene, int depth, float pH, float pW) {
if (depth > scene.maxDepth)
return vec3(0.0f);
const Object* hitObject;
vec3 hitPoint;
if (!Intersection(ray, scene, hitObject, &hitPoint))
return vec3(0.0f);
vec3 color = hitObject->materials.ambient + hitObject->materials.emission;
for (const PointLightSource& light : scene.lights) {
Ray lightRay;
if (light.type == PointLightSource::point) {
lightRay = Ray(light.pos, glm::normalize(hitPoint - light.pos));
}
else {
lightRay = Ray(light.pos,glm::normalize(- lightRay.direction));
}
const float epsilon = 1e-4;
lightRay.o = lightRay.o * epsilon;
const Object* obj;
vec3 lightHit;
if (!Intersection(lightRay, scene, obj, &lightHit) || IsSameVector(hitPoint, lightHit)) {
color += Phong(light, hitObject, ray, hitPoint, scene.attenuation);
}
}
if (glm::any(glm::greaterThan(hitObject->materials.specular, vec3(0.0f)))) {
vec3 unit_normal = glm::normalize(hitObject->InterpolatePointNormal(hitPoint));
vec3 reflect_dir = ray.direction - (unit_normal * (2.0f * glm::dot(ray.direction, unit_normal)));
Ray reflect_ray(hitPoint, reflect_dir);
vec3 temp_color = temp_color+ComputeColor(reflect_ray, scene, depth + 1, pH, pW);
color += hitObject->materials.specular * temp_color;
}
return color;
}
Run Code Online (Sandbox Code Playgroud)
Phong light,这是我计算光的函数:
vec3 Phong(const PointLightSource& light, const Object* hitObject, const Ray& ray, const vec3& hitPoint, const float* attenuation) {
vec3 lightDirection;
if (light.type == PointLightSource::point) {
lightDirection = glm::normalize(light.pos - hitPoint);
}
else {
lightDirection = glm::normalize(light.pos);
}
vec3 normal = glm::normalize(hitObject->InterpolatePointNormal(hitPoint));
// Diffuse light
const Materials& materials = hitObject->materials;
float nDotL = max(glm::dot(normal, lightDirection), 0.0f);
vec3 diffuse = materials.diffuse * light.color * nDotL;
// Specular
vec3 viewDirection = glm::normalize(-ray.direction);
vec3 halfvec = glm::normalize(lightDirection + viewDirection);
float nDotH = max(glm::dot(normal, halfvec), 0.0f);
vec3 specular = materials.specular * light.color * pow(nDotH, materials.shininess);
vec3 result = diffuse + specular;
if (light.type == PointLightSource::point) {
float r = glm::length(light.pos - hitPoint);
float attenuationFactor = 1.0f / (attenuation[2] * r * r + attenuation[1] * r + attenuation[0]);
result *= attenuationFactor;
}
return result;
}
Run Code Online (Sandbox Code Playgroud)
交集,我使用此函数来计算与所有类型对象的交集,在本例中为球体和三角形:
bool Intersection(const Ray& ray, const world& scene, const Object*& hitObject, vec3* hitPoint) {
double minDistance = INFINITY;
hitObject = nullptr;
for (const Object* obj : scene.objects) {
Ray rayObject = Transform(ray, obj);
float dist;
if (obj->Intersect(rayObject, &dist)) {
vec3 localPoint = rayObject.o + rayObject.direction * dist;
vec4 localPointHom(localPoint, 1.0);
localPointHom = localPointHom * obj->transform;
vec3 hitWorld = vec3(localPointHom.x / localPointHom.w, localPointHom.y / localPointHom.w, localPointHom.z / localPointHom.w);
dist = glm::dot(hitWorld - ray.o, ray.direction);
if (dist > 1e-4) {
if (dist < minDistance) {
minDistance = dist;
hitObject = obj;
*hitPoint = hitWorld;
}
}
}
}
return (hitObject != nullptr);
}
Run Code Online (Sandbox Code Playgroud)
编辑:当移动光线时我测试了这个:
lightRay.o = lightRay.o + (epsilon * lightRay.direction);//(this one does note solve "cancer issue" but do not destroy other scenes )
lightRay.o = lightRay.o *(epsilon);//This one solves the issue but others scenes are not correct.
Run Code Online (Sandbox Code Playgroud)
这被称为“癌症”,这是由于从表面发射阴影光线,但光线再次与该表面相交而引起的伪影。结果是您确定某个物体阻挡了光线,但不知道该物体本身在阴影光线的来源处阻挡了光线。这是浮点精度误差的自然结果。
解决该问题的最简单方法之一是引入“epsilon”值,并且不计算距离低于该阈值的交叉点。这允许更复杂的几何体自相交,但有点脏。
更一般地说,您可能决定在光命中测试中排除生成此阴影光线的对象。在更广义的 3D 场景中,一切都是三角形,您可以排除该三角形。但在大量镶嵌的场景中,当您碰到相邻的三角形时,您可能会再次遇到这个问题。
另一种方法是,如果表面法线指向与阴影光线相反的方向,则忽略相交。如上所示,仅当两者的点积为负时才计算交集。但如果场景中存在实际上可以阻挡光线的单面几何体,那么您应该小心这一点。
实际上,结合使用上述措施通常可以解决此问题,但您也可以只选择其中一项。
请注意,反射光线(而不仅仅是阴影光线)也会出现同样的问题。因此,您确实需要仔细地将这个逻辑构建到您的核心光线追踪算法中。
| 归档时间: |
|
| 查看次数: |
85 次 |
| 最近记录: |