OpenGL如何从视锥对齐向量计算世界空间坐标?

时间:2018-12-11 16:21:14

标签: opengl matrix-inverse projection-matrix frustum volume-rendering

我是从事我自己的引擎的图形编程初学者,并尝试实现视锥对齐的体绘制。

这个想法是将多个平面渲染为视锥的整个垂直切片,然后使用这些平面的世界坐标作为程序量。

将切片渲染为3d模型并将顶点位置用作世界空间坐标可以很好地工作:

//Vertex Shader  
gl_Position = P*V*vec4(vertexPosition_worldspace,1);
coordinates_worldspace = vertexPosition_worldspace;

结果:

但是,在视锥空间中渲染切片并尝试对世界空间坐标进行逆向工程确实会产生预期的结果。我最接近的是:

//Vertex Shader
gl_Position = vec4(vertexPosition_worldspace,1);
coordinates_worldspace = (inverse(V) * inverse(P) * vec4(vertexPosition_worldspace,1)).xyz;

结果:

我的猜测是,标准投影矩阵会以某种方式摆脱一些关键的深度信息,但除此之外,我不知道我在做什么错以及如何解决它。

1 个答案:

答案 0 :(得分:0)

嗯,还不是100%清楚您所说的“平截头体空间”是什么意思。我将假定它确实引用了OpenGL中的归一化设备坐标,其中,视锥面(默认情况下)是与轴对齐的立方体-1 <= x,y,z <= 1。我还将假设透视投影,以便NDC z坐标实际上是眼空间z双曲线函数。

  

我的猜测是,标准投影矩阵会以某种方式摆脱一些关键的深度信息,但除此之外,我不知道我在做什么错以及如何解决它。

否,OpenGL中的标准透视矩阵看起来像

( sx   0   tx   0  ) 
(  0  sy   ty   0  )
(  0   0    A   B  )
(  0   0   -1   0  )

将其乘以(x,y,z,1)眼睛空间矢量时,将获得同质的剪辑坐标。仅考虑 矩阵的最后两行作为单独的方程式:

z_clip = A * z_eye + B
w_clip = -z_eye

由于我们将透视图除以w_clip才能从剪辑空间移至NDC,所以最终得到

z_ndc = - A - B/z_eye

实际上是双曲线重新映射的深度信息-以便完全保留信息。 (还要注意,我们也对xy进行了除法。)

计算inverse(P)时,仅反转4D-> 4D同质映射。但是您将得到的结果w不再是1,所以在这里:

coordinates_worldspace = (inverse(V) * inverse(P) * vec4(vertexPosition_worldspace,1)).xyz;
                                                                                       ^^^

造成您的信息丢失。您只需要跳过生成的w并使用xyz分量就可以认为它们是笛卡尔3D坐标,但是它们是表示某些3D点的4D同质坐标。

正确的方法是除以w

vec4 coordinates_worldspace = (inverse(V) * inverse(P) * vec4(vertexPosition_worldspace,1));
coordinates_worldspace /= coordinates_worldspace.w