代码摘自《WebGL Beginners Guide》一书第二章的ch2_RenderingModes.html
<html>
<head>
<title>WebGL Beginner's Guide - Chapter 2 - Rendering Modes</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);
gl_PointSize = 4.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 trapezoidVertexBuffer = null; //The vertex buffer for the trapezoid
var trapezoidIndexBuffer = null; // The index buffer for the trapezoid
var indices = []; //JavaScript array to store the indices of the trapezoid
var vertices = []; //JavaScript array to store the vertices of the trapezoid
var renderingMode = 'TRIANGLES';
/*
* 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.vertexPositionAttribute = gl.getAttribLocation(prg, "aVertexPosition");
}
/*
* Creates the buffers that contain the geometry of the trapezoid
*
* #1 (-0.25,0.5) +--------------+ (0.25,0.5) #3
* / \
* / \
* / .(0,0) \
* / \
* / \
* #0(-0.5,-0.5) +------------+-------------+ (0.5,-0.5) #4
* #2(0,-0.5)
*/
function initBuffers() {
vertices = [
-0.5,-0.5,0.0, //Vertex 0
-0.25,0.5,0.0, //Vertex 1
0.0,-0.5,0.0, //Vertex 2
0.25,0.5,0.0, //Vertex 3
0.5,-0.5,0.0 //Vertex 4
];
indices = [0,1,2,0,2,3,2,3,4]; //For triangles
//The following code snippet creates a vertex buffer and binds the vertices to it
trapezoidVertexBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, trapezoidVertexBuffer);
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
trapezoidIndexBuffer = gl.createBuffer();
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, trapezoidIndexBuffer);
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, trapezoidVertexBuffer);
gl.vertexAttribPointer(prg.aVertexPosition, 3, gl.FLOAT, false, 0, 0);
gl.enableVertexAttribArray(prg.vertexPositionAttribute);
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, trapezoidIndexBuffer);
switch(renderingMode){
case "TRIANGLES": {
indices = [0,1,2,2,3,4];
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(indices), gl.STATIC_DRAW);
gl.drawElements(gl.TRIANGLES, indices.length, gl.UNSIGNED_SHORT,0);
break;
}
case "LINES": {
indices = [1,3,0,4,1,2,2,3];
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(indices), gl.STATIC_DRAW);
gl.drawElements(gl.LINES, indices.length, gl.UNSIGNED_SHORT,0);
break;
}
case 'POINTS': {
indices = [1,2,3];
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(indices), gl.STATIC_DRAW);
gl.drawElements(gl.POINTS, indices.length, gl.UNSIGNED_SHORT,0);
break;
}
case 'LINE_LOOP': {
indices = [2,3,4,1,0];
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(indices), gl.STATIC_DRAW);
gl.drawElements(gl.LINE_LOOP, indices.length, gl.UNSIGNED_SHORT,0);
break;
}
case 'LINE_STRIP': {
indices = [2,3,4,1,0];
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(indices), gl.STATIC_DRAW);
gl.drawElements(gl.LINE_STRIP, indices.length, gl.UNSIGNED_SHORT,0);
break;
}
case 'TRIANGLE_STRIP': {
indices = [0,1,2,3,4];
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(indices), gl.STATIC_DRAW);
gl.drawElements(gl.TRIANGLE_STRIP, indices.length, gl.UNSIGNED_SHORT,0);
break;
}
case 'TRIANGLE_FAN': {
indices = [0,1,2,3,4];
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(indices), gl.STATIC_DRAW);
gl.drawElements(gl.TRIANGLE_FAN, indices.length, gl.UNSIGNED_SHORT,0);
break;
}
}
}
/**
* Render Loop
*/
function renderLoop() {
utils.requestAnimFrame(renderLoop);
drawScene();
}
/**
* Updates the variable renderingMode with the combo box selection.
*/
function changeRenderingMode(op){
renderingMode = (op.options[op.selectedIndex].value);
}
/**
* 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 trapezoid (vertex buffer and index buffer)
initBuffers();
//Renders the trapezoid!
renderLoop();
}
</script>
</head>
<body onLoad='runWebGLApp()'>
<div id='top'>
<h1>WebGL Beginner's Guide - Chapter 2</h1>
<h2>Rendering a trapezoid</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 trapezoid 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'>
Please select one option:
<select onChange='changeRenderingMode(this)'>
<option value='TRIANGLES' select='selected' >TRIANGLES</option>
<option value='LINES'>LINES</option>
<option value='POINTS'>POINTS</option>
<option value='LINE_LOOP'>LINE_LOOP</option>
<option value='LINE_STRIP'>LINE_STRIP</option>
<option value='TRIANGLE_STRIP'>TRIANGLE_STRIP</option>
<option value='TRIANGLE_FAN'>TRIANGLE_FAN</option>
</select>
</div>
<script>cview.run();</script>
</html>
按照几何图形的渲染方式有以下几种情况:
点:POINTS
线:LINES、LINE_STRIP、LINE_LOOP
面:TRIANGLES、TRIANGLE_STRIP、TRIANGLE_FAN
在使用IBO时,对于POINTS、LINES、TRIANGLES来说,对这三者中的连续索引是独立分组的,不同组之间没有使用紧邻的前面或者后面索引;对于LINE_STRIP、LINE_LOOP、TRIANGLE_STRIP来说也是对索引进行了分组,不过后面一组的索引还会用到前面一组中的索引,存在着交叉的现象;TRIANGLE_FAN是比较特殊的,首先第一个索引作为origin,然后后面每两个数字进行独立分组。