OpenGL中如何将窗口空间光标位置转换为世界空间位置?
窗口空间鼠标转世界空间的实现问题
我正在尝试将范围[-1,1]的窗口空间鼠标光标位置转换为世界空间位置,但转换结果未正确响应视图投影矩阵的变化——相机位置改变时结果会偏移,精度也不准确。以下是我的实现代码及细节:
1. 透视投影矩阵实现
static mat4 Perspective4x4(float FOV, float AspectRatio, float FarC, float NearC) { // Positive x is right // Positive y is up // Positive z is forward into the screen float Cotangent = 1.0f / tanf((FOV)*0.5f); float Depth = NearC - FarC; float A = (-FarC - NearC) / Depth; float B = 2.0f * FarC * NearC / Depth; return { Cotangent/AspectRatio, 0.0f, 0.0f, 0.0f, 0.0f, Cotangent, 0.0f, 0.0f, 0.0f, 0.0f, -A, -B, 0.0f, 0.0f, 1.0f, 0.0f, }; } ... float WidthOverHeight = ...; mat4 ProjectionMatrix = Perspective4x4(DegreesToRadians(90.0f), WidthOverHeight, 50.0f, 0.1f);
2. 视图矩阵实现
static mat4 Translate4x4(vec3 V) { return { 1.0f, 0.0f, 0.0f, V.X, 0.0f, 1.0f, 0.0f, V.Y, 0.0f, 0.0f, 1.0f, V.Z, 0.0f, 0.0f, 0.0f, 1.0f }; } ... mat4 ViewMatrix = Translate4x4(-CameraPosition);
3. 世界空间光标位置计算逻辑
mat4 ProjectionMatrix = ...; mat4 ViewMatrix = ...; vec2 CursorP = GetBilateralCursorPos(Input); // Values between -1 and 1 v4_f32 WorldSpacePNear = Inverse(ProjectionMatrix) * V4F32(CursorP, -1.0f, 1.0f); WorldSpacePNear /= WorldSpacePNear.W; WorldSpacePNear = Inverse(ViewMatrix) * WorldSpacePNear; v4_f32 WorldSpacePFar = Inverse(ProjectionMatrix) * V4F32(CursorP, 1.0f, 1.0f); WorldSpacePFar /= WorldSpacePFar.W; WorldSpacePFar = Inverse(ViewMatrix) * WorldSpacePFar; WorldSpacePFar.Z *= -1.0f; WorldSpacePNear.Z *= -1.0f;
备注:我也尝试过把除以W的操作放到最后一步,但效果仍然不佳。
4. 向旧版OpenGL传递矩阵的方式
// I send them transposed because my matrices are row-major mat4 ProjectionMatrix = Transpose(...); mat4 ViewMatrix = Transpose(...); glMatrixMode(GL_PROJECTION); glLoadMatrixf(ProjectionMatrix.E); glMatrixMode(GL_MODELVIEW); glLoadMatrixf(ViewMatrix.E);
当前问题
转换得到的世界空间位置未正确匹配视图投影矩阵,相机位置改变时结果会出现偏移,且精度不准确。
补充说明
- vec4、vec2、mat4是自定义的基于浮点数的数学类型,符合常规定义。
- 已知旧版OpenGL已被弃用,后续会切换到现代OpenGL,但希望先解决当前问题。
内容的提问来源于stack exchange,提问作者cynnad
相关产品推荐
相关产品推荐

