Commits

Diego Cantor committed b2b7ff8

Positional Lighiting exercise renamed

Comments (0)

Files changed (2)

1727_03/ch3_Positinal_Lighting.html

-<html>
-
-<head>
-<title>WebGL Beginner's Guide - Chapter 3 - Positional Lighting</title>
-<meta http-equiv='content-type' content='text/html; charset=ISO-8859-1'>
-
-<!-- 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/colorpicker.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/gl-matrix-min.js'></script>
-<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/colorpicker.js'></script>
-<script type='text/javascript' src='js/codeview.js'></script>
-
-<script id="shader-vs" type="x-shader/x-vertex">
-attribute vec3 aVertexPosition;
-attribute vec3 aVertexNormal;
-
-uniform mat4 uMVMatrix; 
-uniform mat4 uPMatrix; 
-uniform mat4 uNMatrix; 
-
-uniform vec3 uLightPosition;
-
-varying vec3 vNormal;
-varying vec3 vLightRay;
-varying vec3 vEyeVec;
-
-void main(void) {
-
- //Transformed vertex position
- vec4 vertex = uMVMatrix * vec4(aVertexPosition, 1.0);
- 
- //Transformed normal position
- vNormal = vec3(uNMatrix * vec4(aVertexNormal, 1.0));
-
- //Transformed light position
- vec4 light = uMVMatrix * vec4(uLightPosition,1.0);
-	
- //Light position
- vLightRay = vertex.xyz-light.xyz;
- 
- //Vector Eye
- vEyeVec = -vec3(vertex.xyz);
- 
- //Final vertex position
- gl_Position = uPMatrix * uMVMatrix * vec4(aVertexPosition, 1.0);
- 
-}
-</script>
-
-<script id="shader-fs" type="x-shader/x-fragment">
-#ifdef GL_ES
-precision highp float;
-#endif
-
-
-uniform vec4 uLightAmbient;
-uniform vec4 uLightDiffuse;
-uniform vec4 uLightSpecular;
-
-uniform vec4 uMaterialAmbient;
-uniform vec4 uMaterialDiffuse;
-uniform vec4 uMaterialSpecular;
-uniform float uShininess;       
-
-varying vec3 vNormal;
-varying vec3 vLightRay;
-varying vec3 vEyeVec;
-
-void main(void)
-{
-
-    vec3 L = normalize(vLightRay);
-    vec3 N = normalize(vNormal);
-
-    //Lambert's cosine law
-    float lambertTerm = dot(N,-L);
-    
-    //Ambient Term  
-    vec4 Ia = uLightAmbient * uMaterialAmbient;
-
-    //Diffuse Term
-    vec4 Id = vec4(0.0,0.0,0.0,1.0);
-
-    //Specular Term
-    vec4 Is = vec4(0.0,0.0,0.0,1.0);
-
-    if(lambertTerm > 0.0)
-    {
-        Id = uLightDiffuse * uMaterialDiffuse * lambertTerm; 
-        vec3 E = normalize(vEyeVec);
-        vec3 R = reflect(L, N);
-        float specular = pow( max(dot(R, E), 0.0), uShininess);
-        Is = uLightSpecular * uMaterialSpecular * specular;
-    }
-
-    //Final color
-    vec4 finalColor = Ia + Id + Is;
-    finalColor.a = 1.0;
-
-    gl_FragColor = finalColor;
-
-}
-</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 mvMatrix = mat4.create(); // The Model-View matrix
-var pMatrix = mat4.create(); // The projection matrix
-var nMatrix =  mat4.create();      // The normal matrix
-
-var distance = -40;
-var animateFlag = false;
-
-var objects = [];   
-
-/**
-* 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. 
-* The vertex shader and the fragment shader together are called the program.
-*/
-function initProgram() {
-var fragmentShader      = utils.getShader(gl, "shader-fs");
-var vertexShader        = utils.getShader(gl, "shader-vs");
-
-prg = gl.createProgram();
-gl.attachShader(prg, vertexShader);
-gl.attachShader(prg, fragmentShader);
-gl.linkProgram(prg);
-
-if (!gl.getProgramParameter(prg, gl.LINK_STATUS)) {
-alert("Could not initialise shaders");
-}
-
-gl.useProgram(prg);
-
-prg.aVertexPosition     = gl.getAttribLocation(prg, "aVertexPosition");
-prg.aVertexNormal       = gl.getAttribLocation(prg, "aVertexNormal");
-
-prg.uPMatrix            = gl.getUniformLocation(prg, "uPMatrix");
-prg.uMVMatrix           = gl.getUniformLocation(prg, "uMVMatrix");
-prg.uNMatrix            = gl.getUniformLocation(prg, "uNMatrix");
-
-
-prg.uMaterialAmbient    = gl.getUniformLocation(prg, "uMaterialAmbient");
-prg.uMaterialDiffuse    = gl.getUniformLocation(prg, "uMaterialDiffuse");
-prg.uMaterialSpecular   = gl.getUniformLocation(prg, "uMaterialSpecular");
-prg.uShininess          = gl.getUniformLocation(prg, "uShininess");
-
-
-prg.uLightPosition      = gl.getUniformLocation(prg, "uLightPosition");
-prg.uLightAmbient       = gl.getUniformLocation(prg, "uLightAmbient");
-prg.uLightDiffuse       = gl.getUniformLocation(prg, "uLightDiffuse");
-prg.uLightSpecular      = gl.getUniformLocation(prg, "uLightSpecular");
-}
-
-
-function initLights(){
-//Light uniforms
-gl.uniform3fv(prg.uLightPosition,[4.5,3.0,15.0]);        
-gl.uniform4f(prg.uLightAmbient ,1.0,1.0,1.0,1.0);
-gl.uniform4f(prg.uLightDiffuse,1.0,1.0,1.0,1.0);
-gl.uniform4f(prg.uLightSpecular,1.0,1.0,1.0,1.0);
-
-//Object Uniforms
-gl.uniform4f(prg.uMaterialAmbient, 0.1,0.1,0.1,1.0);
-gl.uniform4f(prg.uMaterialDiffuse, 0.5,0.8,0.1,1.0);
-gl.uniform4f(prg.uMaterialSpecular, 0.6,0.6,0.6,1.0);
-gl.uniform1f(prg.uShininess, 200.0);
-
-}
-
-
-/**
-* Creates an AJAX request to load the scene asynchronously
-*/
-function loadScene(){
-loadObject('models/geometry/plane.json');
-loadObject('models/geometry/cone.json','cone');
-loadObject('models/geometry/sphere.json','sphere');
-loadObject('models/geometry/smallsph.json','lightsource');
-}
-
-function getObject(alias){
-for(var i=0; i<objects.length; i++){
-if (alias == objects[i].alias) return objects[i];
-}
-return null;
-}
-
-/**
-* Ajax and JSON in action
-*/ 
-
-function loadObject(filename,alias){
-    var request = new XMLHttpRequest();
-    console.info('Requesting ' + filename);
-    request.open("GET",filename);
-    
-    request.onreadystatechange = function() {
-    if (request.readyState == 4) {
-        if(request.status == 404) {
-            console.info(filename + ' does not exist');
-        }
-        else {
-var o = JSON.parse(request.responseText);
-o.alias = (alias==null)?'none':alias;
-            handleLoadedObject(filename,o);
-        }
-    }
-    }
-    request.send();
-}
-
-/**
-* Creates the buffers that contain the geometry of the object
-*/
-function handleLoadedObject(filename,object) {
-    
-    console.info(filename + ' has been retrieved from the server');
-    
-    var vertexBufferObject = gl.createBuffer();
-    gl.bindBuffer(gl.ARRAY_BUFFER, vertexBufferObject);
-    gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(object.vertices), gl.STATIC_DRAW);
-    
-        
-    var normalBufferObject = gl.createBuffer();
-    gl.bindBuffer(gl.ARRAY_BUFFER, normalBufferObject);
-    gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(utils.calculateNormals(object.vertices, object.indices)), gl.STATIC_DRAW);
-    
-    var indexBufferObject = gl.createBuffer();
-    gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexBufferObject);
-    gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(object.indices), gl.STATIC_DRAW);
-        
-    
-    object.vbo = vertexBufferObject;
-    object.ibo = indexBufferObject;
-    object.nbo = normalBufferObject;
-
-    gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, null);
-    gl.bindBuffer(gl.ARRAY_BUFFER,null);
-    
-    objects.push(object);
-} 
-
-/**
-* Main rendering function. Called every 500ms according to WebGLStart function (see below)
-*/
-function drawScene() {
-    gl.clearColor(0.3,0.3,0.3, 1.0);
-    gl.clearDepth(100.0);
-    gl.enable(gl.DEPTH_TEST);
-    gl.depthFunc(gl.LEQUAL);
-    gl.viewport(0, 0, c_width, c_height);
-    gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
-    mat4.perspective(30, c_width / c_height, 0.1, 1000.0, pMatrix);
-
-    try{
-        gl.enableVertexAttribArray(prg.aVertexPosition);
-        gl.enableVertexAttribArray(prg.aVertexNormal);
-        for (var i = 0; i < objects.length; i++){
-            var object = objects[i];
-            mat4.identity(mvMatrix);
-            mat4.translate(mvMatrix, [0.0, 0.0, distance]); //Sets the camera to a reasonable distance to view the part
-            mat4.rotate(mvMatrix, 30*Math.PI/180, [1,0,0]);
-            mat4.rotate(mvMatrix, angle*Math.PI/180, [0,1,0]);
-            if (object.alias == 'lightsource'){
-                var lightPos = gl.getUniform(prg, prg.uLightPosition);
-                mat4.translate(mvMatrix,lightPos);
-                
-            }
-            
-            gl.uniformMatrix4fv(prg.uMVMatrix, false, mvMatrix);
-            gl.uniformMatrix4fv(prg.uPMatrix, false, pMatrix);
-            mat4.set(mvMatrix, nMatrix);
-            mat4.inverse(nMatrix);
-            mat4.transpose(nMatrix);
-            
-            gl.uniformMatrix4fv(prg.uNMatrix, false, nMatrix);
-            gl.uniform4fv(prg.uMaterialAmbient, object.ambient);
-            gl.uniform4fv(prg.uMaterialDiffuse, object.diffuse);
-            gl.uniform4fv(prg.uMaterialSpecular, object.specular);
-            gl.bindBuffer(gl.ARRAY_BUFFER, object.vbo);
-            gl.vertexAttribPointer(prg.aVertexPosition, 3, gl.FLOAT, false, 0, 0);
-            gl.enableVertexAttribArray(prg.aVertexPosition);
-            
-            gl.bindBuffer(gl.ARRAY_BUFFER, object.nbo);
-            gl.vertexAttribPointer(prg.aVertexNormal, 3, gl.FLOAT, false, 0, 0);
-            gl.enableVertexAttribArray(prg.aVertexNormal);
-            
-            gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, object.ibo);
-            gl.drawElements(gl.TRIANGLES, object.indices.length, gl.UNSIGNED_SHORT,0);
-            gl.bindBuffer(gl.ARRAY_BUFFER, null);
-            gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, null);
-        }
-    }
-    catch(err){
-        alert(err);
-        message(err.description);
-    }
-}
-
-
-
-
-
-
-var lastTime = 0;
-var angle = 0;
-/**
-* Updates the angle of rotation by a little bit each time
-*/
-function animate() {
-    var timeNow = new Date().getTime();
-    if (lastTime != 0) {
-        var elapsed = timeNow - lastTime;
-        if (animateFlag) angle += (90 * elapsed) / 10000.0;
-    }
-    lastTime = timeNow;
-}
-
-/**
-* Render Loop
-*/
-function renderLoop() {
-    requestAnimFrame(renderLoop);
-    drawScene();
-animate();
-}
-
-/**
-* Entry point. This function is invoked when the page is loaded
-*/
-function runWebGLApp() {
-//Obtains a WebGL context
-gl = utils.getGLContext("canvas-element-id");
-//Initializes the program (shaders) 
-    initProgram();
-    //Initializes lights
-    initLights();
-    //Load Scene
-loadScene();
-    //Renders the scene!
-    renderLoop();
-}
-</script>
-</head>
-
-<body onLoad='runWebGLApp()'>
-<div id='top'>
-<h1>WebGL Beginner's Guide - Chapter 3</h1>
-<h2>Positional Lighting</h2>
-<div id='logo-packt'><img src='packt.gif'/></div>
-<p></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'>
-<table style='padding=0px'>
-<tr>
-<td>X:</td><td id='slider-x-value' width='30px'>4.5</td><td width='150px'><div id='slider-x'/></td>
-<td>Shininess:</td><td id='slider-shininess-value'>200</td><td width='150px'><div id='slider-shininess'/></td>
-<td> Sphere Color:</td><td><div id='colorSelectorSphere' class='colorSelector'><div style='background-color:rgb(128,204,26)'></div></div></td>
-</tr>
-<tr>
-<td>Y:</td><td id='slider-y-value'  width='30px'>3.0</td><td width='150px'><div id='slider-y'/></td>
-<td>Distance:</td><td id='slider-distance-value'>40</td><td width='150px'><div id='slider-distance'/></td>
-<td> Cone Color:</td><td><div id='colorSelectorCone' class='colorSelector'><div style='background-color:rgb(204,26,128)'></div></div></td>
-</tr>
-<tr>
-<td>Z:</td> <td id='slider-z-value'  width='30px'>15.0</td><td width='150px'><div id='slider-z'/></td>
-<td><label id='lblanimate' for='animate-btn'>Animate</label><input id='animate-btn' type='checkbox'/></td>
-</tr>
-</table>
-</div>
-<script>cview.run(cview.MODE_VIEW);</script>
-<script> 
-$('#slider-shininess').slider({value:200, min:1, max:300, step:1, slide:updateShininess});
-$('#slider-distance').slider({value:40, min:10, max:100, step:1, slide:updateDistance});
-$('#slider-x').slider({value:4.5, min:-50, max:50, step:0.1, slide:updateLightPosition, change:updateLightPosition});
-$('#slider-y').slider({value:3.0, min:0, max:50, step:0.1, slide:updateLightPosition, change:updateLightPosition});
-$('#slider-z').slider({value:15.0, min:-50, max:50, step:0.1, slide:updateLightPosition, change:updateLightPosition});
-
-
-$('#animate-btn').button();
-$('#animate-btn').click(
-function(){
-    if ($('#animate-btn:checked').val()==null){
-        animateFlag = false;
-    }
-    else{
-        animateFlag = true;
-    }
-});
-function updateShininess(){
-    var v = $('#slider-shininess').slider("value");
-    gl.uniform1f(prg.uShininess, v);
-    $('#slider-shininess-value').html(v);
-}
-
-
-
-function updateLightPosition(){
-    var x = $('#slider-x').slider("value");
-    var y = $('#slider-y').slider("value");
-    var z = $('#slider-z').slider("value");
-    gl.uniform3fv(prg.uLightPosition, [x,y,z]);
-    $('#slider-x-value').html(x);
-    $('#slider-y-value').html(y);
-    $('#slider-z-value').html(z);
-}
-
-
-function updateDistance(){
-    var d = $('#slider-distance').slider("value");
-    $('#slider-distance-value').html(distance);
-    distance = -d;
-}
-
-
-
-function updateObjectColor(alias, r,g,b){
-    var object = getObject(alias);
-    if (object != null){
-        object.diffuse = [r,g,b,1.0];
-    }
-
-}
-
-$('#colorSelectorSphere').ColorPicker({
-onSubmit: function(hsb, hex, rgb, el) {
-        $(el).val(hex);
-        $(el).ColorPickerHide();
-
-    },
-color: '#00ff00',
-onShow: function (colpkr) {
-        $(colpkr).fadeIn(500);
-        return false;
-    },
-onHide: function (colpkr) {
-        $(colpkr).fadeOut(500);
-        return false;
-    },
-onChange: function (hsb, hex, rgb) {
-        $('#colorSelectorSphere div').css('backgroundColor', '#' + hex);
-        updateObjectColor('sphere',rgb.r/256,rgb.g/256,rgb.b/256);
-    },
-    
-onBeforeShow: function (colpkr) {
-        $(colpkr).ColorPickerSetColor('rgb(0.5,0.8,0.1)');
-    }
-})
-
-$('#colorSelectorCone').ColorPicker({
-onSubmit: function(hsb, hex, rgb, el) {
-        $(el).val(hex);
-        $(el).ColorPickerHide();
-
-    },
-color: '#00ff00',
-onShow: function (colpkr) {
-        $(colpkr).fadeIn(500);
-        return false;
-    },
-onHide: function (colpkr) {
-        $(colpkr).fadeOut(500);
-        return false;
-    },
-onChange: function (hsb, hex, rgb) {
-        $('#colorSelectorCone div').css('backgroundColor', '#' + hex);
-        updateObjectColor('cone',rgb.r/256,rgb.g/256,rgb.b/256);
-    },
-    
-onBeforeShow: function (colpkr) {
-        $(colpkr).ColorPickerSetColor('rgb(0.8,0.1,0.5)');
-    }
-}) 
-
-
-</script>
-</body>
-</html>

1727_03/ch3_Positional_Lighting.html

+<html>
+
+<head>
+<title>WebGL Beginner's Guide - Chapter 3 - Positional Lighting</title>
+<meta http-equiv='content-type' content='text/html; charset=ISO-8859-1'>
+
+<!-- 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/colorpicker.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/gl-matrix-min.js'></script>
+<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/colorpicker.js'></script>
+<script type='text/javascript' src='js/codeview.js'></script>
+
+<script id="shader-vs" type="x-shader/x-vertex">
+attribute vec3 aVertexPosition;
+attribute vec3 aVertexNormal;
+
+uniform mat4 uMVMatrix; 
+uniform mat4 uPMatrix; 
+uniform mat4 uNMatrix; 
+
+uniform vec3 uLightPosition;
+
+varying vec3 vNormal;
+varying vec3 vLightRay;
+varying vec3 vEyeVec;
+
+void main(void) {
+
+ //Transformed vertex position
+ vec4 vertex = uMVMatrix * vec4(aVertexPosition, 1.0);
+ 
+ //Transformed normal position
+ vNormal = vec3(uNMatrix * vec4(aVertexNormal, 1.0));
+
+ //Transformed light position
+ vec4 light = uMVMatrix * vec4(uLightPosition,1.0);
+	
+ //Light position
+ vLightRay = vertex.xyz-light.xyz;
+ 
+ //Vector Eye
+ vEyeVec = -vec3(vertex.xyz);
+ 
+ //Final vertex position
+ gl_Position = uPMatrix * uMVMatrix * vec4(aVertexPosition, 1.0);
+ 
+}
+</script>
+
+<script id="shader-fs" type="x-shader/x-fragment">
+#ifdef GL_ES
+precision highp float;
+#endif
+
+
+uniform vec4 uLightAmbient;
+uniform vec4 uLightDiffuse;
+uniform vec4 uLightSpecular;
+
+uniform vec4 uMaterialAmbient;
+uniform vec4 uMaterialDiffuse;
+uniform vec4 uMaterialSpecular;
+uniform float uShininess;       
+
+varying vec3 vNormal;
+varying vec3 vLightRay;
+varying vec3 vEyeVec;
+
+void main(void)
+{
+
+    vec3 L = normalize(vLightRay);
+    vec3 N = normalize(vNormal);
+
+    //Lambert's cosine law
+    float lambertTerm = dot(N,-L);
+    
+    //Ambient Term  
+    vec4 Ia = uLightAmbient * uMaterialAmbient;
+
+    //Diffuse Term
+    vec4 Id = vec4(0.0,0.0,0.0,1.0);
+
+    //Specular Term
+    vec4 Is = vec4(0.0,0.0,0.0,1.0);
+
+    if(lambertTerm > 0.0)
+    {
+        Id = uLightDiffuse * uMaterialDiffuse * lambertTerm; 
+        vec3 E = normalize(vEyeVec);
+        vec3 R = reflect(L, N);
+        float specular = pow( max(dot(R, E), 0.0), uShininess);
+        Is = uLightSpecular * uMaterialSpecular * specular;
+    }
+
+    //Final color
+    vec4 finalColor = Ia + Id + Is;
+    finalColor.a = 1.0;
+
+    gl_FragColor = finalColor;
+
+}
+</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 mvMatrix = mat4.create(); // The Model-View matrix
+var pMatrix = mat4.create(); // The projection matrix
+var nMatrix =  mat4.create();      // The normal matrix
+
+var distance = -40;
+var animateFlag = false;
+
+var objects = [];   
+
+/**
+* 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. 
+* The vertex shader and the fragment shader together are called the program.
+*/
+function initProgram() {
+var fragmentShader      = utils.getShader(gl, "shader-fs");
+var vertexShader        = utils.getShader(gl, "shader-vs");
+
+prg = gl.createProgram();
+gl.attachShader(prg, vertexShader);
+gl.attachShader(prg, fragmentShader);
+gl.linkProgram(prg);
+
+if (!gl.getProgramParameter(prg, gl.LINK_STATUS)) {
+alert("Could not initialise shaders");
+}
+
+gl.useProgram(prg);
+
+prg.aVertexPosition     = gl.getAttribLocation(prg, "aVertexPosition");
+prg.aVertexNormal       = gl.getAttribLocation(prg, "aVertexNormal");
+
+prg.uPMatrix            = gl.getUniformLocation(prg, "uPMatrix");
+prg.uMVMatrix           = gl.getUniformLocation(prg, "uMVMatrix");
+prg.uNMatrix            = gl.getUniformLocation(prg, "uNMatrix");
+
+
+prg.uMaterialAmbient    = gl.getUniformLocation(prg, "uMaterialAmbient");
+prg.uMaterialDiffuse    = gl.getUniformLocation(prg, "uMaterialDiffuse");
+prg.uMaterialSpecular   = gl.getUniformLocation(prg, "uMaterialSpecular");
+prg.uShininess          = gl.getUniformLocation(prg, "uShininess");
+
+
+prg.uLightPosition      = gl.getUniformLocation(prg, "uLightPosition");
+prg.uLightAmbient       = gl.getUniformLocation(prg, "uLightAmbient");
+prg.uLightDiffuse       = gl.getUniformLocation(prg, "uLightDiffuse");
+prg.uLightSpecular      = gl.getUniformLocation(prg, "uLightSpecular");
+}
+
+
+function initLights(){
+//Light uniforms
+gl.uniform3fv(prg.uLightPosition,[4.5,3.0,15.0]);        
+gl.uniform4f(prg.uLightAmbient ,1.0,1.0,1.0,1.0);
+gl.uniform4f(prg.uLightDiffuse,1.0,1.0,1.0,1.0);
+gl.uniform4f(prg.uLightSpecular,1.0,1.0,1.0,1.0);
+
+//Object Uniforms
+gl.uniform4f(prg.uMaterialAmbient, 0.1,0.1,0.1,1.0);
+gl.uniform4f(prg.uMaterialDiffuse, 0.5,0.8,0.1,1.0);
+gl.uniform4f(prg.uMaterialSpecular, 0.6,0.6,0.6,1.0);
+gl.uniform1f(prg.uShininess, 200.0);
+
+}
+
+
+/**
+* Creates an AJAX request to load the scene asynchronously
+*/
+function loadScene(){
+loadObject('models/geometry/plane.json');
+loadObject('models/geometry/cone.json','cone');
+loadObject('models/geometry/sphere.json','sphere');
+loadObject('models/geometry/smallsph.json','lightsource');
+}
+
+function getObject(alias){
+for(var i=0; i<objects.length; i++){
+if (alias == objects[i].alias) return objects[i];
+}
+return null;
+}
+
+/**
+* Ajax and JSON in action
+*/ 
+
+function loadObject(filename,alias){
+    var request = new XMLHttpRequest();
+    console.info('Requesting ' + filename);
+    request.open("GET",filename);
+    
+    request.onreadystatechange = function() {
+    if (request.readyState == 4) {
+        if(request.status == 404) {
+            console.info(filename + ' does not exist');
+        }
+        else {
+var o = JSON.parse(request.responseText);
+o.alias = (alias==null)?'none':alias;
+            handleLoadedObject(filename,o);
+        }
+    }
+    }
+    request.send();
+}
+
+/**
+* Creates the buffers that contain the geometry of the object
+*/
+function handleLoadedObject(filename,object) {
+    
+    console.info(filename + ' has been retrieved from the server');
+    
+    var vertexBufferObject = gl.createBuffer();
+    gl.bindBuffer(gl.ARRAY_BUFFER, vertexBufferObject);
+    gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(object.vertices), gl.STATIC_DRAW);
+    
+        
+    var normalBufferObject = gl.createBuffer();
+    gl.bindBuffer(gl.ARRAY_BUFFER, normalBufferObject);
+    gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(utils.calculateNormals(object.vertices, object.indices)), gl.STATIC_DRAW);
+    
+    var indexBufferObject = gl.createBuffer();
+    gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexBufferObject);
+    gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(object.indices), gl.STATIC_DRAW);
+        
+    
+    object.vbo = vertexBufferObject;
+    object.ibo = indexBufferObject;
+    object.nbo = normalBufferObject;
+
+    gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, null);
+    gl.bindBuffer(gl.ARRAY_BUFFER,null);
+    
+    objects.push(object);
+} 
+
+/**
+* Main rendering function. Called every 500ms according to WebGLStart function (see below)
+*/
+function drawScene() {
+    gl.clearColor(0.3,0.3,0.3, 1.0);
+    gl.clearDepth(100.0);
+    gl.enable(gl.DEPTH_TEST);
+    gl.depthFunc(gl.LEQUAL);
+    gl.viewport(0, 0, c_width, c_height);
+    gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
+    mat4.perspective(30, c_width / c_height, 0.1, 1000.0, pMatrix);
+
+    try{
+        gl.enableVertexAttribArray(prg.aVertexPosition);
+        gl.enableVertexAttribArray(prg.aVertexNormal);
+        for (var i = 0; i < objects.length; i++){
+            var object = objects[i];
+            mat4.identity(mvMatrix);
+            mat4.translate(mvMatrix, [0.0, 0.0, distance]); //Sets the camera to a reasonable distance to view the part
+            mat4.rotate(mvMatrix, 30*Math.PI/180, [1,0,0]);
+            mat4.rotate(mvMatrix, angle*Math.PI/180, [0,1,0]);
+            if (object.alias == 'lightsource'){
+                var lightPos = gl.getUniform(prg, prg.uLightPosition);
+                mat4.translate(mvMatrix,lightPos);
+                
+            }
+            
+            gl.uniformMatrix4fv(prg.uMVMatrix, false, mvMatrix);
+            gl.uniformMatrix4fv(prg.uPMatrix, false, pMatrix);
+            mat4.set(mvMatrix, nMatrix);
+            mat4.inverse(nMatrix);
+            mat4.transpose(nMatrix);
+            
+            gl.uniformMatrix4fv(prg.uNMatrix, false, nMatrix);
+            gl.uniform4fv(prg.uMaterialAmbient, object.ambient);
+            gl.uniform4fv(prg.uMaterialDiffuse, object.diffuse);
+            gl.uniform4fv(prg.uMaterialSpecular, object.specular);
+            gl.bindBuffer(gl.ARRAY_BUFFER, object.vbo);
+            gl.vertexAttribPointer(prg.aVertexPosition, 3, gl.FLOAT, false, 0, 0);
+            gl.enableVertexAttribArray(prg.aVertexPosition);
+            
+            gl.bindBuffer(gl.ARRAY_BUFFER, object.nbo);
+            gl.vertexAttribPointer(prg.aVertexNormal, 3, gl.FLOAT, false, 0, 0);
+            gl.enableVertexAttribArray(prg.aVertexNormal);
+            
+            gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, object.ibo);
+            gl.drawElements(gl.TRIANGLES, object.indices.length, gl.UNSIGNED_SHORT,0);
+            gl.bindBuffer(gl.ARRAY_BUFFER, null);
+            gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, null);
+        }
+    }
+    catch(err){
+        alert(err);
+        message(err.description);
+    }
+}
+
+
+
+
+
+
+var lastTime = 0;
+var angle = 0;
+/**
+* Updates the angle of rotation by a little bit each time
+*/
+function animate() {
+    var timeNow = new Date().getTime();
+    if (lastTime != 0) {
+        var elapsed = timeNow - lastTime;
+        if (animateFlag) angle += (90 * elapsed) / 10000.0;
+    }
+    lastTime = timeNow;
+}
+
+/**
+* Render Loop
+*/
+function renderLoop() {
+    requestAnimFrame(renderLoop);
+    drawScene();
+animate();
+}
+
+/**
+* Entry point. This function is invoked when the page is loaded
+*/
+function runWebGLApp() {
+//Obtains a WebGL context
+gl = utils.getGLContext("canvas-element-id");
+//Initializes the program (shaders) 
+    initProgram();
+    //Initializes lights
+    initLights();
+    //Load Scene
+loadScene();
+    //Renders the scene!
+    renderLoop();
+}
+</script>
+</head>
+
+<body onLoad='runWebGLApp()'>
+<div id='top'>
+<h1>WebGL Beginner's Guide - Chapter 3</h1>
+<h2>Positional Lighting</h2>
+<div id='logo-packt'><img src='packt.gif'/></div>
+<p></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'>
+<table style='padding=0px'>
+<tr>
+<td>X:</td><td id='slider-x-value' width='30px'>4.5</td><td width='150px'><div id='slider-x'/></td>
+<td>Shininess:</td><td id='slider-shininess-value'>200</td><td width='150px'><div id='slider-shininess'/></td>
+<td> Sphere Color:</td><td><div id='colorSelectorSphere' class='colorSelector'><div style='background-color:rgb(128,204,26)'></div></div></td>
+</tr>
+<tr>
+<td>Y:</td><td id='slider-y-value'  width='30px'>3.0</td><td width='150px'><div id='slider-y'/></td>
+<td>Distance:</td><td id='slider-distance-value'>40</td><td width='150px'><div id='slider-distance'/></td>
+<td> Cone Color:</td><td><div id='colorSelectorCone' class='colorSelector'><div style='background-color:rgb(204,26,128)'></div></div></td>
+</tr>
+<tr>
+<td>Z:</td> <td id='slider-z-value'  width='30px'>15.0</td><td width='150px'><div id='slider-z'/></td>
+<td><label id='lblanimate' for='animate-btn'>Animate</label><input id='animate-btn' type='checkbox'/></td>
+</tr>
+</table>
+</div>
+<script>cview.run(cview.MODE_VIEW);</script>
+<script> 
+$('#slider-shininess').slider({value:200, min:1, max:300, step:1, slide:updateShininess});
+$('#slider-distance').slider({value:40, min:10, max:100, step:1, slide:updateDistance});
+$('#slider-x').slider({value:4.5, min:-50, max:50, step:0.1, slide:updateLightPosition, change:updateLightPosition});
+$('#slider-y').slider({value:3.0, min:0, max:50, step:0.1, slide:updateLightPosition, change:updateLightPosition});
+$('#slider-z').slider({value:15.0, min:-50, max:50, step:0.1, slide:updateLightPosition, change:updateLightPosition});
+
+
+$('#animate-btn').button();
+$('#animate-btn').click(
+function(){
+    if ($('#animate-btn:checked').val()==null){
+        animateFlag = false;
+    }
+    else{
+        animateFlag = true;
+    }
+});
+function updateShininess(){
+    var v = $('#slider-shininess').slider("value");
+    gl.uniform1f(prg.uShininess, v);
+    $('#slider-shininess-value').html(v);
+}
+
+
+
+function updateLightPosition(){
+    var x = $('#slider-x').slider("value");
+    var y = $('#slider-y').slider("value");
+    var z = $('#slider-z').slider("value");
+    gl.uniform3fv(prg.uLightPosition, [x,y,z]);
+    $('#slider-x-value').html(x);
+    $('#slider-y-value').html(y);
+    $('#slider-z-value').html(z);
+}
+
+
+function updateDistance(){
+    var d = $('#slider-distance').slider("value");
+    $('#slider-distance-value').html(distance);
+    distance = -d;
+}
+
+
+
+function updateObjectColor(alias, r,g,b){
+    var object = getObject(alias);
+    if (object != null){
+        object.diffuse = [r,g,b,1.0];
+    }
+
+}
+
+$('#colorSelectorSphere').ColorPicker({
+onSubmit: function(hsb, hex, rgb, el) {
+        $(el).val(hex);
+        $(el).ColorPickerHide();
+
+    },
+color: '#00ff00',
+onShow: function (colpkr) {
+        $(colpkr).fadeIn(500);
+        return false;
+    },
+onHide: function (colpkr) {
+        $(colpkr).fadeOut(500);
+        return false;
+    },
+onChange: function (hsb, hex, rgb) {
+        $('#colorSelectorSphere div').css('backgroundColor', '#' + hex);
+        updateObjectColor('sphere',rgb.r/256,rgb.g/256,rgb.b/256);
+    },
+    
+onBeforeShow: function (colpkr) {
+        $(colpkr).ColorPickerSetColor('rgb(0.5,0.8,0.1)');
+    }
+})
+
+$('#colorSelectorCone').ColorPicker({
+onSubmit: function(hsb, hex, rgb, el) {
+        $(el).val(hex);
+        $(el).ColorPickerHide();
+
+    },
+color: '#00ff00',
+onShow: function (colpkr) {
+        $(colpkr).fadeIn(500);
+        return false;
+    },
+onHide: function (colpkr) {
+        $(colpkr).fadeOut(500);
+        return false;
+    },
+onChange: function (hsb, hex, rgb) {
+        $('#colorSelectorCone div').css('backgroundColor', '#' + hex);
+        updateObjectColor('cone',rgb.r/256,rgb.g/256,rgb.b/256);
+    },
+    
+onBeforeShow: function (colpkr) {
+        $(colpkr).ColorPickerSetColor('rgb(0.8,0.1,0.5)');
+    }
+}) 
+
+
+</script>
+</body>
+</html>