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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.06 03:00:54