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版本。     

bab

我只是意识到没有必要在片段着色器中进行这些计算。您可以通过在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页面列出了一些不同的情况,并用着色器代码进行了解释,因此值得在此处发布。 从窗口空间计算眼睛空间。     

要回复问题请先登录注册