【问题标题】:GLSL compute world coordinate from eye depth and screen positionGLSL 根据眼睛深度和屏幕位置计算世界坐标
【发布时间】:2014-12-28 17:44:16
【问题描述】:

我正在尝试恢复一个点的 WORLD 位置,知道它在 EYE 空间中的深度,计算如下(在顶点着色器中):

float depth = - uModelView * vec4( inPos , 1.0 ) ;

其中 inPos 是世界空间中的一个点(显然,我不想恢复这个特定的点,而是一个以该格式表示深度的点)。

它是标准化的屏幕位置(在 0 和 1 之间),计算如下(在片段着色器中):

vec2 screen_pos = ( vec2( gl_FragCoord.xy ) - vec2( 0.5 ) ) / uScreenSize.xy ;

我可以访问以下信息:

  • uScreenSize :顾名思义,就是屏幕的宽度和高度
  • uCameraPos : 世界空间中的相机位置

和标准矩阵:

  • uModelView : 模型视图相机矩阵
  • uModelViewProj : 模型视图投影矩阵
  • uProjMatrix : 投影矩阵

如何计算 WORLD 空间中某个点的位置 (X,Y,Z) ? (不在EYE空间)

我无法访问其他(我不能使用近、远、左、右……),因为投影矩阵不限于透视或正交。

提前致谢。

【问题讨论】:

    标签: opengl glsl


    【解决方案1】:

    我的问题是正确的,您有 x 和 y 作为窗口空间(并且已经转换为标准化设备空间 [-1,1]),但 z 在眼睛空间中,并且想要重新构建世界空间位置。

    我无法访问其他(我无法使用近、远、左、右……) 因为投影矩阵不限于透视或 正交。

    嗯,实际上,除了正交或投影映射之外,没有什么可以通过齐次空间中的矩阵乘法实现的。但是,投影矩阵是足够的,只要它是可逆的(理论上,投影矩阵可以将所有点转换为平面,线或单个点。在这种情况下,一些信息会丢失,它永远无法重建原始数据。但那将是一个非常不典型的情况。

    所以你可以从投影矩阵和你的 2D 位置得到实际上是眼睛空间中的 射线。您可以将其与z=depth 平面相交以获取该点。

    所以你要做的就是计算两个点

    vec4 p = inverse(uProjMatrix) * vec4 (ndc_x,  ndc_y, -1, 1);
    vec4 q = inverse(uProjMatrix) * vec4 (ndc_x,  ndc_y,  1, 1);
    

    这将在眼睛空间的光线上标记两个点。不要忘记将p 和q 除以各自的w 组件以获得3D 坐标。现在,您只需将其与您的z=depth 平面相交并获得眼睛空间x 和y。最后,您可以使用uModelView 矩阵的逆矩阵将该点投影回对象空间。

    但是,你说你想要世界空间。但这是不可能的。您需要view 矩阵来执行此操作,但您没有将其列为给定的。您所拥有的只是model 和view 矩阵的compisition,并且您至少需要知道其中之一才能重建世界空间位置。 cameraPosition 不是 enoguh。您还需要方向。

    【讨论】:

    • 好吧。我喜欢你的回答。我想我可以将视图矩阵传递给着色器并计算交集。我现在无法测试,但我会告诉你它是否有效。
    • 我想指出(inverse(uProjMatrix) * vec4 (ndc_x, ndc_y, 1, 1)).xyz 应该已经给你一个带有z = 1 的向量。因此,您只需将其乘以负深度即可获得眼睛空间中的点坐标。
    • @nils:我写的对于投影矩阵的最通用情况是有效的。如果对所使用的矩阵有更多了解,则可以进一步优化,即具有典型 GL 约定的经典 GL 投影矩阵的最后一行编码为w_clip=-z_eye,因此逆矩阵为z_eye=-w_clip,结果为@上面的 987654341@ 将是 -1。所以是的,你可以走一些捷径。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-08-14
    • 2018-01-29
    • 2011-08-05
    • 2017-05-26
    • 2017-12-11
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多