OpenGL 如何从平截头体对齐向量计算世界空间坐标?
OpenGL How to calculate worldspace coordinates from frustum aligned vectors?
我是一名图形编程初学者,在我自己的引擎上工作并尝试实现平截头体对齐的体积渲染。
我们的想法是将多个平面渲染为视锥体的垂直切片,然后将这些平面的世界坐标用于程序体积。
将切片渲染为 3d 模型并将顶点位置用作世界坐标 space 效果非常好:
//Vertex Shader
gl_Position = P*V*vec4(vertexPosition_worldspace,1);
coordinates_worldspace = vertexPosition_worldspace;
结果:
但是在截锥体-space 中渲染切片并尝试对世界 space 坐标进行逆向工程并没有给出预期的结果。我得到的最接近的是:
//Vertex Shader
gl_Position = vec4(vertexPosition_worldspace,1);
coordinates_worldspace = (inverse(V) * inverse(P) * vec4(vertexPosition_worldspace,1)).xyz;
结果:
我的猜测是,标准投影矩阵以某种方式摆脱了一些关键的深度信息,但除此之外我不知道我做错了什么以及如何解决它。
嗯,"frustum space" 不是 100% 清楚你的意思。我将假设它确实引用了 OpenGL 中的 标准化设备坐标 ,其中视锥体是(默认情况下)轴对齐的立方体 -1 <= x,y,z <= 1
。我还将假设透视投影,因此 NDC z
坐标实际上是眼睛 space z
.[=] 的 双曲线 函数30=]
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)
眼睛 space 向量时,您将得到同质剪辑坐标。只考虑
矩阵的最后两行作为单独的方程式:
z_clip = A * z_eye + B
w_clip = -z_eye
由于我们将透视除以 w_clip
从剪辑 space 到 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
我是一名图形编程初学者,在我自己的引擎上工作并尝试实现平截头体对齐的体积渲染。
我们的想法是将多个平面渲染为视锥体的垂直切片,然后将这些平面的世界坐标用于程序体积。
将切片渲染为 3d 模型并将顶点位置用作世界坐标 space 效果非常好:
//Vertex Shader
gl_Position = P*V*vec4(vertexPosition_worldspace,1);
coordinates_worldspace = vertexPosition_worldspace;
结果:
但是在截锥体-space 中渲染切片并尝试对世界 space 坐标进行逆向工程并没有给出预期的结果。我得到的最接近的是:
//Vertex Shader
gl_Position = vec4(vertexPosition_worldspace,1);
coordinates_worldspace = (inverse(V) * inverse(P) * vec4(vertexPosition_worldspace,1)).xyz;
结果:
我的猜测是,标准投影矩阵以某种方式摆脱了一些关键的深度信息,但除此之外我不知道我做错了什么以及如何解决它。
嗯,"frustum space" 不是 100% 清楚你的意思。我将假设它确实引用了 OpenGL 中的 标准化设备坐标 ,其中视锥体是(默认情况下)轴对齐的立方体 -1 <= x,y,z <= 1
。我还将假设透视投影,因此 NDC z
坐标实际上是眼睛 space z
.[=] 的 双曲线 函数30=]
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)
眼睛 space 向量时,您将得到同质剪辑坐标。只考虑
矩阵的最后两行作为单独的方程式:
z_clip = A * z_eye + B
w_clip = -z_eye
由于我们将透视除以 w_clip
从剪辑 space 到 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