void main()
{
}
GLSL支持三种数据类型:
GLSL是强类型语言,这意味着:
// 会报错,错误信息如下:
// Failed to compile shader: ERROR: 0:56: '=' :
// cannot convert from 'const int' to 'mediump float'
float a1 = 1;
// 会报错,错误信息如下:
// Failed to compile shader: ERROR: 0:56: '=' :
// cannot convert from 'const float' to 'mediump int'
int a1 = 1.0;
// 会报错
// Failed to compile shader: ERROR: 0:57: '*' :
// wrong operand types - no operation '*' exists that
// takes a left-hand operand of type 'mediump float'
// and a right operand of type 'const int'
float a1 = 1.0;
float a2 = a1 * 3;
虽然GLSL是强类型语言,但是我们可以通过显示转换实现数据类型的转变,比如我们可以使用float()将数据类型转换为浮点数,GLSL支持float、int和bool的相互转换
// 将整数转换为浮点数
float(int)
// true被转换为1.0 false被转换为0.0
float(bool)
// 将浮点数的小数删去,整数部分转换为整型
int(float)
// true被转换为1 false被转换为0
int(bool)
// 0.0被转换为false,其他值转换为true
bool(float)
// 0被转换为false,其他值转换为true
bool(int)
GLSL可以通过基本数值类型组合成矢量和矩阵,矢量的数据类型可以是浮点数,整数和bool值,但是矩阵WebGL1.0只支持浮点数
在给矢量或者矩阵赋值的时候,必须遵循:
访问矢量和矩阵可以有两种方式,一种是通过.
运算符,一种是通过[]
使用点运算符访问有三种访问方式:
x,y,z,w
:分别对应矢量的第1、2、3、4个分量,注意:矩阵是不能用该方式访问的
r,g,b,a
:分别对应矢量的第1、2、3、4个分量,注意:矩阵是不能用该方式访问的
s,t,p,q
:分别对应矢量的第1、2、3、4个分量,注意:矩阵是不能用该方式访问的
对于每一种访问方式,都可以混合使用,比如:
// 下面这些访问方式都是正确的
vec4 a1 = vec4(1.0, 1.1, 1.2, 1.3);
float b1 = a1.x;
vec2 c1 = a1.xy;
vec2 d1 = a1.yx;
vec2 e1 = a1.xx;
但是不同访问方式之间不可以混合使用
矩阵的访问更简单,类似于C语言的数组访问,使用[]
,从0开始,0表示第一项,使用[]访问的时候需要注意:
如果一个矢量和一个数值进行运算,结果是该数值和矢量的每个分量进行运算
如果一个矩阵和一个数值进行运算,结果是该数值和矩阵的每个分量进行运算
GLSL使用如下方式定义一个结构体:
struct light
{
vec4 color;
vec3 position;
};
light l1;
light l2;
使用点运算符访问结构体的成员。
GLSL中可以使用数组,但是只可以使用一维数组
以下是数组的声明方式:
float floatArray[4];
vec4 vec4Array[3];
数组的长度必须是大于0的整型常量表达式:
注意:在使用数组的时候,数组的索引只可以是整型常量表达式或者uniform变量。
注意:数组不可以在声明的时候直接初始化,必须显示的对每个元素进行初始化。
GLSL支持一种内置类型-采样器,我们只能通过采样器来获取纹理的数据。
GLSL ES1.0支持两种采样器类型:
采样器只能是uniform变量
我们通过GLSL提供的内置函数来从采样器中访问纹理数据,内置函数有两类,可以参考文章WebGL 1.0 内置函数
唯一能赋值给采样器变量的就是纹理单元编号,而且你必须使用WebGL方法
gl.uniform1i(u_Sampler, 纹理单元编号);
GLSL中可以使用for循环,和C语言很像,但是有些限制:
discard只能在片元着色器使用,表示放弃当前片元的处理。
GLSL的函数和C语言类似,如果我们在函数定义前就调用了函数,需要先对函数进行声明。
对于函数的参数,我们可以为参数指定限定词,以控制参数的行为。
函数参数的限定词有下面几种:
GLSL中的存储限定符有四种:
表明当前变量不可以被修改,是一个常量
const变量定义时就需要赋值。
gl_MaxVertexAttribs
来获取attribute变量支持的数目,对于WebGL环境,最小为8attribute表示逐顶点数据,应该传递顶点独有的属性数据,对于所有顶点共有的属性,应该使用uniform
uniform变量是只读的
gl_MaxVertexUniformVectors
获取顶点着色器支持的uniform变量数量,通过访问内置的全局变量gl_MaxFragmentUniformVectors
获片元着色器支持的uniform变量数量,对于WebGL环境,gl_MaxVertexUniformVectors最小为128,gl_MaxFragmentUniformVectors最小为16varying的中文翻译是变化的
意思,既然为了传递数据,为什么用这么个名字呢?
原因就是我们在片元着色器中看到的varying变量虽然和顶点着色器中的名称和类型一致,但数据已经不一样了,看下面的代码:
// 顶点着色器
attribute vec2 a_Position;
attribute vec3 a_Color;
varying vec3 v_Color;
void main() {
v_Color = a_Color;
gl_Position = vec4(a_Position.x,a_Position.y,0.0,1.0);
}`;
// 片元着色器
varying vec3 v_Color;
void main()
{
gl_FragColor = vec4(v_Color,1.0);
}
我们过一下其中的过程:
从上面的解释可以看出,一般而言,varying都是针对于attribute变量的传递,所以,varying变量的数据类型和attribute变量是一致的。
可以通过访问内置的全局变量gl_MaxVaryingVectors
获取着色器支持的varying变量数量,对于WebGL环境,gl_MaxVaryingVectors最小为8
GLSL ES 新引入了精度限定符,目的是帮助着色器程序提高运行效率,削减内存开支。 顾名思义,精度限定符用来表示每种数据具有的精度 (比特数)。简而言之,高精度的程序需要更大的开销 (包括更大的内存和更久的计算时间),而低精度的程序需要的开销则小得多。使用精度限定符,你就能精细地控制程序在效果和性能间的平衡。
精度限定符有两个作用:
因为我们使用采样器的时候,传递的也是浮点纹理坐标,所以我们总结一下不同的精度限定符对float和int的影响:
实际上,对于现在的机器,大部分的值和上面的默认值不一样,
我们可以使用下面的js方法获取不同精度的描述信息:
getShaderPrecisionFormat(shaderType, precisionType)
gl.FRAGMENT_SHADER
或者gl.VERTEX_SHADER
// 返回对象有三个值,表示精度和取值范围,一看就能明白
// 精度precision: 23
// rangeMax: 127
// rangeMin: 127
var precisionFormat = gl.getShaderPrecisionFormat(gl.VERTEX_SHADER,gl.MEDIUM_FLOAT);
对变量使用精度限定符有两种方式:
// 给float类型统一设置mediump
precision mediump float;
// 给变量单独设置精度限定
mediump float a;
highp vec4 position;
lowp vec3 color;
precision mediump float;
GLSL ES支持预处理,所谓的预处理就是在代码编译之前的处理过程
#if 条件表达式
如果条件表达式为真,执行这里
#endif
#ifdef 某宏
如果定义了某宏,执行这里
#endif
#ifndef 某宏
如果没有定义某宏,执行这里
#endif
// 定义宏
#define 宏名 宏内容
// 取消定义宏
#undef 宏名
// 使用#else
#define NUM 100
#if NUM==100
如果NUM等于100,执行这里
#else
否则执行这里
#endif
GL_FRAGMENT_PRECISION_HIGH
:片元着色器是否支持highp可以使用下面的方式对片元着色器的float进行精度设置
#ifdef GL_ES
#ifdef GL_FRAGMENT_PRECISION_HIGH
precision highp float;
#else
precision mediump float;
#endif
#endif
可以在着色器的顶部
设置WEBGL的版本号
// 100表示设置WEBGL 1.00
#version 100