一般的光线拾取过程应如下(实验结果证明是正确的):
-
将屏幕点变换为标准化设备空间方向向量:
float x = (2.0f * mouse_x) / width - 1.0f;
float y = 1.0f - (2.0f * mouse_y) / height;
float z = 1.0f;
vec3 ray_nds = vec3 (x, y, z);
-
将方向向量变换为齐次剪切坐标
vec4 ray_clip = vec4 (ray_nds.xy, -1.0, 1.0);
-
将方向向量变换为眼空间方向向量
vec4 ray_eye = inverse (projection_matrix) * ray_clip;
将方向向量变换到世界空间,获得具有世界空间相机位置和方向向量的拾取射线
我的问题是,在标准化设备空间中,为什么方向向量的 z 分量是 1.0?
我的意思是,在OpenGL标准化设备空间中,xyz分量应该都在-1~1的范围内,因此相机应该位于平面z=-1的中心。所以方向向量应该是:视图目标位置-相机位置,z分量应该是1-(-1)=2.0f。 (在 DirectX 标准化设备空间中,xy 分量的范围为 -1~1,z 分量的范围为 0~1,相机位置应位于 z=0 平面的中心,即(0, 0,0),方向向量的z分量应为1-0=1)
ray_nds.z
完全无关,因为你无论如何也不会使用它。那是因为你不知道像素的深度。
ray_clip
不是方向,而是投影后近裁剪平面(z=-1)上的位置。如果您撤消此投影(使用逆投影矩阵),您最终会在相机空间中得到相同的点。在相机空间中,相机的中心位于(0, 0, 0)
。射线的方向矢量可以计算为ray_eye - (0, 0, 0)
,这本质上是ray_eye
。因此,如果我们忽略 w 分量,我们可以使用位置作为方向。这仅适用于相机空间!剪辑空间和世界空间都很可能在其他地方有投影中心。
不要混淆不同空间的摄像机位置。在相机空间中,它位于原点。在剪辑空间中,可以假设位于(0, 0, -infinity)
。重点(x, y, ...)
只是被相应像素覆盖的任意点。您需要其中任何一个来定义光线。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)