4.1 OpenGL ES 语言基础
4.1.1 语言基础
1、大小写敏感
着色器语言对于大小写是敏感的,例如aPosition与aposition就是两个变量。
2、强制分号
它每一句语法的最后必须要使用分号结尾,如果漏写会导致程序报错无法执行。
4.1.2 程序入口
着色器语言通过main函数作为程序入口,且没有任何返回值。
4.1.3 注释
在JavaScript中,单行注释使用//,多行注释使用/**/。OpenGL跟JavaScript是一致的。
4.1.4 强类型语言
变量的使用和赋值必须是相同类型,需要时刻注意变量的类型。
// 顶点着色器
const VERTEX_SHADER_SOURCE = `
void main() {
float f = 10.0;
int i = 10;
bool b = true;
}
`;
4.1.5 变量声明
1、数字字母下划线
2、不能是关键字或保留字
3、不能以数字开头
4、不能以gl_、webgl_、_webgl_作为开头
4.1.6 类型和类型转换
1、int():转为整型
2、float():转为浮点型
3、bool():转为布尔型
4.1.7 运算符
4.2 矢量和矩阵
4.2.1 矢量
1、矢量类型
(1)vec2、vec3、vec4具有2、3、4个浮点数元素的矢量
(2)ivec2、ivec3、ivec4具有2、3、4个整型元素的矢量
(3)bvec2、bvec3、bvec4具有2、3、4个布尔值元素的矢量
2、赋值
需要通过构造函数来进行赋值
vec4 position = vec4(0.0, 0.0, 0.0, 1.0); // vec4 就是矢量的构造函数
3、访问矢量里的分量
(1)获取单个分量
vec4 position = vec4(0.1, 0.2, 0.3, 1.0);
position.x // 0.1
position.y // 0.2
position.z // 0.3
(2)获取多个分量
可以通过混合的方式获取多个值,获取到的是一个新的矢量内容。
vec4 position = vec4(0.1, 0.2, 0.3, 1.0);
position.xy // vec2(0.1, 0.2)
position.yx // vec2(0.2, 0.1)
position.zyx // vec3(0.3, 0.2, 0.1)
4.2.2 矩阵
1、矩阵类型
mat2、mat3、mat4对应22、33、4*4的浮点数元素矩阵
2、赋值
矩阵入参,注意:矩阵参数是列主序的
mat4 m = mat4(
1.0, 5.0, 9.0, 13.0,
2.0, 6.0, 10.0, 14.0,
3.0, 7.0, 11.0, 15.0,
4.0, 8.0, 12.0, 16.0
)
4.3 纹理取样器
1、取样器有两种:sampler2D和samplerCube
2、只能声明为uniform变量
// 声明二维纹理
uniform sampler2D uSampler;
// 声明立方体纹理
uniform samplerCube uSamplerCube;
3、二维纹理使用
// 创建纹理对象
const texture = gl.createTexture();
// 翻转图片Y轴
gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, 1);
// 开启一个纹理单元
gl.activeTexture(gl.TEXTURE0);
// 绑定纹理对象
gl.bindTexture(gl.TEXTURE_2D, texture);
// 处理放大缩小的逻辑
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
// 横向 纵向 平铺的方式
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
// 配置纹理图像
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGB, gl.RGB, gl.UNSIGNED_BYTE, img);
gl.uniform1i(uSampler, 0);
4、立方体纹理使用
立方体纹理的使用流程跟二维很类似,区别是gl.TEXTURE_2D变成了gl.TEXTURE_CUBE_MAP,二维只需要处理1个面,立方体需要处理6个面。
// 创建纹理对象
const cubeMap = gl.createTexture();
// 翻转图片Y轴
gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, true);
// 开启一个纹理单元
gl.activeTexture(gl.TEXTURE1);
// 绑定纹理对象
gl.bindTexture(gl.TEXTURE_2D, cubeMap);
// 处理放大缩小的逻辑
gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
// 横向 纵向 平铺的方式
gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
// 配置纹理图像
gl.texImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_Z, 0, gl.RGB, gl.RGB, gl.UNSIGNED_BYTE, images[0]);
gl.texImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_Z, 0, gl.RGB, gl.RGB, gl.UNSIGNED_BYTE, images[1]);
gl.texImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_X, 0, gl.RGB, gl.RGB, gl.UNSIGNED_BYTE, images[2]);
gl.texImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_X, 0, gl.RGB, gl.RGB, gl.UNSIGNED_BYTE, images[3]);
gl.texImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_Y, 0, gl.RGB, gl.RGB, gl.UNSIGNED_BYTE, images[4]);
gl.texImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_Y, 0, gl.RGB, gl.RGB, gl.UNSIGNED_BYTE, images[5]);
gl.uniform1i(uSampler, 0);
4.4 分支和循环
1、分支逻辑
if() {} 和 if() {} else {}
2、循环语句
for() {}
while() {}
do {} while()
3、跳出循环
continue
break
discard:只能在片元着色器中使用,因为着色器是逐个片元来处理的,discard表示放弃当前片元直接处理下一个片元
4.5 函数
1、函数返回值
如果函数需要返回值,那么在函数名前面定义返回类型;如果不需要返回,则在函数名前添加void关键字。
// 主函数不需要返回值
void main() {}
// 需要返回float类型的值
float getFloat() {
return 10.0;
}
2、函数传参
函数接收参数也要定义好类型。
// 函数传参接参
float getFloat(float x, int y) {
return 10.0;
}
getFloat(10.0, 1);
4.6 内置函数介绍
GLSL ES里提供了较多的内置函数,可以直接使用。
4.7 存储限定词
4.7.1 const
声明一个常量,定义之后不能被改变。
4.7.2 attribute
只能出现在顶点着色器中,只能声明为全局变量,表示顶点信息。
4.7.3 uniform
1、可同时出现在顶点着色器和片元着色器中
2、只读类型,强调一致性
3、用来存储的是影响所有顶点的数据,如变换矩阵
4.7.4 varying
从顶点着色器向片元着色器传递数据,需要同时在顶点着色器和片元着色器声明相同的类型和变量名。
4.7.5 精度限定
1、提升运行效率,削减内存开支
2、可以单独针对某个变量声明精度
mediump float f;
3、劣势:会出现精度歧义,也不利于后期维护
例如在使用f的时候,需要将f的精度转为高精度,这样就会出现精度的歧义,也有可能忘记转换精度,出现一些意想不到的效果,而且也不利于维护。
4、通过precision关键字来修改着色器的默认精度
precision mediump float;
4.7.6 精度使用场景
片元着色器中的float类型没有默认精度,所以如果需要在片元着色器中使用浮点型数据的时候,需要修改默认精度。