gl_FragCoord

gl_FragCoord 表示当前片元着色器处理的候选片元窗口相对座标信息,是一个 vec4 类型的变量 (x, y, z, 1/w), 其中 x, y 是当前片元的窗口座标,OpenGL 默认以窗口左下角为原点, 在 着色器中通过布局限定符可以重新设定原点,比如窗口左上角为原点 origin_upper_left,窗口大小由 glViewport() 函数指定。x, y 默认是像素中心 而非 整数, 原点 的窗口座标值为 (0.5, 0.5), 小数部分恒为 0.5, 当viewport 范围 为(0,0,800,600)时, x, y 的取值范围为(0.5, 0.5, 799.5, 599.5), 当在着色器中布局限定符设置为 pixel_center_integer 时, x, y 取值为整数。

第三个分量 z 表示的是当前片元的深度信息,由 vertex shader 处理过后系统插值得到, gl_FragCoord.z 的产生过程:

假设 OpenGL 变换的各座标系统定义如下: world.xyzw 表示 世界座标系的座标, eye.xyzw 表示眼座标系(也叫观察座标系,还有叫相机座标系,呃。。。) 的座标, clip.xyzw 表示 裁剪座标系的座标 , ndc.xyzw 表示 规范化设备座标系座标, win.xyzw 表示 窗口座标系座标, OpenGL 一个完整的空间变换流水线如下:

world coordinate system --> eye coordinate system --> clip coordinate system --> normalized device coordinate system --> window device coordinate system。

gl_FragCoord.z 生成过程:

(1)世界座标系内的座标乘以观察矩阵变换到眼座标空间 eye.xyzw = viewMatrix * world.xyzw;

(2)眼座标系内的座标通过乘上投影矩阵变换到裁剪空间 clip.xyzw = projectMatrix * eye.xyzw;

(3)裁剪座标系内的座标通过透视除法(也就是 w 为 1 化) 到 规范化设备座标系 ndc.xyz = clip.xyz / clip.w;

(4)设备规范化座标系到窗口座标系 win.z = (dfar - dnear)/2 * ndc.z + (dfar+dnear)/2;

可以看出 gl_FragCoord.z 是 win.z 。dnear ,dfar 是由 glDepthRange(dnear, dfar) 给定的,按openGL 默认值 (0,1) , win.z = ndc.z/2 + 0.5。

有时候我们需要在 shader 内反算 眼座标系 或 世界座标系 内的座标, 这在后处理或延迟着色中很有用,不需要另外使用颜色缓存保留物体位置信息,减少带宽占用。反算窗口空间内的片元的空间座标:

ndc.xyzw = ( gl_FragCoord.xy/viewport.wh * 2.0 - 1.0, gl_FragCoord.z * 2.0 - 1.0, 1.0 );

这样我们只需向shader 中传入 矩阵信息 , 就可以获得该片元在指定空间内的座标 ,例如

eye.xyzw = projectionMatrixInverse * ndc.xyzw;
world.xyzw = modelViewProjectionMatrixInverse * ndc.xyzw
注意最终结果要除以 w 分量, eye.xyz = eye.xyz/eye.w;

第四个分量 gl_FragCoord.w

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章