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

先看看透视投影矩阵的推导:

gl_FragCoord.w 是裁剪空间 clip.w 的倒数即 1/clip.w ,  由上面的透视投影矩阵的推导过程可以看出,为了凑透视除法, clip.w 值就是 眼坐标系 z 值的负数,也就是距离相机的距离。 取负数 是因为 眼坐标系 与 规范化设备坐标系 手向性不同, 眼坐标系是右手系, 规范化设备坐标系是左手系。这里暗示我们,对于透视投影, 由 gl_FragCoord.w  可以很方便的知道当前片元在眼坐标系中 距离相机的距离  : gl_FragCoord.w = - 1/Ze  ---------->   Ze = - 1/gl_FragCoord.w;

那么正交投影呢?  没门! 正交投影矩阵的 w 值 恒为 1, 还是乖乖的传矩阵做逆运算吧。当然 用逆矩阵反求 各坐标系的坐标 具有通用性。

总结:

gl_FragCoord 比较有用的是反求各坐标系的空间位置,减少带宽占用。 也可以方便的获取当前片元的窗口坐标和片元深度值。当深度测试开启时, 如果在片元着色器中没有定义 gl_FragDepth 的值, gl_FragCoord.z 即成为默认输出的深度值,并且gl_FragDepth 不会存在未定义输出的情况(因为不是用户定义的值就是系统给定的默认值)。

题外话, 给定一个矩阵,怎样判断投影矩阵 是 透视投影还是正交投影呢?

最后给两个函数,在基于延迟着色的fragment shader 中 反求片元在 眼坐标系 或 世界坐标系的位置:

vec3 decodeCameraSpacePositionFromDepthBuffer(in vec2 texCoord){vec4 clipSpaceLocation;  clipSpaceLocation.xy = texCoord*2.0-1.0;clipSpaceLocation.z  = texture(depthTexture, texCoord).r * 2.0-1.0;clipSpaceLocation.w  = 1.0;vec4 homogenousLocation = projectionMatrixInverse * clipSpaceLocation;return homogenousLocation.xyz/homogenousLocation.w;
}vec3 decodeWorldSpacePositionFromDepthBuffer(in vec2 texCoord){vec4 clipSpaceLocation; clipSpaceLocation.xy = texCoord*2.0-1.0;clipSpaceLocation.z  = texture(depthTexture, texCoord).r * 2.0-1.0;clipSpaceLocation.w  = 1.0;vec4 homogenousLocation = viewProjectionMatrixInverse * clipSpaceLocation;return homogenousLocation.xyz/homogenousLocation.w;
}

gl_FragCoord 的含义相关推荐

  1. WebGL着色器内置变量gl_PointSize、gl_Position、gl_FragColor、gl_FragCoord、gl_PointCoord

    WebGL着色器内置变量 WebGL中文教程网 本文是WebGL教程(电子书)的2.7节内容 着色器语言在GPU的着色器单元执行,javascript语言.C语言在CPU上执行,任何一种语言的语法规则 ...

  2. WebGL空间变换以及gl_FragCoord的运用

    WebGL空间变换 局部坐标系-->世界坐标系-->相机坐标系-->剪裁坐标系-->规范化设备坐标系-->屏幕坐标系 模型变换:world.xyzw = modelMat ...

  3. Java Calendar.add()方法的使用,参数含义。指定时间差。

    cal.add()方法中的参数含义: 第一个参数如果是1则代表的是对年份操作,2是对月份操作,3是对星期操作,5是对日期操作,11是对小时操作,12是对分钟操作,13是对秒操作,14是对毫秒操作. 第 ...

  4. 通俗理解tf.nn.conv2d() tf.nn.conv3d( )参数的含义 pytorhc 卷积

    20210609 例如(3,3,(3,7,7))表示的是输入图像的通道数是3,输出图像的通道数是3,(3,7,7)表示过滤器每次处理3帧图像,卷积核的大小是3 x 7 x 7. https://blo ...

  5. 三维刚体变化中Rcw,tcw的含义

      高翔博士的<视觉SLAM十四讲>中,介绍Tcw指从世界坐标w到c的变换矩阵.但研一学机器人学的时候,讲T12的含义是,坐标系2相对于坐标系1的变换.于是一脸懵逼.昨天想了一晚上,有了一 ...

  6. 在建工程费用化处理_未确认融资费用和未实现融资收益的含义和区别

    在融资的过程中,可能会涉及到未确认融资费用和未实现融资收益的概念.那这两者分别是什么含义呢?又有什么区别?下面大家和小编一起来看看两者之间的关系,希望能够帮助到大家. 未实现融资收益是指未收到租金并未 ...

  7. inum在linux中含义,linux

    Linux 1.  用户,应用层(图形界面),Shell层(Shell层),内核层(系统调用),硬件 2.X Window系统(协议)特点:独立与操作系统 ,网络特性(可以选择语言),源代码免费 3. ...

  8. 龙格-库塔法(runge-kutta)matlab代码及含义,龙格-库塔法(Runge-Kutta)matlab代码及含义...

    龙格-库塔法(Runge-Kutta)matlab代码及含义 龙格-库塔法(Runge-Kutta) 数值分析中,龙格-库塔法(Runge-Kutta)是用于模拟常微分方程的解的重要的一类隐式或显式迭 ...

  9. java中数组的含义_数组

    数组(Array)是有序的元素序列.[1] 若将有限个类型相同的变量的集合命名,那么这个名称为数组名.组成数组的各个变量称为数组的分量,也称为数组的元素,有时也称为下标变量.用于区分数组的各个元素的数 ...

最新文章

  1. UI设计培训之UI设计系统知识
  2. [20160608]自治事务引起死锁.txt
  3. 超强平衡机器人,走钢丝、玩忍者步伐,还可以做瑜伽动作,不受干扰的那种 | IEEE 2020...
  4. ansible2.4 api调用
  5. 第三讲-------Logistic Regression Regularization
  6. php oop 实际工作,PHP OOP注意点(一)
  7. kotlin实现继承_Kotlin程序| 继承的例子
  8. HTTP 协议 -- 浏览器缓存机制
  9. 为什么Mac source ~/.bash_profile只生效一次(macOS Catalina)
  10. 学计算机的心理300字,心理的作文300字7篇
  11. 马斯克身家742亿美元超微软前CEO鲍尔默 成全球第5大富豪
  12. 防止 重复重建相同的表
  13. 51单片机产生1Hz-5kHz可调占空比方波
  14. 桌面音乐频谱linux,音乐频谱桌面特效下载-X Music Spectrum(音乐频谱桌面特效)免费版 v1.0.0.8_系统之家...
  15. Java修改图片格式
  16. MySQL的函数-窗口函数
  17. 2022年各省高考查分时间、入口汇总
  18. piaget读法_读音教学 | 这些手表品牌原来是这么念的!
  19. 用户注册+登录(下)
  20. ThinkPHP 配置详解

热门文章

  1. 大写字母逆序2 (100分)
  2. tongweb java_home_中标麒麟操作系统下部署 Web项目(Tongweb + DM)
  3. oracle 虚拟表 多行,Oracle使用虚拟表dual一次插入多条记录【摘录】
  4. 从诺贝尔奖到“吃鸡守护者”:通往极点的手机散热战争
  5. Unity 安卓 Unable to initialize the Unity Engine / No Enough Space to install unity
  6. php编写六十甲子纳音表_六十甲子顺序表
  7. js对象转byte数组
  8. Echarts图表设置x轴y轴均随滚轮滚动缩+放 区域缩放
  9. Unity游戏配置存储方案
  10. ZipFile 解压多个.zip压缩文件