40 WebGL着色器和着色器程序对象:initShader()函数的内部流程
原创
©著作权归作者所有:来自51CTO博客作者暮志未晚的原创作品,请联系作者获取转载授权,否则将追究法律责任
首先将initShaders()函数的相关代码贴出:
/**
* Create a program object and make current
* @param gl GL context
* @param vshader a vertex shader program (string)
* @param fshader a fragment shader program (string)
* @return true, if the program object was created and successfully made current
*/
function initShaders(gl, vshader, fshader) {
var program = createProgram(gl, vshader, fshader);
if (!program) {
console.log('无法创建程序对象');
return false;
}
gl.useProgram(program);
gl.program = program;
return true;
}
/**
* Create the linked program object
* @param gl GL context
* @param vshader a vertex shader program (string)
* @param fshader a fragment shader program (string)
* @return created program object, or null if the creation has failed
*/
function createProgram(gl, vshader, fshader) {
// 创建着色器对象
var vertexShader = loadShader(gl, gl.VERTEX_SHADER, vshader);
var fragmentShader = loadShader(gl, gl.FRAGMENT_SHADER, fshader);
if (!vertexShader || !fragmentShader) {
return null;
}
// 创建程序对象
var program = gl.createProgram();
if (!program) {
return null;
}
// 为程序对象分配顶点着色器和片元着色器
gl.attachShader(program, vertexShader);
gl.attachShader(program, fragmentShader);
// 连接着色器
gl.linkProgram(program);
// 检查连接
var linked = gl.getProgramParameter(program, gl.LINK_STATUS);
if (!linked) {
var error = gl.getProgramInfoLog(program);
console.log('无法连接程序对象: ' + error);
gl.deleteProgram(program);
gl.deleteShader(fragmentShader);
gl.deleteShader(vertexShader);
return null;
}
return program;
}
/**
* 创建着色器对象
* @param gl GL context
* @param type the type of the shader object to be created
* @param source shader program (string)
* @return created shader object, or null if the creation has failed.
*/
function loadShader(gl, type, source) {
// 创建着色器对象
var shader = gl.createShader(type);
if (shader == null) {
console.log('无法创建着色器');
return null;
}
// 设置着色器源代码
gl.shaderSource(shader, source);
// 编译着色器
gl.compileShader(shader);
// 检查着色器的编译状态
var compiled = gl.getShaderParameter(shader, gl.COMPILE_STATUS);
if (!compiled) {
var error = gl.getShaderInfoLog(shader);
console.log('Failed to compile shader: ' + error);
gl.deleteShader(shader);
return null;
}
return shader;
}
initShaders()函数将调用createProgram()函数,后者负责创建一个连接好的程序对象。
createProgram()函数则又会调用loadShader()函数,后者负责创建一个编译好的着色器对象。
下面讲解一下这三个函数相关的作用:
initShaders():
首先调用createProgram()函数创建一个连接好的程序对象,然后告诉WebGL系统来使用这个程序对象,最后将程序悐设为gl对象的program属性。
createProgram():
通过调用loadShader()函数,创建顶点着色器和片元着色器的着色器对象。loadShader()函数返回的着色器对象已经制定过源码并已经成功编译了。
createProgram()函数自己负责创建程序对象,然后将前面撞见的顶点着色器和片元着色器分配给程序对象。
接着,该函数连接程序对象,并检查是否连接成功。如果连接成功,就返回程序对象。
loadShader():
loadShader()函数首先创建了一个着色器对象,然后为改着色器对象指定源代码,并进行编译,接着检查编译是否成功,如果编译成功,没有出错,就返回着色器对象。