Index: chrome/test/data/gpu/webgl_teapot/teapot_files/demo.js |
=================================================================== |
--- chrome/test/data/gpu/webgl_teapot/teapot_files/demo.js (revision 0) |
+++ chrome/test/data/gpu/webgl_teapot/teapot_files/demo.js (revision 0) |
@@ -0,0 +1,392 @@ |
+/* |
+ * Copyright (c) 2009 The Chromium Authors. All rights reserved. |
+ * |
+ * Redistribution and use in source and binary forms, with or without |
+ * modification, are permitted provided that the following conditions are |
+ * met: |
+ * |
+ * * Redistributions of source code must retain the above copyright |
+ * notice, this list of conditions and the following disclaimer. |
+ * * Redistributions in binary form must reproduce the above |
+ * copyright notice, this list of conditions and the following disclaimer |
+ * in the documentation and/or other materials provided with the |
+ * distribution. |
+ * * Neither the name of Google Inc. nor the names of its |
+ * contributors may be used to endorse or promote products derived from |
+ * this software without specific prior written permission. |
+ * |
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
+ */ |
+ |
+var gl = null; |
+var g_width = 0; |
+var g_height = 0; |
+var g_bumpTexture = null; |
+var g_envTexture = null; |
+var g_programObject = null; |
+var g_vbo = null; |
+var g_elementVbo = null; |
+var g_normalsOffset = 0; |
+var g_tangentsOffset = 0; |
+var g_binormalsOffset = 0; |
+var g_texCoordsOffset = 0; |
+var g_numElements = 0; |
+ |
+// Uniform variables |
+var g_worldLoc = 0; |
+var g_worldInverseTransposeLoc = 0; |
+var g_worldViewProjLoc = 0; |
+var g_viewInverseLoc = 0; |
+var g_normalSamplerLoc = 0; |
+var g_envSamplerLoc = 0; |
+ |
+var g_pendingTextureLoads = 0; |
+ |
+// The "model" matrix is the "world" matrix in Standard Annotations |
+// and Semantics |
+var model = new Matrix4x4(); |
+var view = new Matrix4x4(); |
+var projection = new Matrix4x4(); |
+ |
+var controller = null; |
+ |
+function main() { |
+ var c = document.getElementById("c"); |
+ gl = getWebGLContext(c); |
+ if (!gl) |
+ return; |
+ g_width = c.width; |
+ g_height = c.height; |
+ controller = new CameraController(c); |
+ // Try the following (and uncomment the "pointer-events: none;" in |
+ // the index.html) to try the more precise hit detection |
+ // controller = new CameraController(document.getElementById("body"), c, gl); |
+ controller.onchange = function(xRot, yRot) { |
+ draw(); |
+ }; |
+ init(); |
+ draw(); |
+} |
+ |
+function output(str) { |
+ document.body.appendChild(document.createTextNode(str)); |
+ document.body.appendChild(document.createElement("br")); |
+} |
+ |
+function checkGLError() { |
+ var error = gl.getError(); |
+ if (error != gl.NO_ERROR) { |
+ var str = "GL Error: " + error; |
+ output(str); |
+ throw str; |
+ } |
+} |
+ |
+function init() { |
+ gl.enable(gl.DEPTH_TEST); |
+ // Can use this to make the background opaque |
+ // gl.clearColor(0.3, 0.2, 0.2, 1.); |
+ gl.clearColor(0.0, 0.0, 0.0, 0.0); |
+ gl.viewport(0, 0, g_width, g_height); |
+ initTeapot(); |
+ initShaders(); |
+ g_bumpTexture = loadTexture("bump.jpg"); |
+ g_envTexture = loadCubeMap("skybox", "jpg"); |
+} |
+ |
+function initTeapot() { |
+ g_vbo = gl.createBuffer(); |
+ gl.bindBuffer(gl.ARRAY_BUFFER, g_vbo); |
+ gl.bufferData(gl.ARRAY_BUFFER, |
+ teapotPositions.byteLength + |
+ teapotNormals.byteLength + |
+ teapotTangents.byteLength + |
+ teapotBinormals.byteLength + |
+ teapotTexCoords.byteLength, |
+ gl.STATIC_DRAW); |
+ g_normalsOffset = teapotPositions.byteLength; |
+ g_tangentsOffset = g_normalsOffset + teapotNormals.byteLength; |
+ g_binormalsOffset = g_tangentsOffset + teapotTangents.byteLength; |
+ g_texCoordsOffset = g_binormalsOffset + teapotBinormals.byteLength; |
+ gl.bufferSubData(gl.ARRAY_BUFFER, 0, teapotPositions); |
+ gl.bufferSubData(gl.ARRAY_BUFFER, g_normalsOffset, teapotNormals); |
+ gl.bufferSubData(gl.ARRAY_BUFFER, g_tangentsOffset, teapotTangents); |
+ gl.bufferSubData(gl.ARRAY_BUFFER, g_binormalsOffset, teapotBinormals); |
+ gl.bufferSubData(gl.ARRAY_BUFFER, g_texCoordsOffset, teapotTexCoords); |
+ |
+ g_elementVbo = gl.createBuffer(); |
+ gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, g_elementVbo); |
+ gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, teapotIndices, gl.STATIC_DRAW); |
+ g_numElements = teapotIndices.length; |
+} |
+ |
+var bumpReflectVertexSource = [ |
+ "attribute vec3 g_Position;", |
+ "attribute vec3 g_TexCoord0;", |
+ "attribute vec3 g_Tangent;", |
+ "attribute vec3 g_Binormal;", |
+ "attribute vec3 g_Normal;", |
+ "", |
+ "uniform mat4 world;", |
+ "uniform mat4 worldInverseTranspose;", |
+ "uniform mat4 worldViewProj;", |
+ "uniform mat4 viewInverse;", |
+ "", |
+ "varying vec2 texCoord;", |
+ "varying vec3 worldEyeVec;", |
+ "varying vec3 worldNormal;", |
+ "varying vec3 worldTangent;", |
+ "varying vec3 worldBinorm;", |
+ "", |
+ "void main() {", |
+ " gl_Position = worldViewProj * vec4(g_Position.xyz, 1.);", |
+ " texCoord.xy = g_TexCoord0.xy;", |
+ " worldNormal = (worldInverseTranspose * vec4(g_Normal, 1.)).xyz;", |
+ " worldTangent = (worldInverseTranspose * vec4(g_Tangent, 1.)).xyz;", |
+ " worldBinorm = (worldInverseTranspose * vec4(g_Binormal, 1.)).xyz;", |
+ " vec3 worldPos = (world * vec4(g_Position, 1.)).xyz;", |
+ " worldEyeVec = normalize(worldPos - viewInverse[3].xyz);", |
+ "}" |
+ ].join("\n"); |
+ |
+var bumpReflectFragmentSource = [ |
+ "#ifdef GL_ES\n", |
+ "precision highp float;\n", |
+ "#endif\n", |
+ "const float bumpHeight = 0.2;", |
+ "", |
+ "uniform sampler2D normalSampler;", |
+ "uniform samplerCube envSampler;", |
+ "", |
+ "varying vec2 texCoord;", |
+ "varying vec3 worldEyeVec;", |
+ "varying vec3 worldNormal;", |
+ "varying vec3 worldTangent;", |
+ "varying vec3 worldBinorm;", |
+ "", |
+ "void main() {", |
+ " vec2 bump = (texture2D(normalSampler, texCoord.xy).xy * 2.0 - 1.0) * bumpHeight;", |
+ " vec3 normal = normalize(worldNormal);", |
+ " vec3 tangent = normalize(worldTangent);", |
+ " vec3 binormal = normalize(worldBinorm);", |
+ " vec3 nb = normal + bump.x * tangent + bump.y * binormal;", |
+ " nb = normalize(nb);", |
+ " vec3 worldEye = normalize(worldEyeVec);", |
+ " vec3 lookup = reflect(worldEye, nb);", |
+ " vec4 color = textureCube(envSampler, lookup);", |
+ " gl_FragColor = color;", |
+ "}" |
+ ].join("\n"); |
+ |
+function loadShader(type, shaderSrc) { |
+ var shader = gl.createShader(type); |
+ if (shader == null) { |
+ return null; |
+ } |
+ // Load the shader source |
+ gl.shaderSource(shader, shaderSrc); |
+ // Compile the shader |
+ gl.compileShader(shader); |
+ // Check the compile status |
+ if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) { |
+ var infoLog = gl.getShaderInfoLog(shader); |
+ output("Error compiling shader:\n" + infoLog); |
+ gl.deleteShader(shader); |
+ return null; |
+ } |
+ return shader; |
+} |
+ |
+function initShaders() { |
+ var vertexShader = loadShader(gl.VERTEX_SHADER, bumpReflectVertexSource); |
+ var fragmentShader = loadShader(gl.FRAGMENT_SHADER, bumpReflectFragmentSource); |
+ // Create the program object |
+ var programObject = gl.createProgram(); |
+ if (programObject == null) { |
+ output("Creating program failed"); |
+ return; |
+ } |
+ gl.attachShader(programObject, vertexShader); |
+ gl.attachShader(programObject, fragmentShader); |
+ // Bind attributes |
+ gl.bindAttribLocation(programObject, 0, "g_Position"); |
+ gl.bindAttribLocation(programObject, 1, "g_TexCoord0"); |
+ gl.bindAttribLocation(programObject, 2, "g_Tangent"); |
+ gl.bindAttribLocation(programObject, 3, "g_Binormal"); |
+ gl.bindAttribLocation(programObject, 4, "g_Normal"); |
+ // Link the program |
+ gl.linkProgram(programObject); |
+ // Check the link status |
+ var linked = gl.getProgramParameter(programObject, gl.LINK_STATUS); |
+ if (!linked) { |
+ var infoLog = gl.getProgramInfoLog(programObject); |
+ output("Error linking program:\n" + infoLog); |
+ gl.deleteProgram(programObject); |
+ return; |
+ } |
+ g_programObject = programObject; |
+ // Look up uniform locations |
+ g_worldLoc = gl.getUniformLocation(g_programObject, "world"); |
+ g_worldInverseTransposeLoc = gl.getUniformLocation(g_programObject, "worldInverseTranspose"); |
+ g_worldViewProjLoc = gl.getUniformLocation(g_programObject, "worldViewProj"); |
+ g_viewInverseLoc = gl.getUniformLocation(g_programObject, "viewInverse"); |
+ g_normalSamplerLoc = gl.getUniformLocation(g_programObject, "normalSampler"); |
+ g_envSamplerLoc = gl.getUniformLocation(g_programObject, "envSampler"); |
+ checkGLError(); |
+} |
+ |
+function draw() { |
+ // Note: the viewport is automatically set up to cover the entire Canvas. |
+ gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT); |
+ checkGLError(); |
+ |
+ // For now, don't render if we have incomplete textures, just to |
+ // avoid accidentally incurring OpenGL errors -- although we should |
+ // be fully able to load textures in in the background |
+ if (g_pendingTextureLoads > 0) { |
+ gl.flush(); |
+ return; |
+ } |
+ |
+ // Set up the model, view and projection matrices |
+ projection.loadIdentity(); |
+ projection.perspective(45, g_width / g_height, 10, 500); |
+ view.loadIdentity(); |
+ view.translate(0, -10, -100.0); |
+ |
+ // Add in camera controller's rotation |
+ model.loadIdentity(); |
+ model.rotate(controller.xRot, 1, 0, 0); |
+ model.rotate(controller.yRot, 0, 1, 0); |
+ |
+ // Correct for initial placement and orientation of model |
+ model.translate(0, -10, 0); |
+ model.rotate(90, 1, 0, 0); |
+ |
+ gl.useProgram(g_programObject); |
+ |
+ // Compute necessary matrices |
+ var mvp = new Matrix4x4(); |
+ mvp.multiply(model); |
+ mvp.multiply(view); |
+ mvp.multiply(projection); |
+ var worldInverseTranspose = model.inverse(); |
+ worldInverseTranspose.transpose(); |
+ var viewInverse = view.inverse(); |
+ |
+ // Set up uniforms |
+ gl.uniformMatrix4fv(g_worldLoc, gl.FALSE, new Float32Array(model.elements)); |
+ gl.uniformMatrix4fv(g_worldInverseTransposeLoc, gl.FALSE, new Float32Array(worldInverseTranspose.elements)); |
+ gl.uniformMatrix4fv(g_worldViewProjLoc, gl.FALSE, new Float32Array(mvp.elements)); |
+ gl.uniformMatrix4fv(g_viewInverseLoc, gl.FALSE, new Float32Array(viewInverse.elements)); |
+ gl.activeTexture(gl.TEXTURE0); |
+ gl.bindTexture(gl.TEXTURE_2D, g_bumpTexture); |
+ gl.uniform1i(g_normalSamplerLoc, 0); |
+ gl.activeTexture(gl.TEXTURE1); |
+ gl.bindTexture(gl.TEXTURE_CUBE_MAP, g_envTexture); |
+ gl.uniform1i(g_envSamplerLoc, 1); |
+ checkGLError(); |
+ |
+ // Bind and set up vertex streams |
+ gl.bindBuffer(gl.ARRAY_BUFFER, g_vbo); |
+ gl.vertexAttribPointer(0, 3, gl.FLOAT, false, 0, 0); |
+ gl.enableVertexAttribArray(0); |
+ gl.vertexAttribPointer(1, 3, gl.FLOAT, false, 0, g_texCoordsOffset); |
+ gl.enableVertexAttribArray(1); |
+ gl.vertexAttribPointer(2, 3, gl.FLOAT, false, 0, g_tangentsOffset); |
+ gl.enableVertexAttribArray(2); |
+ gl.vertexAttribPointer(3, 3, gl.FLOAT, false, 0, g_binormalsOffset); |
+ gl.enableVertexAttribArray(3); |
+ gl.vertexAttribPointer(4, 3, gl.FLOAT, false, 0, g_normalsOffset); |
+ gl.enableVertexAttribArray(4); |
+ gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, g_elementVbo); |
+ checkGLError(); |
+ gl.drawElements(gl.TRIANGLES, g_numElements, gl.UNSIGNED_SHORT, 0); |
+ gl.flush(); |
+} |
+ |
+function loadTexture(src) { |
+ var texture = gl.createTexture(); |
+ gl.bindTexture(gl.TEXTURE_2D, texture); |
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR); |
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR); |
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.REPEAT); |
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.REPEAT); |
+ ++g_pendingTextureLoads; |
+ var image = new Image(); |
+ image.onload = function() { |
+ --g_pendingTextureLoads; |
+ 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, image); |
+ checkGLError(); |
+ draw(); |
+ waitForFinish(); |
+ }; |
+ image.src = src; |
+ return texture; |
+} |
+ |
+function loadCubeMap(base, suffix) { |
+ var texture = gl.createTexture(); |
+ gl.bindTexture(gl.TEXTURE_CUBE_MAP, texture); |
+ checkGLError(); |
+ gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); |
+ checkGLError(); |
+ gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE); |
+ checkGLError(); |
+ // FIXME: TEXTURE_WRAP_R doesn't exist in OpenGL ES?! |
+ // gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_WRAP_R, gl.CLAMP_TO_EDGE); |
+ // checkGLError(); |
+ gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_MIN_FILTER, gl.LINEAR); |
+ checkGLError(); |
+ gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_MAG_FILTER, gl.LINEAR); |
+ checkGLError(); |
+ var faces = [["posx", gl.TEXTURE_CUBE_MAP_POSITIVE_X], |
+ ["negx", gl.TEXTURE_CUBE_MAP_NEGATIVE_X], |
+ ["posy", gl.TEXTURE_CUBE_MAP_POSITIVE_Y], |
+ ["negy", gl.TEXTURE_CUBE_MAP_NEGATIVE_Y], |
+ ["posz", gl.TEXTURE_CUBE_MAP_POSITIVE_Z], |
+ ["negz", gl.TEXTURE_CUBE_MAP_NEGATIVE_Z]]; |
+ for (var i = 0; i < faces.length; i++) { |
+ var url = base + "-" + faces[i][0] + "." + suffix; |
+ var face = faces[i][1]; |
+ ++g_pendingTextureLoads; |
+ var image = new Image(); |
+ // Javascript has function, not block, scope. |
+ // See "JavaScript: The Good Parts", Chapter 4, "Functions", |
+ // section "Scope". |
+ image.onload = function(texture, face, image, url) { |
+ return function() { |
+ --g_pendingTextureLoads; |
+ gl.bindTexture(gl.TEXTURE_CUBE_MAP, texture); |
+ gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, false); |
+ gl.texImage2D( |
+ face, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, image); |
+ checkGLError(); |
+ draw(); |
+ waitForFinish(); |
+ } |
+ }(texture, face, image, url); |
+ image.src = url; |
+ } |
+ return texture; |
+} |
+ |
+function waitForFinish() { |
+ if (g_pendingTextureLoads == 0) { |
+ domAutomationController.setAutomationId(1); |
+ domAutomationController.send("ok"); |
+ } |
+} |
Property changes on: chrome\test\data\gpu\webgl_teapot\teapot_files\demo.js |
___________________________________________________________________ |
Added: svn:eol-style |
+ LF |