| // Copyright 2011 The Chromium Authors | |
| // Use of this source code is governed by a BSD-style license that can be | |
| // found in the LICENSE file. | |
| WebGLTestUtils = (function() { | |
| /** | |
| * Converts a WebGL enum to a string | |
| * @param {!WebGLContext} gl The WebGLContext to use. | |
| * @param {number} value The enum value. | |
| * @return {string} The enum as a string. | |
| */ | |
| var glEnumToString = function(gl, value) { | |
| for (var p in gl) { | |
| if (gl[p] == value) { | |
| return p; | |
| } | |
| } | |
| return '0x' + value.toString(16); | |
| }; | |
| var lastError = ''; | |
| /** | |
| * Returns the last compiler/linker error. | |
| * @return {string} The last compiler/linker error. | |
| */ | |
| var getLastError = function() { | |
| return lastError; | |
| }; | |
| // clang-format off | |
| /** | |
| * A vertex shader for a single texture. | |
| * @type {string} | |
| */ | |
| var simpleTextureVertexShader = [ | |
| 'attribute vec4 vPosition;', // | |
| 'attribute vec2 texCoord0;', | |
| 'varying vec2 texCoord;', | |
| 'void main() {', | |
| ' gl_Position = vPosition;', | |
| ' texCoord = texCoord0;', | |
| '}' | |
| ].join('\n'); | |
| /** | |
| * A fragment shader for a single texture. | |
| * @type {string} | |
| */ | |
| var simpleTextureFragmentShader = [ | |
| 'precision mediump float;', | |
| 'uniform sampler2D tex;', | |
| 'varying vec2 texCoord;', | |
| 'void main() {', | |
| ' gl_FragData[0] = texture2D(tex, texCoord);', | |
| '}' | |
| ].join('\n'); | |
| // clang-format on | |
| /** | |
| * Creates a simple texture vertex shader. | |
| * @param {!WebGLContext} gl The WebGLContext to use. | |
| * @return {!WebGLShader} | |
| */ | |
| var setupSimpleTextureVertexShader = function(gl) { | |
| return loadShader(gl, simpleTextureVertexShader, gl.VERTEX_SHADER); | |
| }; | |
| /** | |
| * Creates a simple texture fragment shader. | |
| * @param {!WebGLContext} gl The WebGLContext to use. | |
| * @return {!WebGLShader} | |
| */ | |
| var setupSimpleTextureFragmentShader = function(gl) { | |
| return loadShader(gl, simpleTextureFragmentShader, gl.FRAGMENT_SHADER); | |
| }; | |
| /** | |
| * Creates a program, attaches shaders, binds attrib locations, links the | |
| * program and calls useProgram. | |
| * @param {!Array.<!WebGLShader>} shaders The shaders to attach . | |
| * @param {!Array.<string>} opt_attribs The attribs names. | |
| * @param {!Array.<number>} opt_locations The locations for the attribs. | |
| */ | |
| var setupProgram = function(gl, shaders, opt_attribs, opt_locations) { | |
| var realShaders = []; | |
| var program = gl.createProgram(); | |
| for (var ii = 0; ii < shaders.length; ++ii) { | |
| var shader = shaders[ii]; | |
| if (typeof shader == 'string') { | |
| var element = document.getElementById(shader); | |
| if (element) { | |
| shader = loadShaderFromScript(gl, shader); | |
| } else { | |
| shader = loadShader( | |
| gl, shader, ii ? gl.FRAGMENT_SHADER : gl.VERTEX_SHADER); | |
| } | |
| } | |
| gl.attachShader(program, shader); | |
| } | |
| if (opt_attribs) { | |
| for (var ii = 0; ii < opt_attribs.length; ++ii) { | |
| gl.bindAttribLocation( | |
| program, opt_locations ? opt_locations[ii] : ii, opt_attribs[ii]); | |
| } | |
| } | |
| gl.linkProgram(program); | |
| // Check the link status | |
| var linked = gl.getProgramParameter(program, gl.LINK_STATUS); | |
| if (!linked) { | |
| gl.deleteProgram(program); | |
| return null; | |
| } | |
| gl.useProgram(program); | |
| return program; | |
| }; | |
| /** | |
| * Creates a simple texture program. | |
| * @param {!WebGLContext} gl The WebGLContext to use. | |
| * @param {number} opt_positionLocation The attrib location for position. | |
| * @param {number} opt_texcoordLocation The attrib location for texture | |
| * coords. | |
| * @return {WebGLProgram} | |
| */ | |
| var setupSimpleTextureProgram = function( | |
| gl, opt_positionLocation, opt_texcoordLocation) { | |
| opt_positionLocation = opt_positionLocation || 0; | |
| opt_texcoordLocation = opt_texcoordLocation || 1; | |
| var vs = setupSimpleTextureVertexShader(gl); | |
| var fs = setupSimpleTextureFragmentShader(gl); | |
| if (!vs || !fs) { | |
| return null; | |
| } | |
| var program = setupProgram( | |
| gl, [vs, fs], ['vPosition', 'texCoord0'], | |
| [opt_positionLocation, opt_texcoordLocation]); | |
| if (!program) { | |
| gl.deleteShader(fs); | |
| gl.deleteShader(vs); | |
| } | |
| gl.useProgram(program); | |
| return program; | |
| }; | |
| /** | |
| * Creates buffers for a textured unit quad and attaches them to vertex | |
| * attribs. | |
| * @param {!WebGLContext} gl The WebGLContext to use. | |
| * @param {number} opt_positionLocation The attrib location for position. | |
| * @param {number} opt_texcoordLocation The attrib location for texture | |
| * coords. | |
| * @return {!Array.<WebGLBuffer>} The buffer objects that were | |
| * created. | |
| */ | |
| var setupUnitQuad = function(gl, opt_positionLocation, opt_texcoordLocation) { | |
| opt_positionLocation = opt_positionLocation || 0; | |
| opt_texcoordLocation = opt_texcoordLocation || 1; | |
| var objects = []; | |
| var vertexObject = gl.createBuffer(); | |
| gl.bindBuffer(gl.ARRAY_BUFFER, vertexObject); | |
| gl.bufferData( | |
| gl.ARRAY_BUFFER, new Float32Array([ | |
| 1.0, 1.0, 0.0, -1.0, 1.0, 0.0, -1.0, -1.0, 0.0, 1.0, 1.0, 0.0, -1.0, | |
| -1.0, 0.0, 1.0, -1.0, 0.0 | |
| ]), | |
| gl.STATIC_DRAW); | |
| gl.enableVertexAttribArray(opt_positionLocation); | |
| gl.vertexAttribPointer(opt_positionLocation, 3, gl.FLOAT, false, 0, 0); | |
| objects.push(vertexObject); | |
| var vertexObject = gl.createBuffer(); | |
| gl.bindBuffer(gl.ARRAY_BUFFER, vertexObject); | |
| gl.bufferData( | |
| gl.ARRAY_BUFFER, | |
| new Float32Array( | |
| [1.0, 1.0, 0.0, 1.0, 0.0, 0.0, 1.0, 1.0, 0.0, 0.0, 1.0, 0.0]), | |
| gl.STATIC_DRAW); | |
| gl.enableVertexAttribArray(opt_texcoordLocation); | |
| gl.vertexAttribPointer(opt_texcoordLocation, 2, gl.FLOAT, false, 0, 0); | |
| objects.push(vertexObject); | |
| return objects; | |
| }; | |
| /** | |
| * Creates a program and buffers for rendering a textured quad. | |
| * @param {!WebGLContext} gl The WebGLContext to use. | |
| * @param {number} opt_positionLocation The attrib location for position. | |
| * @param {number} opt_texcoordLocation The attrib location for texture | |
| * coords. | |
| * @return {!WebGLProgram} | |
| */ | |
| var setupTexturedQuad = function( | |
| gl, opt_positionLocation, opt_texcoordLocation) { | |
| var program = setupSimpleTextureProgram( | |
| gl, opt_positionLocation, opt_texcoordLocation); | |
| setupUnitQuad(gl, opt_positionLocation, opt_texcoordLocation); | |
| return program; | |
| }; | |
| /** | |
| * Draws a previously setup quad. | |
| * @param {!WebGLContext} gl The WebGLContext to use. | |
| * @param {!Array.<number>} opt_color The color to fill clear with before | |
| * drawing. A 4 element array where each element is in the range 0 to | |
| * 255. Default [255, 255, 255, 255] | |
| */ | |
| var drawQuad = function(gl, opt_color) { | |
| opt_color = opt_color || [255, 255, 255, 255]; | |
| gl.clearColor( | |
| opt_color[0] / 255, opt_color[1] / 255, opt_color[2] / 255, | |
| opt_color[3] / 255); | |
| gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT); | |
| gl.drawArrays(gl.TRIANGLES, 0, 6); | |
| }; | |
| /** | |
| * Links a WebGL program, throws if there are errors. | |
| * @param {!WebGLContext} gl The WebGLContext to use. | |
| * @param {!WebGLProgram} program The WebGLProgram to link. | |
| * @param {function(string): void) opt_errorCallback callback for errors. | |
| */ | |
| var linkProgram = function(gl, program, opt_errorCallback) { | |
| // Link the program | |
| gl.linkProgram(program); | |
| // Check the link status | |
| var linked = gl.getProgramParameter(program, gl.LINK_STATUS); | |
| if (!linked) { | |
| // something went wrong with the link | |
| gl.deleteProgram(program); | |
| return false; | |
| } | |
| return true; | |
| }; | |
| /** | |
| * Loads a shader. | |
| * @param {!WebGLContext} gl The WebGLContext to use. | |
| * @param {string} shaderSource The shader source. | |
| * @param {number} shaderType The type of shader. | |
| * @param {function(string): void) opt_errorCallback callback for errors. | |
| * @return {!WebGLShader} The created shader. | |
| */ | |
| var loadShader = | |
| function(gl, shaderSource, shaderType, opt_errorCallback) { | |
| var errFn = opt_errorCallback || (_ => {}); | |
| // Create the shader object | |
| var shader = gl.createShader(shaderType); | |
| if (shader == null) { | |
| errFn('*** Error: unable to create shader \'' + shaderSource + '\''); | |
| return null; | |
| } | |
| // Load the shader source | |
| gl.shaderSource(shader, shaderSource); | |
| var err = gl.getError(); | |
| if (err != gl.NO_ERROR) { | |
| errFn( | |
| '*** Error loading shader \'' + shader + | |
| '\':' + glEnumToString(gl, err)); | |
| return null; | |
| } | |
| // Compile the shader | |
| gl.compileShader(shader); | |
| // Check the compile status | |
| var compiled = gl.getShaderParameter(shader, gl.COMPILE_STATUS); | |
| if (!compiled) { | |
| // Something went wrong during compilation; get the error | |
| lastError = gl.getShaderInfoLog(shader); | |
| errFn('*** Error compiling shader \'' + shader + '\':' + lastError); | |
| gl.deleteShader(shader); | |
| return null; | |
| } | |
| return shader; | |
| } | |
| /** | |
| * Loads shaders from source, creates a program, attaches the shaders and | |
| * links. | |
| * @param {!WebGLContext} gl The WebGLContext to use. | |
| * @param {string} vertexShader The vertex shader. | |
| * @param {string} fragmentShader The fragment shader. | |
| * @param {function(string): void) opt_errorCallback callback for errors. | |
| * @return {!WebGLProgram} The created program. | |
| */ | |
| var loadProgram = function( | |
| gl, vertexShader, fragmentShader, opt_errorCallback) { | |
| var program = gl.createProgram(); | |
| gl.attachShader( | |
| program, | |
| loadShader(gl, vertexShader, gl.VERTEX_SHADER, opt_errorCallback)); | |
| gl.attachShader( | |
| program, | |
| loadShader(gl, fragmentShader, gl.FRAGMENT_SHADER, opt_errorCallback)); | |
| return linkProgram(gl, program, opt_errorCallback) ? program : null; | |
| }; | |
| return { | |
| drawQuad: drawQuad, | |
| getLastError: getLastError, | |
| glEnumToString: glEnumToString, | |
| loadProgram: loadProgram, | |
| loadShader: loadShader, | |
| setupProgram: setupProgram, | |
| setupSimpleTextureFragmentShader: setupSimpleTextureFragmentShader, | |
| setupSimpleTextureProgram: setupSimpleTextureProgram, | |
| setupSimpleTextureVertexShader: setupSimpleTextureVertexShader, | |
| setupTexturedQuad: setupTexturedQuad, | |
| setupUnitQuad: setupUnitQuad, | |
| }; | |
| }()); |