文章目录
第二章 着色器基础
2.1 着色器与OpenGL
- 现代OpenGL渲染管线严重依赖着色器来处理传入的数据
2.2 OpenGL的可编程管线
- 4.3版本的图形管线有4个处理阶段和1个通用计算阶段,每个阶段都由一个专门的着色器控制
- 顶点着色阶段(vertex shading stage)-- 接收你在顶点缓存对象中给出的顶点数据,独立处理每个顶点
- 细分着色器阶段(tessellation shading stage)-- 在OpenGL管线内部生成新的几何体;它会收到来自顶点着色阶段输出的数据,并对收到的顶点进行进一步的处理
- 几何着色阶段(geometry shading stage)-- 在OpenGL管线内部对所有的几何图元进行修改;这个阶段会作用于每个独立的几何图元;此时可以选择从输入图元生成更多的几何体,改变几何图元的类型,或者放弃所有的几何体;如果这个阶段被启用,那么几何着色阶段的输入可能来自顶点着色阶段完成的几何图元的顶点处理之后,也可能来自细分着色阶段生成的图元数据
- 片元着色阶段(fragment shading stage)-- 处理OpenGL光栅化之后生成的独立片元(如果启用了采样着色的模式,就是采样数据);在这个阶段,计算一个片元的颜色和深度值,然后传递到管线的片元测试和混合的模块
- 计算着色阶段(compute shading stage)-- 在程序中相对独立的一个阶段,它处理的数据是应用程序给定的范围的内容;它在应用程序中可以处理其他着色器程序所创建和使用的缓存数据,这其中也包括帧缓存的后处理效果
- in和out变量–这两类变量的值会在OpenGL每次执行着色器的时候更新
- uniform变量–直接从OpenGL应用程序中接收数据,不会随这顶点或者片元的变化而变化,它对于所有几何图元的值都是一样的,除非应用程序对它进行了更新
2.3 OpenGL着色语言概述
2.3.1 使用GLSL构建着色器
从这里出发
- 声明GLSL版本
- 没有返回值的main函数
变量的声明
- 透明类型–float double int uint bool
- 不透明类型–采样器(sampler),图像(image),原子计数器(atomic counter)它们声明的变量相当于一个不透明的句柄,可以用来读取纹理贴图、图像,以及原子计数器数据
变量的作用域
- 全局作用域–在任何函数之外定义
- 局部作用域
变量的初始化
- 所有变量都必须在声明的同时进行初始化
构造函数
- GLSL中可以隐式转换的类型
所需的类型 | 可以从这些类型隐式转换 |
---|---|
uint | int |
float | int uint |
double | int uint float |
- 除上述类型类,其他的数值转换都需要提供显式的转换构造函数
聚合类型
- GLSL的向量类型
基本类型 | 2D向量 | 3D向量 | 4D向量 |
---|---|---|---|
float | vec2 | vec3 | vec4 |
double | dvec2 | dvec3 | dvec4 |
int | ivec2 | ivec3 | ivec4 |
uint | ivec2 | ivec3 | ivec4 |
bool | bvec2 | bvec3 | bvec4 |
- GLSL的矩阵类型
矩阵类型(列x行) |
---|
mat2 mat3 mat4 |
mat2x2 mat2x3 mat2x4 |
mat3x2 mat3x3 mat3x4 |
mat4x2 mat4x3 mat4x4 |
访问向量和矩阵中的元素
- 向量和矩阵中的元素可以单独访问和设置。支持两种类型的元素访问方式:分量的名称和数组访问形式
- 向量分量的访问符
分量访问符 | 符号描述 |
---|---|
( x, y, z, w) | 与位置相关的分量 |
( r, g, b, a) | 与颜色相关的分量 |
( s, t, p, q) | 与纹理坐标相关的分量 |
结构体
- 结构体可以简化多组数据传入函数的过程
- 如果定义了一个结构体,OpenGL会自动创建一个新的类型,并且隐式定义一个构造函数,将各中类型的结构体元素做为输入参数