2

我是一名图形编程初学者,在自己的引擎上工作,并尝试实现平截头体对齐的体积渲染。

这个想法是将多个平面渲染为横跨视锥的垂直切片,然后将这些平面的世界坐标用于程序体积。

将切片渲染为 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;

结果:

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

4

1 回答 1

3

好吧,您所说的“平截头体空间”的含义还不是 100% 清楚。我将假设它确实引用了 OpenGL 中的标准化设备坐标,其中视锥体(默认情况下)是轴对齐的立方体-1 <= x,y,z <= 1。我还将假设透视投影,因此 NDCz坐标实际上是眼睛空间的双曲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

这实际上是双曲线重映射的深度信息——这样信息就被完全保留了。(另请注意,我们也为x和进行除法y)。

当您计算 时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
于 2018-12-11T18:54:43.710 回答