glsl提供了一些内置的常量,用来说明当前系统的一些特性. 有时我们需要针对这些特性,对shader程序进行优化,让程序兼容度更好.
在 vertex Shader 中:
1.const mediump int gl_MaxVertexAttribs>=8
gl_MaxVertexAttribs 表示在vertex shader(顶点着色器)中可用的最大attributes数.这个值的大小取决于 OpenGL ES 在某设备上的具体实现, 不过最低不能小于 8 个.
2.const mediump int gl_MaxVertexUniformVectors >= 128
gl_MaxVertexUniformVectors 表示在vertex shader(顶点着色器)中可用的最大uniform vectors数. 这个值的大小取决于 OpenGL ES 在某设备上的具体实现, 不过最低不能小于 128 个.
3.const mediump int gl_MaxVaryingVectors >= 8
gl_MaxVaryingVectors 表示在vertex shader(顶点着色器)中可用的最大varying vectors数. 这个值的大小取决于 OpenGL ES 在某设备上的具体实现, 不过最低不能小于 8 个.
4.const mediump int gl_MaxVertexTextureImageUnits >= 0
gl_MaxVaryingVectors 表示在vertex shader(顶点着色器)中可用的最大纹理单元数(贴图). 这个值的大小取决于 OpenGL ES 在某设备上的具体实现, 甚至可以一个都没有(无法获取顶点纹理)
5.const mediump int gl_MaxCombinedTextureImageUnits >= 8
gl_MaxVaryingVectors 表示在 vertex Shader和fragment Shader总共最多支持多少个纹理单元. 这个值的大小取决于 OpenGL ES 在某设备上的具体实现, 不过最低不能小于 8 个.
在 fragment Shader 中:
1.const mediump int gl_MaxTextureImageUnits >= 8
gl_MaxVaryingVectors 表示在 fragment Shader(片元着色器)中能访问的最大纹理单元数,这个值的大小取决于 OpenGL ES 在某设备上的具体实现, 不过最低不能小于 8 个.
2.const mediump int gl_MaxFragmentUniformVectors >= 16
gl_MaxFragmentUniformVectors 表示在 fragment Shader(片元着色器)中可用的最大uniform vectors数,这个值的大小取决于 OpenGL ES 在某设备上的具体实现, 不过最低不能小于 16 个.
3.const mediump int gl_MaxDrawBuffers = 1
gl_MaxDrawBuffers 表示可用的drawBuffers数,在OpenGL ES 2.0中这个值为1, 在将来的版本可能会有所变化.
glsl中还有一种内置的uniform状态变量, gl_DepthRange 它用来表明全局深度范围.
结构如下:
struct gl_DepthRangeParameters {
highp float near; // n
highp float far; // f
highp float diff; // f - n
};
uniform gl_DepthRangeParameters gl_DepthRange;
除了 gl_DepthRange 外的所有uniform状态常量都已在glsl 1.30 中废弃.
glsl的流控制和c语言非常相似,这里不必再做过多说明,唯一不同的是片段着色器中有一种特殊的控制流discard. 使用discard会退出片段着色器,不执行后面的片段着色操作。片段也不会写入帧缓冲区。
1.for语句
for (l = 0; l < numLights; l++)
{
if (!lightExists[l]);
continue;
color += light[l];
}
2.while语句
while (i < num)
{
sum += color[i];
i++;
}
3. do while语句
do{
color += light[lightNum];
lightNum--;
}while (lightNum > 0)
4.if语句
if (true)
discard;//跳出流程
glsl提供了非常丰富的函数库,这些功能都是非常有用的,按功能大致可以分成7类:
1.通用函数:
该类函数的类型 T 可以是 float, vec2, vec3, vec4,且可以逐分量操作
2.角度或三角函数:
该类函数的 类型 T可以是 float, vec2, vec3, vec4,且可以逐分量操作.
3.指数函数:
该类函数的 类型 T可以是 float, vec2, vec3, vec4,且可以逐分量操作.
4.几何函数:
该类函数的 类型 T可以是 float, vec2, vec3, vec4,且可以逐分量操作.
5.矩阵函数
mat可以为任意类型矩阵.
方法 | 说明 |
---|---|
mat matrixCompMult(mat x, mat y) | 将矩阵 x 和 y的元素逐分量相乘 |
6.向量函数
该类函数的 类型 T可以是 vec2, vec3, vec4, 且可以逐分量操作.
bvec指的是由bool类型组成的一个向量,如:
vec3 v3= vec3(0.,0.,0.);
vec3 v3_1= vec3(1.,1.,1.);
bvec3 aa= lessThan(v3,v3_1);//bvec3(true,true,true)
7.纹理查询函数:
图像纹理有两种 一种是平面2d纹理,另一种是盒纹理,针对不同的纹理类型有不同访问方法.
纹理查询的最终目的是从sampler中提取指定坐标的颜色信息. 函数中带有Cube字样的是指 需要传入盒状纹理. 带有Proj字样的是指带投影的版本.
以下函数只在vertex shader中可用:
以下函数只在fragment shader中可用:
在 vertex shader 与 fragment shader 中都可用:
Vertex Shader:
uniform mat4 mvp_matrix; //透视矩阵 * 视图矩阵 * 模型变换矩阵
uniform mat3 normal_matrix; //法线变换矩阵(用于物体变换后法线跟着变换)
uniform vec3 ec_light_dir; //光照方向
attribute vec4 a_vertex; // 顶点坐标
attribute vec3 a_normal; //顶点法线
attribute vec2 a_texcoord; //纹理坐标
varying float v_diffuse; //法线与入射光的夹角
varying vec2 v_texcoord; //2d纹理坐标
void main(void)
{
//归一化法线
vec3 ec_normal = normalize(normal_matrix * a_normal);
//v_diffuse 是法线与光照的夹角.根据向量点乘法则,当两向量长度为1是 乘积即cosθ值
v_diffuse = max(dot(ec_light_dir, ec_normal), 0.0);
v_texcoord = a_texcoord;
gl_Position = mvp_matrix * a_vertex;
}
Fragment Shader:
precision mediump float;
uniform sampler2D t_reflectance;
uniform vec4 i_ambient;
varying float v_diffuse;
varying vec2 v_texcoord;
void main (void)
{
vec4 color = texture2D(t_reflectance, v_texcoord);
//这里分解开来是 color*vec3(1,1,1)*v_diffuse + color*i_ambient
//色*光*夹角cos + 色*环境光
gl_FragColor = color*(vec4(v_diffuse) + i_ambient);
}