本文参考WebGL: Up and Running By Tony Parisi 中译本:WebGL入门指南
github上的源代码:https://github.com/tparisi/WebGLBook
WebGL就是一个服用了兴奋剂的绘制库。要知道他爸爸是OpenGL ES,他爷爷是OpenGL。
为了确定一个绘制窗口最基本需要:
画布及绘制上下文
所有的WebGL呈现都发生在一个上下文环境中,这是一个提供了所有WebGL开发接口的JS的DOM对象。
一个WebGL程序首先需要一个关联了DOM的画布和有这个画布衍生出来的上下文环境。
1、一个canvas元素
<canvas id="webglcanvas" style="border: none;" width="500" height="500"></canvas>
2、一个gl的上下文,通过dom获取
function initWebGL(canvas){
var gl;
try{
gl=canvas.getContext("experimental-webgl");
}
catch(e){
var msg="Error creating WebGL Context!:" + e.toString();
alert(msg);
throw Error(msg);
}
return gl;
}
绘制图元
利用上面准备好的工具把图元绘制到视口中展现给观众。
3、绘制函数
// Draw the scene
function draw(gl, obj) {
// clear the background(with black)
gl.clearColor(0.0,0.0,0.0,1.0);
gl.clear(gl.COLOR_BUFFER_BIT);
// set the vertex buffer to be drawn
gl.bindBuffer(gl.ARRAY_BUFFER,obj.buffer);
//set the shader to use
gl.useProgram(shaderProgram);
//connect up the shader parameters: vertex position and projection/model matrices
gl.vertexAttribPointer(shaderVertexPositionAttribute, obj.vertSize,gl.FLOAT, false, 0, 0);
gl.uniformMatrix4fv(shaderProjectionMatrixUniform, false, projectionMatrix);
gl.uniformMatrix4fv(shaderModelViewMatrixUniform, false, modelViewMatrix);
// draw the object
gl.drawArrays(obj.primtype, 0, obj.nVerts);
}
到这里
如果要绘制图形就需要加上
着色器
规定图元如何被绘制。着色器在WebGL是必须的,它是一些可以供GPU执行的代码段。这也就意味着电脑上要运行WebGL的程序就要有GPU,没有GPU着色器语言就不能被正确的翻译,屏幕上显示就会异常,关键是没有着色器WebGL应用程序是不能运行的。
1、着色器(Shader)
着色器的处理分为创建和初始化两部分
创建:
function createShader(gl, str, type) {
var shader;
if(type == "fragment"){
shader = gl.createShader(gl.FRAGMENT_SHADER);
} else if (type == "vertex") {
shader = gl.createShader(gl.VERTEX_SHADER);
} else {
return null;
}
gl.shaderSource(shader,str);
gl.compileShader(shader);
if(!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
alert(gl.getShaderInfoLog(shader));
return null;
}
return shader;
}
// The vertex and fragment shaders
var vertexShaderSource = " attribute vec3 vertexPos;\n" +
" uniform mat4 modelViewMatrix;\n" +
" uniform mat4 projectionMatrix;\n" +
" void main(void) {\n" +
" // Return the transformed and projected vertex\n" +
" gl_Position = projectionMatrix * modelViewMatrix*\n" +
" vec4(vertexPos,1.0);\n" + " }\n";
var fragmentShaderSource = " void main(void) {\n" +
" // Return the pixel color: always output white\n" +
" gl_FragColor = vec4(1.0,0.0,0.0,1.0);\n" +
" }\n";
初始化:
var shaderProgram,
shaderVertexPositionAttribute,
shaderProjectionMatrixUniform,
shaderModelViewMatrixUniform;
function initShader(gl){
// load and compile the fragment and vertex shader
var fragmentShader = createShader(gl, fragmentShaderSource,"fragment");
var vertexShader = createShader(gl,vertexShaderSource,"vertex");
// link them together into a new program
shaderProgram = gl.createProgram();
gl.attachShader(shaderProgram,vertexShader);
gl.attachShader(shaderProgram,fragmentShader);
gl.linkProgram(shaderProgram);
// get pointers to the shader params
shaderVertexPositionAttribute = gl.getAttribLocation(shaderProgram, "vertexPos");
gl.enableVertexAttribArray(shaderVertexPositionAttribute);
shaderProjectionMatrixUniform = gl.getUniformLocation(shaderProgram, "projectionMatrix");
shaderModelViewMatrixUniform = gl.getUniformLocation(shaderProgram, "modelViewMatrix");
if(!gl.getProgramParameter(shaderProgram, gl.LINK_STATUS)) {
alert("Could not initialize shaders");
}
}
绘制对象(数据缓存、数组缓存、带类型的数组)
准备用于表示绘制图元的数据缓存、数组缓存、带类型的数组
2、数据缓存
// Create the vertex data for a square to be drawn
function createSquare(gl){
var vertexBuffer;
vertexBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER,vertexBuffer);
var verts = [
.5, .5, 0.0,
-.5, .5, 0.0,
.5, -.5, 0.0,
-.5, -.5, 0,0
];
gl.bufferData(gl.ARRAY_BUFFER,new Float32Array(verts), gl.STATIC_DRAW);
var square = {buffer:vertexBuffer, vertSize:3,nVerts:4, primtype:gl.TRIANGLE_STRIP};
return square;
}
变换矩阵
在三维应用中模型矩阵和投影矩阵事关能否正确绘制对象。
3、变换矩阵
var projectionMatrix,modelViewMatrix;
function initMatrices(){
//The transform matrix for the square-translate b ack in z for the camera
modelViewMatrix = new Float32Array(
[1,0,0,0,
0,1,0,0,
0,0,1,0,
0,0,-3.333,1]);
// The projection matrix (for a 45 degree field of view)
// projcetionMatrix = new Float32Array(
projectionMatrix = new Float32Array(
[2.41421,0,0,0,
0,2.41421,0,0,
0,0,-1.002002,-1,
0,0,-0.2002002,0]);
}
视口
告诉WebGL API绘制的范围。
4、视口(Viewport)
function initViewport(gl,canvas){
gl.viewport(0,0,canvas.width,canvas.height);
}
最后
由HTML5加载函数执行以上步骤。
function onLoad(){
var canvas = document.getElementById("webglcanvas");
var gl = initWebGL(canvas);
// initViewport(gl, canvas);
// initMatrices();
var square = createSquare(gl);
// initShader(gl);
draw(gl,square);
}