因为每一个WebGL程序都需要以下二个步骤:
-
从canvas获取WebGL上下文
-
创建vertex shader和fragment shader并链接成一个shader program
所以这里,我们把这些操作封装成函数并放到webgl_utils.js里面:
1. 从canvas里面获取WebGL上下文
function createGLContext(canvas_id){
var canvas = document.getElementById(canvas_id)
var names = ["webgl",
"experimental-webgl",
"webkit-3d",
"moz-webgl"];
var gl;
for (var i = 0; i < names.length; ++i){
try{
gl = canvas.getContext(names[i]);
}catch(e){
throw("contex can't be created!");
}
if(gl) break;
}
if(gl == null)
alert('WebGL is not available')
return gl
}
2. 创建shader
//根据shdaer的str和type来创建vertex shader和fragment shader
function createShader(gl,str,type){
var shader = gl.createShader(type);
gl.shaderSource(shader,str);
gl.compileShader(shader);
if(!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
throw gl.getShaderInfoLog(shader);
}
return shader
}
3. 创建program
function createProgram(gl,vstr,fstr){
var program = gl.createProgram();
var vshader = createShader(gl,vstr,gl.VERTEX_SHADER);
var fshader = createShader(gl,fstr,gl.FRAGMENT_SHADER);
gl.attachShader(program,vshader);
gl.attachShader(program,fshader);
gl.linkProgram(program);
if(!gl.getProgramParameter(program, gl.LINK_STATUS)) {
throw gl.getProgramInfoLog(program);
}
return program
}
4. 定义自己的script标签
本节我们将使用自定义的标签来放置vertex shader和fragment shader.
因为html5的标准规定,如果script标签里面的type不是text/javascript或者src=”…”之类的话,浏览器会把这段script标签里面的内容解析成文本。
因此,我们自定义两种type分别用来存放vertex shader和fragment shader:
//下面是vertex shader的定义
<script type="x-shader/x-vertex" id="vertex-shader">
attribute vec2 a_position;
uniform mat4 u_ModelViewMatrix;
uniform mat4 u_PMatrix;
void main()
{
gl_Position = u_PMatrix * u_ModelViewMatrix * vec4(a_position,0.0,1.0);
}
</script>
//下面是fragment shader的定义
<script type="x-shader/x-fragment" id="fragment-shader">
//this line must be added
precision mediump float;
uniform vec4 u_color;
void main()
{
gl_FragColor = u_color;
}
</script>
最后,为了方便使用,我还封装了下面的函数用来从script id来创建shader program.
function createProgramFromElementId(gl,vertex_id,fragment_id){
var vertex = document.getElementById(vertex_id)
var fragment = document.getElementById(fragment_id)
return createProgram(gl,vertex.text,fragment.text)
}