GLSL有几个以gl_为前缀的变量(内建变量),它们在着色器中能直接获取和使用,并且都有着很重要的意义,gl_Position 和 gl_FragCoord 就是两个典型的内建变量

一、顶点着色器变量

gl_Position:

顶点着色器裁切空间输出的位置向量。想让屏幕上渲染出东西,那么就必须使用,否则将什么都看不到,在第一次接触顶点着色器之后,就一直在用它了

gl_PointSize:

渲染出的点的大小,需要满足以下两个条件,gl_PointSize才会是有效的:

  • glEnable(GL_PROGRAM_POINT_SIZE):允许在着色器中设置点的大小
  • 绘制时渲染的基本图形(primitive)是 GL_POINTS

它是一个float变量,可以以像素的方式设置点的高度和宽度,在着色器中描述每个顶点做为点被绘制出来的大小:

#version 330 core
layout (location = 0) in vec3 position;
layout (location = 1) in vec3 normal;
layout (location = 2) in vec2 texture;
out vec2 texIn;
out vec3 normalIn;
out vec3 fragPosIn;
uniform mat4 model;             //模型矩阵
uniform mat4 view;              //观察矩阵
uniform mat4 projection;        //投影矩阵
void main()
{gl_Position = projection * view * model * vec4(position, 1.0);gl_PointSize = gl_Position.z;texIn = texture;fragPosIn = vec3(model * vec4(position, 1.0f));normalIn = mat3(transpose(inverse(model))) * normal;
}

看上去比较惊悚,改变了绘制模式为GL_POINTS,着色器修改如上:当顶点距离观察者更远的时候,它就会变得更大,后面的一些粒子效果也是通过这个实现的

gl_VertexID:

上面的gl_Position和gl_PointSize都是输出变量,它们的值是作为顶点着色器的输出被读取的,因此可以向它们写入数据来影响结果,而gl_VertexID是一个输入变量,只能够读取

gl_VertexID是个整型变量,它储存着我们绘制的当前顶点的ID,当进行索引渲染(glDrawElements)时,这个变量保存着当前绘制的顶点的索引,当用的不是索引绘制(glDrawArrays)时,这个变量保存的是从渲染开始起直到当前处理的这个顶点的(当前顶点)编号,目前没什么用

二、片段着色器变量

gl_FragCoord:

在《OpenGL基础29:深度测试》这一章就用过了,只读输入变量vec4,其中x和y为窗口坐标(别忘了openGL默认以左下为原点),其中小数部分恒为(0.5, 0.5),这是因为原点并非(0, 0)而是(0.5, 0.5)的原因,整数部分就是数第几个像素点了,若viewport范围 为(0, 0, 2560, 1440)时, x, y 的取值范围就为(0.5, 0.5, 2559.5, 1439.5);z坐标为当前片元的深度信息,由顶点坐标系处理过后系统插值得到,第4个分量为 1/w

用这个可以实现很多好玩的东西,例如修改之前的天空盒着色器如下:

#version 330 core
in vec3 texIn;
out vec4 color;
uniform samplerCube skybox;
void main()
{if(gl_FragCoord.x < 400)color = vec4(1.0f, 0.0f, 0.0f, 1.0f);elsecolor = texture(skybox, texIn);
}

通过gl_FragCoord,就可以实现类似于分屏的效果,着色器可以给出2个完全不同的效果,一个显示在左半部分,一个显示在右半部分

gl_FrontFacing:

在《OpenGL基础32:面剔除》这一章中,知道了OpenGL如何根据顶点绘制顺序判断一个面是正面还是背面,并在开启面剔除后直接背面直接不进行绘制,而gl_FrontFacing变量正能告诉我们当前片段是某个正面的一部分还是背面的一部分

有了这个之后,就可以对于一个面的正反两面,分别使用不同的纹理或者展现不同的效果

当然了,不要开启面剔除,不然就毫无意义

gl_FragDepth:

上面的gl_FragCoord是只读的,不能修改它的值,而如果你想修改深度值,那么也是OK的,GLSL提供了一个叫做gl_FragDepth的变量,可以用它在着色器中设置像素的深度值

不过一旦设置了gl_FragDepth,OpenGL就会关闭所有的前置深度测试,因为OpenGL并不会知道你会设成什么值

深度测试是在片段着色器已经模板测试执行之后,但是现在大部分的GPU都提供一个叫做提前深度测试(Early Depth Testing)的硬件特性,提前深度测试允许深度测试在片段着色器之前运行,只要清楚一个片段永远不会是可见的(它在其他物体之后),就能提前丢弃这个片段,是一个很不错的优化手段

这样的话,设置gl_FragDepth就会影响OpenGL的性能

一环扣一环,如果我们能保证设置的深度值一定比gl_FragCoord.z更大或者更小,那么其实OpenGL就可以不用关闭前置深度测试因为不影响结果,因此,在OpenGL4.x版本后,它允许我们做个承诺,以保证我们设置的gl_FragDepth值满足一定条件

layout (depth_<condition>) out float gl_FragDepth:condition可以为以下4种之一

  • any:默认值,前置深度测试会被关闭
  • greater:深度值只会比gl_FragCoord.z大
  • less:深度值只会比gl_FragCoord.z小
  • unchanged:

如果发现不能用,说明openGL的版本可能比较低

三、接口块

着色器之间传数据通过 in 和 out 关键字,只需要在当前着色器中声明一个输出,在下一个着色器中声明一个同类型同名字的输入就可以,当然,也可以将一堆数据包在一个“块”里一起传过去,和结构体很像,在这里是接口块(Interface Blocks):

修改之前的着色器,非常简单:

#version 330 core
layout (location = 0) in vec3 position;
layout (location = 1) in vec2 texture;
out VS_OUT
{vec2 texIn;
}param;
uniform mat4 model;             //模型矩阵
uniform mat4 view;              //观察矩阵
uniform mat4 projection;        //投影矩阵
void main()
{gl_Position = projection * view * model * vec4(position, 1.0);param.texIn = texture;
}///#version 330 core
out vec4 color;
in VS_OUT
{vec2 texIn;
}param;
uniform sampler2D texOut;
void main()
{vec4 texColor = texture(texOut, param.texIn);if(texColor.a < 0.1 || (texColor.r < 0.5 && texColor.g < 0.5 && texColor.b < 0.5))discard;color = texColor;
}

传递数据只需要块名一样,不需要实例名相同

OpenGL基础39:GLSL内建变量与接口块相关推荐

  1. OpenGL ES着色器语言之语句和结构体(官方文档第六章)内建变量(官方文档第七、八章)...

    OpenGL ES着色器语言之语句和结构体(官方文档第六章) OpenGL ES着色器语言的程序块基本构成如下: 语句和声明 函数定义 选择(if-else) 迭代(for, while, do-wh ...

  2. arm7汇编中怎么使用c中的变量_MDK-ARM armasm汇编器——内建变量和常量.pdf

    MDK-ARM armasm汇编器--内建变量和常量 Assembler User Guide: Built-in variables and constants Page 1 of 5 Built- ...

  3. awk内建变量示例详解之NR、FNR、NF

    NR表示从awk开始执行后,按照记录分隔符读取的数据次数,默认的记录分隔符为换行符,因此默认的就是读取的数据行数,NR可以理解为Number of Record的缩写. 在awk处理多个输入文件的时候 ...

  4. linux NR==变量,LINUX中详解AWK内建变量FS,NF,NR,RT,RS,ORS,OFS

    看了网上好多关于AWK内建变量的文章,这里加上个人的理解和记忆,可以让大家掌握这些变量的基本用法. FS 指定字段un列分隔符(Font Space) [~/AWK_learning]$ echo & ...

  5. AWK 内建变量FS,NF,NR,FNR,RT,RS,ORS,OFS

      看了网上好多关于AWK内建变量的文章,这里加上个人的理解和记忆,可以让大家掌握这些变量的基本用法. FS 指定字段列分隔符(Font Space) [~/AWK_learning]$ echo & ...

  6. GLSL内置变量和内置函数

    shader内置变量: attribute vec4 gl_Color; // 顶点颜色 attribute vec4 gl_SecondaryColor; // 辅助顶点颜色 attribute v ...

  7. 2-2 内建变量类型

    代码:https://github.com/NIGHTFIGHTING/go_learning/blob/master/src/basic/basic.go package mainimport (& ...

  8. OpenGL基础41:几何着色器

    在顶点着色器之后,片段着色器之前,还有几何着色器,它是可选的,在<OpenGL基础3:渲染管线>这一章中就有提到了,有了几何着色器后可以做很多骚操作,更容易实现很多有意思的效果 一.最简单 ...

  9. OpenGL基础40:Uniform缓冲

    前置:OpenGL基础39:GLSL内建变量与接口块 想想之前代码,glUniform()和glGetUniformLocation()的使用数量是不是过于频繁了,对于每个着色器的每一个uniform ...

最新文章

  1. MySql UBUNTU下复制配置
  2. 笔记-组织级项目管理与大型项目管理-大型及复杂项目
  3. P1351 联合权值
  4. 如何关闭Windows7的UAC
  5. golang 多协程的同步方法总结
  6. YII2 实现后台操作记录日志
  7. Linux下的sniffer工具--Tcpdump的安装和使用
  8. Linux安装caffe问题汇总
  9. 十大硬盘数据恢复软件
  10. 提升效率!技术宅、学生党必备!大学四年使用的几十个高效工具都在这里了
  11. 我的AI之路(52)--如何制作自己的UCF101数据集
  12. 浅谈博客、微博与轻博客的区别与联系
  13. UE TurnInPlace 转身动画的解决方案和常见问题
  14. 腾讯云服务器被黑客攻击的解决办法
  15. 服务器光纤信号灯lan,光纤猫光信号灯不亮怎么办 光纤猫光信号灯不亮解决方法...
  16. Java Swing 课程设计 ---- 实验室设备管理系统
  17. 当前的安全设置不允许从该位置下载文件--解决方法
  18. HTML||从一个页面跳转至另一个html页面的子页面(超链接)
  19. 大数据开发和java的前景_大数据开发和javaEE后端开发哪个就业前景好?
  20. 义乌市python培训

热门文章

  1. python是什么语言-Python是什么?为什么现在越来越多的人选择学习Python语言
  2. 基于python的在线考试系统-Python在线考试系统防作弊功能的思路和实现
  3. 怎么实现语音识别_手机语音识别怎么设置
  4. HTML 制作简历表单
  5. vue实现树形结构增删改查
  6. 怎样选择mysql的版本升级_mysql版本升级
  7. jdbc取款怎样限制条件_京东张亮:我们是怎样打造一款分布式数据库的
  8. python爬虫使用模块_10分钟教你Python爬虫(下)--爬虫的基本模块与简单的实战...
  9. java ognl使用_java框架篇---struts之OGNL详解
  10. layui数据表格格式化