关于实验 2.4, generate_ray() 参数 depth 的问题

在 generate_ray 函数中,输出 x 和 y 都是几十几百的,所以是物理成像平面。但是在 WhittedRenderer::render 函数中,给 depth 传的是 1.0f,也就是归一化成像平面的 depth。所以在 generate_ray 函数中,需不需要把文档中的

Vector4f view_pos_specified = 
        Vector4f(pos.x()-center.x(), -(pos.y()-center.y()), -depth, 1.0f);

改为

Vector4f view_pos_specified =
        Vector4f(pos.x()-center.x(), -(pos.y()-center.y()), -depth/ratio, 1.0f);

之后我通过乘 ratio 和 inv_view 矩阵,把 view_pos_specified 转换成 world_pos,但是这样也出现了改变相机位置,渲染结果不变的问题,所以这样对 depth 操作是否有问题?或者我对这个过程的理解不对?

另外,我用实验 2.2 的参数 (light 位置{2.0f, 2.0f, 2.0f}, camera 位置{2,.0f, 2.0f, 2.0f}) 渲染,用时四分半,这时长正常吗?

总体而言,是你对射线生成过程的理解有问题。

在 generate_ray 函数中,输出 x 和 y 都是几十几百的,所以是物理成像平面。

这里就已经出错了。参考 开发者文档:generate_ray 的说明可知,这个函数的参数中,宽、高、横纵坐标都以像素为单位。而我们从来没有指定过一个像素在世界坐标系下是多大,所以这些坐标都是相对于宽度和高度的坐标,不是物理成像平面上的坐标(任何一个坐标系下都不是)。你也不可能用任何方法直接算出 xy 这两个参数对应的 z 值(深度值),因为它们实际上不对应任何 z 值(深度值)。

正确的做法是:

  1. 根据深度值 1 和相机的 fov 参数算出归一化成像平面的大小(以及左上角或者中心点)
  2. generate_rayx / y 参数算出这个点在成像平面上的相对位置(相对于左上角或中心点都可以)
  3. 用参考点(左上角或中心点)加上相对的偏移量算出这个点的观察坐标
  4. 将观察坐标变换回世界坐标

整个过程中完全不涉及物理成像平面的坐标值,“物理成像平面”只是一个辅助理解的工具。