diff options
author | luchen@google.com <luchen@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-06-17 22:51:39 +0000 |
---|---|---|
committer | luchen@google.com <luchen@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-06-17 22:51:39 +0000 |
commit | 084391bc16e3cc8696ae40eaea28b7f2d4009d69 (patch) | |
tree | b2dac0727ae0bbd0d6dc555b5a41b01ba2558234 /o3d | |
parent | 3e069baf03d84e01ff9814709038ecb12d620b91 (diff) | |
download | chromium_src-084391bc16e3cc8696ae40eaea28b7f2d4009d69.zip chromium_src-084391bc16e3cc8696ae40eaea28b7f2d4009d69.tar.gz chromium_src-084391bc16e3cc8696ae40eaea28b7f2d4009d69.tar.bz2 |
o3d-webgl: adding generate-texture demo, with implementation of texture.set.
Review URL: http://codereview.chromium.org/2821004
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@50154 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'o3d')
-rw-r--r-- | o3d/samples/o3d-webgl-samples/generate-texture.html | 259 | ||||
-rw-r--r-- | o3d/samples/o3d-webgl/texture.js | 119 |
2 files changed, 341 insertions, 37 deletions
diff --git a/o3d/samples/o3d-webgl-samples/generate-texture.html b/o3d/samples/o3d-webgl-samples/generate-texture.html new file mode 100644 index 0000000..7e10e51 --- /dev/null +++ b/o3d/samples/o3d-webgl-samples/generate-texture.html @@ -0,0 +1,259 @@ +<!-- +Copyright 2009, Google Inc. +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. +--> + +<!-- +How to generate a texture. +--> +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" + "http://www.w3.org/TR/html4/loose.dtd"> +<html> +<head> +<meta http-equiv="content-type" content="text/html; charset=UTF-8"> +<title> +Generate Texture. +</title> +<script type="text/javascript" src="../o3d-webgl/base.js"></script> +<script type="text/javascript" src="../o3djs/base.js"></script> +<script type="text/javascript" id="o3dscript"> +o3djs.base.o3d = o3d; +o3djs.require('o3djs.webgl'); +o3djs.require('o3djs.util'); +o3djs.require('o3djs.math'); +o3djs.require('o3djs.rendergraph'); +o3djs.require('o3djs.primitives'); +o3djs.require('o3djs.material'); + +// global variables +var g_o3d; +var g_math; +var g_client; +var g_pack; +var g_viewInfo; +var g_finished = false; // for selenium testing +var g_samplers = []; + +/** + * Creates the client area. + */ +function init() { + // Comment out the line below to run the sample in the browser + // JavaScript engine. This may be helpful for debugging. + o3djs.util.setMainEngine(o3djs.util.Engine.V8); + o3djs.webgl.makeClients(initStep2, 'FloatingPointTextures'); +} + +/** + * Initializes O3D, loads an effect, creates some textures + * and quads to display them. + * @param {Array} clientElements Array of o3d object elements. + */ +function initStep2(clientElements) { + // Initializes global variables and libraries. + var o3dElement = clientElements[0]; + g_o3d = o3dElement.o3d; + g_math = o3djs.math; + + // Set window.g_client as well. Otherwise when the sample runs in + // V8, selenium won't be able to find this variable (it can only see + // the browser environment). + window.g_client = g_client = o3dElement.client; + + // Create a pack to manage our resources/assets + g_pack = g_client.createPack(); + + // Create the render graph for a view. + g_viewInfo = o3djs.rendergraph.createBasicView( + g_pack, + g_client.root, + g_client.renderGraphRoot); + + var clientWidth = g_client.width; + var clientHeight = g_client.height; + g_viewInfo.drawContext.projection = g_math.matrix4.orthographic( + -clientWidth * 0.5, + clientWidth * 0.5, + -clientHeight * 0.5, + clientHeight * 0.5, + 0.001, + 1000); + g_viewInfo.drawContext.view = g_math.matrix4.lookAt( + [0, 500, 0], // eye + [0, 0, 0], // target + [0, 0, -1]); // up + + // Create and load the effects. + var effectInfos = { + texture_only: {name: 'texture-only-glsl.shader'} + }; + for (var key in effectInfos) { + var info = effectInfos[key]; + var material = o3djs.material.createMaterialFromFile( + g_pack, + '../shaders/' + info.name, + g_viewInfo.zOrderedDrawList); + + // Create a quad. + var shape = o3djs.primitives.createPlane(g_pack, + material, + 1, + 1, + 1, + 1); + info.shape = shape; + } + + // display our shape 4 times with 4 different textures + // by overriding the sampler on each instance. + for (var s = 0; s < 4; ++s) { + // create a transform for an instance + var transform = g_pack.createObject('Transform'); + var x = s % 3; + var z = Math.floor(s / 3); + transform.translate((x - 1) * 140, 0, (z - 0.5) * 140); + transform.scale(128, 1, 128); + transform.parent = g_client.root; + + // Create a ParamSampler on the transform with the same name as in + // the effect so this param will be used instead of the one on the material. + var samplerParam = transform.createParam('texSampler0', 'ParamSampler'); + + var sampler = g_pack.createObject('Sampler'); + samplerParam.value = sampler; + sampler.addressModeU = g_o3d.Sampler.CLAMP; + sampler.addressModeV = g_o3d.Sampler.CLAMP; + g_samplers[s] = sampler; + + // Create a texture. + { + var pixels = []; + var format; + + switch (s) { + case 0: { // XRGB8 + transform.addShape(effectInfos.texture_only.shape); + format = g_o3d.Texture.XRGB8; + for (var y = 0; y < 32; ++y) { + for (var x = 0; x < 32; ++x) { + var offset = (y * 32 + x) * 3; // rgb + var u = x / 32 * Math.PI * 0.5; + var v = y / 32 * Math.PI * 0.5; + pixels[offset + 0] = Math.cos(u); // red + pixels[offset + 1] = Math.sin(v); // green + pixels[offset + 2] = Math.sin(u); // blue + } + } + break; + } + case 1: { // ARGB8 + transform.addShape(effectInfos.texture_only.shape); + format = g_o3d.Texture.ARGB8; + for (var y = 0; y < 32; ++y) { + for (var x = 0; x < 32; ++x) { + var offset = (y * 32 + x) * 4; // rgba + var u = x / 32 * Math.PI * 0.5; + var v = y / 32 * Math.PI * 0.5; + pixels[offset + 0] = Math.floor(y / 4) % 2; // red + pixels[offset + 1] = Math.sin(v); // green + pixels[offset + 2] = Math.floor(x / 4) % 2; // blue + pixels[offset + 3] = Math.abs(Math.sin(v * 4)); // alpha + } + } + break; + } + case 2: { // ABGR16F + transform.addShape(effectInfos.texture_only.shape); + format = g_o3d.Texture.ABGR16F; + for (var y = 0; y < 32; ++y) { + for (var x = 0; x < 32; ++x) { + var offset = (y * 32 + x) * 4; // rgba + var u = x / 32 * Math.PI * 0.5; + var v = y / 32 * Math.PI * 0.5; + pixels[offset + 0] = Math.cos(v); // red + pixels[offset + 1] = Math.sin(u); // green + pixels[offset + 2] = Math.sin(v); // blue + pixels[offset + 3] = Math.abs(Math.sin(u * 8)); // alpha + } + } + break; + } + case 3: { // ABGR32F + transform.addShape(effectInfos.texture_only.shape); + format = g_o3d.Texture.ABGR32F; + for (var y = 0; y < 32; ++y) { + for (var x = 0; x < 32; ++x) { + var offset = (y * 32 + x) * 4; // rgba + var u = x / 32 * Math.PI * 0.5; + var v = y / 32 * Math.PI * 0.5; + pixels[offset + 0] = Math.cos(v); // red + pixels[offset + 1] = Math.sin(u); // green + pixels[offset + 2] = Math.sin(v); // blue + pixels[offset + 3] = Math.abs(Math.sin(u * 8)); // alpha + } + } + break; + } + + /** + * Note that R32F is not supported in WebGL. + */ + } + var texture = g_pack.createTexture2D(32, 32, format, 1, false); + texture.set(0, pixels); + sampler.texture = texture; + } + } + window.o3d_prepForSelenium = prepForSelenium; + window.g_finished = true; // for selenium testing. +} + +// Turn off all filtering in the samplers to get consistent testing +// results. +function prepForSelenium() { + for (var i = 0; i < g_samplers.length; i++) { + g_samplers[i].magFilter = g_o3d.Sampler.POINT; + g_samplers[i].minFilter = g_o3d.Sampler.POINT; + g_samplers[i].mipFilter = g_o3d.Sampler.NONE; + } +} + + +</script> +</head> +<body onload="init()"> +<h1>Generate Texture</h1> +Shows how to create textures in Javascript. +<br/> + +<!-- Start of O3D plugin --> +<div id="o3d" style="width: 600px; height: 600px;"></div> +<!-- End of O3D plugin --> +</body> +</html> diff --git a/o3d/samples/o3d-webgl/texture.js b/o3d/samples/o3d-webgl/texture.js index e8ea889..cfc7b77 100644 --- a/o3d/samples/o3d-webgl/texture.js +++ b/o3d/samples/o3d-webgl/texture.js @@ -185,6 +185,34 @@ o3d.Texture.nextHighestPowerOfTwo_ = function(value) { /** + * Returns the GL texture format that is closest to this texture's O3D texture + * format. Not all formats specified in o3d.Texture have a webgl equivalent, + * thus we return the one with the correct number of channels, if such exists. + * + * @return {number} A webgl format. + * @private + */ +o3d.Texture.prototype.getGLTextureFormat_ = function() { + switch (this.format) { + case o3d.Texture.XRGB8: + return this.gl.RGB; + + case o3d.Texture.ARGB8: + case o3d.Texture.ABGR16F: + case o3d.Texture.ABGR32F: + return this.gl.RGBA; + + case o3d.Texture.R32F: + case o3d.Texture.DXT1: + case o3d.Texture.DXT3: + case o3d.Texture.DXT5: + notImplemented(); + return 0; + } +} + + +/** * Creates a webgl texture from the given image object rescaling to the * smallest power of 2 in each dimension still no smaller than the original * size. @@ -231,6 +259,54 @@ o3d.Texture.prototype.setFromCanvas_ = /** + * Sets the values of the data stored in the texture. + * + * It is not recommend that you call this for large textures but it is useful + * for making simple ramps or noise textures for shaders. + * + * NOTE: the number of values must equal the size of the texture * the number + * of elements. In other words, for a XRGB8 texture there must be + * width * height * 3 values. For an ARGB8, ABGR16F or ABGR32F texture there + * must be width * height * 4 values. For an R32F texture there must be + * width * height values. + * + * NOTE: the order of channels is R G B for XRGB8 textures and R G B A + * for ARGB8, ABGR16F and ABGR32F textures so for example for XRGB8 textures + * + * [1, 0, 0] = a red pixel + * [0, 0, 1] = a blue pixel + * + * For ARGB8, ABGR16F, ABGR32F textures + * + * [1, 0, 0, 0] = a red pixel with zero alpha + * [1, 0, 0, 1] = a red pixel with one alpha + * [0, 0, 1, 1] = a blue pixel with one alpha + * + * @param {number} level the mip level to update. + * @param {number} values Values to be stored in the buffer. + */ +o3d.Texture.prototype.set = + function(level, values) { + var target = this.texture_target_; + if (target == this.gl.TEXTURE_CUBE_MAP) { + target = this.gl.TEXTURE_CUBE_MAP_POSITIVE_X + face; + } + + var pixels = new WebGLUnsignedByteArray(values.length); + for (var i = 0; i < values.length; ++i) { + pixels[i] = Math.min(255, Math.max(0, values[i] * 256.0)); + } + + var format = this.getGLTextureFormat_(); + + this.gl.bindTexture(target, this.texture_); + this.gl.texSubImage2D( + target, level, 0, 0, this.texture_width_, this.texture_height_, + format, this.gl.UNSIGNED_BYTE, pixels); +}; + + +/** * A class for 2D textures that defines the interface for getting * the dimensions of the texture, its memory format and number of mipmap levels. * @@ -264,7 +340,6 @@ o3d.inherit('Texture2D', 'Texture'); o3d.ParamObject.setUpO3DParam_(o3d.Texture2D, 'width', 'ParamInteger'); o3d.ParamObject.setUpO3DParam_(o3d.Texture2D, 'height', 'ParamInteger'); - /** * Initializes this Texture2D object of the specified size and format and * reserves the necessary resources for it. @@ -285,6 +360,7 @@ o3d.Texture2D.prototype.init_ = function(width, height, format, levels, enable_render_surfaces) { this.width = width; this.height = height; + this.format = format; this.levels = levels; this.texture_ = this.gl.createTexture(); this.texture_target_ = this.gl.TEXTURE_2D; @@ -292,11 +368,13 @@ o3d.Texture2D.prototype.init_ = if (width != undefined && height != undefined) { this.gl.bindTexture(this.gl.TEXTURE_2D, this.texture_); + var format = this.getGLTextureFormat_(); + // TODO(petersont): remove this allocation once Firefox supports // passing null as argument to this form of ... some function. - var t = new WebGLUnsignedByteArray(width * height * 4); - this.gl.texImage2D(this.gl.TEXTURE_2D, 0, this.gl.RGBA, width, height, - 0, this.gl.RGBA, this.gl.UNSIGNED_BYTE, t); + var pixels = new WebGLUnsignedByteArray(width * height * 4); + this.gl.texImage2D(this.gl.TEXTURE_2D, 0, format, width, height, + 0, format, this.gl.UNSIGNED_BYTE, pixels); this.texture_width_ = width; this.texture_height_ = height; } @@ -323,39 +401,6 @@ o3d.Texture2D.prototype.getRenderSurface = /** - * Sets the values of the data stored in the texture. - * - * It is not recommend that you call this for large textures but it is useful - * for making simple ramps or noise textures for shaders. - * - * NOTE: the number of values must equal the size of the texture * the number - * of elements. In other words, for a XRGB8 texture there must be - * width * height * 3 values. For an ARGB8, ABGR16F or ABGR32F texture there - * must be width * height * 4 values. For an R32F texture there must be - * width * height values. - * - * NOTE: the order of channels is R G B for XRGB8 textures and R G B A - * for ARGB8, ABGR16F and ABGR32F textures so for example for XRGB8 textures\n - * \n - * [1, 0, 0] = a red pixel\n - * [0, 0, 1] = a blue pixel\n - * \n - * For ARGB8, ABGR16F, ABGR32F textures\n - * \n - * [1, 0, 0, 0] = a red pixel with zero alpha\n - * [1, 0, 0, 1] = a red pixel with one alpha\n - * [0, 0, 1, 1] = a blue pixel with one alpha\n - * - * @param {number} level the mip level to update. - * @param {number} values Values to be stored in the buffer. - */ -o3d.Texture2D.prototype.set = - function(level, values) { - o3d.notImplemented(); -}; - - -/** * Sets a rectangular area of values in a texture. * * Does clipping. In other words if you pass in a 10x10 pixel array |