• 作者:老汪软件技巧
  • 发表时间:2024-09-06 21:03
  • 浏览量:

1. 内置变量

前面的文章中,在着色器程序中你一定会发现有gl_Position和gl_FragColor变量,但并没有声明,它们就是WebGL着色器提供的内置变量,WebGL提供了很多内置变量,先来简单列举一下常用内置变量:

1.1 gl_PointSize

内置变量 gl_PointSiz 表示绘制模式为gl.POINTS时,绘制的点的大小。换而言之就是调用gl.drawArrays()绘制图形时的绘制模式是点模式gl.POINTS的时候,才会用到内置变量gl_PointSize。

看一下示例程序是如何使用内置变量gl_PointSize设置绘制的点的大小

1.2 gl_Position

gl_Position变量表示在逐顶点处理时,当前顶点的坐标,通常在JavaScript程序中会传入一系列的顶点,在顶点着色器中将每个处理完的顶点存放在该gl_Position变量中供片元着色器使用,通过下面这个例子来了解gl_Position如何使用

var VSHADER_SOURCE = '' +
  'attribute vec4 a_Position;\n' + //声明attribute变量a_Position,用来存放顶点位置信息
  'attribute vec4 a_Color;\n' + //声明attribute变量a_Color,用来存放顶点颜色信息
  'uniform mat4 u_MvpMatrix;\n' + //声明uniform变量u_MvpMatrix,用来存放模型视图投影组合矩阵
  'varying vec4 v_Color;\n' + //声明varying变量v_Color,用来向片元着色器传值顶点颜色信息
  'void main(){\n' +
  '  gl_Position = u_MvpMatrix * a_Position;\n' + //将模型视图投影组合矩阵与顶点坐标相乘赋值给顶点着色器内置变量gl_Position
  '  v_Color = a_Color;\n' + //将顶点颜色信息传给片元着色器,
  '}\n';

1.3 gl_FragColorgl_FragColor逐片元处理时,当前片元的颜色,通常会在片元着色器中使用,WebGL绘制图形时,经过光栅化处理得到一个个的片元,这时在片元着色器中可以对这些片元逐个处理,处理完成后写入颜色缓冲区供WegGL输出到屏幕上,来看一个逐片元处理漫反射和环境光的例子加深一下理解

//片元着色器
var FSHADER_SOURCE = '' +
  '#ifdef GL_ES\n' +
  ' precision mediump float;\n' + // 设置精度
  '#endif\n' +
  'uniform vec3 u_PointLightColor;\n' + //声明uniform变量u_PointLightColor,用来存放点光源颜色
  'uniform vec3 u_PointLightPosition;\n' + //声明uniform变量u_PointLightPosition,用来存放点光源位置
  'uniform vec3 u_AmbientLightColor;\n' + //声明uniform变量u_AmbientLightColor,用来存放环境光颜色
  'varying vec4 v_Color;\n' + //声明varying变量v_Color,用来接收顶点着色器传送的片元颜色信息
  'varying vec3 v_Normal;\n' + //声明varying变量v_Normal,用来接收顶点着色器传送的顶点法向量
  'varying vec3 v_Position;\n' + //声明varying变量v_Position,用来接收顶点着色器传送的顶点坐标
  'void main(){\n' +
  '  vec3 normal = normalize(v_Normal);\n' + //对法线进行归一化处理,因为内插后长度不一定是1.0
  '  vec3 lightDirection = normalize(u_PointLightPosition - v_Position);\n' + //计算点光源照射物体表面的光线方向,并归一化
  '  float nDotL = max(dot(lightDirection, normal), 0.0);\n' + //计算光线方向和法向量点积
  '  vec3 diffuse = u_PointLightColor * vec3(v_Color) * nDotL;\n' + //计算漫反射光的颜色
  '  vec3 ambient = u_AmbientLightColor * vec3(v_Color);\n' + //计算环境漫反射光的颜色
  '  gl_FragColor = vec4(diffuse + ambient, v_Color.a);\n' + //将漫反射光的颜色和环境漫反射光的颜色相加的结果赋值给内置变量gl_FragColor
  '}\n';

1.4 gl_FragCoord

内置变量gl_FragCoord 表示绘制模式为gl.POINTS时,片元在canvas坐标系中的坐标。canvas坐标系以画布的左上角为原点,水平向右为X轴正方向,垂直向下为Y轴正方向,用gl_FragCoord.x、gl_FragCoord.y 可以获取到当前片元在canvas坐标系中的坐标,来看一个通过内置变量gl_FragCoord模拟着色器进行线性内插的过程

1.5 gl_PointCoord

gl_PointCoord表示绘制模式为gl.POINTS时,当前片元在所属点内的坐标,所属点内的坐标原点为当前点的左上角,也是水平向右为X轴正方向,垂直向下为Y轴正方向,X轴和Y轴的坐标范围都是从0.0到1.0。看一个使用gl_PointCoord将一个方形的点绘制成圆形的例子

2. 内置函数

GLSL ES 提供了大量的内置函数方便开发人员调用,这些函数按功能可以分成7类,来一一认识一下。

说明:下文中的类型T 没有特殊说明表示可以是 float, vec2, vec3, vec4,矢量类型逐分量处理

2.1 通用函数

2.2 角度和三角函数

2.3 指数函数

_内建着色器源码剖析_着色器代码

2.4 几何函数

2.5 矩阵函数

说明:下表中的类型T 表示可以是 mat2, mat3, mat4

2.6 矢量函数

说明:下表中的类型T 表示可以是 vec2,vec3,vec4,ivec2,ivec3,ivec4;BT表示可以是 bvec2,bvec3, bvec4*

2.7 纹理查询函数

纹理查询函数主要用于处理WebGL的纹理图像,通过uv坐标从纹理上获取纹素,纹理有两种,一种是平面2d纹理,另一种是盒纹理,针对不同的纹理使用不同的访问方法

2.7.1 texture2D()

texture2D()函数的功能是从二维纹理中提取纹素,主要有以下两种形式的声明

vec4 texture2D(sampler2D sampler, vec2 coord);vec4 texture2D(sampler2D sampler, vec2 coord, float bias);

参数说明

texture2D()使用示例

2.7.2 textureCube()

textureCube()函数的功能是从盒纹理中提取纹素,也有两种形式的声明

vec4 textureCube(samplerCube sampler, vec2 coord);vec4 textureCube(samplerCube sampler, vec2 coord, float bias);

参数说明

textureCube()的使用与texture2D()的使用雷同,请参照texture2D()的使用示例

2.7.3 texture2DProj()

texture2DProj()函数的功能是从投影纹理中提取纹素,与texture2D相比texture2DProj内部会除以coord的最后一个分量,所以纹理的坐标需要从coord的最后一个分量中解析出来,vec4类型的第三个分量将会被忽略。他有以下四种形式的声明

vec4 texture2DProj(sampler2D sampler, vec3 coord);vec4 texture2DProj(sampler2D sampler, vec3 coord, float bias);vec4 texture2DProj(sampler2D sampler, vec4 coord);vec4 texture2DProj(sampler2D sampler, vec4 coord, float bias);

参数说明

2.7.4 texture2DLod()、texture2DProjLod()、textureCubeLod()

通过名称可以发现这些函数有个共同特点就是都有Lod字符,前面说的三类纹理查询函数都是第三个参数存在时,只能在片元着色器中使用,而带有Lod字符的函数就是支持第三个参数给顶点着色器来使用的,接下来看看它们的声明形式

参数说明