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

光线追踪器反射异常:物体仅变暗无反射的问题排查

光线追踪器反射效果异常问题排查

我正在实现一个简易光线追踪器,尝试添加反射效果,但物体仅呈现变暗状态,没有预期的反射效果。场景期望棋盘格能无缝反射球体,但目前无法实现。我已确认法线计算、相交检测方法以及变换矩阵均正确,且调整trace方法中closest_shape相关逻辑前反射功能正常。

以下是trace方法中反射逻辑的代码:

Color Renderer::trace(Ray const& ray, float depth) {
    // Maximaler Rekursionstiefe für Reflexionen
    if (depth > max_depth) {
        return background_color;
    }

    float closest_distance = std::numeric_limits<float>::max();
    std::shared_ptr<Shape> closest_shape = nullptr;
    Ray transformed_ray = ray;
    HitPoint hit;
    HitPoint closest_object_hitpoint;
    closest_object_hitpoint.distance = std::numeric_limits<float>::max();

    for (auto const& shape : scene_.shape_container) {
        transformed_ray = transform_ray(shape->get_world_transformation_inv(), ray); //ray wird transformiert

        hit = shape->intersect(transformed_ray); //hit mit transformed ray

        if (hit.intersection) {
            float distance = glm::length(hit.intersection_point - scene_.camera_container[0]->origin);
            if (hit.distance < closest_object_hitpoint.distance) {
//                closest_distance = distance;
                closest_shape = shape;
                closest_object_hitpoint = hit;
            }
        }
    }

    if (closest_object_hitpoint.intersection) {
        Color local_color = shade(closest_object_hitpoint, closest_shape, closest_distance);

        // Reflexion
        if (closest_shape->get_Material()->reflectivity > 0.0f) {
            float reflection_factor = closest_shape->get_Material()->reflectivity; // Reflexionskoeffizient

            // Berechnung des reflektierten Rays
            glm::vec3 reflected_direction = glm::reflect(glm::normalize(ray.direction), glm::normalize(closest_object_hitpoint.normale));
            glm::vec3 reflected_location = closest_object_hitpoint.intersection_point;
            reflected_location = reflected_location + 0.01f * reflected_direction;

            Ray reflected_ray = {reflected_location, reflected_direction};

            Color reflected_color = trace(reflected_ray, depth + 1);

            //lokale Farbe wird mit reflektierter Farbe kombiniert
            local_color.r = (1.0f - reflection_factor) * local_color.r + reflection_factor * reflected_color.r;
            local_color.g = (1.0f - reflection_factor) * local_color.g + reflection_factor * reflected_color.g;
            local_color.b = (1.0f - reflection_factor) * local_color.b + reflection_factor * reflected_color.b;
        }

        return local_color;
        // return shade(closest_object_hitpoint, closest_shape, closest_distance);
    } else {
        return background_color;
    }
}

问题根源分析

  1. closest_distance未正确赋值
    代码中注释掉了closest_distance = distance;,导致shade函数传入的是初始极大值std::numeric_limits<float>::max()。如果shade依赖这个距离计算光照衰减或其他参数,会直接让局部颜色local_color异常(比如趋近于黑色)。此时即便混合反射颜色,整体也只会呈现变暗状态,看不到反射内容。

  2. 命中距离的一致性问题
    当前用变换后空间的hit.distance(射线的t参数)判断远近,但计算的distance是世界空间直线距离。存在缩放变换时,两者数值不匹配,可能导致距离计算错误。正确做法是统一用射线t参数判断远近,同时确保shade使用的是正确的世界空间距离(可通过t * glm::length(ray.direction)计算,前提是射线方向已归一化)。

修复建议

  • 取消注释closest_distance = distance;,确保shade能拿到正确的世界空间命中距离,让局部光照计算正常运行。
  • 若hit.distance是变换后空间的t参数,建议用hit.distance * glm::length(ray.direction)替代glm::length(hit.intersection_point - camera_origin)计算世界空间距离,避免变换带来的偏差,同时保持远近判断的一致性。

内容的提问来源于stack exchange,提问作者fran.zip

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.18 20:35:17