更新于 

特殊声明

全局变量与局部变量
  • 全局变量 声明在函数外面
  • 局部变量 声明在函数内部

attribute、varying、uniform变量都必须是全局变量

存储限定字

const变量

const变量声明时 必须进行初始化

1
2
3
4
5
6
const int lightspeed = 299792458;

void main(){
const vec4 red = vec4(1.0,0.0,0.0,1.0);
const mat4 identity = mat4(1.0);
}

试图向const变量赋值 会导致编译报错

1
2
const int lightspeed = w299792458;
lightspeed = 300000000; //error
attribute变量
声明限制
  • 只能出现在 顶点着色器
  • 只能是 全局变量
  • 只能是 浮点、矢量、矩阵 类型
1
2
attribute vec4 a_Color;  
attribute float a_PointSize;
uniform变量
声明限制
  • 只能是 全局变量
  • 只能是 除数组或结构体之外 的任意类型
类型特征
  • uniform变量是 只读的
  • VertexShader和FragmentShader声明的同名uniform变量,会被两个着色器共享
  • uniform变量主要包含适用于 每个顶点/片元 的数据
varying变量
声明限制
  • 只能是 全局变量
  • 需要在两个着色器中 声明同名、同类型 的varying变量
  • 只能是 浮点数、矢量、矩阵 类型
为什么要对varying变量类型进行限制?

答: 顶点着色器的varying值在传给片元着色器的同名同类型varying值时,
经历了 光栅化过程。根据绘制的图形,顶点与顶点之间的片元属性值需要通过内插计算
因此varying变量的数据类型都必须能够进行内插计算。

数量限制

attribute、uniform、varying的数量限制 都与设备有关

精度限定字

所谓精度限定字就是用来表示每种数据具有的精度

为什么要引入精度限定字?

答: 因为需要帮助着色器程序 提高运行效率,削减内存开支
通过使用精度限定字,可以精细地控制程序在效果和性能间的平衡

WebGL程序的精度级别
  • highp 高精度
  • mediump 中精度
  • lowp 低精度

WebGL在低精度下运行结果会比较粗糙或不准确。

数值范围和精度的检查

可以在WebGL环境下使用 gl.getShaderPrecisionFormat() 来检查系统环境的数值范围和精度。

1
2
//WebGLShaderPrecisionFormat{rangeMin: 127, rangeMax: 127, precision: 23}
gl.getShaderPrecisionFormat(gl.VERTEX_SHADER,gl.MEDIUM_FLOAT)
精度声明
声明单个变量的精度
1
2
3
mediump float size; //中精度浮点数
highp vec4 position; //高精度4维矢量
lowp vec4 color; //低精度4维矢量
声明默认精度

默认精度是指 着色器的默认精度
指定类型 的变量其默认精度由 精度限定字 指定,
也即 不以精度限定字修饰该类型变量,其精度就是 默认精度

声明格式

1
precision 精度限定字 类型名称;
着色器默认精度

只有 片元着色器的float类型 没有默认精度。
其它数据类型默认精度如下:

预处理指令

预处理指令是用来在真正编译之前对代码进行预处理的

小例子:检查是否已经定义了GL_ES宏

1
2
3
#ifdef GL_ES
precision mediump float;
#endif
GLSL ES中可能用到的三种预处理指令
1
2
3
#if 条件表达式
条件为真时执行
#endif
1
2
3
#ifdef 某宏
定义了某宏时执行
#endif
1
2
3
#ifndef 某宏
没有定义某宏时执行
#endif
分支预处理
1
2
3
4
5
6
#define NUM 100
#if NUM== 100
NUM==100时执行
#else
NUM!=100时执行
#endif
宏定义
宏定义格式
1
2
#define 宏名 宏内容  // 宏定义
#undef 宏名 //解除宏定义
内置宏

使用内置宏进行精度限制

1
2
3
4
5
6
7
#ifdef GL_ES
#ifdef GL_FRAGMENT_PRECISION_HIGH
precision highp float; //支持高精度
#else
precision mediump float; //不支持高精度
#endif
#endif
#version

是用于指定着色器使用的 GLSL ES版本的。

#version指令必须放在着色器的最顶部。

使用格式

1
#version number

可以接受的版本有:

  • 100 GLSL ES 1.00
  • 101 GLSL ES 1.01

指定GLSL ES版本为1.01

1
#version 101