diff options
author | petersont@google.com <petersont@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-08-29 02:56:15 +0000 |
---|---|---|
committer | petersont@google.com <petersont@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-08-29 02:56:15 +0000 |
commit | 1fc0028e763b6fcfba140940fa33bdec0502a473 (patch) | |
tree | 523d836c073364782cb0fa172b4158d52002bec8 /o3d/samples | |
parent | 41ffdc7bf92a79ca6d6b917ab943989185b9d1a0 (diff) | |
download | chromium_src-1fc0028e763b6fcfba140940fa33bdec0502a473.zip chromium_src-1fc0028e763b6fcfba140940fa33bdec0502a473.tar.gz chromium_src-1fc0028e763b6fcfba140940fa33bdec0502a473.tar.bz2 |
Added capability for an error (default) cube map texture, so if a cube sampler doesn't have a texture associated with it, it doesn't choke WebGL.
Review URL: http://codereview.chromium.org/3162048
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@57808 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'o3d/samples')
-rw-r--r-- | o3d/samples/o3d-webgl/client.js | 79 | ||||
-rw-r--r-- | o3d/samples/o3d-webgl/effect.js | 18 | ||||
-rw-r--r-- | o3d/samples/o3d-webgl/param.js | 8 | ||||
-rw-r--r-- | o3d/samples/o3d-webgl/primitive.js | 5 | ||||
-rw-r--r-- | o3d/samples/o3d-webgl/sampler.js | 10 | ||||
-rw-r--r-- | o3d/samples/o3d-webgl/texture.js | 305 | ||||
-rw-r--r-- | o3d/samples/o3djs/texture.js | 4 |
7 files changed, 308 insertions, 121 deletions
diff --git a/o3d/samples/o3d-webgl/client.js b/o3d/samples/o3d-webgl/client.js index 3706958..5e940a6 100644 --- a/o3d/samples/o3d-webgl/client.js +++ b/o3d/samples/o3d-webgl/client.js @@ -449,7 +449,6 @@ o3d.Client.RENDERMODE_ON_DEMAND = 1; o3d.Client.prototype.renderMode = o3d.Client.RENDERMODE_CONTINUOUS; - /** * Forces a render of the current scene if the current render mode is * RENDERMODE_ON_DEMAND. @@ -517,7 +516,6 @@ o3d.Client.prototype.render_stats = {} */ o3d.Client.prototype.renderTree = function(render_node) { - this.render_stats_ = { drawElementsCulled: 0, drawElementsProcessed: 0, @@ -678,10 +676,18 @@ o3d.Client.prototype.initWithCanvas = function(canvas) { height: canvas.height}; o3d.State.createDefaultState_(gl).push_(); - // Create the default error texture. - var defaultTexture = new o3d.Texture2D(); - defaultTexture.gl = this.gl; - defaultTexture.init_(8, 8, o3d.Texture.ARGB8, 1, false); + this.initErrorTextures_(); + + return true; +} + + +/** + * Creates the yellow-and-red 8x8 error textures. + * @private + */ +o3d.Client.prototype.initErrorTextures_ = function() { + // First create the yellow-and-red pattern. var r = [1, 0, 0, 1]; var Y = [1, 1, 0, 1]; var error = [r, r, r, r, r, r, r, r, @@ -698,12 +704,29 @@ o3d.Client.prototype.initWithCanvas = function(canvas) { pixels[i * 4 + j] = error[i][j]; } } + + // Create the default error cube map using the same data. + var defaultTextureCube = new o3d.TextureCUBE(); + + defaultTextureCube.gl = this.gl; + defaultTextureCube.init_(8, o3d.Texture.ARGB8, 1, false, true); + + for (var i = 0; i < 6; ++i) { + defaultTextureCube.set(i, 0, pixels); + } + defaultTextureCube.name = 'DefaultTextureCube'; + this.error_texture_cube_ = defaultTextureCube; + this.fallback_error_texture_cube_ = defaultTextureCube; + + // Create the default error texture. + var defaultTexture = new o3d.Texture2D(); + defaultTexture.gl = this.gl; + defaultTexture.init_(8, 8, o3d.Texture.ARGB8, 1, false); + defaultTexture.set(0, pixels); defaultTexture.name = 'DefaultTexture'; - this.fallback_error_texture_ = defaultTexture; this.error_texture_ = defaultTexture; - - return true; + this.fallback_error_texture_ = defaultTexture; }; @@ -973,6 +996,21 @@ o3d.Client.prototype.setErrorTexture = /** + * Sets the cubemap texture to use when a Texture or Sampler is missing while + * rendering. The default is a red texture with a yellow no symbol. + * <span style="color:yellow; background-color: red;">Ø. + * If you set it to null you'll get an error if you try to render something + * that is missing a needed Texture, Sampler or ParamSampler. + * + * @param {o3d.Texture} texture Texture to use for missing textures or null. + */ +o3d.Client.prototype.setErrorTextureCube = + function(texture) { + this.error_texture_cube_map_ = texture; +}; + + +/** * Sets a callback for when the client ticks. The client processes some things * like animation timers at up to 100hz. This callback will get called before * each of those process ticks. @@ -1182,23 +1220,42 @@ o3d.Client.prototype.cursor = null; /** * The current error texture. * - * @type {o3d.Texture} + * @type {o3d.Texture2D} * @private */ o3d.Client.prototype.error_texture_ = null; /** + * The current error cube texture. + * + * @type {o3d.TextureCUBE} + * @private + */ +o3d.Client.prototype.error_texture_cube_ = null; + + +/** * The fallback error texture. Should only be initialized once per client and * is read-only. * - * @type {!o3d.Texture} + * @type {!o3d.Texture2D} * @private */ o3d.Client.prototype.fallback_error_texture_ = null; /** + * The fallback error texture. Should only be initialized once per client and + * is read-only. + * + * @type {!o3d.TextureCUBE} + * @private + */ +o3d.Client.prototype.fallback_error_texture_cube_ = null; + + +/** * The last error reported by the plugin. * * @type {string} diff --git a/o3d/samples/o3d-webgl/effect.js b/o3d/samples/o3d-webgl/effect.js index 3d9f85e..f45dab0 100644 --- a/o3d/samples/o3d-webgl/effect.js +++ b/o3d/samples/o3d-webgl/effect.js @@ -229,7 +229,7 @@ o3d.Effect.prototype.loadVertexShaderFromString = function(shaderString) { var success = this.loadShaderFromString(shaderString, this.gl.VERTEX_SHADER); - this.vertexShaderLoaded_ = true; + this.vertexShaderLoaded_ = success; o3d.Effect.prototype.bindAttributesAndLinkIfReady(); return success; }; @@ -244,7 +244,7 @@ o3d.Effect.prototype.loadPixelShaderFromString = function(shaderString) { var success = this.loadShaderFromString(shaderString, this.gl.FRAGMENT_SHADER); - this.fragmentShaderLoaded_ = true; + this.fragmentShaderLoaded_ = success; this.bindAttributesAndLinkIfReady(); return success; }; @@ -260,8 +260,11 @@ o3d.Effect.prototype.loadPixelShaderFromString = o3d.Effect.prototype.loadFromFXString = function(shaderString) { var splitIndex = shaderString.indexOf('// #o3d SplitMarker'); - return this.loadVertexShaderFromString(shaderString.substr(0, splitIndex)) && - this.loadPixelShaderFromString(shaderString.substr(splitIndex)); + var vertexShaderString = shaderString.substr(0, splitIndex); + var pixelShaderString = shaderString.substr(splitIndex); + var result = this.loadVertexShaderFromString(vertexShaderString) && + this.loadPixelShaderFromString(pixelShaderString); + return result; }; @@ -409,6 +412,7 @@ o3d.Effect.reverseSemanticMap_ = []; } })(); + /** * For each of the effect's uniform parameters, creates corresponding * parameters on the given ParamObject. Skips SAS Parameters. @@ -552,7 +556,11 @@ o3d.Effect.prototype.searchForParams_ = function(object_list) { if (uniformInfo.kind == o3d.Effect.ARRAY) { param.applyToLocations(this.gl, uniformInfo.locations); } else { - param.applyToLocation(this.gl, uniformInfo.location); + if (uniformInfo.info.type == this.gl.SAMPLER_CUBE) { + param.applyToLocation(this.gl, uniformInfo.location, true); + } else { + param.applyToLocation(this.gl, uniformInfo.location); + } } filled_map[name] = true; } diff --git a/o3d/samples/o3d-webgl/param.js b/o3d/samples/o3d-webgl/param.js index 0f8a819..9ea8bd0 100644 --- a/o3d/samples/o3d-webgl/param.js +++ b/o3d/samples/o3d-webgl/param.js @@ -893,8 +893,12 @@ o3d.Param.texture_index_ = 0; * Called to specify the value of a uniform variable. * @param {WebGLContext} gl The current context. * @param {WebGLUniformLocation} location The location to which to apply. + * @param {boolean} opt_isCube Optional boolean indicating whether the Sampler + * connects to a samplerCube type uniform. If set to true, and there is an + * error, we use the error cube map. */ -o3d.ParamSampler.prototype.applyToLocation = function(gl, location) { +o3d.ParamSampler.prototype.applyToLocation = + function(gl, location, opt_isCube) { // When before the effect object assigns values to parameters, // it sets this variable to 0. var i = o3d.Param.texture_index_; @@ -914,7 +918,7 @@ o3d.ParamSampler.prototype.applyToLocation = function(gl, location) { } } - sampler.bindAndSetParameters_(); + sampler.bindAndSetParameters_(opt_isCube); gl.uniform1i(location, i); o3d.Param.texture_index_++; }; diff --git a/o3d/samples/o3d-webgl/primitive.js b/o3d/samples/o3d-webgl/primitive.js index 7c15ac2..dcf8959 100644 --- a/o3d/samples/o3d-webgl/primitive.js +++ b/o3d/samples/o3d-webgl/primitive.js @@ -132,6 +132,10 @@ o3d.Primitive.prototype.render = function() { var field = stream.field; var buffer = field.buffer; + if (gl_index == undefined) { + this.gl.client.error_callback('uknown semantic'); + } + var stream_param = streams[semantic_index]; while (!stream_param.owner_.updateStreams && stream_param.inputConnection) { @@ -147,6 +151,7 @@ o3d.Primitive.prototype.render = function() { enabled_attribs.push(gl_index); var kFloatSize = Float32Array.BYTES_PER_ELEMENT; + this.gl.vertexAttribPointer( gl_index, field.numComponents, this.gl.FLOAT, false, buffer.totalComponents * kFloatSize, field.offset_ * kFloatSize); diff --git a/o3d/samples/o3d-webgl/sampler.js b/o3d/samples/o3d-webgl/sampler.js index e4d6513..60f94c0 100644 --- a/o3d/samples/o3d-webgl/sampler.js +++ b/o3d/samples/o3d-webgl/sampler.js @@ -260,13 +260,19 @@ o3d.Sampler.defaultSampler_.magFilter = o3d.Sampler.POINT; /** * Binds the texture for this sampler and sets texParameters according to the * states of the sampler. + * @param {boolean} opt_isCube Optional boolean indicating if this is a cube + * map, so we can use the right error texture. */ -o3d.Sampler.prototype.bindAndSetParameters_ = function() { +o3d.Sampler.prototype.bindAndSetParameters_ = function(opt_isCube) { var currentTexture = null; if (this.texture) { currentTexture = this.texture; } else if (!this.gl.client.reportErrors_()) { - currentTexture = this.gl.client.error_texture_; + if (opt_isCube) { + currentTexture = this.gl.client.error_texture_cube_; + } else { + currentTexture = this.gl.client.error_texture_; + } } else { currentTexture = this.gl.client.fallback_error_texture_; this.gl.client.error_callback("Missing texture for sampler " + this.name); diff --git a/o3d/samples/o3d-webgl/texture.js b/o3d/samples/o3d-webgl/texture.js index b2ee1a2..ec35293 100644 --- a/o3d/samples/o3d-webgl/texture.js +++ b/o3d/samples/o3d-webgl/texture.js @@ -65,6 +65,8 @@ o3d.Texture = function() { /** * The associated GL texture target: TEXTURE_2D or TEXTURE_CUBE_MAP. + * This is the argument "target" to calls to bindTeture. + * NOT THE SAME THING AS the argument "target" to texImage2D. * @type {number} * @private */ @@ -156,6 +158,7 @@ o3d.Texture.prototype.generateMips = function(source_level, num_levels) { this.gl.bindTexture(this.texture_target_, this.texture_); this.gl.generateMipmap(this.texture_target_); + this.levels = num_levels; }; @@ -214,6 +217,46 @@ o3d.Texture.prototype.getGLTextureFormat_ = function() { /** + * Helper function to determine the proper argument for the texture target + * This is either gl.TEXTURE_2D or gl.TEXTURE_CUBE_MAP_POSITIVE_X + face. + * + * @param {o3d.TextureCUBE.CubeFace} face The current face if applicable. + * @return {number} The proper argument for the texture target. + */ +o3d.Texture.prototype.getTexImage2DTarget_ = function(opt_face) { + if (this.texture_target_ == this.gl.TEXTURE_CUBE_MAP) { + return this.gl.TEXTURE_CUBE_MAP_POSITIVE_X + opt_face; + } else { + return this.gl.TEXTURE_2D; + } +}; + + +/** + * Computes the maximum number of levels of mips a given width and height could + * use. + * @param {number} width Width of texture. + * @param {number} height Height of texture. + * @return {number} The maximum number of levels for the given width and height. + */ +o3d.Texture.maxLevels_ = function(width, height) { + if (width == 0 || height == 0) { + return 0; + } + var max = Math.max(width, height); + var levels = 0; + while (max > 0) { + ++levels; + max = max >> 1; + } + return levels; +}; + + +var g_counter = 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. @@ -221,13 +264,13 @@ o3d.Texture.prototype.getGLTextureFormat_ = function() { * @param {boolean} resize_to_pot Whether or not to resize to a power of two * size. * @param {boolean} generate_mips Whether or not to generate mips. - * + * @param {o3d.TextureCUBE.CubeFace} opt_face The face number, if this is a + * cube map. * @private */ o3d.Texture.prototype.setFromCanvas_ = - function(canvas, resize_to_pot, flip, generate_mips, face) { + function(canvas, resize_to_pot, flip, generate_mips, opt_face) { var gl = this.gl; - gl.bindTexture(this.texture_target_, this.texture_); if (resize_to_pot && (!o3d.Texture.isPowerOfTwo_(canvas.width) || !o3d.Texture.isPowerOfTwo_(canvas.height))) { @@ -243,15 +286,15 @@ o3d.Texture.prototype.setFromCanvas_ = canvas = scratch; } - var target = this.texture_target_; - if (target == this.gl.TEXTURE_CUBE_MAP) { - target = this.gl.TEXTURE_CUBE_MAP_POSITIVE_X + face; - } - gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, flip); - gl.texImage2D( - target, 0 /*level*/, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, canvas); + + gl.bindTexture(this.texture_target_, this.texture_); + gl.texImage2D(this.getTexImage2DTarget_(opt_face), 0 /*level*/, gl.RGBA, + gl.RGBA, gl.UNSIGNED_BYTE, canvas); + gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, 0); + + this.texture_width_ = canvas.width; this.texture_height_ = canvas.height; @@ -259,33 +302,158 @@ o3d.Texture.prototype.setFromCanvas_ = // The texture target is already bound so why bind it again by calling // this.generateMip. this.gl.generateMipmap(this.texture_target_); + this.levels = o3d.Texture.maxLevels_( + this.texture_width_, this.texture_height_); } + + g_counter++; +}; + + +/** + * Copy pixels from source bitmap to certain mip level. + * Scales if the width and height of source and dest do not match. + * + * @param {HTMLCanvas} source_img The source canvas. + * @param {number} source_x x-coordinate of the starting pixel in the + * source image. + * @param {number} source_y y-coordinate of the starting pixel in the + * source image. + * @param {number} source_width width of the source image to draw. + * @param {number} source_height Height of the source image to draw. + * @param {number} dest_mip on which mip level to draw to. + * @param {number} dest_x x-coordinate of the starting pixel in the + * destination texture. + * @param {number} dest_y y-coordinate of the starting pixel in the + * destination texture. + * @param {number} dest_width width of the dest image. + * @param {number} dest_height height of the dest image. + * @param {number} opt_face The face number if this is a cube map. + */ +o3d.Texture.prototype.drawImageFromCanvas_ = + function(source_canvas, source_x, source_y, source_width, source_height, + dest_mip, dest_x, dest_y, dest_width, dest_height, opt_face) { + var canvas = o3d.Bitmap.getScratchCanvas_(); + canvas.width = dest_width; + canvas.height = dest_height; + + // Get a scratch canvas and set its size to that of the source material. + // Set up transformation so that the draw into the canvas fill it with the + // source bitmap. + var context = canvas.getContext('2d'); + context.save(); + + context.translate(-source_x, -source_y); + context.scale(dest_width / source_width, + dest_height / source_height); + + // Draw the source image into the canvas, filling it. + context.drawImage( + source_canvas, 0, 0, source_canvas.width, source_canvas.height); + + // Call texSubImage2D to upload the source image from the scratch canvas + // to the texture. + var gl = this.gl; + gl.bindTexture(this.texture_target_, this.texture_); + var format = this.getGLTextureFormat_(); + + //*/ + // TODO(petersont): Replace this with a call to texSubImage2D once + // browsers support it. + gl.texImage2D(this.getTexImage2DTarget_(opt_face), dest_mip, gl.RGBA, + gl.RGBA, gl.UNSIGNED_BYTE, canvas); + /*/ + gl.texSubImage2D(target, 0, dest_x, dest_y, dest_width, dest_height, + gl.RGBA, gl.UNSIGNED_BYTE, canvas); + //*/ + this.texture_width_ = canvas.width; + this.texture_height_ = canvas.height; + + context.restore(); }; /** * Sets the values of the data stored in the texture. * - * @param {number} target The target to bind this texture to. * @param {number} level the mip level to update. * @param {number} values Values to be stored in the buffer. + * @param {o3d.TextureCUBE.CubeFace} opt_face The face to set if this is a cube + * texture. * @private */ -o3d.Texture.prototype.setValues_ = function(target, level, values) { +o3d.Texture.prototype.setValues_ = function(level, values, opt_face) { var pixels = new Uint8Array(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_, + this.gl.bindTexture(this.texture_target_, this.texture_); + + this.gl.texSubImage2D(this.getTexImage2DTarget_(opt_face), + level, 0, 0, this.texture_width_, this.texture_height_, format, this.gl.UNSIGNED_BYTE, pixels); }; /** + * Initializes this Texture2D object of the specified size and format and + * reserves the necessary resources for it. + * + * Note: If enable_render_surfaces is true, then the dimensions must be a + * power of two. + * + * @param {number} texture_target The apropriate value for texture_target. + * @param {number} width The width of the texture area in texels (max = 2048) + * @param {number} height The height of the texture area in texels (max = 2048) + * @param {o3d.Texture.Format} format The memory format of each texel + * @param {number} levels The number of mipmap levels. Use zero to create the + * compelete mipmap chain. + * @param {boolean} enable_render_surfaces If true, the texture object will + * expose RenderSurface objects through GetRenderSurface(...). + * @return {!o3d.Texture2D} The Texture2D object. + */ +o3d.Texture.prototype.initWithTarget_ = + function(texture_target, width, height, format, levels, + enable_render_surfaces, debug) { + this.width = width; + this.height = height; + this.format = format; + this.levels = levels; + this.texture_ = this.gl.createTexture(); + this.texture_target_ = texture_target; + + if (width != undefined && height != undefined) { + this.gl.bindTexture(this.texture_target_, 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 pixels = new Uint8Array(width * height * 4); + + var canvas = o3d.Bitmap.getScratchCanvas_(); + canvas.width = width; + canvas.height = height; + + var numFaces = 1; + if (this.texture_target_ == this.gl.TEXTURE_CUBE_MAP) { + numFaces = 6; + } + + for (var face = 0; face < numFaces; ++face) { + this.gl.texImage2D(this.getTexImage2DTarget_(face), 0, format, width, + height, 0, format, this.gl.UNSIGNED_BYTE, pixels); + } + + this.texture_width_ = width; + this.texture_height_ = height; + } +}; + + +/** * A class for 2D textures that defines the interface for getting * the dimensions of the texture, its memory format and number of mipmap levels. * @@ -319,6 +487,7 @@ 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. @@ -337,26 +506,8 @@ o3d.ParamObject.setUpO3DParam_(o3d.Texture2D, 'height', 'ParamInteger'); */ 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; - - 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 pixels = new Uint8Array(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; - } + this.initWithTarget_(this.gl.TEXTURE_2D, + width, height, format, levels, enable_render_surfaces); }; @@ -408,8 +559,7 @@ o3d.Texture2D.prototype.getRenderSurface = */ o3d.Texture2D.prototype.set = function(level, values) { - var target = this.texture_target_; - this.setValues_(target, level, values); + this.setValues_(level, values); }; @@ -437,7 +587,6 @@ o3d.Texture2D.prototype.setRect = var format = this.getGLTextureFormat_(); var numChannels = (format == this.gl.RGB ? 3 : 4); var source_height = (values.length / numChannels) / source_width; - var target = this.texture_target_; // If completely clipped off, do nothing and return. if (destination_x > this.width || destination_y > this.height || @@ -484,9 +633,9 @@ o3d.Texture2D.prototype.setRect = var where_x = Math.max(destination_x, 0); var where_y = this.height - (Math.max(destination_y, 0) + size_y); - this.gl.bindTexture(target, this.texture_); - this.gl.texSubImage2D(target, level, where_x, where_y, size_x, size_y, - format, this.gl.UNSIGNED_BYTE, keptPixels); + this.gl.bindTexture(this.texture_target_, this.texture_); + this.gl.texSubImage2D(this.gl.TEXTURE_2D, level, where_x, where_y, + size_x, size_y, format, this.gl.UNSIGNED_BYTE, keptPixels); }; @@ -516,7 +665,7 @@ o3d.Texture2D.prototype.getRect = * @param {o3d.Bitmap} bitmap The bitmap to copy data from. */ o3d.Texture2D.prototype.setFromBitmap = function(bitmap) { - // Whether resize the texture to power-of-two size + // Whether to resize the texture to power-of-two size. var resize_to_pot = bitmap.defer_mipmaps_to_texture_; this.setFromCanvas_(bitmap.canvas_, resize_to_pot, @@ -526,12 +675,11 @@ o3d.Texture2D.prototype.setFromBitmap = function(bitmap) { /** - * Copy pixels from source bitmap to certain mip level. + * Copy pixels from source bitmap to certain face and mip level. * Scales if the width and height of source and dest do not match. - * TODO(petersont): Takes optional arguments. * * @param {o3d.Bitmap} source_img The source bitmap. - * @param {number} source_mip which mip from the source to copy from. + * @param {number} source_mip which mip of the source to copy from. * @param {number} source_x x-coordinate of the starting pixel in the * source image. * @param {number} source_y y-coordinate of the starting pixel in the @@ -543,35 +691,15 @@ o3d.Texture2D.prototype.setFromBitmap = function(bitmap) { * destination texture. * @param {number} dest_y y-coordinate of the starting pixel in the * destination texture. - * @param {number} dest_width width of the dest image. - * @param {number} dest_height height of the dest image. + * @param {number} dest_width width of the destination image. + * @param {number} dest_height height of the destination image. */ o3d.Texture2D.prototype.drawImage = function(source_img, source_mip, source_x, source_y, source_width, - source_height, dest_mip, dest_x, dest_y, dest_width, - dest_height) { - var canvas = o3d.Bitmap.getScratchCanvas_(); - canvas.width = dest_width; - canvas.height = dest_height; - - var context = canvas.getContext('2d'); - - context.translate(-source_x, -source_y); - context.scale(dest_width / source_width, - dest_height / source_height); - - context.drawImage(source_img.canvas_, - 0, 0, source_img.canvas_.width, source_img.canvas_.height); - - var gl = this.gl; - gl.bindTexture(gl.TEXTURE_2D, this.texture_); - // TODO(petersont): replace this with a call to texSubImage2D once - // Firefox supports it. - gl.texImage2D( - gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, canvas); - // this.gl.texSubImage2D(this.gl.TEXTURE_2D, 0, 0, 0, canvas); - this.texture_width_ = canvas.width; - this.texture_height_ = canvas.height; + source_height, dest_mip, dest_x, dest_y, dest_width, dest_height) { + this.drawImageFromCanvas_(source_img.canvas_, + source_x, source_y, source_width, source_height, dest_mip, + dest_x, dest_y, dest_width, dest_height); }; @@ -649,26 +777,9 @@ o3d.ParamObject.setUpO3DParam_(o3d.TextureCUBE, 'edgeLength', 'ParamInteger'); * @private */ o3d.TextureCUBE.prototype.init_ = - function(edgeLength, format, levels, enableRenderSurfaces) { - this.edgeLength = edgeLength; - this.texture_ = this.gl.createTexture(); - this.texture_target_ = this.gl.TEXTURE_CUBE_MAP; - this.texture_width_ = edgeLength; - this.texture_height_ = edgeLength; - this.format = format; - - this.gl.bindTexture(this.gl.TEXTURE_CUBE_MAP, this.texture_); - // TODO(petersont): remove this allocation once Firefox supports - // passing null as argument to this form of texImage2D. - var t = new Uint8Array(edgeLength * edgeLength * 4); - for (var ii = 0; ii < 6; ++ii) { - this.gl.texImage2D(this.gl.TEXTURE_CUBE_MAP_POSITIVE_X + ii, - 0, this.gl.RGBA, edgeLength, edgeLength, 0, - this.gl.RGBA, this.gl.UNSIGNED_BYTE, t); - } - - this.texture_width_ = edgeLength; - this.texture_height_ = edgeLength; + function(edgeLength, format, levels, enable_render_surfaces, debug) { + this.initWithTarget_(this.gl.TEXTURE_CUBE_MAP, + edgeLength, edgeLength, format, levels, enable_render_surfaces, debug); }; @@ -703,8 +814,7 @@ o3d.TextureCUBE.prototype.getRenderSurface = */ o3d.TextureCUBE.prototype.set = function(face, level, values) { - var target = this.gl.TEXTURE_CUBE_MAP_POSITIVE_X + face; - this.setValues_(target, level, values); + this.setValues_(level, values, face); this.faces_set_[face] = true; }; @@ -764,20 +874,17 @@ o3d.TextureCUBE.prototype.getRect = */ o3d.TextureCUBE.prototype.setFromBitmap = function(face, bitmap) { - var generate_mipmaps = bitmap.defer_mipmaps_to_texture_; for (var f in this.faces_set_) { generate_mipmaps = generate_mipmaps && - (this.faces_set_[f] || f==face); + (this.faces_set_[f] || f == face); } - var resize_to_pot = bitmap.defer_mipmaps_to_texture_; this.setFromCanvas_(bitmap.canvas_, resize_to_pot, false, // Never flip cube maps. generate_mipmaps, face); - this.faces_set_[face] = true; }; @@ -808,7 +915,9 @@ o3d.TextureCUBE.prototype.drawImage = function(source_img, source_mip, source_x, source_y, source_width, source_height, face, dest_mip, dest_x, dest_y, dest_width, dest_height) { - o3d.notImplemented(); + this.drawImageFromCanvas_(source_img.canvas_, + source_x, source_y, source_width, source_height, dest_mip, + dest_x, dest_y, dest_width, dest_height, face); }; diff --git a/o3d/samples/o3djs/texture.js b/o3d/samples/o3djs/texture.js index 8232d26..c299df0 100644 --- a/o3d/samples/o3djs/texture.js +++ b/o3d/samples/o3djs/texture.js @@ -212,7 +212,6 @@ o3djs.texture.createTextureFromBitmaps = function( pack, bitmaps, opt_generateMips) { - if (bitmaps.length == 0) { throw 'no bitmaps'; } @@ -288,8 +287,7 @@ o3djs.texture.createCubeTextureFrom6Bitmaps = function( edgeLength, bitmaps[0].format, numMips, false); for (var ii = 0; ii < 6; ++ii) { var bitmap = bitmaps[ii]; - texture.drawImage(bitmap, 0, 0, 0, bitmap.width, bitmap.height, - ii, 0, 0, edgeLength, edgeLength); + texture.setFromBitmap(ii, bitmap); } texture.generateMips(0, numMips - 1); return texture; |