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

光线追踪器渲染物体过大问题排查求助

问题根源与解决方法

你的问题不是因为在相机空间计算,而是射线生成逻辑和球体半径处理的两处关键错误导致的:

1. 射线生成的变换错误(核心问题)

在RayThruPixel函数里,你对射线的原点和方向做了错误的变换:

  • 相机空间下,相机原点固定是(0,0,0),不需要用modelview变换eye——modelview矩阵的作用是把世界空间的点转换到相机空间,而世界空间的相机位置eye转换到相机空间就是原点,所以射线原点应该直接设为vec3(0,0,0)。
  • 射线方向是方向向量,必须用齐次坐标w=0来做变换(避免引入平移),你用vec4(alpha * u + beta * v - w, 1.0f)会把方向向量当成点来处理,导致方向被错误扭曲;而且你还做了两次normalize,这会进一步破坏方向的缩放关系,最终导致视野被过度放大。

修正后的射线生成代码:

Ray* RayThruPixel(Camera* camera, int x, int y) {
    const vec3 a = eye - center;
    const vec3 b = up;
    const vec3 w = glm::normalize(a);
    const vec3 u = glm::normalize(glm::cross(b, w));
    const vec3 v = glm::cross(w, u);
    const float aspect = ((float)width) / height;
    float fovyrad = glm::radians(camera->fovy);
    const float fovx = 2 * atan(tan(fovyrad * 0.5) * aspect);
    const float alpha = tan(fovx * 0.5) * (x - (width * 0.5)) / (width * 0.5);
    const float beta = tan(fovyrad * 0.5) * ((height * 0.5) - y) / (height * 0.5);

    // 相机空间原点就是(0,0,0)
    vec3 origin = vec3(0.0f);
    // 先构造世界空间下的方向向量,再用modelview矩阵(w=0)转换到相机空间,最后归一化
    vec3 world_dir = alpha * u + beta * v - w;
    vec3 cam_dir = glm::normalize(vec3(modelview * vec4(world_dir, 0.0f)));

    return new Ray(origin, cam_dir);
}

2. 球体半径的错误缩放

在球体碰撞检测代码里,float radius = sphere->radius / center2.z;是完全错误的操作:

  • 相机空间的变换是仿射变换,球体的半径应该根据modelview矩阵的缩放分量来调整(如果你的物体变换包含缩放的话),但你直接除以center2.z会让远处的球体半径被异常放大(因为相机空间中物体的z坐标是负数,绝对值越大,除以它得到的半径越大)。
  • 正确的做法是:如果object->transform没有缩放,直接用原始半径sphere->radius;如果有缩放,需要计算变换矩阵的缩放因子(比如取矩阵列向量的长度)来调整半径。

修正后的球体碰撞检测代码片段:

Sphere* sphere = dynamic_cast<Sphere*>(object);
float t;
vec3 p0 = ray->origin;
vec3 p1 = ray->direction;
float a = glm::dot(p1, p1);
vec3 center2 = vec3(modelview * object->transform * glm::vec4(sphere->center, 1.0f)); // camera coords
float b = 2 * glm::dot(p1, (p0 - center2));
// 删掉错误的半径缩放,用原始半径
float radius = sphere->radius;
float c = glm::dot((p0 - center2), (p0 - center2)) - radius * radius;
// ... 后续判断逻辑保持不变

额外验证点

检查你的modelview矩阵是否正确:它应该是相机的视图矩阵,即把世界空间转换到相机空间的矩阵(通常是lookAt(eye, center, up)的结果)。如果矩阵构造错误,也会导致整个场景的缩放或位置异常。

内容的提问来源于stack exchange,提问作者user2566395

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.06 10:50:28