【问题标题】:C++/OpenGL convert world coords to screen(2D) coordsC++/OpenGL 将世界坐标转换为屏幕(2D)坐标
【发布时间】:2012-01-19 10:42:48
【问题描述】:

我正在使用 OpenGL 制作游戏,其中我在世界空间中有一些对象。我想创建一个函数,我可以在其中获取对象的位置(3D)并将其转换为屏幕的位置(2D)并返回它。

我在以下变量中知道对象、投影矩阵和视图矩阵的 3D 位置:

Matrix projectionMatrix;
Matrix viewMatrix;
Vector3 point3D;

【问题讨论】:

    标签: c++ opengl matrix


    【解决方案1】:

    要进行此转换,您必须首先获取模型空间位置并将它们转换为剪辑空间。这是通过矩阵乘法完成的。我将使用 GLSL 风格的代码来明确我在做什么:

    vec4 clipSpacePos = projectionMatrix * (viewMatrix * vec4(point3D, 1.0));
    

    请注意我是如何在乘法之前将您的 3D 向量转换为 4D 向量的。这是必要的,因为矩阵是 4x4,您不能将 4x4 矩阵与 3D 向量相乘。你需要第四个组件。

    下一步是将此位置从剪辑空间转换为标准化设备坐标空间(NDC 空间)。 NDC 空间在所有三个轴上的范围 [-1, 1] 上。这是通过将前三个坐标除以第四个坐标来完成的:

    vec3 ndcSpacePos = clipSpacePos.xyz / clipSpacePos.w;
    

    显然,如果clipSpacePos.w 为零,则说明您有问题,因此您应该事先检查。如果为零,则表示对象在投影平面内;它的视图空间深度为零。并且这样的顶点会被 OpenGL 自动裁剪掉。

    下一步是从这个 [-1, 1] 空间转换为窗口相对坐标。这需要使用您传递给glViewport 的值。前两个参数是窗口左下角的偏移量(vec2 viewOffset),后两个参数是视口区域的宽度/高度(vec2 viewSize)。鉴于这些,窗口空间位置是:

    vec2 windowSpacePos = ((ndcSpacePos.xy + 1.0) / 2.0) * viewSize + viewOffset;
    

    这就是你所能做的。请记住:OpenGL 的窗口空间是相对于窗口的左下角,而不是左上角。

    【讨论】:

    • 如何在不使用着色器程序的情况下实现这一点?我的意思是,只是普通的 OpenGL 函数?
    • 我在谷歌上搜索了一段时间后找到的最佳答案,也是我发现的唯一一个提到必须除以 clipSpacePos.w 的答案。
    • 注意:如果窗口空间相对于窗口的左上角,那么windowSpacePos应该是vec2( ((ndcSpacePos.x + 1.0) / 2.0) * viewSize.x + viewOffset.x, ((1.0 - ndcSpacePos.y) / 2.0) * viewSize.y + viewOffset.y )
    猜你喜欢
    • 1970-01-01
    • 2013-04-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-02-25
    相关资源
    最近更新 更多