着色器语言(GLSL)基础学习三

内置的常量

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,且可以逐分量操作
着色器语言(GLSL)基础学习三_第1张图片
2.角度或三角函数:

该类函数的 类型 T可以是 float, vec2, vec3, vec4,且可以逐分量操作.
着色器语言(GLSL)基础学习三_第2张图片
3.指数函数:
该类函数的 类型 T可以是 float, vec2, vec3, vec4,且可以逐分量操作.
着色器语言(GLSL)基础学习三_第3张图片
4.几何函数:
该类函数的 类型 T可以是 float, vec2, vec3, vec4,且可以逐分量操作.
着色器语言(GLSL)基础学习三_第4张图片
5.矩阵函数
mat可以为任意类型矩阵.

方法 说明
mat matrixCompMult(mat x, mat y) 将矩阵 x 和 y的元素逐分量相乘

6.向量函数
该类函数的 类型 T可以是 vec2, vec3, vec4, 且可以逐分量操作.
着色器语言(GLSL)基础学习三_第5张图片

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中可用:

  1. vec4 texture2DLod(sampler2D sampler, vec2 coord, float lod);
  2. vec4 texture2DProjLod(sampler2D sampler, vec3 coord, float lod);
  3. vec4 texture2DProjLod(sampler2D sampler, vec4 coord, float lod);
  4. vec4 textureCubeLod(samplerCube sampler, vec3 coord, float lod);

以下函数只在fragment shader中可用:

  1. vec4 texture2D(sampler2D sampler, vec2 coord, float bias);
  2. vec4 texture2DProj(sampler2D sampler, vec3 coord, float bias);
  3. vec4 texture2DProj(sampler2D sampler, vec4 coord, float bias);
  4. vec4 textureCube(samplerCube sampler, vec3 coord, float bias);

在 vertex shader 与 fragment shader 中都可用:

  1. vec4 texture2D(sampler2D sampler, vec2 coord);
  2. vec4 texture2DProj(sampler2D sampler, vec3 coord);
  3. vec4 texture2DProj(sampler2D sampler, vec4 coord);
  4. vec4 textureCube(samplerCube sampler, vec3 coord);

官方的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);
}

你可能感兴趣的:(threejs-着色器)