初始化着色器流程
<canvas id="glcanvas" width="640" height="480"></canvas>
复制代码
// 初始化着色器程序,让WebGL知道如何绘制我们的数据
function initShaders(gl, vshader, fshader) {
// 创建指定类型的着色器
var vertexShader = loadShader(gl, gl.VERTEX_SHADER, vshader);
var fragmentShader = loadShader(gl, gl.FRAGMENT_SHADER, fshader);
if (!vertexShader || !fragmentShader) {
return null;
}
// s4. 创建 WebGLProgram
var program = gl.createProgram();
if (!program) {
return null;
}
// s5. 把 WebGLShader 添加到 WebGLProgram
gl.attachShader(program, vertexShader);
gl.attachShader(program, fragmentShader);
// s6. 链接给入的 WebGLProgram 对象,从而完成为程序的片元和顶点着色器准备GPU代码的过程
gl.linkProgram(program);
// 检查链接的结果
var linked = gl.getProgramParameter(program, gl.LINK_STATUS); // 返回WebGLProgram程序对象的信息
if (!linked) {
var error = gl.getProgramInfoLog(program); // 返回 WebGLProgram 对象的信息日志
console.log('Failed to link program: ' + error);
gl.deleteProgram(program); // 删除 WebGLProgram
gl.deleteShader(fragmentShader); // 删除 WebGLShader
gl.deleteShader(vertexShader); // 删除 WebGLShader
return null;
}
if (!program) {
console.log('Failed to create program');
return false;
}
// s7. 将定义好的 WebGLProgram 对象添加到当前的渲染状态中
gl.useProgram(program);
return true;
}
// 创建指定类型的着色器,上传source源码并编译
function loadShader(gl, type, source) {
// s1. 创建一个 WebGLShader 着色器对象
var shader = gl.createShader(type);
if (shader == null) {
console.log('unable to create shader');
return null;
}
// s2. 设置 WebGLShader 着色器(顶点着色器及片元着色器)的GLSL程序代码。
gl.shaderSource(shader, source);
// s3. 编译一个GLSL着色器,使其成为为二进制数据,然后就可以被WebGLProgram对象所使用.
gl.compileShader(shader);
// 检查编译结果
var compiled = gl.getShaderParameter(shader, gl.COMPILE_STATUS); // 返回着色器的信息
if (!compiled) {
var error = gl.getShaderInfoLog(shader); // 返回 WebGLShader 对象的信息日志
console.log('Failed to compile shader: ' + error);
gl.deleteShader(shader); // 删除 WebGLShader
return null;
}
return shader;
}
复制代码
// 顶点着色器程序
const VSHADER_SOURCE =
`void main() {
gl_Position = vec4(0.0, 0.0, 0.0, 1.0); // 设置坐标
gl_PointSize = 10.0; // 设置尺寸
}`
// 片元着色器程序
const FSHADER_SOURCE =
`void main() {
gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0); // 设置颜色
}`
function main() {
// 1.获取canvas元素
const canvas = document.getElementById('glcanvas')
// 2.获取webgl绘图上下文
const gl = canvas.getContext('webgl')
if (!gl) {
alert('不支持webgl')
return
}
// 初始化着色器
if (!initShaders(gl, VSHADER_SOURCE, FSHADER_SOURCE)) {
console.log('着色器初始化失败')
return
}
// 3.设置背景色(指定清空canvas的颜色)
gl.clearColor(0.0, 1.0, 0.0, 1.0)
// 4.清空canvas
gl.clear(gl.COLOR_BUFFER_BIT)
// 5.绘制一个点
gl.drawArrays(gl.POINTS, 0, 1)
}
main()
复制代码
分析
上一篇文章中分析了绘制一个点的流程,但是初始化着色器这步是忽略的,现在具体分析着色器的初始化流程
- 1.创建一个 WebGLShader 着色器对象------gl.createShader
- 2.设置 WebGLShader 着色器的GLSL程序代码------gl.shaderSource
- 3.编译一个GLSL着色器,使其成为为二进制数据,然后就可以被WebGLProgram对象所使用------gl.compileShader
- 4.创建 WebGLProgram 程序对象------gl.createProgram
- 5.把 WebGLShader 添加到 WebGLProgram------gl.attachShader
- 6.链接给入的 WebGLProgram 对象,从而完成为程序的片元和顶点着色器准备GPU代码的过程------gl.linkProgram
- 7.将定义好的 WebGLProgram 对象添加到当前的渲染状态中------gl.useProgram
gl.createShader()
WebGLRenderingContext.createShader() 用于创建一个 WebGLShader 着色器对象,该对象可以使用 WebGLRenderingContext.shaderSource() 和 WebGLRenderingContext.compileShader() 方法配置着色器代码
/**
* @param type 参数为gl.VERTEX_SHADER 或 gl.FRAGMENT_SHADER两者中的一个
* gl.VERTEX_SHADER // 用于创建顶点着色器
* gl.FRAGMENT_SHADER // 用于创建片段着色器
*/
WebGLShader gl.createShader(type);
复制代码
gl.shaderSource()
WebGLRenderingContext.shaderSource() 方法用于设置 WebGLShader 着色器(顶点着色器及片元着色器)的GLSL程序代码
/**
* 将source指定的字符串形式的代码传入shader指定的着色器。如果之前已经向shader传入过代码了,旧的代码将会被替代掉
* @param shader 用于设置程序代码的 WebGLShader (着色器对象)
* @param source 包含GLSL程序代码的字符串
*/
void gl.shaderSource(shader, source);
复制代码
gl.compileShader()
WebGLRenderingContext.compileShader() 用于编译一个GLSL着色器,使其成为为二进制数据,然后就可以被WebGLProgram对象所使用
/**
* @param shader 一个片元或顶点着色器 (WebGLShader)
*/
void gl.compileShader(shader)
复制代码
gl.createProgram()
WebGLRenderingContext.createProgram() 方法用于创建和初始化一个 WebGLProgram 对象
WebGLProgram gl.createProgram();
复制代码
gl.attachShader()
WebGLRenderingContext.attachShader() 方法负责往 WebGLProgram 添加一个片段或者顶点着色器
/**
* @param program 一个 WebGLProgram 对象
* @param shader 一个类型为片段或者顶点的 WebGLShader
*/
void gl.attachShader(program, shader);
复制代码
gl.linkProgram()
WebGLRenderingContext.linkProgram() 方法链接给定的WebGLProgram,从而完成为程序的片元和顶点着色器准备GPU代码的过程
/**
* @param program 一个用于链接的 WebGLProgram
*/
void gl.linkProgram(program);
复制代码
gl.useProgram()
WebGLRenderingContext.useProgram() 方法将定义好的 WebGLProgram 对象添加到当前的渲染状态中
/**
* @param program 需要添加的WebGLProgram对象
*/
void gl.useProgram(program);
复制代码