You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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í

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.13 18:45:09