首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >OpenGL:从窗口空间坐标计算眼睛空间坐标?

OpenGL:从窗口空间坐标计算眼睛空间坐标?
EN

Stack Overflow用户
提问于 2011-04-15 04:30:34
回答 5查看 5.1K关注 0票数 3

我如何根据窗口空间(帧缓冲区中的像素)坐标+ GLSL中的像素深度值(可以这么说,GLSL中的gluUnproject)来计算眼睛空间坐标?

EN

回答 5

Stack Overflow用户

回答已采纳

发布于 2011-04-17 02:57:16

好吧,opengl.org上的一个人指出,投影产生的剪辑空间坐标是用clipPos.w除以计算归一化设备坐标的。在将ndc上的片段转换为裁剪空间坐标时,需要重新构造w(恰好是来自相应视图空间(相机)坐标的-z ),并将ndc坐标与该值相乘,以计算出合适的裁剪空间坐标(您可以通过将其与逆投影矩阵相乘,将其转换为视图空间坐标)。

下面的代码假设您正在post过程中处理帧缓冲区。在渲染几何体的同时对其进行处理时,可以使用gl_FragCoord.z代替texture2D (sceneDepth,ndcPos.xy).r。

代码如下:

代码语言:javascript
复制
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版本。

票数 0
EN

Stack Overflow用户

发布于 2011-04-15 20:57:58

看起来是GLSL convert gl_FragCoord.z into eye-space z的副本。

编辑(完整答案):

代码语言:javascript
复制
// 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
票数 3
EN

Stack Overflow用户

发布于 2011-04-15 18:28:31

假设您坚持使用固定的管道样式的模型、视图和投影,那么您只需精确地实现gluUnProject man page中给出的公式即可。

GLSL中没有内置的矩阵求逆,所以理想情况下你应该在CPU上这样做。因此,您需要提供合成modelViewProjection矩阵的逆矩阵的一致性。gl_FragCoord位于窗口坐标中,因此您还需要提供视图尺寸。

所以,你可能会以这样的方式结束(即席编码):

代码语言:javascript
复制
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);

如果您已经实现了自己的旧矩阵堆栈的模拟,那么您可能可以很好地反转矩阵。否则,它可能是一个超出您预期的more daunting topic,您最好使用MESA的open source implementation (请参阅invert_matrix,该文件中的第三个函数),因为它经过了良好的测试。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/5669287

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档