openGL 光线拾取
Posted
技术标签:
【中文标题】openGL 光线拾取【英文标题】:openGL ray pick 【发布时间】:2014-03-05 02:06:41 【问题描述】:一般的Ray拾取过程如下(实验结果证明是正确的):
将屏幕点转换为标准化的设备空间方向向量:
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的中心。所以方向向量应该是:view target position - camera position,z分量应该是1-(-1)=2.0f。 (在 DirectX 归一化设备空间中,xy 分量在 -1~1 范围内,z 分量在 0~1 范围内,相机位置应该在平面 z=0 的中心,例如,(0, 0,0),方向向量的z分量应该是1-0=1)
【问题讨论】:
【参考方案1】:ray_nds.z
完全无关紧要,因为无论如何你都不使用它。那是因为你不知道像素的深度。
ray_clip
不是方向,而是投影后近剪裁平面(z=-1)上的位置。如果您撤消此投影(使用逆投影矩阵),您最终会在相机空间中得到相同的点。在相机空间中,相机以(0, 0, 0)
为中心。射线的方向向量可以用ray_eye - (0, 0, 0)
计算,本质上就是ray_eye
。所以如果我们忽略 w 分量,我们可以使用位置作为方向。这仅适用于相机空间!剪辑空间和世界空间最有可能将投影中心放在其他地方。
不要混淆不同空间中的相机位置。在相机空间中,它位于原点。在剪辑空间中,可以假设它位于(0, 0, -infinity)
。点(x, y, ...)
只是被相应像素覆盖的任意点。您需要其中任何一个来定义射线。
【讨论】:
【参考方案2】:摄像头不在 z=-1(或 0)处,它甚至位于其后面。
near clip plane
位于 z=-1。这使得这类数学变得复杂,因为所有涉及的方程如果被追踪,就会产生不通过 0 的曲线。因此,我们总是会携带大量的 zn
和 zm
。
检查一下,等式 4.2:http://www.arcsynthesis.org/gltut/Positioning/Tut04%20Perspective%20Projection.html。
更可怕但更完整:http://www.songho.ca/opengl/gl_projectionmatrix.html
更多链接: http://unspecified.wordpress.com/2012/06/21/calculating-the-gluperspective-matrix-and-other-opengl-matrix-maths/
http://schabby.de/projection-matrix/
【讨论】:
以上是关于openGL 光线拾取的主要内容,如果未能解决你的问题,请参考以下文章
OpenGL C++ 鼠标光线拾取 glm:unproject