webgl: a new platform for 3d games advanced games programming by jarek francik 2011
TRANSCRIPT
WebGL: a New Platformfor 3D Games
Advanced Games Programmingby Jarek Francik
2011
HTML5, Canvas & WebGL
• Google Chrome ok• Mozilla Firefox ok, but not today• Safari dev version only• Opera dev version only• Internet Explorer NO!!!
HTML5<!DOCTYPE html>
<html>
<head> <title>WebGL Tutorial</title> <meta http-equiv="content-type" content="text/html; charset=ISO-8859-1"> <meta http-equiv="X-UA-Compatible" content="chrome=1"> <script type="text/javascript" src="glMatrix-0.9.5.min.js"></script>
<script type="text/javascript"></script>
</head><body> <h1>WebGL Tutorial</h1> <canvas id="idCanvas" style="border: none;" width="800" height="600"></canvas> <p>If nothing visible, try to run with the latest version of Chrome.</p> <p>If it still doesn't help, try to upload to any web server and run through http.</p></body>
</html>
Fragment Shader<script id="shader-fs" type="x-shader/x-fragment">
#ifdef GL_ES precision highp float; #endif
varying vec4 vColor;
void main(void) { gl_FragColor = vColor; }</script>
Vertex Shader<script id="shader-vs" type="x-shader/x-vertex">
attribute vec3 aVertexPosition;
uniform mat4 uMVMatrix; uniform mat4 uPMatrix;
varying vec4 vColor;
void main(void) { gl_Position = uPMatrix * uMVMatrix * vec4(aVertexPosition, 1.0); vColor = vec4(1.0, 1.0, 1.0, 1.0); }</script>
main function (1)<body onload="main();">
main function (2)function main() { // Initialize WebGL context var canvas = document.getElementById("idCanvas"); var gl = canvas.getContext("experimental-webgl"); gl.viewport(0, 0, canvas.width, canvas.height); gl.clearColor(0.0, 0.0, 0.0, 1.0); gl.enable(gl.DEPTH_TEST);
// .... // see following slides
main function (3)
// Initialize Shader Program var txtShaderFrag = document.getElementById("shader-fs").innerText; var txtShaderVert = document.getElementById("shader-vs").innerText;
var shaderProgram = gl.createProgram();
var fragmentShader = gl.createShader(gl.FRAGMENT_SHADER); gl.shaderSource(fragmentShader, txtShaderFrag); gl.compileShader(fragmentShader); gl.attachShader(shaderProgram, fragmentShader);
var vertexShader = gl.createShader(gl.VERTEX_SHADER); gl.shaderSource(vertexShader, txtShaderVert); gl.compileShader(vertexShader); gl.attachShader(shaderProgram, vertexShader);
gl.linkProgram(shaderProgram); gl.useProgram(shaderProgram); gl.enableVertexAttribArray(gl.getAttribLocation(shaderProgram, "aVertexPosition")); gl.enableVertexAttribArray(gl.getAttribLocation(shaderProgram, "aVertexColor"));
gl.shaderProgram = shaderProgram;
main function (4)
// Init Objects initObjects(gl);
// Render buffers render(gl); }
main functionfunction main() { // Initialize WebGL context var canvas = document.getElementById("idCanvas"); var gl = canvas.getContext("experimental-webgl"); gl.viewport(0, 0, canvas.width, canvas.height); gl.clearColor(0.0, 0.0, 0.0, 1.0); gl.enable(gl.DEPTH_TEST);
// Initialize Shader Program var txtShaderFrag = document.getElementById("shader-fs").innerText; var txtShaderVert = document.getElementById("shader-vs").innerText;
var shaderProgram = gl.createProgram();
var fragmentShader = gl.createShader(gl.FRAGMENT_SHADER); gl.shaderSource(fragmentShader, txtShaderFrag); gl.compileShader(fragmentShader); gl.attachShader(shaderProgram, fragmentShader);
var vertexShader = gl.createShader(gl.VERTEX_SHADER); gl.shaderSource(vertexShader, txtShaderVert); gl.compileShader(vertexShader); gl.attachShader(shaderProgram, vertexShader);
gl.linkProgram(shaderProgram); gl.useProgram(shaderProgram); gl.enableVertexAttribArray(gl.getAttribLocation(shaderProgram, "aVertexPosition")); gl.enableVertexAttribArray(gl.getAttribLocation(shaderProgram, "aVertexColor"));
gl.shaderProgram = shaderProgram;
// Init Objects initObjects(gl);
// Render buffers render(gl); }
initObjects function initObjects(gl) { var bufVertexPositions = gl.createBuffer(); gl.bindBuffer(gl.ARRAY_BUFFER, bufVertexPositions); var vertices = [ 0.0, 1.0, 0.0, // triangle -1.0, -1.0, 0.0, 1.0, -1.0, 0.0,
1.0, 1.0, 0.0, // square -1.0, 1.0, 0.0, 1.0, -1.0, 0.0, -1.0, -1.0, 0.0, ]; gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW); gl.bufVertexPositions = bufVertexPositions; }
render (1)function render(gl) { // clear canvas gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
// bind and set the vertex buffer gl.bindBuffer(gl.ARRAY_BUFFER, gl.bufVertexPositions); loc = gl.getAttribLocation(gl.shaderProgram, "aVertexPosition"); gl.vertexAttribPointer(loc, 3, gl.FLOAT, false, 0, 0);
render (2)// set-up the view matrix
var pMatrix = mat4.create(); mat4.perspective(45, gl.canvas.width / gl.canvas.height, 0.1, 100.0, pMatrix); mat4.translate(pMatrix, [0, 0.0, -7.0]); loc = gl.getUniformLocation(gl.shaderProgram, "uPMatrix"); gl.uniformMatrix4fv(loc, false, pMatrix);
// set up the world matrix var mvMatrix = mat4.create(); mat4.identity(mvMatrix); mat4.translate(mvMatrix, [-1.5, 0.0, 0.0]); loc = gl.getUniformLocation(gl.shaderProgram, "uMVMatrix"); gl.uniformMatrix4fv(loc, false, mvMatrix);
render (3)// draw the triangle (3 vertices)
gl.drawArrays(gl.TRIANGLES, 0, 3);
// modify the world matrix mat4.translate(mvMatrix, [3.0, 0.0, 0.0]); loc = gl.getUniformLocation(gl.shaderProgram, "uMVMatrix"); gl.uniformMatrix4fv(loc, false, mvMatrix);
// draw the square (4 vertices, starting from no 3) gl.drawArrays(gl.TRIANGLE_STRIP, 3, 4); }
renderfunction render(gl) { // clear canvas gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
// bind and set the vertex buffer gl.bindBuffer(gl.ARRAY_BUFFER, gl.bufVertexPositions); loc = gl.getAttribLocation(gl.shaderProgram, "aVertexPosition"); gl.vertexAttribPointer(loc, 3, gl.FLOAT, false, 0, 0);
// set-up the view matrix var pMatrix = mat4.create(); mat4.perspective(45, gl.canvas.width / gl.canvas.height, 0.1, 100.0, pMatrix); mat4.translate(pMatrix, [0, 0.0, -7.0]); loc = gl.getUniformLocation(gl.shaderProgram, "uPMatrix"); gl.uniformMatrix4fv(loc, false, pMatrix);
// set up the world matrix var mvMatrix = mat4.create(); mat4.identity(mvMatrix); mat4.translate(mvMatrix, [-1.5, 0.0, 0.0]); loc = gl.getUniformLocation(gl.shaderProgram, "uMVMatrix"); gl.uniformMatrix4fv(loc, false, mvMatrix);
// draw the triangle (3 vertices) gl.drawArrays(gl.TRIANGLES, 0, 3);
// modify the world matrix mat4.translate(mvMatrix, [3.0, 0.0, 0.0]); loc = gl.getUniformLocation(gl.shaderProgram, "uMVMatrix"); gl.uniformMatrix4fv(loc, false, mvMatrix);
// draw the square (4 vertices, starting from no 3) gl.drawArrays(gl.TRIANGLE_STRIP, 3, 4); }
animate (1)
1. Add (before render):
var angle = 0;
2. Add (in world matrix configuration):
mat4.rotateY(mvMatrix, angle);
3. Replace render() call in main() with:
// Start animation loop animate(gl);
animate (2) function animate(gl) { window.webkitRequestAnimationFrame(function() { animate(gl); }); render(gl); angle += 0.025; }
Next Stages
1. (Animated Triangle and Square)2. Added Colours3. Added 3D: Pyramid and Cube4. Added Texture5. Added Lighting (not covered today)
Three.js: HTML<!DOCTYPE html><html>
<head><title>WebGL/Three.js Tutorial</title><script type="text/javascript" src="Three.js"></script>
</head>
<script type="text/javascript"></script>
<body onload="main();"> <div id="container"/>
<body></html>
Three.js: javascript (1)var camera, scene, renderer, sphere;
function main() { // create a renderer, camera, and scene renderer = new THREE.WebGLRenderer(); renderer.setSize( window.innerWidth, window.innerHeight );
camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 10000);
camera.position.z = 600;
scene = new THREE.Scene();
Three.js: javascript (2) var texture = THREE.ImageUtils.loadTexture( "land_ocean_ice_cloud_2048.jpg" ); sphere = new THREE.Mesh(new THREE.SphereGeometry(200, 100, 100), new THREE.MeshBasicMaterial( { map:texture } )); scene.add(sphere);
// add lighting var light = new THREE.DirectionalLight(0xFFFFFF); light.position.x = 150; light.position.y = 250; light.position.z = 150; scene.add(light);
// attach the scene to the DOM document.getElementById("container").appendChild(renderer.domElement);
animate();}
Three.js: javascript function animate() { window.webkitRequestAnimationFrame(animate); renderer.render(scene, camera); }
Three.js: javascriptvar camera, scene, renderer, sphere;
function main(){ // create a renderer, camera, and scene renderer = new THREE.WebGLRenderer(); renderer.setSize( window.innerWidth, window.innerHeight );
camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 10000); camera.position.z = 600;
scene = new THREE.Scene();
var texture = THREE.ImageUtils.loadTexture( "land_ocean_ice_cloud_2048.jpg" ); sphere = new THREE.Mesh(new THREE.SphereGeometry(200, 100, 100), new THREE.MeshBasicMaterial( { map:texture } )); scene.add(sphere);
// add lighting var light = new THREE.DirectionalLight(0xFFFFFF); light.position.x = 150; light.position.y = 250; light.position.z = 150; scene.add(light);
// attach the scene to the DOM document.getElementById("container").appendChild(renderer.domElement);
animate();} function animate(){ window.webkitRequestAnimationFrame(animate); renderer.render(scene, camera);}