微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

OpenGL:从GLSL中的窗口空间坐标计算出眼睛空间坐标?

如何解决OpenGL:从GLSL中的窗口空间坐标计算出眼睛空间坐标?

| 如何从GLSL中的窗口空间(帧缓冲区中的像素)坐标+像素深度值(可以说GLSL中的gluUnproject)计算出眼睛空间坐标?     

解决方法

看起来像是GLSL的副本,将gl_FragCoord.z转换为眼睛空间z。 编辑(完整答案):
// input: x_coord,y_coord,samplerDepth
vec2 xy = vec2(x_coord,y_coord); //in [0,1] range
vec4 v_screen = vec4(xy,texture(samplerDepth,xy),1.0 );
vec4 v_homo = inverse(gl_ProjectionMatrix) * 2.0*(v_screen-vec4(0.5));
vec3 v_eye = v_homo.xyz / v_homo.w; //transfer from homogeneous coordinates
    ,假设您坚持使用固定的管道样式模型,视图和投影,则可以完全实现gluUnProject手册页中给出的公式。 GLSL没有内置矩阵求逆,因此理想情况下,您应该在CPU上使用。因此,您需要提供组成的modelViewProjection矩阵的逆矩阵的统一形式。 gl_FragCoord在窗口坐标中,因此您还需要提供视图尺寸。 因此,您可能最终会得到类似(临时编码)的信息:
vec4 unProjectedPosition = invertedModelViewProjection * vec4( 
               2.0 * (gl_FragCoord.x - view[0]) / view[2] - 1.0,2.0 * (gl_FragCoord.y - view[1]) / view[3] - 1.0,2.0 * gl_FragCoord.z - 1.0,1.0);
如果您已经实现了自己的旧矩阵堆栈的模拟物,那么您可以很好地反转矩阵。否则,它可能是比您预期的更令人生畏的话题,并且使用MESA的开源实现(最好查看该文件中的第三个函数invert_matrix)可能会更好,因为它已经过充分测试没有其他的。     ,好吧,opengl.org上的一个人指出,投影生成的剪辑空间坐标被clipPos.w除以计算归一化的设备坐标。从ndc上的片段反转到剪辑空间坐标的步骤时,您需要重建w(恰好是从对应的视图空间(相机)坐标开始的-z),并将ndc坐标乘以该值以计算适当的剪辑空间坐标(您可以通过将其乘以逆投影矩阵将其转换为视图空间坐标)。 以下代码假定您正在后期处理中处理帧缓冲区。在渲染几何图形时进行处理时,可以使用gl_FragCoord.z代替texture2D(sceneDepth,ndcPos.xy).r。 这是代码:
uniform sampler2D sceneDepth;
uniform mat4 projectionInverse;
uniform vec2 clipPlanes; // zNear,zFar
uniform vec2 windowSize; // window width,height

#define ZNEAR clipPlanes.x
#define ZFAR clipPlanes.y

#define A (ZNEAR + ZFAR)
#define B (ZNEAR - ZFAR)
#define C (2.0 * ZNEAR * ZFAR)
#define D (ndcPos.z * B)
#define ZEYE -(C / (A + D))

void main() 
{
vec3 ndcPos;
ndcPos.xy = gl_FragCoord.xy / windowSize;
ndcPos.z = texture2D (sceneDepth,ndcPos.xy).r; // or gl_FragCoord.z
ndcPos -= 0.5;
ndcPos *= 2.0;
vec4 clipPos;
clipPos.w = -ZEYE;
clipPos.xyz = ndcPos * clipPos.w;
vec4 eyePos = projectionInverse * clipPos;
}
基本上,这是gluUnproject的GLSL版本。     ,我只是意识到没有必要在片段着色器中进行这些计算。您可以通过在CPU上执行此操作并将其与MVP逆数相乘来节省一些操作(假设
glDepthRange(0,1)
,可以随时进行编辑):
glm::vec4 vp(left,right,width,height);
glm::mat4 viewportMat = glm::translate(
    vec3(-2.0 * vp.x / vp.z - 1.0,-2.0 * vp.y / vp.w - 1.0,-1.0))
  * glm::scale(glm::vec3(2.0 / vp.z,2.0 / vp.w,2.0));
glm::mat4 mvpInv = inverse(mvp);
glm::mat4 vmvpInv = mvpInv * viewportMat;
shader->uniform(\"vmvpInv\",vmvpInv);
在着色器中:
vec4 eyePos = vmvpInv * vec4(gl_FragCoord.xyz,1);
vec3 pos = eyePos.xyz / eyePos.w;
    ,我认为所有可用的答案都从一个方面触及了问题,
khronos.org
的Wiki页面列出了一些不同的情况,并用着色器代码进行了解释,因此值得在此处发布。 从窗口空间计算眼睛空间。     

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。