initShaders函数
步骤简述
编译GLSL ES代码,创建和初始化着色器提供WebGL使用。
Step1 gl.createShader()
创建着色器对象
Step2 gl.shaderSource()
向着色器对象中填充着色器程序的源代码
Step3 gl.compileShader
编译着色器
Step4 gl.createProgram()
创建程序对象
Step5 gl.attachShader()
为程序对象分配着色器
Step6 gl.linkProgram()
连接程序对象
Step7 gl.useProgram()
使用程序对象
着色器对象 shader object
- 管理一个 顶点着色器 或 片元着色器
- 每一个着色器都有一个 着色器对象
程序对象 program object
- 管理 着色器对象 的容器
- 一个程序对象必须包含一个 顶点着色器 和一个 片元着色器
步骤详述
Step1 创建着色器对象
参数指定 着色器类型:
- gl.VERTEX_SHADER 顶点着色器
- gl.FRAGMENT_SHADER 片元着色器
如果着色器对象还在使用,deleteShader不会立刻执行,
而是等待着色器不再被占用后再将其删除。
Step2 指定着色器对象的代码
Step3 编译着色器
如果调用 shaderSource 重新指定着色器代码,
就一定要使用 compileShader 手动重新编译,
否则WebGL系统中旧代码部分不会被自动替换。
是用来 检查着色器的状态的 ,第二个参数pname和返回值有如下关系:
pname | description | return |
---|---|---|
gl.SHADER_TYPE | 着色器类型 | gl.VERTEX_SHADER/gl.FRAGMENT_SHADER |
gl.DELETE_STATUS | 是否被删除成功 | true/false |
gl.COMPILE_STATUS | 是否被编译成功 | true/false |
在 编译失败 的情况下使用,
即在 gl.getShaderParameter(shader,gl.COMPILE_STATUS) = false 的情况下。
返回值为编译错误时 WebGL写入着色器的 信息日志(information log)。
Step4 创建程序对象
用于 创建程序对象。
1 | let a_Position = gl.getAttribLocation(gl.program,'a_Position'); |
gl.getAttribLocation 和 gl.getUniformLocation 的第一个参数 gl.program 就是 程序对象
用于 删除程序对象。
Step5 为程序对象分配着色器对象
用于 分配着色器,
每个程序必须对应 一个顶点着色器 和 一个片元着色器。
把空的着色器附给程序对象也可以
用于 解除已分配的着色器。
Step6 连接程序对象
用于 连接顶点着色器和片元着色器。
- 对顶点/片元着色器的 varying变量 进行 同名同类型对应
- 确保顶点着色器的 每个varying都赋了值
- 对顶点/片元着色器的 uniform变量 进行 同类型对应
- 确保attribute、uniform、varying变量的个数没有超过 着色器的上限
用于检查 着色器是否连接成功。
- 连接成功 向WebGL系统返回一个 二进制可执行模块
- 连接失败 会在 信息日志 中生产成 连接出错信息LINK_STATUS和VALIDATE_STATUS的区别
- LINK_STATUS 程序是否 成功连接
- 仅检测 连接阶段
- VALIDATE_STATUS 程序是否 通过验证
- 检测 运行阶段
- 性能开销很大,通常在 调试程序 时这样做
- LINK_STATUS 程序是否 成功连接
用于 从信息日志中获取连接出错信息
Step7 告知WebGL系统所使用的程序对象
这也为WebGL提供了一个强大的特性:
只需要准备多个 程序对象,
绘制时根据需要 切换程序对象。
内部流程
initShaders(gl, vshader, fshader)
1 | function initShaders(gl, vshader, fshader) { |
createProgram(gl, vshader, fshader)
1 | function createProgram(gl, vshader, fshader) { |
loadShader(gl, type, source)
1 | function loadShader(gl, type, source) { |