代码摘自《WebGL Beginners Guide》一书第二章的ch2_Square.html
<html>
<head>
<title>WebGL Beginner's Guide - Chapter 2 - Rendering a Square</title>
<!-- CSS Styles //-->
<link href='css/style.css' type='text/css' rel='stylesheet'>
<link href='css/desert.css' type='text/css' rel='stylesheet'/>
<link href='css/smoothness/jquery-ui-1.8.13.custom.css' type='text/css' rel='stylesheet' />
<!-- JavaScript Libraries //-->
<script type='text/javascript' src='js/jquery-1.5.1.min.js'></script>
<script type='text/javascript' src='js/jquery-ui-1.8.13.custom.min.js'></script>
<script type='text/javascript' src='js/prettify.js'></script>
<script type='text/javascript' src='js/utils.js'></script>
<script type='text/javascript' src='js/codeview.js'></script>
<!-- Fragment Shader //-->
<script id="shader-fs" type="x-shader/x-fragment">
#ifdef GL_ES
precision highp float;
#endif
void main(void) {
gl_FragColor = vec4(0.5,0.5,1.0, 1.0);
}
</script>
<!-- Vertex Shader //-->
<script id="shader-vs" type="x-shader/x-vertex">
attribute vec3 aVertexPosition;
void main(void) {
gl_Position = vec4(aVertexPosition,1.0);
}
</script>
<script id="code-js" type="text/javascript">
var gl = null; // WebGL context
var prg = null; // The program (shaders)
var c_width = 0; // Variable to store the width of the canvas
var c_height = 0; // Variable to store the height of the canvas
var squareVertexBuffer = null; //The vertex buffer for the square
var squareIndexBuffer = null; // The index buffer for the square
var indices = []; //JavaScript array to store the indices of the square
var vertices = []; //JavaScript array to store the vertices of the square
/*
* The program contains a series of instructions that tell the Graphic Processing Unit (GPU)
* what to do with every vertex and fragment that we pass it. (more about this on chapter 3)
* The vertex shader and the fragment shader together are called the program.
*/
function initProgram() {
var fgShader = utils.getShader(gl, "shader-fs");
var vxShader = utils.getShader(gl, "shader-vs");
prg = gl.createProgram();
gl.attachShader(prg, vxShader);
gl.attachShader(prg, fgShader);
gl.linkProgram(prg);
if (!gl.getProgramParameter(prg, gl.LINK_STATUS)) {
alert("Could not initialise shaders");
}
gl.useProgram(prg);
//The following lines allow us obtaining a reference to the uniforms and attributes defined in the shaders.
//This is a necessary step as the shaders are NOT written in JavaScript but in a
//specialized language called GLSL. More about this on chapter 3.
prg.vertexPosition = gl.getAttribLocation(prg, "aVertexPosition");
}
/*
* Creates the buffers that contain the geometry of the square
*
* #0 (-0.5,0.5) +--------------+ (0.5,0.5) #3
* | |
* | |
* | .(0,0) |
* | |
* | |
* #1(-0.5,-0.5) +--------------+ (0.5,-0.5) #2
*/
function initBuffers() {
vertices = [
-0.5,0.5,0.0, //Vertex 0
-0.5,-0.5,0.0, //Vertex 1
0.5,-0.5,0.0, //Vertex 2
0.5,0.5,0.0]; //Vertex 3
indices = [3,2,1,3,1,0];
//The following code snippet creates a vertex buffer and binds the vertices to it
squareVertexBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, squareVertexBuffer);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW);
gl.bindBuffer(gl.ARRAY_BUFFER, null);
//The following code snippet creates a vertex buffer and binds the indices to it
squareIndexBuffer = gl.createBuffer();
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, squareIndexBuffer);
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(indices), gl.STATIC_DRAW);
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, null);
}
/**
* Draws the scene
*/
function drawScene(){
gl.clearColor(0.0, 0.0, 0.0, 1.0);
gl.enable(gl.DEPTH_TEST);
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
gl.viewport(0,0,c_width, c_height);
gl.bindBuffer(gl.ARRAY_BUFFER, squareVertexBuffer);
gl.vertexAttribPointer(prg.aVertexPosition, 3, gl.FLOAT, false, 0, 0);
gl.enableVertexAttribArray(prg.vertexPosition);
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, squareIndexBuffer);
gl.drawElements(gl.TRIANGLES, indices.length, gl.UNSIGNED_SHORT,0);
}
/**
* Render Loop
*/
function renderLoop() {
utils.requestAnimFrame(renderLoop);
drawScene();
}
/**
* Executes the WebGL application
* This function is invoked on the onLoad event of the webpage.
*/
function runWebGLApp(){
//Obtains a WebGL context
gl = utils.getGLContext('canvas-element-id');
//Initializes the program (shaders). More about this on chapter 3!
initProgram();
//Initializes the buffers that we are going to use to draw the square (vertex buffer and index buffer)
initBuffers();
//Renders the square!
renderLoop();
}
</script>
</head>
<body onLoad='runWebGLApp()'>
<div id='top'>
<h1>WebGL Beginner's Guide - Chapter 2</h1>
<h2>Rendering a Square</h2>
<div id='logo-packt'><img src='packt.gif'/></div>
<p>WebGL uses buffers to store and process vertex and index data. The mechanism is the same whether we are rendering
a simple object like a square or a racing car as we will see later on.</p>
</div>
<div id='contents'>
<div id='canvasContainer'>
<canvas id='canvas-element-id' width='480' height='400'>
Your browser does not support the HTML5 canvas element.
</canvas>
</div>
</div>
<div id='bottom'>
</div>
<script>cview.run();</script>
</html>
对attribute进行赋值时,在initShaders时,首先要通过gl.getAttribLocation(shader,"attributeName")获取attribute变量的地址,然后通过调用gl.enableVertexAtribArray(attributeLocation)来启用该attribute变量(或者像上面的代码一样在给attribute赋值之后再启用它)。上面的操作只需要调用一次即可。然后在循环drawScene的时候,如果buffer之前就已经通过gl.bufferData赋值(比如在initialBuffers()的时候对其赋值),并且buffer的值没有改变(比如坐标值未变)那么就不需要在每次渲染的时候再通过bufferData在对其赋值,只需在每次渲染的时候,通过gl.bindBuffer和gl.vertexAttribPointer将buffer的值传递给着色器中的attribute变量即可,对shader中的attribute变量进行赋值。