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

八叉树光线投射的射线预计算与相机矩阵应用疑问

问题解答

1. 射线预计算的正确性

CalculateRayDirection的核心逻辑是正确的,但有两处细节需要注意:

  • 像素偏移x+0.5f和y+0.5f的处理正确,确保射线穿过像素中心,避免采样偏移。
  • 视场角转弧度、宽高比修正的计算逻辑没问题,但要确认相机空间的方向定义:你当前让射线看向+z方向,若后续相机矩阵是基于标准“相机看向-z方向”的定义,需统一空间坐标系,否则会出现方向矛盾。

另外CalculateRays函数中分配了ray_dir_frac但未返回或释放,会造成内存泄漏,需处理。

2. 相机矩阵变换的错误(畸变根源)

当前变换逻辑存在两处核心错误,这是旋转时出现畸变的原因:

射线起点错误

你将from设为(0,0,0)后用相机矩阵变换,这完全错误。相机空间中射线起点就是相机原点,对应到世界空间就是cam_pos(相机的世界位置),无需用矩阵变换(0,0,0)。

射线方向变换错误

若cam_mat是世界空间转相机空间的视图矩阵,那么它的作用是把世界空间的点转换到相机空间。反过来,要将相机空间的射线方向转换到世界空间,必须使用该矩阵的逆矩阵(如果是纯旋转矩阵,用转置矩阵即可,因为正交矩阵的逆等于转置)。你直接用原矩阵变换方向,相当于把相机空间的射线又转了一次到相机空间,方向完全混乱,导致畸变。

修正后的渲染循环代码

//For loop for x & y pixels

int pixel_index = y * world->screen_width + x;

auto cam_pos = world->camera_position;
// 假设cam_mat是世界转相机的视图矩阵,获取其逆矩阵(纯旋转时可用转置)
auto cam_mat_inv = cam_mat.Inverse();

float3 ray_dir_cam = world->ray_directions[pixel_index];
// 将相机空间射线方向转换到世界空间
float3 ray_dir_world = cam_mat_inv.MultiplyVector(ray_dir_cam);
// 确保方向归一化,避免精度问题
ray_dir_world = ray_dir_world.Normalized();
float3 ray_frac = { 1.0f / ray_dir_world.x, 1.0f / ray_dir_world.y, 1.0f / ray_dir_world.z };

// 射线起点直接使用相机的世界位置
float3 from = cam_pos;

float3 normal;

if (IntersectsOctree(root, from, ray_frac, normal) == true) {
    output[pixel_index].x = 255.0f;
    output[pixel_index].y = 0;
    output[pixel_index].z = 0;
}
else {
    output[pixel_index].x = world->clear_color.x;
    output[pixel_index].y = world->clear_color.y;
    output[pixel_index].z = world->clear_color.z;
}

若cam_mat本身是相机空间到世界空间的矩阵(比如相机的模型矩阵),则可直接用它变换射线方向,但射线起点仍需用cam_pos。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.13 21:09:52