C++光线追踪颜色计算异常:球体出现黑点且表面不光滑
光线追踪框架渲染错误排查求助
我正在实现光线追踪框架,但渲染结果不符合预期:
- 预期效果:光滑的球体渲染图
- 实际效果:球体表面存在黑点且不光滑
以下是核心实现代码及调试尝试,求错误原因排查方向:
ComputeColor函数(光线反弹与颜色计算)
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; }
Phong函数(光照计算)
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; }
Intersection函数(相交检测)
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); }
调试尝试
- 调整lightRay偏移时,
lightRay.o = lightRay.o + (epsilon * lightRay.direction)无法解决黑点,但不影响其他场景; lightRay.o = lightRay.o * epsilon解决了黑点,但导致其他场景异常。
内容的提问来源于stack exchange,提问作者Aleix Martí
相关产品推荐
相关产品推荐

