# GLSL 语法与内建函数

最近一直对Creative Coding
部分很感兴趣,也在不断地探索与学习,在学习WebGL
部分地时候接触到了GLSL
这门美妙且神奇的语言。虽然现在学的还是云里雾里的,但是为了后期方便查询一些 API,在该篇文章中记录一下GLSL
的基本语法以及内建函数。
GLSL
全称为OpenGL Shading Language
,是为了实现着色器的功能而向开发人员提供的一种开发语言,对其只要能理解到这个层次就可以了。
每个 shader 只处理一个像素单元
# GLSL 的修饰符与基本数据类型
# 🌟 修饰符
const
:用于声明非可写的编译时常量变量。attribute
:用于经常更改的信息,只能在顶点着色器中使用。uniform
:用于不经常更改的信息,可用于顶点着色器和片元着色器。varying
:用于修饰从顶点着色器向片元着色器传递的变量。这个修饰符修饰的变量均用于在
Vertex Shader
和Fragment Shader
之间传递参数。首先在顶点着色器中声明这个类型的变量代表纹理的坐标点,并且对这个变量进行赋值,代码如下:attribute vec2 texcoord; varying vec2 v_texcoord; void main(void) { // 计算顶点坐标 v_texcoord = texcoord; }
紧接着在
Fragment Shader
中也声明同名的变量,然后使用texture2D
方法取出二维纹理中该纹理坐标点上的纹理像素值,代码如下(GLSL 代码):varying vec2 v_texcoord; vec4 texel = texture2D(texSampler, v_texcoord);
取出了该坐标点上的像素值之后,就可以进行像素变化操作了,比如说提高对比度,最终将改变的像素值赋值给
gl_FragColor
。
# 🌟 基本数据类型
int
、float
、bool
,这些与 C 语言都是一致的,需要强调的一点就是,这里面的 float 是有一个修饰符的,即可以指定精度。三种修饰符的范围(范围一般视显卡而定)和应用情况具体如下。
highp
:32bit,一般用于顶点坐标(vertex Coordinate)。medium
:16bit,一般用于纹理坐标(texture Coordinate)。lowp
:8bit,一般用于颜色表示(color)。
# 👉 向量类型
向量类型
是 Shader 中非常重要的一个数据类型,在做数据传递的时候需要经常传递多个参数,相较于写多个基本数据类型,使用向量类型是非常好的选择
声明方式如下(GLSL 代码):
attribute vec4 position;//vec4表示四维向量
# 矩阵类型
矩阵类型
在 Shader 的语法中也是一个非常重要的类型,有一些效果器需要开发者传入矩阵类型的数据,比如后面会接触到的怀旧效果器,就需要传入一个矩阵来改变原始的像素数据。声明方式如下(GLSL 代码):
uniform lowp mat4 colorMatrix;//mat4表示4x4的浮点矩阵
# 纹理类型
一般仅在 Fragment Shader 中使用这个类型,二维纹理的声明方式如下(GLSL 代码):
uniform sampler2D texSampler;
当客户端接收到这个句柄时,就可以为它绑定一个纹理,代码如下(客户端代码): glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, texId); glUniform1i(mGLUniformTexture, 0); 注意上述代码中第一行激活的是哪一个纹理句柄,第三行代码中的第二个参数需要传递对应的 Index,就像代码中激活的纹理句柄是 GL_TEXTURE0,对应的 Index 就是 0,如果激活的纹理句柄是 GL_TEXTURE1,那么对应的 Index 就是 1
# 二、GLSL 的内置函数与内置变量
# 🌟 内置变量
# Vertex Shader 的内置变量:
vec4 gl_position
:用来设置顶点转换到屏幕坐标的位置,Vertex Shader 一定要去更新这个数值。float gl_pointSize
:在粒子效果的场景下,需要为粒子设置大小,改变该内置变量的值就是为了设置每一个粒子矩形的大小。
# Fragment Shader 的内置变量:
vec4 gl_FragColor
:用于指定当前纹理坐标所代表的像素点的最终颜色值。
# 🌟 内置函数
abs(genType x)
:绝对值函数。floor(genType x)
:向下取整函数。ceil(genType x)
:向上取整函数。mod(genType x, genType y)
:取模函数。min(genType x, genType y)
:取得最小值函数。max(genType x, genType y)
:取得最大值函数。clamp(genType x, genType y, genType z)
:取得中间值函数。step(genType edge, genType x)
:如果 x < edge,则返回 0.0,否则返回 1.0。smoothstep(genType edge0, genType edge1, genType x)
:如果 x≤edge0,则返回 0.0;如果 x≥edge1,则返回 1.0;如果 edge0 < x < edge1,则执行 0 ~ 1 之间的平滑差值。mix(genType x, genType y, genType a)
:返回线性混合的 x 和 y,用公式表示为:x*(1-a)+y*a,这个函数在 mix 两个纹理图像的时候非常有用。