数据类型
着色语言有许多内置原生数据类型以及构建数据类型。这些数据类型可以分为标量、向量、矩阵、采样器、结构体以及数组等几类。
数据类型 | 表示 | 分类 |
---|---|---|
浮点型 | float | 标量 |
布尔型 | bool | 标量 |
有符号整型 | int | 标量 |
无符号整型 | uint | 标量 |
矩阵型 | matrix | 矩阵 |
向量型 | vec2、vec3等 | 向量 |
标量
标量由常见数据类型组成,不过多阐述。需要注意的是GLSL支持uint无符号整型。
向量
向量分量有两种使用方式:1、<向量名>.<分量名>;2、<向量名>[position]。 不但可以通过分量名称set-get,同时可以像数组一样通过下标获取分量。
向量类型 | 说明 |
---|---|
vec2 | 包含2个浮点数的向量 |
vec4 | 包含4个浮点数的向量 |
ivec2 | 包含2个整数的向量 |
ivec4 | 包含4个整数的向量 |
bec2 | 包含2个布尔数的向量 |
bec4 | 包含4个布尔数的向量 |
uvec2 | 包含2个无符号整数的向量 |
uvec4 | 包含4个无符号整数的向量 |
矩阵
矩阵主要运用在3D场景中的移位、旋转、缩放等变换。因此,OpenGL ES着色语言中也提供了对矩阵类型的支持也方便了开发快速创建矩阵。
矩阵类型 | 说明 |
---|---|
mat2 | 2x2浮点数矩阵 |
mat4 | 4x4浮点数矩阵 |
mat3x2 | 3x2浮点数矩阵 |
mat3x4 | 3x4浮点数矩阵 |
mat4x3 | 4x3浮点数矩阵 |
矩阵是按列顺序组织的,可以比作几个列向量组成。因此矩阵分量获取形式可以是二维数组的获取形式。
采样器
采样器类型 | 说明 |
---|---|
sampler2D | 用于访问浮点型二维纹理 |
sampler3D | 用于访问浮点型三维纹理 |
samplerCube | 用于访问浮点型的立方贴图纹理 |
samplerCubeShadow | 用于访问浮点型的立方阴影纹理 |
sampler2DShadow | 用于访问浮点型的二维贴图纹理 |
sampler2DArray | 用于访问浮点型的2D纹理数组 |
sampler2DArrayShadow | 用于访问浮点型的2D阴影纹理数组 |
isampler2D | 用于访问整型二维纹理 |
isampler3D | 用于访问整型三维纹理 |
isampler... | 用于访问整型系列的相关纹理(同上) |
usampler... | 用于访问无符号整型系列的相关纹理(同上) |
一般情况下采样器变量都用uniform限定符来修饰,采样器变量也可以用作函数的参数,但是作为函数参数时不可以使用out或inout修饰符来修饰。
结构体
着色语言结构体类似于C语言中的自定义结构体。
struct info{
vec3 color;
vec3 position;
vec2 textureCoor;
}
数据类型使用
- 变量的声明及作用域与C++语法类似:分为局部变量与全局变量。
- 由于系统中有很多内建变量都是以“gl_”作为开头,开发者自定义变量不能以“gl_”作为开头。
- 向量和矩阵的初始化。
vec2 va = vec2(2.3,2.5);
vec3 vb = vec3(va,2.5);
vec4 vc1 = vec4(va,va); // 可以用两个vec2向量赋值
vec4 vc2 = vec4(2.0);// 向量每个分量都是2.0
vec3 vb2 = vec3(vc2);// 可以用vec4向量赋值,抛弃vec4最后一个分量
mat2 ma2 = mat2(0.1,0.2,0.3,0.4);
vec3 vb1 = vec3(2.1,2.5);
vec3 vb2 = vec3(2.2,2.5);
vec3 vb3 = vec3(2.3,2.5);
mat3 ma3 = mat3(vb1,vb2,vb3); //可以用三个vec3向量赋值
mat4 ma4 = mat4(vb1,vb2,vb3);
vec2 ve2 = vec2(2.1,2.5);
mat4x2 ma4_2 = mat4x2(ve2,ve2,ve2,ve2);
mat2x3 ma2_3 = mat2x3(ma4_2); //用ma4_2赋值,一列是三个分量,缺失的用0补齐,结果为[2.1,2.5,0,2.1,2.5,0]
mat2x2 ma2_2 = mat2x2(0.1); // 矩阵不填充所有值 结果为[0.1,0,0.1,0]
运算符
运算符与其他编程语言大同小异,没有特别语法糖设定,基本和常用编程语言一致。
运算符 | 说明 | |||
---|---|---|---|---|
() | 括号分组 | |||
++ -- | 自加1 自减1 | |||
+ - ~ ! | 一元运算符 | |||
+ - * / % | 加 减 乘 除 求余 | |||
<> <= >= | 关系运算符 | |||
& | ^ && | 与 或 异或 | ||
?: | 选择 | |||
%= <<= >>= &= ^= | = | 赋值运算 | ||
[] | 数组下标 | |||
>> << | 位运算 | |||
== != | 等于 不等于 |
- 着色语言对于类型匹配要求严格,赋值表达式中的两个操作数类型必须完全相同。
- 类型转换只能通过构造函数实现。
float f = 1.0;
bool b = bool(f); // 非0是true,其他是false
float f1 = float(b); // true是1.0,false是0.0
int i = int(f1); // 去掉小数部分
float f2 = 1; // 属于语法错误
限定符
限定符 | 说明 |
---|---|
const | 声明常量 |
in | 一般声明着色器输入变量 |
out | 一般声明着色器输出变量 |
uniform | 一般声明采样器或是一组顶点组成的单个3D物体所有顶点相同的量 |
插值限定符
插值(interpolation)限定符,其主要用于控制顶点着色器传递到片元着色器数据的插值方式。
插值限定符 | 说明 |
---|---|
smooth | 默认插值类型,以平滑方式插值得到片元输入变量 |
flat | 不对片元输入变量进行插值,直接使用特定值代替 |
layout限定符
layout限定符是从OpenGL ES 3.0开始出现的,其主要用于设置变量的存储索引(即引用)值。
<layout限定符> uniform
<layout限定符> <接口限定符> <变量声明>
场景应用如下
layout (location=0) in vec3 aPosition; // 输入变量的引用值为0
layout (location=2) in vec3 aColor;
layout (location=3) out vec3 aPosition2;
layout (location=4) out vec3 aColor2;
流程控制
流程控制大致上就是常见的条件判断、循环、中断等操作。基本关键字:if-else、switch、while、do-while、for、break、countinue。
GLSL内建变量
除了开发者自己使用变量外,在着色器中还有一些内置变量。这些内置变量不需要开发者声明即可使用。内建变量也分为输入量和输出量,输入量负责将渲染管线的固定信息传递给着色器,输出量负责着色器产生的信息传递给渲染管线。
内建输入变量
- gl_VertexID 顶点着色器的一个内建输入变量,类型为“highp int”
- gl_InstanceID 顶点着色器的一个内建输入变量,类型为“highp int”
内建输出变量
- gl_Position 顶点坐标,顶点着色器从渲染管线中获得原始的顶点位置数据,类型是vec4。
- gl_PointSize 点的大小,顶点着色器中可以计算一个点的大小(单位为像素)
这里只举例了个别内建变量,实际内建变量不只这些。另外除了内建变量外还有内建常量等,有兴趣可以通过GLSL语法书第七节[Built-in Variables]查找更多。
着色语言内置函数
内建变量、内建常量外,GLSL还提供了许多内置函数为开发带来方便。数学函数中常用方法基本都有:正弦函数、余弦函数、正切函数、角度转弧度、弧度转角度等。同样可通过第八节Built-in Functions查看更多。
编写GLSL代码
最后回到开篇时贴出的着色器代码注释内容。
顶点着色器vsh文件
aPosition是坐标输入量,使用的是vec3,在gl_Position内置变量赋值时通过vec4计算出16个顶点位置。 aColor是点颜色输入量,使用的是vec4,正好是16个点的颜色。 gl_PointSize是内置变量,设置点大小。
#version 300 es
layout (location = 0) in vec3 aPosition; //顶点位置
layout (location = 1) in vec4 aColor; //顶点颜色
out vec4 vColor; //用于传递给片元着色器的变量
void main()
{
gl_Position = vec4(aPosition,1); //根据总变换矩阵计算此次绘制此顶点位置
vColor = aColor;//将接收的颜色传递给片元着色器
gl_PointSize = 10.0;//点大小
}
片元着色器fsh文件
输入vColor给输出fragColor赋值,这里的fragColor就是内置变量gl_FragColor。 这里的vColor就是顶点着色器代码中输入的vColor。
#version 300 es
precision mediump float;
in vec4 vColor; //接收从顶点着色器过来的参数
out vec4 fragColor;//输出到的片元颜色
void main()
{
fragColor = vColor;//给此片元颜色值
}
参考
- 《OpenGL ES 3.x游戏开发》
- The OpenGL ES Shading Language