在进入三维世界前,我们先看看三维世界的基石吧,这一篇得先看看什么是着色器,知道着色器语言怎么读和写,这样在之后的三维渲染中更加容易理解。
GLSL ES(OpenGL ES Shading Language)是一种编写着色器程序的语言,用于在OpenGL ES图形API中实现高度定制化的渲染效果。它是基于C语言,它支持向量和矩阵运算、纹理采样、光照计算等操作,可以用于在图形渲染管线中实现各种各样的渲染效果。
在之前的篇章中,每个例子中都会设计两个着色器,顶点着色器和片元着色器,顶点着色器负责将顶点转换到屏幕坐标系中,而片段着色器则计算每个像素的颜色值。
强类型语言
GLSL ES是强类型语言,"强类型语言"指的是编程语言中对变量和表达式的类型进行严格检查的语言,相对于js弱类型语言,这就得在声明变量的时候指出其数据类型了,且该类型不能被隐式转换为其他类型。
基本数据类型
- 数值类型: 整数型和浮点型
- 布尔值类型: true和false
基本类型
| 类型 | 描述 |
|---|---|
| float | 单精度浮点类型 |
| int | 整数型 |
| bool | 布尔型, true、false |
类型转换
既然是强类型语言,那么类型转换就不能简单的用再次赋值来了,得用内置函数了
| 转换 | 函数 | 描述 |
|---|---|---|
| 转换为整数型 | int(number) | 小数点和后面的数截掉; true转换成1 |
| 转换为浮点数 | float(number) | float(8) => 8.0; float(true) => 1.0 |
| 转换为布尔值 | bool(number) | bool(1.0) => true |
矢量和矩阵
- 矢量是一组有序的实数,可以表示一个点、向量、颜色等。
- 矩阵是一个二维数组,可以用于表示变换矩阵、投影矩阵、纹理矩阵等。
数据类型
| 类别 | 数据类型 | 描述 |
|---|---|---|
| 矢量 | (/i/b)vec(2/3/4) | 具有(2/3/4)个(浮点数/整数型/布尔值)元素的矢量 |
| 矩阵 | mat2、mat3、 mat4 | 2x2、3x3、4x4的浮点数元素的矩阵 |
矢量
vec2 v2 = vec2(1.0, 2.0);
vec4 v4 = vec4(1.0);
矩阵
在WebGL中,矩阵中是以列主序排列的
mat4 m4 = mat4(
1, 2, 3, 4,
5, 6, 7, 8,
1, 2, 3, 4,
5, 6, 7, 8,
);
那么m4就是
那么m4[0] = ?
由于m4是GLSL ES语言中的以列主序的矩阵,那么就是第一列的数据[1, 2, 3, 4]
访问元素
| 类别 | 描述 |
|---|---|
| x, y, z, w | 用来获取顶点坐标分量 |
| r, g, b, a | 用来获取颜色分量 |
| s, t, p, q | 用来获取纹理坐标分量 |
vec3 v3 = vec3(1.0, 2.0, 3.0);
float f;
f = v3.x;
vec2 v2;
v2 = v3.yz; // (2.0, 3.0)
v2 = v3.xx; // (1.0, 1.0)
这里从同一个集合中抽取多个分量,就可以获取某个分量的值,并进行赋值。
取样器
在 WebGL 中,取样器使用 sampler2D 类型表示,它可以被声明为一个 uniform 变量,并且可以在着色器中使用。
precision mediump float;
varying vec2 v_texCoord;
uniform sampler2D u_texture;
void main() {
gl_FragColor = texture2D(u_texture, v_texCoord);
}
首先在顶点着色器中声明了一个 varying 变量 v_texCoord,用于在顶点着色器和片元着色器之间传递纹理坐标信息。然后在片元着色器中声明了一个 uniform 变量 u_texture,它是一个取样器类型的变量,用于访问纹理。最后,在片元着色器中使用 texture2D() 函数对纹理进行采样,并将采样结果赋值给 gl_FragColor,用于输出颜色。
存储限定字
存储限定字(Storage Qualifier)是用于指定变量存储方式的关键字。存储限定字可以用于在内存中指定变量的存储位置、生命周期和可访问性等信息。
const
表示该变量的值不能被改变
Attribute
attribute变量只能出现在顶点着色器中,并且只能被声明为全局变量,被用来表示逐顶点的信息
uniform
uniform变量可以用在顶点着色器和片元着色器中,并且必须是全局变量。uniform变量是只读的,如果顶点着色器和片元着色器中声明了同名的uniform变量,那么它就会被两种着色器共享。
varying
varying变量必须是全局变量,它的作用是从顶点着色器向片元着色器中传输数据。
in
用于声明片元着色器的输入变量
out
用于声明片元着色器的输出变量
精度限定字
精度限定字,目的是帮助着色器程序提高运行效率,减少内存的开支。
| 精度限定字 | 描述 | Float | int |
|---|---|---|---|
| highp | 高精度 | (-2^62, 2^62 ) | (-2^16, 2^16 ) |
| mediump | 中精度 | (-2^14, 2^14 ) | (-2^10, 2^10 ) |
| lowp | 低精度 | (-2, 2) | (-2^8, 2^8 ) |
小结
- 数据类型:GLSL ES 支持的基本数据类型包括 float、int、bool、vec2、vec3、vec4、mat2、mat3、mat4 等。与 GLSL 不同的是,GLSL ES 中没有双精度浮点数类型 double。
- 着色器类型:GLSL ES 支持的着色器类型包括顶点着色器、片元着色器、几何着色器和计算着色器。与 GLSL 不同的是,GLSL ES 中不支持外壳着色器和细分着色器。
- 内置变量和函数:GLSL ES 中内置了一些变量和函数,例如 gl_Position、gl_FragColor、texture2D 等。与 GLSL 不同的是,GLSL ES 中的内置变量和函数有所不同,且数量较少。
- 存储限定字:GLSL ES 中的存储限定字包括 const、attribute、uniform、varying、in、out 等,用于指定变量的存储方式和生命周期等信息。
- 精度修饰符:GLSL ES 中的精度修饰符包括 highp、mediump 和 lowp,用于指定浮点数的精度。与 GLSL 不同的是,GLSL ES 中的默认精度为 mediump。
- 预处理指令:GLSL ES 中支持的预处理指令包括 #define、#ifdef、#ifndef、#else、#endif 等,用于在编译前进行宏替换和条件编译等操作。
- 控制流语句:GLSL ES 中支持的控制流语句包括 if、else、while、for、do-while 等,用于实现程序的逻辑控制和循环操作。
- 内置变量和函数:GLSL ES 中内置了一些变量和函数,例如 gl_Position、gl_FragColor、texture2D 等。与 GLSL 不同的是,GLSL ES 中的内置变量和函数有所不同,且数量较少。