我是一名图形编程初学者,正在研究自己的引擎,并尝试实现平截头体对齐的体积渲染。
这个想法是将多个平面渲染为跨视锥体的垂直切片,然后使用这些平面的世界坐标作为程序体积。
将切片渲染为 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;
结果:
我的猜测是,标准投影矩阵以某种方式消除了一些关键的深度信息,但除此之外,我不知道我做错了什么以及如何修复它。
最佳答案
嗯,“截锥体空间”的含义并不是 100% 清楚。我假设它确实引用了 OpenGL 中的标准化设备坐标,其中视锥体(默认情况下)是轴对齐的立方体 -1 <= x,y,z <= 1
。我还将假设一个透视投影,以便 NDC z
坐标实际上是眼睛空间的双曲函数 z
.
My guess is, that the standard projection matrix somehow gets rid of some crucial depth information, but other than that i have no clue what i am doing wrong and how to fix it.
不,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
关于OpenGL如何从平截头体对齐向量计算世界空间坐标?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53728282/