var projectionMatrix, modelViewMatrix; var rotationAxis; var shaderProgram, shaderVertexPositionAttribute var shaderTexCoordAttribute, shaderSamplerUniform; var shaderProjectionMatrixUniform, shaderModelViewMatrixUniform; var duration = 5000; // ms var currentTime = Date.now(); var okToRun = false; var webGLTexture; function handleTextureLoaded(gl, texture) { gl.bindTexture(gl.TEXTURE_2D, texture); gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, true); gl.texImage2D( gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, texture.image); gl.texParameteri( gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST); gl.texParameteri( gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST); gl.bindTexture(gl.TEXTURE_2D, null); okToRun = true; } function initTexture(gl) { webGLTexture = gl.createTexture(); webGLTexture.image = new Image(); webGLTexture.image.onload = function () { handleTextureLoaded(gl, webGLTexture) } webGLTexture.image.src = "images/gravatar-256.jpg"; } function initWebGL(canvas) { var gl = null; var msg = "Your browser does not support WebGL, " + "or it is not enabled by default."; try { gl = canvas.getContext("experimental-webgl"); } catch (e) { msg = "Error creating WebGL Context!: " + e.toString(); } if (!gl) { alert(msg); throw new Error(msg); } return gl; } function initViewport(gl, canvas) { gl.viewport(0, 0, canvas.width, canvas.height); } // Create the vertex, color, and index data for a // multicolored cube function createCube(gl) { // Vertex Data var vertexBuffer; vertexBuffer = gl.createBuffer(); gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer); var verts = [ // Front face -1.0, -1.0, 1.0, 1.0, -1.0, 1.0, 1.0, 1.0, 1.0, -1.0, 1.0, 1.0, // Back face -1.0, -1.0, -1.0, -1.0, 1.0, -1.0, 1.0, 1.0, -1.0, 1.0, -1.0, -1.0, // Top face -1.0, 1.0, -1.0, -1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, -1.0, // Bottom face -1.0, -1.0, -1.0, 1.0, -1.0, -1.0, 1.0, -1.0, 1.0, -1.0, -1.0, 1.0, // Right face 1.0, -1.0, -1.0, 1.0, 1.0, -1.0, 1.0, 1.0, 1.0, 1.0, -1.0, 1.0, // Left face -1.0, -1.0, -1.0, -1.0, -1.0, 1.0, -1.0, 1.0, 1.0, -1.0, 1.0, -1.0 ]; gl.bufferData( gl.ARRAY_BUFFER, new Float32Array(verts), gl.STATIC_DRAW); var texCoordBuffer = gl.createBuffer(); gl.bindBuffer(gl.ARRAY_BUFFER, texCoordBuffer); var textureCoords = [ // Front face 0.0, 0.0, 1.0, 0.0, 1.0, 1.0, 0.0, 1.0, // Back face 1.0, 0.0, 1.0, 1.0, 0.0, 1.0, 0.0, 0.0, // Top face 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 1.0, 1.0, // Bottom face 1.0, 1.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, // Right face 1.0, 0.0, 1.0, 1.0, 0.0, 1.0, 0.0, 0.0, // Left face 0.0, 0.0, 1.0, 0.0, 1.0, 1.0, 0.0, 1.0, ]; gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(textureCoords), gl.STATIC_DRAW); // Index data (defines the triangles to be drawn) var cubeIndexBuffer = gl.createBuffer(); gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, cubeIndexBuffer); var cubeIndices = [ 0, 1, 2, 0, 2, 3, // Front face 4, 5, 6, 4, 6, 7, // Back face 8, 9, 10, 8, 10, 11, // Top face 12, 13, 14, 12, 14, 15, // Bottom face 16, 17, 18, 16, 18, 19, // Right face 20, 21, 22, 20, 22, 23 // Left face ]; gl.bufferData( gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(cubeIndices), gl.STATIC_DRAW); var cube = { buffer:vertexBuffer, texCoordBuffer:texCoordBuffer, indices:cubeIndexBuffer, vertSize:3, nVerts:24, texCoordSize:2, nTexCoords: 24, nIndices:36, primtype:gl.TRIANGLES}; return cube; } function initMatrices(canvas) { modelViewMatrix = mat4.create(); mat4.translate( modelViewMatrix, modelViewMatrix, [0, 0, -4.6]); // Create a project matrix with 45 degree field of view projectionMatrix = mat4.create(); mat4.perspective(projectionMatrix, Math.PI / 4, canvas.width / canvas.height, 1, 10000); rotationAxis = vec3.create(); vec3.normalize(rotationAxis, [1, 1, 1]); } function createShader(gl, id, type) { var shader; var str = document.getElementById(id).text; 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; } function initShader(gl, vertex, fragment) { // load and compile the fragment and vertex shader var fragmentShader = createShader(gl, fragment, "fragment"); var vertexShader = createShader(gl, vertex, "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); shaderTexCoordAttribute = gl.getAttribLocation( shaderProgram, "texCoord"); gl.enableVertexAttribArray(shaderTexCoordAttribute); shaderProjectionMatrixUniform = gl.getUniformLocation( shaderProgram, "projectionMatrix"); shaderModelViewMatrixUniform = gl.getUniformLocation( shaderProgram, "modelViewMatrix"); shaderSamplerUniform = gl.getUniformLocation( shaderProgram, "uSampler"); if (!gl.getProgramParameter(shaderProgram, gl.LINK_STATUS)) { alert("Could not initialise shaders"); } } function draw(gl, obj) { // clear the background (transparent) gl.clearColor(0.0, 0.0, 0.0, 0.0); // // clear the background (black) // 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); // set the shader to use gl.useProgram(shaderProgram); // connect up the shader parameters: vertex position, // color, and projection/model matrices // set up the buffers gl.bindBuffer(gl.ARRAY_BUFFER, obj.buffer); gl.vertexAttribPointer( shaderVertexPositionAttribute, obj.vertSize, gl.FLOAT, false, 0, 0); gl.bindBuffer(gl.ARRAY_BUFFER, obj.texCoordBuffer); gl.vertexAttribPointer( shaderTexCoordAttribute, obj.texCoordSize, gl.FLOAT, false, 0, 0); gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, obj.indices); gl.uniformMatrix4fv(shaderProjectionMatrixUniform, false, projectionMatrix); gl.uniformMatrix4fv(shaderModelViewMatrixUniform, false, modelViewMatrix); gl.activeTexture(gl.TEXTURE0); gl.bindTexture(gl.TEXTURE_2D, webGLTexture); gl.uniform1i(shaderSamplerUniform, 0); // draw the object gl.drawElements( obj.primtype, obj.nIndices, gl.UNSIGNED_SHORT, 0); } function animate() { var now = Date.now(); var deltat = now - currentTime; currentTime = now; var fract = deltat / duration; var angle = Math.PI * 2 * fract; mat4.rotate( modelViewMatrix, modelViewMatrix, angle, rotationAxis); } function run(gl, cube) { requestAnimationFrame(function() { run(gl, cube); }); if (okToRun) { draw(gl, cube); animate(); } } function startGl() { // Get A WebGL context var canvas = document.getElementById("cube"); var gl = initWebGL(canvas); var obj = createCube(gl); initViewport(gl, canvas); initMatrices(canvas); initShader( gl, "texture-vertex-shader", "texture-fragment-shader"); initTexture(gl); run(gl, obj); } /* vim: set ts=4 sw=4: */