opengl之高级GLSL(1)-顶点着色器变量与片段着色器变量
官方教程位置
openglCN
GLSL的内建变量:
- 我们已经学会使用顶点属性、uniform和采样器来完成这一任务了。然而,除此之外,GLSL还定义了另外几个以gl_为前缀的变量,它们能提供给我们更多的方式来读取/写入数据。我们已经在前面教程中接触过其中的两个了:顶点着色器的输出向量gl_Position,和片段着色器的gl_FragCoord。
顶点着色器变量
- List item我们已经见过gl_Position了,它是顶点着色器的裁剪空间输出位置向量。如果你想在屏幕上显示任何东西,在顶点着色器中设置gl_Position是必须的步骤。这已经是它的全部功能了。
- gl_PointSize:
我们能够选用的其中一个图元是GL_POINTS,如果使用它的话,每一个顶点都是一个图元,都会被渲染为一个点。我们可以通过OpenGL的glPointSize函数来设置渲染出来的点的大小,但我们也可以在顶点着色器中修改这个值。
GLSL定义了一个叫做gl_PointSize输出变量,它是一个float变量,你可以使用它来设置点的宽高(像素)。在顶点着色器中修改点的大小的话,你就能对每个顶点设置不同的值了。
在顶点着色器中修改点大小的功能默认是禁用的,如果你需要启用它的话,你需要启用OpenGL的GL_PROGRAM_POINT_SIZE:
glEnable(GL_PROGRAM_POINT_SIZE);
//一个简单的例子就是将点的大小设置为裁剪空间位置的z值,也就是顶点距观察者的距离。点的大小会随着观察者距顶点距离变远而增大。
//结果就是,当我们远离这些点的时候,它们会变得更大
void main()
{gl_Position = projection * view * model * vec4(aPos, 1.0); gl_PointSize = gl_Position.z;
}
gl_VertexID (目前没有什么具体用途)
gl_Position和gl_PointSize都是输出变量,因为它们的值是作为顶点着色器的输出被读取的。我们可以对它们进行写入,来改变结果。顶点着色器还为我们提供了一个有趣的输入变量,我们只能对它进行读取,它叫做gl_VertexID。整型变量gl_VertexID储存了正在绘制顶点的当前ID。当(使用glDrawElements)进行索引渲染的时候,这个变量会存储正在绘制顶点的当前索引。当(使用glDrawArrays)不使用索引进行绘制的时候,这个变量会储存从渲染调用开始的已处理顶点数量。
虽然现在它没有什么具体的用途,但知道我们能够访问这个信息总是好的。
片段着色器变量
gl_FragCoord:
我们已经见过gl_FragCoord很多次了,因为gl_FragCoord的z分量等于对应片段的深度值。然而,我们也能使用它的x和y分量来实现一些有趣的效果。gl_FragCoord的x和y分量是片段的窗口空间(Window-space)坐标,其原点为窗口的左下角。我们已经使用glViewport设定了一个800x600的窗口了,所以片段窗口空间坐标的x分量将在0到800之间,y分量在0到600之间。
通过利用片段着色器,我们可以根据片段的窗口坐标,计算出不同的颜色。gl_FragCoord的一个常见用处是用于对比不同片段计算的视觉输出效果,这在技术演示中可以经常看到。比如说,我们能够将屏幕分成两部分,在窗口的左侧渲染一种输出,在窗口的右侧渲染另一种输出。下面这个例子片段着色器会根据窗口坐标输出不同的颜色:
你可以将它用于测试不同的光照技巧。
void main()
{ if(gl_FragCoord.x < 400)FragColor = vec4(1.0, 0.0, 0.0, 1.0);elseFragColor = vec4(0.0, 1.0, 0.0, 1.0);
}
自己代码效果:x小于400才进行光的反射渲染,注意X值随着角度发生改变
gl_FrontFacing:段着色器另外一个很有意思的输入变量是gl_FrontFacing。在面剔除教程中,我们提到OpenGL能够根据顶点的环绕顺序来决定一个面是正向还是背向面。如果我们不(启用GL_FACE_CULL来)使用面剔除,那么gl_FrontFacing将会告诉我们当前片段是属于正向面的一部分还是背向面的一部分。举例来说,我们能够对正向面计算出不同的颜色。
gl_FrontFacing变量是一个bool,如果当前片段是正向面的一部分那么就是true,否则就是false。比如说,我们可以这样子创建一个立方体,在内部和外部使用不同的纹理:
#version 330 core
out vec4 FragColor;in vec2 TexCoords;uniform sampler2D frontTexture;
uniform sampler2D backTexture;void main()
{ //注意这里使用了 gl_FrontFacing来进行正反面判断if(gl_FrontFacing)FragColor = texture(frontTexture, TexCoords);elseFragColor = texture(backTexture, TexCoords);
}
gl_FragDepth:输入变量gl_FragCoord能让我们读取当前片段的窗口空间坐标,并获取它的深度值,但是它是一个只读(Read-only)变量。我们不能修改片段的窗口空间坐标,但实际上修改片段的深度值还是可能的。GLSL提供给我们一个叫做gl_FragDepth的输出变量,我们可以使用它来在着色器内设置片段的深度值。
要想设置深度值,我们直接写入一个0.0到1.0之间的float值到输出变量就可以了
gl_FragDepth = 0.0; // 这个片段现在的深度值为 0.0
如果着色器没有写入值到gl_FragDepth,它会自动取用gl_FragCoord.z的值。
然而,由我们自己设置深度值有一个很大的缺点,只要我们在片段着色器中对gl_FragDepth进行写入,OpenGL就会(像深度测试小节中讨论的那样)禁用所有的提前深度测试(Early Depth Testing)。它被禁用的原因是,OpenGL无法在片段着色器运行之前得知片段将拥有的深度值,因为片段着色器可能会完全修改这个深度值。
在写入gl_FragDepth时,你就需要考虑到它所带来的性能影响。然而,从OpenGL 4.2起,我们仍可以对两者进行一定的调和,在片段着色器的顶部使用深度条件(Depth Condition)重新声明gl_FragDepth变量:
layout (depth_<condition>) out float gl_FragDepth;
通过将深度条件设置为greater或者less,OpenGL就能假设你只会写入比当前片段深度值更大或者更小的值了。这样子的话,当深度值比片段的深度值要小的时候,OpenGL仍是能够进行提前深度测试的。
下面这个例子中,我们对片段的深度值进行了递增,但仍然也保留了一些提前深度测试:
#version 420 core // 注意GLSL的版本!
out vec4 FragColor;
layout (depth_greater) out float gl_FragDepth;void main()
{ FragColor = vec4(1.0);gl_FragDepth = gl_FragCoord.z + 0.1;
}
opengl之高级GLSL(1)-顶点着色器变量与片段着色器变量相关推荐
- opengl之高级GLSL(2)-接口块,Uniform缓冲对象,Uniform块布局等
接口块 当程序变得更大时,你希望发送的可能就不只是几个变量了,它还可能包括数组和结构体. 为了帮助我们管理这些变量,GLSL为我们提供了一个叫做接口块(Interface Block)的东西,来方便我 ...
- 第二十二章 opengl之高级OpenGL(几何着色器)
OpenGL 使用几何着色器 用点造物体 爆破物体 法向量可视化 在顶点和片段着色器之间有一个可选的几何着色器(Geometry Shader), 几何着色器的输入是一个图元(如点或三角形)的一组顶点 ...
- OpenGL高级-GLSL
引言 我们会讨论一些内建变量(Built-in Variable).组织着色器输入和输出的新方式以及一个叫做uniform缓冲对象(Uniform Buffer Object)的非常有用的工具. G ...
- Learn OpenGL(四)——片段着色器(Fragment Shader)
片段着色器(Fragment Shader) 片段着色器是第二个也是最终我们打算创建的用于渲染三角形的着色器. 片段着色器的全部, 都是用来计算你的像素的最后颜色输出. 为了让事情比较简单, 我们的片 ...
- 顶点与片段着色器的例子
视窗坐标 Shader "Custom/WindowCoordinates/Base" {SubShader {Pass {CGPROGRAM#pragma vertex vert ...
- LearnOpenGL-高级OpenGL-8.高级GLSL
本人初学者,文中定有代码.术语等错误,欢迎指正 文章目录 高级GLSL GLSL的内建变量 在顶点着色器的内建变量 gl_PointSize gl_VertexID 在片段着色器的内建变量 gl_Fr ...
- 【OpenGL】高级片段着色器——在片段着色器中生成图像数据茹利亚集Julia set
茹利亚集:z(n) = z(n-1)^2 + c , z是顶点纹理坐标,c是统一值,片段着色器会迭代最大max_iterations次,其中若z值大于阈值threshold_squared则跳出,其迭 ...
- OpenGL 高级GLSL(Advanced GLSL)
OpenGL 高级GLSL OpenGL 高级GLSL简介 GLSL的内建变量 顶点着色器变量 片段着色器变量 接口块 Uniform缓冲对象 Uniform块布局 使用Uniform缓冲 一个简单的 ...
- QT+OpenGL高级数据和高级GLSL
QT+OpenGL高级数据和高级GLSL 本篇完整工程见gitee:QtOpenGL 对应点的tag,由turbolove提供技术支持,您可以关注博主或者私信博主 高级数据 OpenGL中的缓冲区 对 ...
最新文章
- Keras vs PyTorch,哪一个更适合做深度学习?
- 微服务架构10个最重要的设计模式
- RIPv1和v2综合实验(CCNP阶段)
- 2410Init.s
- Java笔记-使用jjwt生成jwt
- Spring整合Quartz实现持久化、动态设定时间
- Material UI 4.10 Skeleton 骨架
- 用Java写一个浪费cpu的程序_Java程序是如何浪费内存的
- idea 2019最新版无法打开报错问题,Error occurred during initialization of VM Initial heap size set to a larger va
- SAP 服务器文件上传和下载
- 有哪些写项目策划书注意事项
- 记TUP对话大师系列之-Jeffery Richter
- 南京周边城市两日游方案
- 2021年蓝桥杯CC++大学B组
- 20V,30V,40V输入的LDO稳压芯片
- Opencv实战(二) 文字区域的提取 (VS2013 + C++)
- 前端开发——在线工具推荐
- 【户外之上,磨房之下系列】20190829强烈要求做单的依梅同学
- vimdesktop --goreliu 版本配置
- PTA 10-53 查询部分专业的学生
热门文章
- VBS创建二进制文件的两种方法
- SUSE Linux – Zypper 命令示例
- yolov3 训练自己的数据集 手把手教学 ubuntu 18.04 显卡1650 显存4g 跟着操作做保证学会
- ubuntu18.04 Intel NUC 配置开启VNC
- lichee pi zero 荔枝派zero uboot编译 烧录
- GPS坐标转UTM坐标
- npm报错:Error: EPERM: operation not permitted, uv_cwd
- ES9已经来了 Are you ready?
- 一个房地产商真实告白:老百姓为什么买不起房子?
- 17092601_CentOS7(64)下Oracle11g设置开机自启动