零、前言
GLSL (OpenGL Shading Language) 是一种 面向过程 高级着色语言,用于图形渲染编程。
使用 GLSL 进行编写顶点着色器和片元着色器,编写两种着色器的语法上没有差异。
一、OpenGL ES 着色器语言简介
GLSL 是基于 C/C++ 基本语法和流程控制的语言,但不支持:双精度浮点数(double)、字节型(byte)、短整型(short)、长整型(long),而且取消联合体(union)、枚举(enum) 。增加了向量(vec) 、矩阵(mat)类型。
二、着色器的结构
以上篇《Hello OpenGL ES! 启航!》中三角形“顶点着色器”和“片元着色器”为例:
顶点着色器
#version 300 es
uniform mat4 uMVPMatrix;
in vec3 aPosition;
in vec4 aColor;
out vec4 vColor;
void main() {
gl_Position = uMVPMatrix * vec4(aPosition, 1.0);
vColor = aColor;
}
片元着色器
#version 300 es
precision mediump float;
in vec4 vColor;
out vec4 fragColor;
void main() {
fragColor = vColor;
}
通过以上代码,可以知道一个着色器程序包括了:
- glsl 版本声明。 如果是 2.0 的版本,可以不用书写该注释。
- 全局变量声明。 这里包括输入和输出变量,着色器内部使用的全局变量等。
- 自定义函数。 我们需要在着色器中调用的函数,上面的着色器很简单所以就没有这一部分(后续会分享如何定义一个着色器函数)。被调用的着色器函数需要在调用函数之前,且定义的函数不可以进行递归调用。
- main 函数。 着色器的入口函数,每个着色器都必须定义,管线会调用该函数驱动逻辑。
二、数据类型
GLSL ES 数据类型:标量、向量、矩阵、采样器、结构体、数组、空类型。
1、标量
描述: 只具有大小,不具有方向的值。例如:质量、体积。
包括:
- bool:布尔型,glsl 的流程控制只能使用布尔类型的值作为表达式。
bool b = true;
- int:有符号 32 位整型。
int a = 15; // 默认为有符号整型
- uint:无符号 32 位整型,需要在整数后增加 “u” 或 “U” ,否则字面常量为有符号整数。
uint b = 3u; // 无符号的类型需要使用 u 或 U 结尾
GLSL ES 整数可以使用十进制、八进制(数字前用数字 0 )、十六进制(数字前用 0x )。
https://registry.khronos.org/OpenGL/specs/es/3.0/GLSL_ES_Specification_3.00.pdf
4.1.3 Integers 有进行描述
// 有符号整数
int signedDec = 123;
int signedOct = 0177;
int signedHex = 0xFF;
// 无符号整数
uint unsignedDec = 123u;
uint unsignedOct = 0177u;
uint unsignedHex = 0xFFu;
- float:浮点型,32 位单精度,可以使用十进制和指数形式表示。
float g = 2.0;
float j = 3e2;
GLSL ES 没有 double 类型,所以不管是否添加 “f” 后缀,小数点形式的数字默认都被视为 float 类型,例如:1.0 和 1.0f 都是 float 类型。
虽然不加 “f” 后缀也能工作,但为了代码一致性或移植性,可以考虑添加 “f” ,添加 “f” 不会导致错误,只是在 GLSL ES 中会显得有些冗余。
2、向量
向量是由相同类型的标量组成,从上一小节知道基本类型分为:bool、int、uint、float 四种,所以向量有以下的类型。
2-1、类型
向量类型 | 说明 |
---|---|
vec2 | 包含了 2 个浮点数的向量 |
vec3 | 包含了 3 个浮点数的向量 |
vec4 | 包含了 4 个浮点数的向量 |
ivec2 | 包含了 2 个整数的向量 |
ivec3 | 包含了 3 个整数的向量 |
ivec4 | 包含了 4 个整数的向量 |
bvec2 | 包含了 2 个布尔数的向量 |
bvec3 | 包含了 3 个布尔数的向量 |
bvec4 | 包含了 4 个布尔数的向量 |
uvec2 | 包含了 2 个无符号整数的向量 |
uvec3 | 包含了 3 个无符号整数的向量 |
uvec4 | 包含了 4 个无符号整数的向量 |
2-2、使用方法
向量在不同场景使用时,表示着不同的含义。可以当作三种场景使用:颜色、位置、纹理坐标,具体每个分量的名称如下所示。
用法 | 4 个分量名 | 3 个分量名 | 2 个分量名 | 使用 |
---|---|---|---|---|
颜色 | r、g、b、a | r、g、b | r、g | aColor.r 或者 aColor[0] |
位置 | x、y、z、w | x、y、z | x、y | aPosition.x 或者 aPosition[0] |
纹理坐标 | s、t、p、q | s、t、p | s、t | aTexColor.s 或者 aTexColor[0] |
GLSL 的向量由硬件原生支持,进行向量运算时是各分量并行一次完成(n 个分量只需要一次计算),效率很高。