From fe326f73e1b9bb1e9160fa5bc4f8ce062addd27e Mon Sep 17 00:00:00 2001 From: Dan Bagnell Date: Thu, 1 Mar 2018 15:47:06 -0500 Subject: [PATCH 01/14] Re-add changes to fix Firefox warnings. --- Source/Core/PixelFormat.js | 20 ++++++++++ Source/Renderer/CubeMap.js | 40 +++++++++++--------- Source/Renderer/CubeMapFace.js | 57 ++++++++++++++++++++++++---- Source/Renderer/Texture.js | 68 +++++++++++++++++++++++++++++----- 4 files changed, 150 insertions(+), 35 deletions(-) diff --git a/Source/Core/PixelFormat.js b/Source/Core/PixelFormat.js index 5c01b6999909..6654608f5b21 100644 --- a/Source/Core/PixelFormat.js +++ b/Source/Core/PixelFormat.js @@ -281,6 +281,26 @@ define([ componentsLength = 1; } return componentsLength * PixelDatatype.sizeInBytes(pixelDatatype) * width * height; + }, + + /** + * @private + */ + createTypedArray : function(pixelFormat, pixelDatatype, width, height) { + var constructor; + var sizeInBytes = PixelDatatype.sizeInBytes(pixelDatatype); + if (sizeInBytes === Uint8Array.BYTES_PER_ELEMENT) { + constructor = Uint8Array; + } else if (sizeInBytes === Uint16Array.BYTES_PER_ELEMENT) { + constructor = Uint16Array; + } else if (sizeInBytes === Float32Array.BYTES_PER_ELEMENT && pixelDatatype === PixelDatatype.FLOAT) { + constructor = Float32Array; + } else { + constructor = Uint32Array; + } + + var size = PixelFormat.componentsLength(pixelFormat) * width * height; + return new constructor(size); } }; diff --git a/Source/Renderer/CubeMap.js b/Source/Renderer/CubeMap.js index e08eccd1c718..00a3fe450861 100644 --- a/Source/Renderer/CubeMap.js +++ b/Source/Renderer/CubeMap.js @@ -33,7 +33,6 @@ define([ 'use strict'; function CubeMap(options) { - options = defaultValue(options, defaultValue.EMPTY_OBJECT); //>>includeStart('debug', pragmas.debug); @@ -121,25 +120,29 @@ define([ gl.activeTexture(gl.TEXTURE0); gl.bindTexture(textureTarget, texture); - function createFace(target, sourceFace) { + function createFace(target, sourceFace, preMultiplyAlpha, flipY) { + // TODO: gl.pixelStorei(gl._UNPACK_ALIGNMENT, 4); if (sourceFace.arrayBufferView) { + gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, false); + gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, false); gl.texImage2D(target, 0, pixelFormat, size, size, 0, pixelFormat, pixelDatatype, sourceFace.arrayBufferView); } else { + // Only valid for DOM-Element uploads + gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, preMultiplyAlpha); + gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, flipY); + + // Source: ImageData, HTMLImageElement, HTMLCanvasElement, or HTMLVideoElement gl.texImage2D(target, 0, pixelFormat, pixelFormat, pixelDatatype, sourceFace); } } if (defined(source)) { - // TODO: _gl.pixelStorei(_gl._UNPACK_ALIGNMENT, 4); - gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, preMultiplyAlpha); - gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, flipY); - - createFace(gl.TEXTURE_CUBE_MAP_POSITIVE_X, source.positiveX); - createFace(gl.TEXTURE_CUBE_MAP_NEGATIVE_X, source.negativeX); - createFace(gl.TEXTURE_CUBE_MAP_POSITIVE_Y, source.positiveY); - createFace(gl.TEXTURE_CUBE_MAP_NEGATIVE_Y, source.negativeY); - createFace(gl.TEXTURE_CUBE_MAP_POSITIVE_Z, source.positiveZ); - createFace(gl.TEXTURE_CUBE_MAP_NEGATIVE_Z, source.negativeZ); + createFace(gl.TEXTURE_CUBE_MAP_POSITIVE_X, source.positiveX, preMultiplyAlpha, flipY); + createFace(gl.TEXTURE_CUBE_MAP_NEGATIVE_X, source.negativeX, preMultiplyAlpha, flipY); + createFace(gl.TEXTURE_CUBE_MAP_POSITIVE_Y, source.positiveY, preMultiplyAlpha, flipY); + createFace(gl.TEXTURE_CUBE_MAP_NEGATIVE_Y, source.negativeY, preMultiplyAlpha, flipY); + createFace(gl.TEXTURE_CUBE_MAP_POSITIVE_Z, source.positiveZ, preMultiplyAlpha, flipY); + createFace(gl.TEXTURE_CUBE_MAP_NEGATIVE_Z, source.negativeZ, preMultiplyAlpha, flipY); } else { gl.texImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_X, 0, pixelFormat, size, size, 0, pixelFormat, pixelDatatype, null); gl.texImage2D(gl.TEXTURE_CUBE_MAP_NEGATIVE_X, 0, pixelFormat, size, size, 0, pixelFormat, pixelDatatype, null); @@ -163,12 +166,13 @@ define([ this._flipY = flipY; this._sampler = undefined; - this._positiveX = new CubeMapFace(gl, texture, textureTarget, gl.TEXTURE_CUBE_MAP_POSITIVE_X, pixelFormat, pixelDatatype, size, preMultiplyAlpha, flipY); - this._negativeX = new CubeMapFace(gl, texture, textureTarget, gl.TEXTURE_CUBE_MAP_NEGATIVE_X, pixelFormat, pixelDatatype, size, preMultiplyAlpha, flipY); - this._positiveY = new CubeMapFace(gl, texture, textureTarget, gl.TEXTURE_CUBE_MAP_POSITIVE_Y, pixelFormat, pixelDatatype, size, preMultiplyAlpha, flipY); - this._negativeY = new CubeMapFace(gl, texture, textureTarget, gl.TEXTURE_CUBE_MAP_NEGATIVE_Y, pixelFormat, pixelDatatype, size, preMultiplyAlpha, flipY); - this._positiveZ = new CubeMapFace(gl, texture, textureTarget, gl.TEXTURE_CUBE_MAP_POSITIVE_Z, pixelFormat, pixelDatatype, size, preMultiplyAlpha, flipY); - this._negativeZ = new CubeMapFace(gl, texture, textureTarget, gl.TEXTURE_CUBE_MAP_NEGATIVE_Z, pixelFormat, pixelDatatype, size, preMultiplyAlpha, flipY); + var initialized = defined(source); + this._positiveX = new CubeMapFace(gl, texture, textureTarget, gl.TEXTURE_CUBE_MAP_POSITIVE_X, pixelFormat, pixelDatatype, size, preMultiplyAlpha, flipY, initialized); + this._negativeX = new CubeMapFace(gl, texture, textureTarget, gl.TEXTURE_CUBE_MAP_NEGATIVE_X, pixelFormat, pixelDatatype, size, preMultiplyAlpha, flipY, initialized); + this._positiveY = new CubeMapFace(gl, texture, textureTarget, gl.TEXTURE_CUBE_MAP_POSITIVE_Y, pixelFormat, pixelDatatype, size, preMultiplyAlpha, flipY, initialized); + this._negativeY = new CubeMapFace(gl, texture, textureTarget, gl.TEXTURE_CUBE_MAP_NEGATIVE_Y, pixelFormat, pixelDatatype, size, preMultiplyAlpha, flipY, initialized); + this._positiveZ = new CubeMapFace(gl, texture, textureTarget, gl.TEXTURE_CUBE_MAP_POSITIVE_Z, pixelFormat, pixelDatatype, size, preMultiplyAlpha, flipY, initialized); + this._negativeZ = new CubeMapFace(gl, texture, textureTarget, gl.TEXTURE_CUBE_MAP_NEGATIVE_Z, pixelFormat, pixelDatatype, size, preMultiplyAlpha, flipY, initialized); this.sampler = defined(options.sampler) ? options.sampler : new Sampler(); } diff --git a/Source/Renderer/CubeMapFace.js b/Source/Renderer/CubeMapFace.js index 83e9a165cd73..152cb59c9dfa 100644 --- a/Source/Renderer/CubeMapFace.js +++ b/Source/Renderer/CubeMapFace.js @@ -1,21 +1,25 @@ define([ '../Core/Check', '../Core/defaultValue', + '../Core/defined', '../Core/defineProperties', '../Core/DeveloperError', + '../Core/PixelFormat', './PixelDatatype' ], function( Check, defaultValue, + defined, defineProperties, DeveloperError, + PixelFormat, PixelDatatype) { 'use strict'; /** * @private */ - function CubeMapFace(gl, texture, textureTarget, targetFace, pixelFormat, pixelDatatype, size, preMultiplyAlpha, flipY) { + function CubeMapFace(gl, texture, textureTarget, targetFace, pixelFormat, pixelDatatype, size, preMultiplyAlpha, flipY, initialized) { this._gl = gl; this._texture = texture; this._textureTarget = textureTarget; @@ -25,6 +29,7 @@ define([ this._size = size; this._preMultiplyAlpha = preMultiplyAlpha; this._flipY = flipY; + this._initialized = initialized; } defineProperties(CubeMapFace.prototype, { @@ -91,15 +96,52 @@ define([ var target = this._textureTarget; // TODO: gl.pixelStorei(gl._UNPACK_ALIGNMENT, 4); - gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, this._preMultiplyAlpha); - gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, this._flipY); + gl.activeTexture(gl.TEXTURE0); gl.bindTexture(target, this._texture); - if (source.arrayBufferView) { - gl.texSubImage2D(this._targetFace, 0, xOffset, yOffset, source.width, source.height, this._pixelFormat, this._pixelDatatype, source.arrayBufferView); - } else { - gl.texSubImage2D(this._targetFace, 0, xOffset, yOffset, this._pixelFormat, this._pixelDatatype, source); + var uploaded = false; + if (!this._initialized) { + if (xOffset === 0 && yOffset === 0 && source.width === this._size && source.height === this._size) { + // initialize the entire texture + if (defined(source.arrayBufferView)) { + gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, false); + gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, false); + + gl.texImage2D(this._targetFace, 0, this._pixelFormat, this._size, this._size, 0, this._pixelFormat, this._pixelDatatype, source.arrayBufferView); + } else { + // Only valid for DOM-Element uploads + gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, this._preMultiplyAlpha); + gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, this._flipY); + + gl.texImage2D(this._targetFace, 0, this._pixelFormat, this._pixelFormat, this._pixelDatatype, source); + } + uploaded = true; + } else { + gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, false); + gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, false); + + // initialize the entire texture to zero + var bufferView = PixelFormat.createTypedArray(this._pixelFormat, this._pixelDatatype, this._size, this._size); + gl.texImage2D(this._targetFace, 0, this._pixelFormat, this._size, this._size, 0, this._pixelFormat, this._pixelDatatype, bufferView); + } + this._initialized = true; + } + + if (!uploaded) { + if (source.arrayBufferView) { + gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, false); + gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, false); + + gl.texSubImage2D(this._targetFace, 0, xOffset, yOffset, source.width, source.height, this._pixelFormat, this._pixelDatatype, source.arrayBufferView); + } else { + // Only valid for DOM-Element uploads + gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, this._preMultiplyAlpha); + gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, this._flipY); + + // Source: ImageData, HTMLImageElement, HTMLCanvasElement, or HTMLVideoElement + gl.texSubImage2D(this._targetFace, 0, xOffset, yOffset, this._pixelFormat, this._pixelDatatype, source); + } } gl.bindTexture(target, null); @@ -160,6 +202,7 @@ define([ gl.bindTexture(target, this._texture); gl.copyTexSubImage2D(this._targetFace, 0, xOffset, yOffset, framebufferXOffset, framebufferYOffset, width, height); gl.bindTexture(target, null); + this._initialized = true; }; return CubeMapFace; diff --git a/Source/Renderer/Texture.js b/Source/Renderer/Texture.js index 2ba7284e05c7..9d7387962a41 100644 --- a/Source/Renderer/Texture.js +++ b/Source/Renderer/Texture.js @@ -164,19 +164,22 @@ define([ var preMultiplyAlpha = options.preMultiplyAlpha || pixelFormat === PixelFormat.RGB || pixelFormat === PixelFormat.LUMINANCE; var flipY = defaultValue(options.flipY, true); + var initialized = true; + var gl = context._gl; var textureTarget = gl.TEXTURE_2D; var texture = gl.createTexture(); + // TODO: gl.pixelStorei(gl._UNPACK_ALIGNMENT, 4); + gl.activeTexture(gl.TEXTURE0); gl.bindTexture(textureTarget, texture); if (defined(source)) { - // TODO: _gl.pixelStorei(_gl._UNPACK_ALIGNMENT, 4); - gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, preMultiplyAlpha); - gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, flipY); - if (defined(source.arrayBufferView)) { + gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, false); + gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, false); + // Source: typed array if (isCompressed) { gl.compressedTexImage2D(textureTarget, 0, internalFormat, width, height, 0, source.arrayBufferView); @@ -184,6 +187,9 @@ define([ gl.texImage2D(textureTarget, 0, internalFormat, width, height, 0, pixelFormat, pixelDatatype, source.arrayBufferView); } } else if (defined(source.framebuffer)) { + gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, false); + gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, false); + // Source: framebuffer if (source.framebuffer !== context.defaultFramebuffer) { source.framebuffer._bind(); @@ -195,11 +201,16 @@ define([ source.framebuffer._unBind(); } } else { + // Only valid for DOM-Element uploads + gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, preMultiplyAlpha); + gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, flipY); + // Source: ImageData, HTMLImageElement, HTMLCanvasElement, or HTMLVideoElement gl.texImage2D(textureTarget, 0, internalFormat, pixelFormat, pixelDatatype, source); } } else { gl.texImage2D(textureTarget, 0, internalFormat, width, height, 0, pixelFormat, pixelDatatype, null); + initialized = false; } gl.bindTexture(textureTarget, null); @@ -224,6 +235,7 @@ define([ this._sizeInBytes = sizeInBytes; this._preMultiplyAlpha = preMultiplyAlpha; this._flipY = flipY; + this._initialized = initialized; this._sampler = undefined; this.sampler = defined(options.sampler) ? options.sampler : new Sampler(); @@ -469,15 +481,50 @@ define([ var target = this._textureTarget; // TODO: gl.pixelStorei(gl._UNPACK_ALIGNMENT, 4); - gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, this._preMultiplyAlpha); - gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, this._flipY); + gl.activeTexture(gl.TEXTURE0); gl.bindTexture(target, this._texture); - if (source.arrayBufferView) { - gl.texSubImage2D(target, 0, xOffset, yOffset, source.width, source.height, this._pixelFormat, this._pixelDatatype, source.arrayBufferView); - } else { - gl.texSubImage2D(target, 0, xOffset, yOffset, this._pixelFormat, this._pixelDatatype, source); + var uploaded = false; + if (!this._initialized) { + if (xOffset === 0 && yOffset === 0 && source.width === this._width && source.height === this._height) { + // initialize the entire texture + if (defined(source.arrayBufferView)) { + gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, false); + gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, false); + gl.texImage2D(target, 0, this._pixelFormat, this._width, this._height, 0, this._pixelFormat, this._pixelDatatype, source.arrayBufferView); + } else { + // Only valid for DOM-Element uploads + gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, this._preMultiplyAlpha); + gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, this._flipY); + + gl.texImage2D(target, 0, this._pixelFormat, this._pixelFormat, this._pixelDatatype, source); + } + uploaded = true; + } else { + gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, false); + gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, false); + + // initialize the entire texture to zero + var bufferView = PixelFormat.createTypedArray(this._pixelFormat, this._pixelDatatype, this._width, this._height); + gl.texImage2D(target, 0, this._pixelFormat, this._width, this._height, 0, this._pixelFormat, this._pixelDatatype, bufferView); + } + this._initialized = true; + } + + if (!uploaded) { + if (source.arrayBufferView) { + gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, false); + gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, false); + + gl.texSubImage2D(target, 0, xOffset, yOffset, source.width, source.height, this._pixelFormat, this._pixelDatatype, source.arrayBufferView); + } else { + // Only valid for DOM-Element uploads + gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, this._preMultiplyAlpha); + gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, this._flipY); + + gl.texSubImage2D(target, 0, xOffset, yOffset, this._pixelFormat, this._pixelDatatype, source); + } } gl.bindTexture(target, null); @@ -536,6 +583,7 @@ define([ gl.bindTexture(target, this._texture); gl.copyTexSubImage2D(target, 0, xOffset, yOffset, framebufferXOffset, framebufferYOffset, width, height); gl.bindTexture(target, null); + this._initialized = true; }; /** From 4c81e8c4520a402f8f6a0edea3d75ea63d8c45a8 Mon Sep 17 00:00:00 2001 From: Dan Bagnell Date: Thu, 1 Mar 2018 16:14:58 -0500 Subject: [PATCH 02/14] Flip water mask. --- Source/Scene/GlobeSurfaceTile.js | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/Source/Scene/GlobeSurfaceTile.js b/Source/Scene/GlobeSurfaceTile.js index 1026832675b8..16d99356a0a7 100644 --- a/Source/Scene/GlobeSurfaceTile.js +++ b/Source/Scene/GlobeSurfaceTile.js @@ -658,7 +658,15 @@ define([ return; } } else { + var flippedWaterMask; + flippedWaterMask = new Uint8Array(waterMaskLength); var textureSize = Math.sqrt(waterMaskLength); + for (var i = 0; i < textureSize; ++i) { + for (var j = 0; j < textureSize; ++j) { + flippedWaterMask[(textureSize - i - 1) * textureSize + j] = waterMask[i * textureSize + j]; + } + } + texture = new Texture({ context : context, pixelFormat : PixelFormat.LUMINANCE, @@ -666,7 +674,7 @@ define([ source : { width : textureSize, height : textureSize, - arrayBufferView : waterMask + arrayBufferView : flippedWaterMask }, sampler : waterMaskData.sampler }); From 3588b29743d342a7c768ea6dbaf7d812dd2cc83e Mon Sep 17 00:00:00 2001 From: Dan Bagnell Date: Thu, 1 Mar 2018 16:18:34 -0500 Subject: [PATCH 03/14] Update CHANGES.md. --- CHANGES.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/CHANGES.md b/CHANGES.md index 6717a6d5ba99..35fe0aba81da 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,6 +1,11 @@ Change Log ========== +### 1.44 - 2018-04-02 + +##### Fixes :wrench: +* Fix Firefox WebGL console warnings. [#5912](https://github.com/AnalyticalGraphicsInc/cesium/issues/5912) + ### 1.43 - 2018-03-01 ##### Major Announcements :loudspeaker: From fbd2ed8ca4095f3cc999f355f75285fda7ae9790 Mon Sep 17 00:00:00 2001 From: Dan Bagnell Date: Fri, 2 Mar 2018 16:19:53 -0500 Subject: [PATCH 04/14] Flip y for array buffer views when creating a texture or cubemap. --- Source/Core/PixelFormat.js | 16 ++++++++++ Source/Renderer/CubeMap.js | 9 ++++-- Source/Renderer/CubeMapFace.js | 44 ++++++++++++++++++-------- Source/Renderer/Texture.js | 53 +++++++++++++++++++++++--------- Source/Scene/GlobeSurfaceTile.js | 10 +----- 5 files changed, 93 insertions(+), 39 deletions(-) diff --git a/Source/Core/PixelFormat.js b/Source/Core/PixelFormat.js index 6654608f5b21..98eb4be1e56e 100644 --- a/Source/Core/PixelFormat.js +++ b/Source/Core/PixelFormat.js @@ -150,6 +150,7 @@ define([ // Many GPUs store RGB as RGBA internally // https://devtalk.nvidia.com/default/topic/699479/general-graphics-programming/rgb-auto-converted-to-rgba/post/4142379/#4142379 case PixelFormat.RGB: + return 3; case PixelFormat.RGBA: return 4; case PixelFormat.LUMINANCE_ALPHA: @@ -301,6 +302,21 @@ define([ var size = PixelFormat.componentsLength(pixelFormat) * width * height; return new constructor(size); + }, + + /** + * @private + */ + flipY : function(bufferView, pixelFormat, pixelDatatype, width, height) { + var flipped = PixelFormat.createTypedArray(pixelFormat, pixelDatatype, width, height); + var numberOfComponents = PixelFormat.componentsLength(pixelFormat); + var textureWidth = width * numberOfComponents; + for (var i = 0; i < height; ++i) { + for (var j = 0; j < textureWidth; ++j) { + flipped[(height - i - 1) * height + j] = bufferView[i * height + j]; + } + } + return flipped; } }; diff --git a/Source/Renderer/CubeMap.js b/Source/Renderer/CubeMap.js index 00a3fe450861..b5523bc9f803 100644 --- a/Source/Renderer/CubeMap.js +++ b/Source/Renderer/CubeMap.js @@ -122,10 +122,15 @@ define([ function createFace(target, sourceFace, preMultiplyAlpha, flipY) { // TODO: gl.pixelStorei(gl._UNPACK_ALIGNMENT, 4); - if (sourceFace.arrayBufferView) { + var arrayBufferView = sourceFace.arrayBufferView; + if (arrayBufferView) { gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, false); gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, false); - gl.texImage2D(target, 0, pixelFormat, size, size, 0, pixelFormat, pixelDatatype, sourceFace.arrayBufferView); + + if (flipY) { + arrayBufferView = PixelFormat.flipY(arrayBufferView, pixelFormat, pixelDatatype, size, size); + } + gl.texImage2D(target, 0, pixelFormat, size, size, 0, pixelFormat, pixelDatatype, arrayBufferView); } else { // Only valid for DOM-Element uploads gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, preMultiplyAlpha); diff --git a/Source/Renderer/CubeMapFace.js b/Source/Renderer/CubeMapFace.js index 152cb59c9dfa..ba5dbf317278 100644 --- a/Source/Renderer/CubeMapFace.js +++ b/Source/Renderer/CubeMapFace.js @@ -94,27 +94,42 @@ define([ var gl = this._gl; var target = this._textureTarget; + var targetFace = this._targetFace; // TODO: gl.pixelStorei(gl._UNPACK_ALIGNMENT, 4); gl.activeTexture(gl.TEXTURE0); gl.bindTexture(target, this._texture); + var width = source.width; + var height = source.height; + var arrayBufferView = source.arrayBufferView; + + var size = this._size; + var pixelFormat = this._pixelFormat; + var pixelDatatype = this._pixelDatatype; + + var preMultiplyAlpha = this._preMultiplyAlpha; + var flipY = this._flipY; + var uploaded = false; if (!this._initialized) { - if (xOffset === 0 && yOffset === 0 && source.width === this._size && source.height === this._size) { + if (xOffset === 0 && yOffset === 0 && width === size && height === size) { // initialize the entire texture - if (defined(source.arrayBufferView)) { + if (defined(arrayBufferView)) { gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, false); gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, false); - gl.texImage2D(this._targetFace, 0, this._pixelFormat, this._size, this._size, 0, this._pixelFormat, this._pixelDatatype, source.arrayBufferView); + if (flipY) { + arrayBufferView = PixelFormat.flipY(arrayBufferView, pixelFormat, pixelDatatype, size, size); + } + gl.texImage2D(targetFace, 0, pixelFormat, size, size, 0, pixelFormat, pixelDatatype, arrayBufferView); } else { // Only valid for DOM-Element uploads - gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, this._preMultiplyAlpha); - gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, this._flipY); + gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, preMultiplyAlpha); + gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, flipY); - gl.texImage2D(this._targetFace, 0, this._pixelFormat, this._pixelFormat, this._pixelDatatype, source); + gl.texImage2D(targetFace, 0, pixelFormat, pixelFormat, pixelDatatype, source); } uploaded = true; } else { @@ -122,25 +137,28 @@ define([ gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, false); // initialize the entire texture to zero - var bufferView = PixelFormat.createTypedArray(this._pixelFormat, this._pixelDatatype, this._size, this._size); - gl.texImage2D(this._targetFace, 0, this._pixelFormat, this._size, this._size, 0, this._pixelFormat, this._pixelDatatype, bufferView); + var bufferView = PixelFormat.createTypedArray(pixelFormat, pixelDatatype, size, size); + gl.texImage2D(targetFace, 0, pixelFormat, size, size, 0, pixelFormat, pixelDatatype, bufferView); } this._initialized = true; } if (!uploaded) { - if (source.arrayBufferView) { + if (arrayBufferView) { gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, false); gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, false); - gl.texSubImage2D(this._targetFace, 0, xOffset, yOffset, source.width, source.height, this._pixelFormat, this._pixelDatatype, source.arrayBufferView); + if (flipY) { + arrayBufferView = PixelFormat.flipY(arrayBufferView, pixelFormat, pixelDatatype, width, height); + } + gl.texSubImage2D(targetFace, 0, xOffset, yOffset, width, height, pixelFormat, pixelDatatype, arrayBufferView); } else { // Only valid for DOM-Element uploads - gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, this._preMultiplyAlpha); - gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, this._flipY); + gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, preMultiplyAlpha); + gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, flipY); // Source: ImageData, HTMLImageElement, HTMLCanvasElement, or HTMLVideoElement - gl.texSubImage2D(this._targetFace, 0, xOffset, yOffset, this._pixelFormat, this._pixelDatatype, source); + gl.texSubImage2D(targetFace, 0, xOffset, yOffset, pixelFormat, pixelDatatype, source); } } diff --git a/Source/Renderer/Texture.js b/Source/Renderer/Texture.js index 9d7387962a41..f3d700b59ade 100644 --- a/Source/Renderer/Texture.js +++ b/Source/Renderer/Texture.js @@ -181,10 +181,14 @@ define([ gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, false); // Source: typed array + var arrayBufferView = source.arrayBufferView; if (isCompressed) { - gl.compressedTexImage2D(textureTarget, 0, internalFormat, width, height, 0, source.arrayBufferView); + gl.compressedTexImage2D(textureTarget, 0, internalFormat, width, height, 0, arrayBufferView); } else { - gl.texImage2D(textureTarget, 0, internalFormat, width, height, 0, pixelFormat, pixelDatatype, source.arrayBufferView); + if (flipY) { + arrayBufferView = PixelFormat.flipY(arrayBufferView, pixelFormat, pixelDatatype, width, height); + } + gl.texImage2D(textureTarget, 0, internalFormat, width, height, 0, pixelFormat, pixelDatatype, arrayBufferView); } } else if (defined(source.framebuffer)) { gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, false); @@ -485,20 +489,36 @@ define([ gl.activeTexture(gl.TEXTURE0); gl.bindTexture(target, this._texture); + var width = source.width; + var height = source.height; + var arrayBufferView = source.arrayBufferView; + + var textureWidth = this._width; + var textureHeight = this._height; + var pixelFormat = this._pixelFormat; + var pixelDatatype = this._pixelDatatype; + + var preMultiplyAlpha = this._preMultiplyAlpha; + var flipY = this._flipY; + var uploaded = false; if (!this._initialized) { - if (xOffset === 0 && yOffset === 0 && source.width === this._width && source.height === this._height) { + if (xOffset === 0 && yOffset === 0 && width === textureWidth && height === textureHeight) { // initialize the entire texture - if (defined(source.arrayBufferView)) { + if (defined(arrayBufferView)) { gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, false); gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, false); - gl.texImage2D(target, 0, this._pixelFormat, this._width, this._height, 0, this._pixelFormat, this._pixelDatatype, source.arrayBufferView); + + if (flipY) { + arrayBufferView = PixelFormat.flipY(arrayBufferView, pixelFormat, pixelDatatype, textureWidth, textureHeight); + } + gl.texImage2D(target, 0, pixelFormat, textureWidth, textureHeight, 0, pixelFormat, pixelDatatype, arrayBufferView); } else { // Only valid for DOM-Element uploads - gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, this._preMultiplyAlpha); - gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, this._flipY); + gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, preMultiplyAlpha); + gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, flipY); - gl.texImage2D(target, 0, this._pixelFormat, this._pixelFormat, this._pixelDatatype, source); + gl.texImage2D(target, 0, pixelFormat, pixelFormat, pixelDatatype, source); } uploaded = true; } else { @@ -506,24 +526,27 @@ define([ gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, false); // initialize the entire texture to zero - var bufferView = PixelFormat.createTypedArray(this._pixelFormat, this._pixelDatatype, this._width, this._height); - gl.texImage2D(target, 0, this._pixelFormat, this._width, this._height, 0, this._pixelFormat, this._pixelDatatype, bufferView); + var bufferView = PixelFormat.createTypedArray(pixelFormat, pixelDatatype, textureWidth, textureHeight); + gl.texImage2D(target, 0, pixelFormat, textureWidth, textureHeight, 0, pixelFormat, pixelDatatype, bufferView); } this._initialized = true; } if (!uploaded) { - if (source.arrayBufferView) { + if (arrayBufferView) { gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, false); gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, false); - gl.texSubImage2D(target, 0, xOffset, yOffset, source.width, source.height, this._pixelFormat, this._pixelDatatype, source.arrayBufferView); + if (flipY) { + arrayBufferView = PixelFormat.flipY(arrayBufferView, pixelFormat, pixelDatatype, width, height); + } + gl.texSubImage2D(target, 0, xOffset, yOffset, width, height, pixelFormat, pixelDatatype, arrayBufferView); } else { // Only valid for DOM-Element uploads - gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, this._preMultiplyAlpha); - gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, this._flipY); + gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, preMultiplyAlpha); + gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, flipY); - gl.texSubImage2D(target, 0, xOffset, yOffset, this._pixelFormat, this._pixelDatatype, source); + gl.texSubImage2D(target, 0, xOffset, yOffset, pixelFormat, pixelDatatype, source); } } diff --git a/Source/Scene/GlobeSurfaceTile.js b/Source/Scene/GlobeSurfaceTile.js index 16d99356a0a7..1026832675b8 100644 --- a/Source/Scene/GlobeSurfaceTile.js +++ b/Source/Scene/GlobeSurfaceTile.js @@ -658,15 +658,7 @@ define([ return; } } else { - var flippedWaterMask; - flippedWaterMask = new Uint8Array(waterMaskLength); var textureSize = Math.sqrt(waterMaskLength); - for (var i = 0; i < textureSize; ++i) { - for (var j = 0; j < textureSize; ++j) { - flippedWaterMask[(textureSize - i - 1) * textureSize + j] = waterMask[i * textureSize + j]; - } - } - texture = new Texture({ context : context, pixelFormat : PixelFormat.LUMINANCE, @@ -674,7 +666,7 @@ define([ source : { width : textureSize, height : textureSize, - arrayBufferView : flippedWaterMask + arrayBufferView : waterMask }, sampler : waterMaskData.sampler }); From 70a15945fc46439aa01bbe4a0bf4a36710bcc72a Mon Sep 17 00:00:00 2001 From: Dan Bagnell Date: Mon, 26 Mar 2018 15:00:28 -0400 Subject: [PATCH 05/14] Updates from review. --- Source/Core/PixelFormat.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Source/Core/PixelFormat.js b/Source/Core/PixelFormat.js index 98eb4be1e56e..59c693acda4d 100644 --- a/Source/Core/PixelFormat.js +++ b/Source/Core/PixelFormat.js @@ -147,8 +147,6 @@ define([ */ componentsLength : function(pixelFormat) { switch (pixelFormat) { - // Many GPUs store RGB as RGBA internally - // https://devtalk.nvidia.com/default/topic/699479/general-graphics-programming/rgb-auto-converted-to-rgba/post/4142379/#4142379 case PixelFormat.RGB: return 3; case PixelFormat.RGBA: @@ -312,8 +310,10 @@ define([ var numberOfComponents = PixelFormat.componentsLength(pixelFormat); var textureWidth = width * numberOfComponents; for (var i = 0; i < height; ++i) { + var row = i * height; + var flippedRow = (height - i - 1) * height; for (var j = 0; j < textureWidth; ++j) { - flipped[(height - i - 1) * height + j] = bufferView[i * height + j]; + flipped[flippedRow + j] = bufferView[row + j]; } } return flipped; From b61bb41bb01bc53bfea3d01df219824e1c39f45d Mon Sep 17 00:00:00 2001 From: Dan Bagnell Date: Mon, 26 Mar 2018 16:25:17 -0400 Subject: [PATCH 06/14] fix clipping plane collection tests. --- Specs/Scene/ClippingPlaneCollectionSpec.js | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/Specs/Scene/ClippingPlaneCollectionSpec.js b/Specs/Scene/ClippingPlaneCollectionSpec.js index f8e4c0d2434b..1973cd9da42e 100644 --- a/Specs/Scene/ClippingPlaneCollectionSpec.js +++ b/Specs/Scene/ClippingPlaneCollectionSpec.js @@ -186,7 +186,7 @@ defineSuite([ var rgba; var gl = scene.frameState.context._gl; - spyOn(gl, 'texSubImage2D').and.callFake(function(target, level, xoffset, yoffset, width, height, format, type, arrayBufferView) { + spyOn(gl, 'texImage2D').and.callFake(function(target, level, xoffset, yoffset, width, height, format, type, arrayBufferView) { rgba = arrayBufferView; }); @@ -317,7 +317,7 @@ defineSuite([ var rgba; var gl = scene.frameState.context._gl; - spyOn(gl, 'texSubImage2D').and.callFake(function(target, level, xoffset, yoffset, width, height, format, type, arrayBufferView) { + spyOn(gl, 'texImage2D').and.callFake(function(target, level, xoffset, yoffset, width, height, format, type, arrayBufferView) { rgba = arrayBufferView; }); @@ -399,7 +399,7 @@ defineSuite([ var scene = createScene(); var gl = scene.frameState.context._gl; - spyOn(gl, 'texSubImage2D').and.callThrough(); + spyOn(gl, 'texImage2D').and.callThrough(); clippingPlanes = new ClippingPlaneCollection({ planes : planes, @@ -407,13 +407,13 @@ defineSuite([ edgeColor : Color.RED, modelMatrix : transform }); - expect(gl.texSubImage2D.calls.count()).toEqual(0); + expect(gl.texImage2D.calls.count()).toEqual(0); clippingPlanes.update(scene.frameState); - expect(gl.texSubImage2D.calls.count()).toEqual(1); + expect(gl.texImage2D.calls.count()).toEqual(2); clippingPlanes.update(scene.frameState); - expect(gl.texSubImage2D.calls.count()).toEqual(1); + expect(gl.texImage2D.calls.count()).toEqual(2); clippingPlanes.destroy(); scene.destroyForSpecs(); @@ -423,6 +423,7 @@ defineSuite([ var scene = createScene(); var gl = scene.frameState.context._gl; + spyOn(gl, 'texImage2D').and.callThrough(); spyOn(gl, 'texSubImage2D').and.callThrough(); clippingPlanes = new ClippingPlaneCollection({ @@ -431,13 +432,13 @@ defineSuite([ edgeColor : Color.RED, modelMatrix : transform }); - expect(gl.texSubImage2D.calls.count()).toEqual(0); + expect(gl.texImage2D.calls.count()).toEqual(0); clippingPlanes.update(scene.frameState); - expect(gl.texSubImage2D.calls.count()).toEqual(1); + expect(gl.texImage2D.calls.count()).toEqual(2); clippingPlanes.update(scene.frameState); - expect(gl.texSubImage2D.calls.count()).toEqual(2); + expect(gl.texSubImage2D.calls.count()).toEqual(1); clippingPlanes.destroy(); scene.destroyForSpecs(); From 7fcd57c0d1554fc54d30ff228082c7185b255f1e Mon Sep 17 00:00:00 2001 From: Dan Bagnell Date: Mon, 26 Mar 2018 17:02:10 -0400 Subject: [PATCH 07/14] Fix remaining tests. --- Specs/Renderer/TextureSpec.js | 6 +++--- Specs/Scene/Cesium3DTilesetSpec.js | 4 ++-- Specs/Scene/Instanced3DModel3DTileContentSpec.js | 4 ++-- Specs/Scene/ModelSpec.js | 6 +++--- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/Specs/Renderer/TextureSpec.js b/Specs/Renderer/TextureSpec.js index e26a3cc8afc8..638ecb4255e6 100644 --- a/Specs/Renderer/TextureSpec.js +++ b/Specs/Renderer/TextureSpec.js @@ -118,7 +118,7 @@ defineSuite([ var expectedHeight = context.canvas.clientHeight; expect(texture.width).toEqual(expectedWidth); expect(texture.height).toEqual(expectedHeight); - expect(texture.sizeInBytes).toEqual(expectedWidth * expectedHeight * 4); + expect(texture.sizeInBytes).toEqual(expectedWidth * expectedHeight * PixelFormat.componentsLength(texture.pixelFormat)); command.color = Color.WHITE; command.execute(context); @@ -158,7 +158,7 @@ defineSuite([ var expectedHeight = context.canvas.clientHeight; expect(texture.width).toEqual(expectedWidth); expect(texture.height).toEqual(expectedHeight); - expect(texture.sizeInBytes).toEqual(expectedWidth * expectedHeight * 4); + expect(texture.sizeInBytes).toEqual(expectedWidth * expectedHeight * PixelFormat.componentsLength(texture.pixelFormat)); // Clear to white command.color = Color.WHITE; @@ -583,7 +583,7 @@ defineSuite([ // Uncompressed formats expectTextureByteSize(16, 16, PixelFormat.ALPHA, PixelDatatype.UNSIGNED_BYTE, 256); - expectTextureByteSize(16, 16, PixelFormat.RGB, PixelDatatype.UNSIGNED_BYTE, 256 * 4); + expectTextureByteSize(16, 16, PixelFormat.RGB, PixelDatatype.UNSIGNED_BYTE, 256 * 3); expectTextureByteSize(16, 16, PixelFormat.RGBA, PixelDatatype.UNSIGNED_BYTE, 256 * 4); expectTextureByteSize(16, 16, PixelFormat.LUMINANCE, PixelDatatype.UNSIGNED_BYTE, 256); expectTextureByteSize(16, 16, PixelFormat.LUMINANCE_ALPHA, PixelDatatype.UNSIGNED_BYTE, 256 * 2); diff --git a/Specs/Scene/Cesium3DTilesetSpec.js b/Specs/Scene/Cesium3DTilesetSpec.js index ce9f61a122cb..8f6985c0870b 100644 --- a/Specs/Scene/Cesium3DTilesetSpec.js +++ b/Specs/Scene/Cesium3DTilesetSpec.js @@ -740,8 +740,8 @@ defineSuite([ var b3dmGeometryMemory = 840; // Only one box in the tile, unlike most other test tiles var i3dmGeometryMemory = 840; - // Texture is 211x211 RGBA bytes, but upsampled to 256x256 because the wrap mode is REPEAT - var texturesByteLength = 262144; + // Texture is 211x211 RGB bytes, but upsampled to 256x256 because the wrap mode is REPEAT + var texturesByteLength = 196608; var expectedGeometryMemory = b3dmGeometryMemory * 2 + i3dmGeometryMemory * 3; var expectedTextureMemory = texturesByteLength * 5; diff --git a/Specs/Scene/Instanced3DModel3DTileContentSpec.js b/Specs/Scene/Instanced3DModel3DTileContentSpec.js index c5e409bdc083..c3626c773e57 100644 --- a/Specs/Scene/Instanced3DModel3DTileContentSpec.js +++ b/Specs/Scene/Instanced3DModel3DTileContentSpec.js @@ -280,8 +280,8 @@ defineSuite([ // (24 * 8 * 4) + (36 * 2) = 840 var geometryByteLength = 840; - // Texture is 211x211 RGBA bytes, but upsampled to 256x256 because the wrap mode is REPEAT - var texturesByteLength = 262144; + // Texture is 211x211 RGB bytes, but upsampled to 256x256 because the wrap mode is REPEAT + var texturesByteLength = 196608; // One RGBA byte pixel per feature var batchTexturesByteLength = content.featuresLength * 4; diff --git a/Specs/Scene/ModelSpec.js b/Specs/Scene/ModelSpec.js index ef402d3f9d58..04dc3e05651c 100644 --- a/Specs/Scene/ModelSpec.js +++ b/Specs/Scene/ModelSpec.js @@ -2735,10 +2735,10 @@ defineSuite([ model.zoomTo(); var gl = scene.frameState.context._gl; - spyOn(gl, 'texSubImage2D').and.callThrough(); + spyOn(gl, 'texImage2D').and.callThrough(); scene.renderForSpecs(); - var callsBeforeClipping = gl.texSubImage2D.calls.count(); + var callsBeforeClipping = gl.texImage2D.calls.count(); expect(model._modelViewMatrix).toEqual(Matrix4.IDENTITY); @@ -2750,7 +2750,7 @@ defineSuite([ model.update(scene.frameState); scene.renderForSpecs(); - expect(gl.texSubImage2D.calls.count() - callsBeforeClipping * 2).toEqual(1); + expect(gl.texImage2D.calls.count() - callsBeforeClipping * 2).toEqual(2); primitives.remove(model); }); From f3e20991c3747587c59d18d8bbbeb77bc294cfa6 Mon Sep 17 00:00:00 2001 From: Dan Bagnell Date: Mon, 26 Mar 2018 17:53:12 -0400 Subject: [PATCH 08/14] Add tests for new code paths in texture abd cube map. --- Specs/Renderer/CubeMapSpec.js | 119 +++++++++++++++++++++++++++++++--- Specs/Renderer/TextureSpec.js | 19 ++++++ 2 files changed, 130 insertions(+), 8 deletions(-) diff --git a/Specs/Renderer/CubeMapSpec.js b/Specs/Renderer/CubeMapSpec.js index 6615a2ad47f9..306add5432d7 100644 --- a/Specs/Renderer/CubeMapSpec.js +++ b/Specs/Renderer/CubeMapSpec.js @@ -2,6 +2,7 @@ defineSuite([ 'Renderer/CubeMap', 'Core/Cartesian3', 'Core/Color', + 'Core/defined', 'Core/PixelFormat', 'Core/Resource', 'Renderer/ClearCommand', @@ -18,6 +19,7 @@ defineSuite([ CubeMap, Cartesian3, Color, + defined, PixelFormat, Resource, ClearCommand, @@ -44,14 +46,17 @@ defineSuite([ 'uniform mediump vec3 u_direction;' + 'void main() { gl_FragColor = textureCube(u_texture, normalize(u_direction)); }'; - var faceDirections = [ - new Cartesian3(1.0, 0.0, 0.0), // +X - new Cartesian3(-1.0, 0.0, 0.0), // -X - new Cartesian3(0.0, 1.0, 0.0), // +Y - new Cartesian3(0.0, -1.0, 0.0), // -Y - new Cartesian3(0.0, 0.0, 1.0), // +Z - new Cartesian3(0.0, 0.0, -1.0) // -Z - ]; + var faceDirections = options.faceDirections; + if (!defined(faceDirections)) { + faceDirections = [ + new Cartesian3(1.0, 0.0, 0.0), // +X + new Cartesian3(-1.0, 0.0, 0.0), // -X + new Cartesian3(0.0, 1.0, 0.0), // +Y + new Cartesian3(0.0, -1.0, 0.0), // -Y + new Cartesian3(0.0, 0.0, 1.0), // +Z + new Cartesian3(0.0, 0.0, -1.0) // -Z + ]; + } var uniformMap = { direction : undefined, @@ -497,6 +502,104 @@ defineSuite([ }); }); + it('sub copies images to a cube map', function() { + cubeMap = new CubeMap({ + context : context, + width : 2, + height : 2 + }); + cubeMap.positiveX.copyFrom({ + width : 1, + height : 1, + arrayBufferView : new Uint8Array([0, 255, 255, 255]) + }); + cubeMap.negativeX.copyFrom({ + width : 1, + height : 1, + arrayBufferView : new Uint8Array([0, 0, 255, 255]) + }); + cubeMap.positiveY.copyFrom({ + width : 1, + height : 1, + arrayBufferView : new Uint8Array([0, 255, 0, 255]) + }); + cubeMap.negativeY.copyFrom({ + width : 1, + height : 1, + arrayBufferView : new Uint8Array([255, 0, 0, 255]) + }); + cubeMap.positiveZ.copyFrom({ + width : 1, + height : 1, + arrayBufferView : new Uint8Array([255, 0, 255, 255]) + }); + cubeMap.negativeZ.copyFrom({ + width : 1, + height : 1, + arrayBufferView : new Uint8Array([0, 255, 0, 255]) + }, 1, 0); + + var negativeZDirection = new Cartesian3(0.25, 0.0, -1.0); + Cartesian3.normalize(negativeZDirection, negativeZDirection); + + expectCubeMapFaces({ + cubeMap : cubeMap, + expectedColors : [ + [0, 64, 64, 255], // +X + [0, 0, 64, 255], // -X + [0, 64, 0, 255], // +Y + [64, 0, 0, 255], // -Y + [64, 0, 64, 255], // +Z + [0, 32, 0, 255] // -Z + ], + faceDirections : [ + new Cartesian3(1.0, 0.0, 0.0), // +X + new Cartesian3(-1.0, 0.0, 0.0), // -X + new Cartesian3(0.0, 1.0, 0.0), // +Y + new Cartesian3(0.0, -1.0, 0.0), // -Y + new Cartesian3(0.0, 0.0, 1.0), // +Z + negativeZDirection // -Z + ] + }); + }); + + it('sub copies array buffers to a cube map', function() { + cubeMap = new CubeMap({ + context : context, + width : 2, + height : 2 + }); + cubeMap.positiveX.copyFrom(blueImage); + cubeMap.negativeX.copyFrom(greenImage); + cubeMap.positiveY.copyFrom(blueImage); + cubeMap.negativeY.copyFrom(greenImage); + cubeMap.positiveZ.copyFrom(blueImage); + cubeMap.negativeZ.copyFrom(greenImage, 1, 0); + + var negativeZDirection = new Cartesian3(0.25, 0.0, -1.0); + Cartesian3.normalize(negativeZDirection, negativeZDirection); + + expectCubeMapFaces({ + cubeMap : cubeMap, + expectedColors : [ + [0, 0, 64, 255], // +X + [0, 64, 0, 255], // -X + [0, 0, 64, 255], // +Y + [0, 64, 0, 255], // -Y + [0, 0, 64, 255], // +Z + [0, 32, 0, 255] // -Z + ], + faceDirections : [ + new Cartesian3(1.0, 0.0, 0.0), // +X + new Cartesian3(-1.0, 0.0, 0.0), // -X + new Cartesian3(0.0, 1.0, 0.0), // +Y + new Cartesian3(0.0, -1.0, 0.0), // -Y + new Cartesian3(0.0, 0.0, 1.0), // +Z + negativeZDirection // -Z + ] + }); + }); + it('copies from the framebuffer', function() { var cxt = createContext({ webgl : { diff --git a/Specs/Renderer/TextureSpec.js b/Specs/Renderer/TextureSpec.js index 638ecb4255e6..d51602e5d6ee 100644 --- a/Specs/Renderer/TextureSpec.js +++ b/Specs/Renderer/TextureSpec.js @@ -406,6 +406,25 @@ defineSuite([ }).contextToRender(Color.NAVY.toBytes()); }); + it('can copy from a DOM element', function() { + texture = new Texture({ + context : context, + pixelFormat : PixelFormat.RGB, + pixelDatatype : PixelDatatype.UNSIGNED_BYTE, + width : blueImage.width, + height : blueImage.height + }); + + texture.copyFrom(blueImage); + + expect({ + context : context, + fragmentShader : fs, + uniformMap : uniformMap, + epsilon : 1 + }).contextToRender([0, 0, 255, 255]); + }); + it('can replace a subset of a texture', function() { texture = new Texture({ context : context, From 6c1149b7d4959f3ed674f991119db7828f3d9839 Mon Sep 17 00:00:00 2001 From: Dan Bagnell Date: Tue, 27 Mar 2018 14:54:22 -0400 Subject: [PATCH 09/14] Do not flip batch table texture. --- Source/Renderer/Context.js | 6 ++++-- Source/Scene/Cesium3DTileBatchTable.js | 3 ++- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/Source/Renderer/Context.js b/Source/Renderer/Context.js index f3a1902328dd..367c90a246cc 100644 --- a/Source/Renderer/Context.js +++ b/Source/Renderer/Context.js @@ -720,7 +720,8 @@ define([ width : 1, height : 1, arrayBufferView : new Uint8Array([255, 255, 255, 255]) - } + }, + flipY : false }); } @@ -753,7 +754,8 @@ define([ negativeY : face, positiveZ : face, negativeZ : face - } + }, + flipY : false }); } diff --git a/Source/Scene/Cesium3DTileBatchTable.js b/Source/Scene/Cesium3DTileBatchTable.js index 42c32407f0c9..d1a834b58091 100644 --- a/Source/Scene/Cesium3DTileBatchTable.js +++ b/Source/Scene/Cesium3DTileBatchTable.js @@ -848,7 +848,7 @@ define([ ' float centerY = tile_textureStep.w; \n' + ' float xId = mod(batchId, tile_textureDimensions.x); \n' + ' float yId = floor(batchId / tile_textureDimensions.x); \n' + - ' return vec2(centerX + (xId * stepX), 1.0 - (centerY + (yId * stepY))); \n' + + ' return vec2(centerX + (xId * stepX), centerY + (yId * stepY)); \n' + '} \n'; } @@ -1505,6 +1505,7 @@ define([ height : dimensions.y, arrayBufferView : bytes }, + flipY : false, sampler : new Sampler({ minificationFilter : TextureMinificationFilter.NEAREST, magnificationFilter : TextureMagnificationFilter.NEAREST From 0bd4045caef24480166b7996982fe53efbd7b830 Mon Sep 17 00:00:00 2001 From: Dan Bagnell Date: Tue, 27 Mar 2018 15:29:17 -0400 Subject: [PATCH 10/14] Fix failing tests. --- Source/Core/PixelFormat.js | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/Source/Core/PixelFormat.js b/Source/Core/PixelFormat.js index 59c693acda4d..d5225aee883b 100644 --- a/Source/Core/PixelFormat.js +++ b/Source/Core/PixelFormat.js @@ -306,12 +306,15 @@ define([ * @private */ flipY : function(bufferView, pixelFormat, pixelDatatype, width, height) { + if (height === 1) { + return bufferView; + } var flipped = PixelFormat.createTypedArray(pixelFormat, pixelDatatype, width, height); var numberOfComponents = PixelFormat.componentsLength(pixelFormat); var textureWidth = width * numberOfComponents; for (var i = 0; i < height; ++i) { - var row = i * height; - var flippedRow = (height - i - 1) * height; + var row = i * height * numberOfComponents; + var flippedRow = (height - i - 1) * height * numberOfComponents; for (var j = 0; j < textureWidth; ++j) { flipped[flippedRow + j] = bufferView[row + j]; } From 57790afad90c1639302b9fa466ecdf35a1bf6c00 Mon Sep 17 00:00:00 2001 From: Dan Bagnell Date: Mon, 2 Apr 2018 16:50:42 -0400 Subject: [PATCH 11/14] Update CHANGES.md. --- CHANGES.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/CHANGES.md b/CHANGES.md index 5c21af41eba1..4cd85e68d643 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,6 +1,11 @@ Change Log ========== +### 1.45 - 2018-05-01 + +##### Fixes :wrench: +* Fix Firefox WebGL console warnings. [#5912](https://github.com/AnalyticalGraphicsInc/cesium/issues/5912) + ### 1.44 - 2018-04-02 ##### Breaking Changes :mega: From 07e52da3d804e1873c925bfa1bcfde3ba8a9ce2c Mon Sep 17 00:00:00 2001 From: Dan Bagnell Date: Thu, 5 Apr 2018 13:52:58 -0400 Subject: [PATCH 12/14] Do not flip water mask, batch table or OIT framebuffer textures. --- Source/Scene/BatchTable.js | 5 +++-- Source/Scene/GlobeSurfaceTile.js | 3 ++- Source/Scene/OIT.js | 22 ++++++---------------- Source/Shaders/GlobeFS.glsl | 1 + 4 files changed, 12 insertions(+), 19 deletions(-) diff --git a/Source/Scene/BatchTable.js b/Source/Scene/BatchTable.js index be1b9d5a45c2..c86067b95f12 100644 --- a/Source/Scene/BatchTable.js +++ b/Source/Scene/BatchTable.js @@ -371,7 +371,8 @@ define([ sampler : new Sampler({ minificationFilter : TextureMinificationFilter.NEAREST, magnificationFilter : TextureMagnificationFilter.NEAREST - }) + }), + flipY : false }); } @@ -456,7 +457,7 @@ define([ ' float numberOfAttributes = float('+ stride + '); \n' + ' float xId = mod(batchId * numberOfAttributes, batchTextureDimensions.x); \n' + ' float yId = floor(batchId * numberOfAttributes / batchTextureDimensions.x); \n' + - ' return vec2(centerX + (xId * stepX), 1.0 - (centerY + (yId * stepY))); \n' + + ' return vec2(centerX + (xId * stepX), centerY + (yId * stepY)); \n' + '} \n'; } diff --git a/Source/Scene/GlobeSurfaceTile.js b/Source/Scene/GlobeSurfaceTile.js index 1026832675b8..46bba1be5100 100644 --- a/Source/Scene/GlobeSurfaceTile.js +++ b/Source/Scene/GlobeSurfaceTile.js @@ -668,7 +668,8 @@ define([ height : textureSize, arrayBufferView : waterMask }, - sampler : waterMaskData.sampler + sampler : waterMaskData.sampler, + flipY : false }); texture.referenceCount = 0; diff --git a/Source/Scene/OIT.js b/Source/Scene/OIT.js index c7a38d68700d..a33fe8d767f3 100644 --- a/Source/Scene/OIT.js +++ b/Source/Scene/OIT.js @@ -111,29 +111,19 @@ define([ function updateTextures(oit, context, width, height) { destroyTextures(oit); - // Use zeroed arraybuffer instead of null to initialize texture - // to workaround Firefox 50. https://github.com/AnalyticalGraphicsInc/cesium/pull/4762 - var source = new Float32Array(width * height * 4); - oit._accumulationTexture = new Texture({ context : context, + width : width, + height : height, pixelFormat : PixelFormat.RGBA, - pixelDatatype : PixelDatatype.FLOAT, - source : { - arrayBufferView : source, - width : width, - height : height - } + pixelDatatype : PixelDatatype.FLOAT }); oit._revealageTexture = new Texture({ context : context, + width : width, + height : height, pixelFormat : PixelFormat.RGBA, - pixelDatatype : PixelDatatype.FLOAT, - source : { - arrayBufferView : source, - width : width, - height : height - } + pixelDatatype : PixelDatatype.FLOAT }); } diff --git a/Source/Shaders/GlobeFS.glsl b/Source/Shaders/GlobeFS.glsl index 6186d322c9b0..9b3b21a640a4 100644 --- a/Source/Shaders/GlobeFS.glsl +++ b/Source/Shaders/GlobeFS.glsl @@ -183,6 +183,7 @@ void main() vec2 waterMaskTranslation = u_waterMaskTranslationAndScale.xy; vec2 waterMaskScale = u_waterMaskTranslationAndScale.zw; vec2 waterMaskTextureCoordinates = v_textureCoordinates.xy * waterMaskScale + waterMaskTranslation; + waterMaskTextureCoordinates.y = 1.0 - waterMaskTextureCoordinates.y; float mask = texture2D(u_waterMask, waterMaskTextureCoordinates).r; From 229f3a6ff873702f47036dac801bc34ea7a7ecdd Mon Sep 17 00:00:00 2001 From: Sean Lilley Date: Thu, 5 Apr 2018 14:10:25 -0400 Subject: [PATCH 13/14] Fix CHANGES.md merge --- CHANGES.md | 7 ------- 1 file changed, 7 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index d77c2821db9b..7e22c39a0be0 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -61,15 +61,8 @@ Change Log * Fixed improper zoom during model load failure. [#6305](https://github.com/AnalyticalGraphicsInc/cesium/pull/6305) * Fixed rendering vector tiles when using `invertClassification`. [#6349](https://github.com/AnalyticalGraphicsInc/cesium/pull/6349) * Fixed occlusion when `globe.show` is `false`. [#6374](https://github.com/AnalyticalGraphicsInc/cesium/pull/6374) -* Fixed double-sided flag for glTF materials with `BLEND` enabled. [#6371](https://github.com/AnalyticalGraphicsInc/cesium/pull/6371) -* Fixed crash for entities with static geometry and time-dynamic attributes [#6377](https://github.com/AnalyticalGraphicsInc/cesium/pull/6377) -* Fix geometry tile rendering in IE. [#6406](https://github.com/AnalyticalGraphicsInc/cesium/pull/6406) * Fixed crash for entities with static geometry and time-dynamic attributes. [#6377](https://github.com/AnalyticalGraphicsInc/cesium/pull/6377) * Fixed geometry tile rendering in IE. [#6406](https://github.com/AnalyticalGraphicsInc/cesium/pull/6406) -* Fixed double-sided flag for glTF materials with `BLEND` enabled. [#6371](https://github.com/AnalyticalGraphicsInc/cesium/pull/6371) -* Fixed crash for entities with static geometry and time-dynamic attributes [#6377](https://github.com/AnalyticalGraphicsInc/cesium/pull/6377) -* Fix geometry tile rendering in IE. [#6406](https://github.com/AnalyticalGraphicsInc/cesium/pull/6406) -* Fix Firefox WebGL console warnings. [#5912](https://github.com/AnalyticalGraphicsInc/cesium/issues/5912) ### 1.43 - 2018-03-01 From 295372d8a1c2df8d5ad100d11638d610ebdd6b86 Mon Sep 17 00:00:00 2001 From: Dan Bagnell Date: Thu, 5 Apr 2018 16:14:23 -0400 Subject: [PATCH 14/14] Fix OIT warning. --- Source/Scene/OIT.js | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/Source/Scene/OIT.js b/Source/Scene/OIT.js index a33fe8d767f3..1e90699d313d 100644 --- a/Source/Scene/OIT.js +++ b/Source/Scene/OIT.js @@ -118,12 +118,20 @@ define([ pixelFormat : PixelFormat.RGBA, pixelDatatype : PixelDatatype.FLOAT }); + + // Use zeroed arraybuffer instead of null to initialize texture + // to workaround Firefox. Only needed for the second color attachment. + var source = new Float32Array(width * height * 4); oit._revealageTexture = new Texture({ context : context, - width : width, - height : height, pixelFormat : PixelFormat.RGBA, - pixelDatatype : PixelDatatype.FLOAT + pixelDatatype : PixelDatatype.FLOAT, + source : { + arrayBufferView : source, + width : width, + height : height + }, + flipY : false }); }