Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(2568)

Unified Diff: chrome/test/data/gpu/webgl_teapot/teapot_files/demo.js

Issue 4723006: Add test fixture for GPU browser tests which do image comparisons.... (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: '' Created 10 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
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
« no previous file with comments | « chrome/test/data/gpu/webgl_teapot/teapot_files/context.js ('k') | chrome/test/data/gpu/webgl_teapot/teapot_files/matrix4x4.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698