|
@@ -16,6 +16,8 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils,
|
|
|
const _videoTextures = new WeakMap();
|
|
|
let _canvas;
|
|
|
|
|
|
+ const _sources = new WeakMap(); // maps WebglTexture objects to instances of Source
|
|
|
+
|
|
|
// cordova iOS (as of 5.0) still uses UIWebView, which provides OffscreenCanvas,
|
|
|
// also OffscreenCanvas.getContext("webgl"), but not OffscreenCanvas.getContext("2d")!
|
|
|
// Some implementations may only implement OffscreenCanvas partially (e.g. lacking 2d).
|
|
@@ -239,8 +241,6 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils,
|
|
|
|
|
|
}
|
|
|
|
|
|
- info.memory.textures --;
|
|
|
-
|
|
|
}
|
|
|
|
|
|
function onRenderTargetDispose( event ) {
|
|
@@ -261,12 +261,51 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils,
|
|
|
|
|
|
if ( textureProperties.__webglInit === undefined ) return;
|
|
|
|
|
|
- _gl.deleteTexture( textureProperties.__webglTexture );
|
|
|
+ // check if it's necessary to remove the WebGLTexture object
|
|
|
+
|
|
|
+ const source = texture.source;
|
|
|
+ const webglTextures = _sources.get( source );
|
|
|
+
|
|
|
+ if ( webglTextures ) {
|
|
|
+
|
|
|
+ const webglTexture = webglTextures[ textureProperties.__cacheKey ];
|
|
|
+ webglTexture.usedTimes --;
|
|
|
+
|
|
|
+ // the WebGLTexture object is not used anymore, remove it
|
|
|
+
|
|
|
+ if ( webglTexture.usedTimes === 0 ) {
|
|
|
+
|
|
|
+ deleteTexture( texture );
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ // remove the weak map entry if no WebGLTexture uses the source anymore
|
|
|
+
|
|
|
+ if ( Object.keys( webglTextures ).length === 0 ) {
|
|
|
+
|
|
|
+ _sources.delete( source );
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
|
|
|
properties.remove( texture );
|
|
|
|
|
|
}
|
|
|
|
|
|
+ function deleteTexture( texture ) {
|
|
|
+
|
|
|
+ const textureProperties = properties.get( texture );
|
|
|
+ _gl.deleteTexture( textureProperties.__webglTexture );
|
|
|
+
|
|
|
+ const source = texture.source;
|
|
|
+ const webglTextures = _sources.get( source );
|
|
|
+ delete webglTextures[ textureProperties.__cacheKey ];
|
|
|
+
|
|
|
+ info.memory.textures --;
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
function deallocateRenderTarget( renderTarget ) {
|
|
|
|
|
|
const texture = renderTarget.texture;
|
|
@@ -358,6 +397,28 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils,
|
|
|
|
|
|
}
|
|
|
|
|
|
+ function getTextureCacheKey( texture ) {
|
|
|
+
|
|
|
+ const array = [];
|
|
|
+
|
|
|
+ array.push( texture.wrapS );
|
|
|
+ array.push( texture.wrapT );
|
|
|
+ array.push( texture.magFilter );
|
|
|
+ array.push( texture.minFilter );
|
|
|
+ array.push( texture.anisotropy );
|
|
|
+ array.push( texture.internalFormat );
|
|
|
+ array.push( texture.format );
|
|
|
+ array.push( texture.type );
|
|
|
+ array.push( texture.generateMipmaps );
|
|
|
+ array.push( texture.premultiplyAlpha );
|
|
|
+ array.push( texture.flipY );
|
|
|
+ array.push( texture.unpackAlignment );
|
|
|
+ array.push( texture.encoding );
|
|
|
+
|
|
|
+ return array.join();
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
//
|
|
|
|
|
|
function setTexture2D( texture, slot ) {
|
|
@@ -520,452 +581,528 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils,
|
|
|
|
|
|
function initTexture( textureProperties, texture ) {
|
|
|
|
|
|
+ let forceUpload = false;
|
|
|
+
|
|
|
if ( textureProperties.__webglInit === undefined ) {
|
|
|
|
|
|
textureProperties.__webglInit = true;
|
|
|
|
|
|
texture.addEventListener( 'dispose', onTextureDispose );
|
|
|
|
|
|
- textureProperties.__webglTexture = _gl.createTexture();
|
|
|
+ }
|
|
|
|
|
|
- info.memory.textures ++;
|
|
|
+ // create Source <-> WebGLTextures mapping if necessary
|
|
|
|
|
|
- }
|
|
|
+ const source = texture.source;
|
|
|
+ let webglTextures = _sources.get( source );
|
|
|
|
|
|
- }
|
|
|
+ if ( webglTextures === undefined ) {
|
|
|
|
|
|
- function uploadTexture( textureProperties, texture, slot ) {
|
|
|
+ webglTextures = {};
|
|
|
+ _sources.set( source, webglTextures );
|
|
|
|
|
|
- let textureType = _gl.TEXTURE_2D;
|
|
|
+ }
|
|
|
|
|
|
- if ( texture.isDataTexture2DArray ) textureType = _gl.TEXTURE_2D_ARRAY;
|
|
|
- if ( texture.isDataTexture3D ) textureType = _gl.TEXTURE_3D;
|
|
|
+ // check if there is already a WebGLTexture object for the given texture parameters
|
|
|
|
|
|
- initTexture( textureProperties, texture );
|
|
|
+ const textureCacheKey = getTextureCacheKey( texture );
|
|
|
|
|
|
- state.activeTexture( _gl.TEXTURE0 + slot );
|
|
|
- state.bindTexture( textureType, textureProperties.__webglTexture );
|
|
|
+ if ( textureCacheKey !== textureProperties.__cacheKey ) {
|
|
|
|
|
|
- _gl.pixelStorei( _gl.UNPACK_FLIP_Y_WEBGL, texture.flipY );
|
|
|
- _gl.pixelStorei( _gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, texture.premultiplyAlpha );
|
|
|
- _gl.pixelStorei( _gl.UNPACK_ALIGNMENT, texture.unpackAlignment );
|
|
|
- _gl.pixelStorei( _gl.UNPACK_COLORSPACE_CONVERSION_WEBGL, _gl.NONE );
|
|
|
+ // if not, create a new instance of WebGLTexture
|
|
|
|
|
|
- const needsPowerOfTwo = textureNeedsPowerOfTwo( texture ) && isPowerOfTwo( texture.image ) === false;
|
|
|
- let image = resizeImage( texture.image, needsPowerOfTwo, false, maxTextureSize );
|
|
|
- image = verifyColorSpace( texture, image );
|
|
|
+ if ( webglTextures[ textureCacheKey ] === undefined ) {
|
|
|
|
|
|
- const supportsMips = isPowerOfTwo( image ) || isWebGL2,
|
|
|
- glFormat = utils.convert( texture.format, texture.encoding );
|
|
|
+ // create new entry
|
|
|
|
|
|
- let glType = utils.convert( texture.type ),
|
|
|
- glInternalFormat = getInternalFormat( texture.internalFormat, glFormat, glType, texture.encoding, texture.isVideoTexture );
|
|
|
+ webglTextures[ textureCacheKey ] = {
|
|
|
+ texture: _gl.createTexture(),
|
|
|
+ usedTimes: 0
|
|
|
+ };
|
|
|
|
|
|
- setTextureParameters( textureType, texture, supportsMips );
|
|
|
+ info.memory.textures ++;
|
|
|
|
|
|
- let mipmap;
|
|
|
- const mipmaps = texture.mipmaps;
|
|
|
+ // when a new instance of WebGLTexture was created, a texture upload is required
|
|
|
+ // even if the image contents are identical
|
|
|
|
|
|
- const useTexStorage = ( isWebGL2 && texture.isVideoTexture !== true );
|
|
|
- const allocateMemory = ( textureProperties.__version === undefined );
|
|
|
- const levels = getMipLevels( texture, image, supportsMips );
|
|
|
+ forceUpload = true;
|
|
|
|
|
|
- if ( texture.isDepthTexture ) {
|
|
|
+ }
|
|
|
|
|
|
- // populate depth texture with dummy data
|
|
|
+ webglTextures[ textureCacheKey ].usedTimes ++;
|
|
|
|
|
|
- glInternalFormat = _gl.DEPTH_COMPONENT;
|
|
|
+ // every time the texture cache key changes, it's necessary to check if an instance of
|
|
|
+ // WebGLTexture can be deleted in order to avoid a memory leak.
|
|
|
|
|
|
- if ( isWebGL2 ) {
|
|
|
+ const webglTexture = webglTextures[ textureProperties.__cacheKey ];
|
|
|
|
|
|
- if ( texture.type === FloatType ) {
|
|
|
+ if ( webglTexture !== undefined ) {
|
|
|
|
|
|
- glInternalFormat = _gl.DEPTH_COMPONENT32F;
|
|
|
+ webglTextures[ textureProperties.__cacheKey ].usedTimes --;
|
|
|
|
|
|
- } else if ( texture.type === UnsignedIntType ) {
|
|
|
+ if ( webglTexture.usedTimes === 0 ) {
|
|
|
|
|
|
- glInternalFormat = _gl.DEPTH_COMPONENT24;
|
|
|
+ deleteTexture( texture );
|
|
|
|
|
|
- } else if ( texture.type === UnsignedInt248Type ) {
|
|
|
+ }
|
|
|
|
|
|
- glInternalFormat = _gl.DEPTH24_STENCIL8;
|
|
|
+ }
|
|
|
|
|
|
- } else {
|
|
|
+ // store references to cache key and WebGLTexture object
|
|
|
|
|
|
- glInternalFormat = _gl.DEPTH_COMPONENT16; // WebGL2 requires sized internalformat for glTexImage2D
|
|
|
+ textureProperties.__cacheKey = textureCacheKey;
|
|
|
+ textureProperties.__webglTexture = webglTextures[ textureCacheKey ].texture;
|
|
|
|
|
|
- }
|
|
|
+ }
|
|
|
|
|
|
- } else {
|
|
|
+ return forceUpload;
|
|
|
|
|
|
- if ( texture.type === FloatType ) {
|
|
|
+ }
|
|
|
|
|
|
- console.error( 'WebGLRenderer: Floating point depth texture requires WebGL2.' );
|
|
|
+ function uploadTexture( textureProperties, texture, slot ) {
|
|
|
|
|
|
- }
|
|
|
+ let textureType = _gl.TEXTURE_2D;
|
|
|
|
|
|
- }
|
|
|
+ if ( texture.isDataTexture2DArray ) textureType = _gl.TEXTURE_2D_ARRAY;
|
|
|
+ if ( texture.isDataTexture3D ) textureType = _gl.TEXTURE_3D;
|
|
|
|
|
|
- // validation checks for WebGL 1
|
|
|
+ const forceUpload = initTexture( textureProperties, texture );
|
|
|
+ const source = texture.source;
|
|
|
|
|
|
- if ( texture.format === DepthFormat && glInternalFormat === _gl.DEPTH_COMPONENT ) {
|
|
|
+ state.activeTexture( _gl.TEXTURE0 + slot );
|
|
|
+ state.bindTexture( textureType, textureProperties.__webglTexture );
|
|
|
|
|
|
- // The error INVALID_OPERATION is generated by texImage2D if format and internalformat are
|
|
|
- // DEPTH_COMPONENT and type is not UNSIGNED_SHORT or UNSIGNED_INT
|
|
|
- // (https://www.khronos.org/registry/webgl/extensions/WEBGL_depth_texture/)
|
|
|
- if ( texture.type !== UnsignedShortType && texture.type !== UnsignedIntType ) {
|
|
|
+ if ( source.version !== source.__currentVersion || forceUpload === true ) {
|
|
|
|
|
|
- console.warn( 'THREE.WebGLRenderer: Use UnsignedShortType or UnsignedIntType for DepthFormat DepthTexture.' );
|
|
|
+ _gl.pixelStorei( _gl.UNPACK_FLIP_Y_WEBGL, texture.flipY );
|
|
|
+ _gl.pixelStorei( _gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, texture.premultiplyAlpha );
|
|
|
+ _gl.pixelStorei( _gl.UNPACK_ALIGNMENT, texture.unpackAlignment );
|
|
|
+ _gl.pixelStorei( _gl.UNPACK_COLORSPACE_CONVERSION_WEBGL, _gl.NONE );
|
|
|
|
|
|
- texture.type = UnsignedShortType;
|
|
|
- glType = utils.convert( texture.type );
|
|
|
+ const needsPowerOfTwo = textureNeedsPowerOfTwo( texture ) && isPowerOfTwo( texture.image ) === false;
|
|
|
+ let image = resizeImage( texture.image, needsPowerOfTwo, false, maxTextureSize );
|
|
|
+ image = verifyColorSpace( texture, image );
|
|
|
|
|
|
- }
|
|
|
+ const supportsMips = isPowerOfTwo( image ) || isWebGL2,
|
|
|
+ glFormat = utils.convert( texture.format, texture.encoding );
|
|
|
|
|
|
- }
|
|
|
+ let glType = utils.convert( texture.type ),
|
|
|
+ glInternalFormat = getInternalFormat( texture.internalFormat, glFormat, glType, texture.encoding, texture.isVideoTexture );
|
|
|
|
|
|
- if ( texture.format === DepthStencilFormat && glInternalFormat === _gl.DEPTH_COMPONENT ) {
|
|
|
+ setTextureParameters( textureType, texture, supportsMips );
|
|
|
|
|
|
- // Depth stencil textures need the DEPTH_STENCIL internal format
|
|
|
- // (https://www.khronos.org/registry/webgl/extensions/WEBGL_depth_texture/)
|
|
|
- glInternalFormat = _gl.DEPTH_STENCIL;
|
|
|
+ let mipmap;
|
|
|
+ const mipmaps = texture.mipmaps;
|
|
|
|
|
|
- // The error INVALID_OPERATION is generated by texImage2D if format and internalformat are
|
|
|
- // DEPTH_STENCIL and type is not UNSIGNED_INT_24_8_WEBGL.
|
|
|
- // (https://www.khronos.org/registry/webgl/extensions/WEBGL_depth_texture/)
|
|
|
- if ( texture.type !== UnsignedInt248Type ) {
|
|
|
+ const useTexStorage = ( isWebGL2 && texture.isVideoTexture !== true );
|
|
|
+ const allocateMemory = ( textureProperties.__version === undefined );
|
|
|
+ const levels = getMipLevels( texture, image, supportsMips );
|
|
|
|
|
|
- console.warn( 'THREE.WebGLRenderer: Use UnsignedInt248Type for DepthStencilFormat DepthTexture.' );
|
|
|
+ if ( texture.isDepthTexture ) {
|
|
|
|
|
|
- texture.type = UnsignedInt248Type;
|
|
|
- glType = utils.convert( texture.type );
|
|
|
+ // populate depth texture with dummy data
|
|
|
|
|
|
- }
|
|
|
+ glInternalFormat = _gl.DEPTH_COMPONENT;
|
|
|
|
|
|
- }
|
|
|
+ if ( isWebGL2 ) {
|
|
|
|
|
|
- //
|
|
|
+ if ( texture.type === FloatType ) {
|
|
|
|
|
|
- if ( useTexStorage && allocateMemory ) {
|
|
|
+ glInternalFormat = _gl.DEPTH_COMPONENT32F;
|
|
|
|
|
|
- state.texStorage2D( _gl.TEXTURE_2D, 1, glInternalFormat, image.width, image.height );
|
|
|
+ } else if ( texture.type === UnsignedIntType ) {
|
|
|
|
|
|
- } else {
|
|
|
+ glInternalFormat = _gl.DEPTH_COMPONENT24;
|
|
|
|
|
|
- state.texImage2D( _gl.TEXTURE_2D, 0, glInternalFormat, image.width, image.height, 0, glFormat, glType, null );
|
|
|
+ } else if ( texture.type === UnsignedInt248Type ) {
|
|
|
|
|
|
- }
|
|
|
+ glInternalFormat = _gl.DEPTH24_STENCIL8;
|
|
|
|
|
|
- } else if ( texture.isDataTexture ) {
|
|
|
+ } else {
|
|
|
|
|
|
- // use manually created mipmaps if available
|
|
|
- // if there are no manual mipmaps
|
|
|
- // set 0 level mipmap and then use GL to generate other mipmap levels
|
|
|
+ glInternalFormat = _gl.DEPTH_COMPONENT16; // WebGL2 requires sized internalformat for glTexImage2D
|
|
|
|
|
|
- if ( mipmaps.length > 0 && supportsMips ) {
|
|
|
+ }
|
|
|
|
|
|
- if ( useTexStorage && allocateMemory ) {
|
|
|
+ } else {
|
|
|
|
|
|
- state.texStorage2D( _gl.TEXTURE_2D, levels, glInternalFormat, mipmaps[ 0 ].width, mipmaps[ 0 ].height );
|
|
|
+ if ( texture.type === FloatType ) {
|
|
|
|
|
|
- }
|
|
|
+ console.error( 'WebGLRenderer: Floating point depth texture requires WebGL2.' );
|
|
|
|
|
|
- for ( let i = 0, il = mipmaps.length; i < il; i ++ ) {
|
|
|
+ }
|
|
|
|
|
|
- mipmap = mipmaps[ i ];
|
|
|
+ }
|
|
|
|
|
|
- if ( useTexStorage ) {
|
|
|
+ // validation checks for WebGL 1
|
|
|
|
|
|
- state.texSubImage2D( _gl.TEXTURE_2D, 0, 0, 0, mipmap.width, mipmap.height, glFormat, glType, mipmap.data );
|
|
|
+ if ( texture.format === DepthFormat && glInternalFormat === _gl.DEPTH_COMPONENT ) {
|
|
|
|
|
|
- } else {
|
|
|
+ // The error INVALID_OPERATION is generated by texImage2D if format and internalformat are
|
|
|
+ // DEPTH_COMPONENT and type is not UNSIGNED_SHORT or UNSIGNED_INT
|
|
|
+ // (https://www.khronos.org/registry/webgl/extensions/WEBGL_depth_texture/)
|
|
|
+ if ( texture.type !== UnsignedShortType && texture.type !== UnsignedIntType ) {
|
|
|
+
|
|
|
+ console.warn( 'THREE.WebGLRenderer: Use UnsignedShortType or UnsignedIntType for DepthFormat DepthTexture.' );
|
|
|
|
|
|
- state.texImage2D( _gl.TEXTURE_2D, i, glInternalFormat, mipmap.width, mipmap.height, 0, glFormat, glType, mipmap.data );
|
|
|
+ texture.type = UnsignedShortType;
|
|
|
+ glType = utils.convert( texture.type );
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
- texture.generateMipmaps = false;
|
|
|
+ if ( texture.format === DepthStencilFormat && glInternalFormat === _gl.DEPTH_COMPONENT ) {
|
|
|
|
|
|
- } else {
|
|
|
+ // Depth stencil textures need the DEPTH_STENCIL internal format
|
|
|
+ // (https://www.khronos.org/registry/webgl/extensions/WEBGL_depth_texture/)
|
|
|
+ glInternalFormat = _gl.DEPTH_STENCIL;
|
|
|
|
|
|
- if ( useTexStorage ) {
|
|
|
+ // The error INVALID_OPERATION is generated by texImage2D if format and internalformat are
|
|
|
+ // DEPTH_STENCIL and type is not UNSIGNED_INT_24_8_WEBGL.
|
|
|
+ // (https://www.khronos.org/registry/webgl/extensions/WEBGL_depth_texture/)
|
|
|
+ if ( texture.type !== UnsignedInt248Type ) {
|
|
|
|
|
|
- if ( allocateMemory ) {
|
|
|
+ console.warn( 'THREE.WebGLRenderer: Use UnsignedInt248Type for DepthStencilFormat DepthTexture.' );
|
|
|
|
|
|
- state.texStorage2D( _gl.TEXTURE_2D, levels, glInternalFormat, image.width, image.height );
|
|
|
+ texture.type = UnsignedInt248Type;
|
|
|
+ glType = utils.convert( texture.type );
|
|
|
|
|
|
}
|
|
|
|
|
|
- state.texSubImage2D( _gl.TEXTURE_2D, 0, 0, 0, image.width, image.height, glFormat, glType, image.data );
|
|
|
+ }
|
|
|
+
|
|
|
+ //
|
|
|
+
|
|
|
+ if ( useTexStorage && allocateMemory ) {
|
|
|
+
|
|
|
+ state.texStorage2D( _gl.TEXTURE_2D, 1, glInternalFormat, image.width, image.height );
|
|
|
|
|
|
} else {
|
|
|
|
|
|
- state.texImage2D( _gl.TEXTURE_2D, 0, glInternalFormat, image.width, image.height, 0, glFormat, glType, image.data );
|
|
|
+ state.texImage2D( _gl.TEXTURE_2D, 0, glInternalFormat, image.width, image.height, 0, glFormat, glType, null );
|
|
|
|
|
|
}
|
|
|
|
|
|
- }
|
|
|
-
|
|
|
- } else if ( texture.isCompressedTexture ) {
|
|
|
+ } else if ( texture.isDataTexture ) {
|
|
|
|
|
|
- if ( useTexStorage && allocateMemory ) {
|
|
|
+ // use manually created mipmaps if available
|
|
|
+ // if there are no manual mipmaps
|
|
|
+ // set 0 level mipmap and then use GL to generate other mipmap levels
|
|
|
|
|
|
- state.texStorage2D( _gl.TEXTURE_2D, levels, glInternalFormat, mipmaps[ 0 ].width, mipmaps[ 0 ].height );
|
|
|
+ if ( mipmaps.length > 0 && supportsMips ) {
|
|
|
|
|
|
- }
|
|
|
+ if ( useTexStorage && allocateMemory ) {
|
|
|
|
|
|
- for ( let i = 0, il = mipmaps.length; i < il; i ++ ) {
|
|
|
+ state.texStorage2D( _gl.TEXTURE_2D, levels, glInternalFormat, mipmaps[ 0 ].width, mipmaps[ 0 ].height );
|
|
|
|
|
|
- mipmap = mipmaps[ i ];
|
|
|
+ }
|
|
|
|
|
|
- if ( texture.format !== RGBAFormat ) {
|
|
|
+ for ( let i = 0, il = mipmaps.length; i < il; i ++ ) {
|
|
|
|
|
|
- if ( glFormat !== null ) {
|
|
|
+ mipmap = mipmaps[ i ];
|
|
|
|
|
|
if ( useTexStorage ) {
|
|
|
|
|
|
- state.compressedTexSubImage2D( _gl.TEXTURE_2D, i, 0, 0, mipmap.width, mipmap.height, glFormat, mipmap.data );
|
|
|
+ state.texSubImage2D( _gl.TEXTURE_2D, 0, 0, 0, mipmap.width, mipmap.height, glFormat, glType, mipmap.data );
|
|
|
|
|
|
} else {
|
|
|
|
|
|
- state.compressedTexImage2D( _gl.TEXTURE_2D, i, glInternalFormat, mipmap.width, mipmap.height, 0, mipmap.data );
|
|
|
+ state.texImage2D( _gl.TEXTURE_2D, i, glInternalFormat, mipmap.width, mipmap.height, 0, glFormat, glType, mipmap.data );
|
|
|
|
|
|
}
|
|
|
|
|
|
- } else {
|
|
|
-
|
|
|
- console.warn( 'THREE.WebGLRenderer: Attempt to load unsupported compressed texture format in .uploadTexture()' );
|
|
|
-
|
|
|
}
|
|
|
|
|
|
+ texture.generateMipmaps = false;
|
|
|
+
|
|
|
} else {
|
|
|
|
|
|
if ( useTexStorage ) {
|
|
|
|
|
|
- state.texSubImage2D( _gl.TEXTURE_2D, i, 0, 0, mipmap.width, mipmap.height, glFormat, glType, mipmap.data );
|
|
|
+ if ( allocateMemory ) {
|
|
|
+
|
|
|
+ state.texStorage2D( _gl.TEXTURE_2D, levels, glInternalFormat, image.width, image.height );
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ state.texSubImage2D( _gl.TEXTURE_2D, 0, 0, 0, image.width, image.height, glFormat, glType, image.data );
|
|
|
|
|
|
} else {
|
|
|
|
|
|
- state.texImage2D( _gl.TEXTURE_2D, i, glInternalFormat, mipmap.width, mipmap.height, 0, glFormat, glType, mipmap.data );
|
|
|
+ state.texImage2D( _gl.TEXTURE_2D, 0, glInternalFormat, image.width, image.height, 0, glFormat, glType, image.data );
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
- }
|
|
|
+ } else if ( texture.isCompressedTexture ) {
|
|
|
|
|
|
- } else if ( texture.isDataTexture2DArray ) {
|
|
|
+ if ( useTexStorage && allocateMemory ) {
|
|
|
|
|
|
- if ( useTexStorage ) {
|
|
|
+ state.texStorage2D( _gl.TEXTURE_2D, levels, glInternalFormat, mipmaps[ 0 ].width, mipmaps[ 0 ].height );
|
|
|
|
|
|
- if ( allocateMemory ) {
|
|
|
+ }
|
|
|
|
|
|
- state.texStorage3D( _gl.TEXTURE_2D_ARRAY, levels, glInternalFormat, image.width, image.height, image.depth );
|
|
|
+ for ( let i = 0, il = mipmaps.length; i < il; i ++ ) {
|
|
|
|
|
|
- }
|
|
|
+ mipmap = mipmaps[ i ];
|
|
|
|
|
|
- state.texSubImage3D( _gl.TEXTURE_2D_ARRAY, 0, 0, 0, 0, image.width, image.height, image.depth, glFormat, glType, image.data );
|
|
|
+ if ( texture.format !== RGBAFormat ) {
|
|
|
|
|
|
- } else {
|
|
|
+ if ( glFormat !== null ) {
|
|
|
|
|
|
- state.texImage3D( _gl.TEXTURE_2D_ARRAY, 0, glInternalFormat, image.width, image.height, image.depth, 0, glFormat, glType, image.data );
|
|
|
+ if ( useTexStorage ) {
|
|
|
|
|
|
- }
|
|
|
+ state.compressedTexSubImage2D( _gl.TEXTURE_2D, i, 0, 0, mipmap.width, mipmap.height, glFormat, mipmap.data );
|
|
|
+
|
|
|
+ } else {
|
|
|
+
|
|
|
+ state.compressedTexImage2D( _gl.TEXTURE_2D, i, glInternalFormat, mipmap.width, mipmap.height, 0, mipmap.data );
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ } else {
|
|
|
+
|
|
|
+ console.warn( 'THREE.WebGLRenderer: Attempt to load unsupported compressed texture format in .uploadTexture()' );
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ } else {
|
|
|
+
|
|
|
+ if ( useTexStorage ) {
|
|
|
|
|
|
- } else if ( texture.isDataTexture3D ) {
|
|
|
+ state.texSubImage2D( _gl.TEXTURE_2D, i, 0, 0, mipmap.width, mipmap.height, glFormat, glType, mipmap.data );
|
|
|
|
|
|
- if ( useTexStorage ) {
|
|
|
+ } else {
|
|
|
|
|
|
- if ( allocateMemory ) {
|
|
|
+ state.texImage2D( _gl.TEXTURE_2D, i, glInternalFormat, mipmap.width, mipmap.height, 0, glFormat, glType, mipmap.data );
|
|
|
|
|
|
- state.texStorage3D( _gl.TEXTURE_3D, levels, glInternalFormat, image.width, image.height, image.depth );
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
|
|
|
}
|
|
|
|
|
|
- state.texSubImage3D( _gl.TEXTURE_3D, 0, 0, 0, 0, image.width, image.height, image.depth, glFormat, glType, image.data );
|
|
|
+ } else if ( texture.isDataTexture2DArray ) {
|
|
|
|
|
|
- } else {
|
|
|
+ if ( useTexStorage ) {
|
|
|
|
|
|
- state.texImage3D( _gl.TEXTURE_3D, 0, glInternalFormat, image.width, image.height, image.depth, 0, glFormat, glType, image.data );
|
|
|
+ if ( allocateMemory ) {
|
|
|
|
|
|
- }
|
|
|
+ state.texStorage3D( _gl.TEXTURE_2D_ARRAY, levels, glInternalFormat, image.width, image.height, image.depth );
|
|
|
|
|
|
- } else if ( texture.isFramebufferTexture ) {
|
|
|
+ }
|
|
|
|
|
|
- if ( useTexStorage && allocateMemory ) {
|
|
|
+ state.texSubImage3D( _gl.TEXTURE_2D_ARRAY, 0, 0, 0, 0, image.width, image.height, image.depth, glFormat, glType, image.data );
|
|
|
|
|
|
- state.texStorage2D( _gl.TEXTURE_2D, levels, glInternalFormat, image.width, image.height );
|
|
|
+ } else {
|
|
|
|
|
|
- } else {
|
|
|
+ state.texImage3D( _gl.TEXTURE_2D_ARRAY, 0, glInternalFormat, image.width, image.height, image.depth, 0, glFormat, glType, image.data );
|
|
|
|
|
|
- state.texImage2D( _gl.TEXTURE_2D, 0, glInternalFormat, image.width, image.height, 0, glFormat, glType, null );
|
|
|
+ }
|
|
|
|
|
|
- }
|
|
|
+ } else if ( texture.isDataTexture3D ) {
|
|
|
|
|
|
- } else {
|
|
|
+ if ( useTexStorage ) {
|
|
|
|
|
|
- // regular Texture (image, video, canvas)
|
|
|
+ if ( allocateMemory ) {
|
|
|
|
|
|
- // use manually created mipmaps if available
|
|
|
- // if there are no manual mipmaps
|
|
|
- // set 0 level mipmap and then use GL to generate other mipmap levels
|
|
|
+ state.texStorage3D( _gl.TEXTURE_3D, levels, glInternalFormat, image.width, image.height, image.depth );
|
|
|
|
|
|
- if ( mipmaps.length > 0 && supportsMips ) {
|
|
|
+ }
|
|
|
+
|
|
|
+ state.texSubImage3D( _gl.TEXTURE_3D, 0, 0, 0, 0, image.width, image.height, image.depth, glFormat, glType, image.data );
|
|
|
+
|
|
|
+ } else {
|
|
|
+
|
|
|
+ state.texImage3D( _gl.TEXTURE_3D, 0, glInternalFormat, image.width, image.height, image.depth, 0, glFormat, glType, image.data );
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ } else if ( texture.isFramebufferTexture ) {
|
|
|
|
|
|
if ( useTexStorage && allocateMemory ) {
|
|
|
|
|
|
- state.texStorage2D( _gl.TEXTURE_2D, levels, glInternalFormat, mipmaps[ 0 ].width, mipmaps[ 0 ].height );
|
|
|
+ state.texStorage2D( _gl.TEXTURE_2D, levels, glInternalFormat, image.width, image.height );
|
|
|
+
|
|
|
+ } else {
|
|
|
+
|
|
|
+ state.texImage2D( _gl.TEXTURE_2D, 0, glInternalFormat, image.width, image.height, 0, glFormat, glType, null );
|
|
|
|
|
|
}
|
|
|
|
|
|
- for ( let i = 0, il = mipmaps.length; i < il; i ++ ) {
|
|
|
+ } else {
|
|
|
|
|
|
- mipmap = mipmaps[ i ];
|
|
|
+ // regular Texture (image, video, canvas)
|
|
|
|
|
|
- if ( useTexStorage ) {
|
|
|
+ // use manually created mipmaps if available
|
|
|
+ // if there are no manual mipmaps
|
|
|
+ // set 0 level mipmap and then use GL to generate other mipmap levels
|
|
|
|
|
|
- state.texSubImage2D( _gl.TEXTURE_2D, i, 0, 0, glFormat, glType, mipmap );
|
|
|
+ if ( mipmaps.length > 0 && supportsMips ) {
|
|
|
|
|
|
- } else {
|
|
|
+ if ( useTexStorage && allocateMemory ) {
|
|
|
|
|
|
- state.texImage2D( _gl.TEXTURE_2D, i, glInternalFormat, glFormat, glType, mipmap );
|
|
|
+ state.texStorage2D( _gl.TEXTURE_2D, levels, glInternalFormat, mipmaps[ 0 ].width, mipmaps[ 0 ].height );
|
|
|
|
|
|
}
|
|
|
|
|
|
- }
|
|
|
+ for ( let i = 0, il = mipmaps.length; i < il; i ++ ) {
|
|
|
|
|
|
- texture.generateMipmaps = false;
|
|
|
+ mipmap = mipmaps[ i ];
|
|
|
|
|
|
- } else {
|
|
|
+ if ( useTexStorage ) {
|
|
|
|
|
|
- if ( useTexStorage ) {
|
|
|
+ state.texSubImage2D( _gl.TEXTURE_2D, i, 0, 0, glFormat, glType, mipmap );
|
|
|
|
|
|
- if ( allocateMemory ) {
|
|
|
+ } else {
|
|
|
+
|
|
|
+ state.texImage2D( _gl.TEXTURE_2D, i, glInternalFormat, glFormat, glType, mipmap );
|
|
|
|
|
|
- state.texStorage2D( _gl.TEXTURE_2D, levels, glInternalFormat, image.width, image.height );
|
|
|
+ }
|
|
|
|
|
|
}
|
|
|
|
|
|
- state.texSubImage2D( _gl.TEXTURE_2D, 0, 0, 0, glFormat, glType, image );
|
|
|
+ texture.generateMipmaps = false;
|
|
|
|
|
|
} else {
|
|
|
|
|
|
- state.texImage2D( _gl.TEXTURE_2D, 0, glInternalFormat, glFormat, glType, image );
|
|
|
+ if ( useTexStorage ) {
|
|
|
+
|
|
|
+ if ( allocateMemory ) {
|
|
|
+
|
|
|
+ state.texStorage2D( _gl.TEXTURE_2D, levels, glInternalFormat, image.width, image.height );
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ state.texSubImage2D( _gl.TEXTURE_2D, 0, 0, 0, glFormat, glType, image );
|
|
|
+
|
|
|
+ } else {
|
|
|
+
|
|
|
+ state.texImage2D( _gl.TEXTURE_2D, 0, glInternalFormat, glFormat, glType, image );
|
|
|
+
|
|
|
+ }
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
- }
|
|
|
+ if ( textureNeedsGenerateMipmaps( texture, supportsMips ) ) {
|
|
|
|
|
|
- if ( textureNeedsGenerateMipmaps( texture, supportsMips ) ) {
|
|
|
+ generateMipmap( textureType );
|
|
|
|
|
|
- generateMipmap( textureType );
|
|
|
+ }
|
|
|
+
|
|
|
+ source.__currentVersion = source.version;
|
|
|
+
|
|
|
+ if ( texture.onUpdate ) texture.onUpdate( texture );
|
|
|
|
|
|
}
|
|
|
|
|
|
textureProperties.__version = texture.version;
|
|
|
|
|
|
- if ( texture.onUpdate ) texture.onUpdate( texture );
|
|
|
-
|
|
|
}
|
|
|
|
|
|
function uploadCubeTexture( textureProperties, texture, slot ) {
|
|
|
|
|
|
if ( texture.image.length !== 6 ) return;
|
|
|
|
|
|
- initTexture( textureProperties, texture );
|
|
|
+ const forceUpload = initTexture( textureProperties, texture );
|
|
|
+ const source = texture.source;
|
|
|
|
|
|
state.activeTexture( _gl.TEXTURE0 + slot );
|
|
|
state.bindTexture( _gl.TEXTURE_CUBE_MAP, textureProperties.__webglTexture );
|
|
|
|
|
|
- _gl.pixelStorei( _gl.UNPACK_FLIP_Y_WEBGL, texture.flipY );
|
|
|
- _gl.pixelStorei( _gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, texture.premultiplyAlpha );
|
|
|
- _gl.pixelStorei( _gl.UNPACK_ALIGNMENT, texture.unpackAlignment );
|
|
|
- _gl.pixelStorei( _gl.UNPACK_COLORSPACE_CONVERSION_WEBGL, _gl.NONE );
|
|
|
+ if ( source.version !== source.__currentVersion || forceUpload === true ) {
|
|
|
|
|
|
- const isCompressed = ( texture.isCompressedTexture || texture.image[ 0 ].isCompressedTexture );
|
|
|
- const isDataTexture = ( texture.image[ 0 ] && texture.image[ 0 ].isDataTexture );
|
|
|
+ _gl.pixelStorei( _gl.UNPACK_FLIP_Y_WEBGL, texture.flipY );
|
|
|
+ _gl.pixelStorei( _gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, texture.premultiplyAlpha );
|
|
|
+ _gl.pixelStorei( _gl.UNPACK_ALIGNMENT, texture.unpackAlignment );
|
|
|
+ _gl.pixelStorei( _gl.UNPACK_COLORSPACE_CONVERSION_WEBGL, _gl.NONE );
|
|
|
|
|
|
- const cubeImage = [];
|
|
|
+ const isCompressed = ( texture.isCompressedTexture || texture.image[ 0 ].isCompressedTexture );
|
|
|
+ const isDataTexture = ( texture.image[ 0 ] && texture.image[ 0 ].isDataTexture );
|
|
|
|
|
|
- for ( let i = 0; i < 6; i ++ ) {
|
|
|
+ const cubeImage = [];
|
|
|
|
|
|
- if ( ! isCompressed && ! isDataTexture ) {
|
|
|
+ for ( let i = 0; i < 6; i ++ ) {
|
|
|
|
|
|
- cubeImage[ i ] = resizeImage( texture.image[ i ], false, true, maxCubemapSize );
|
|
|
+ if ( ! isCompressed && ! isDataTexture ) {
|
|
|
|
|
|
- } else {
|
|
|
+ cubeImage[ i ] = resizeImage( texture.image[ i ], false, true, maxCubemapSize );
|
|
|
+
|
|
|
+ } else {
|
|
|
|
|
|
- cubeImage[ i ] = isDataTexture ? texture.image[ i ].image : texture.image[ i ];
|
|
|
+ cubeImage[ i ] = isDataTexture ? texture.image[ i ].image : texture.image[ i ];
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ cubeImage[ i ] = verifyColorSpace( texture, cubeImage[ i ] );
|
|
|
|
|
|
}
|
|
|
|
|
|
- cubeImage[ i ] = verifyColorSpace( texture, cubeImage[ i ] );
|
|
|
+ const image = cubeImage[ 0 ],
|
|
|
+ supportsMips = isPowerOfTwo( image ) || isWebGL2,
|
|
|
+ glFormat = utils.convert( texture.format, texture.encoding ),
|
|
|
+ glType = utils.convert( texture.type ),
|
|
|
+ glInternalFormat = getInternalFormat( texture.internalFormat, glFormat, glType, texture.encoding );
|
|
|
|
|
|
- }
|
|
|
+ const useTexStorage = ( isWebGL2 && texture.isVideoTexture !== true );
|
|
|
+ const allocateMemory = ( textureProperties.__version === undefined );
|
|
|
+ let levels = getMipLevels( texture, image, supportsMips );
|
|
|
|
|
|
- const image = cubeImage[ 0 ],
|
|
|
- supportsMips = isPowerOfTwo( image ) || isWebGL2,
|
|
|
- glFormat = utils.convert( texture.format, texture.encoding ),
|
|
|
- glType = utils.convert( texture.type ),
|
|
|
- glInternalFormat = getInternalFormat( texture.internalFormat, glFormat, glType, texture.encoding );
|
|
|
+ setTextureParameters( _gl.TEXTURE_CUBE_MAP, texture, supportsMips );
|
|
|
|
|
|
- const useTexStorage = ( isWebGL2 && texture.isVideoTexture !== true );
|
|
|
- const allocateMemory = ( textureProperties.__version === undefined );
|
|
|
- let levels = getMipLevels( texture, image, supportsMips );
|
|
|
+ let mipmaps;
|
|
|
|
|
|
- setTextureParameters( _gl.TEXTURE_CUBE_MAP, texture, supportsMips );
|
|
|
+ if ( isCompressed ) {
|
|
|
|
|
|
- let mipmaps;
|
|
|
+ if ( useTexStorage && allocateMemory ) {
|
|
|
|
|
|
- if ( isCompressed ) {
|
|
|
+ state.texStorage2D( _gl.TEXTURE_CUBE_MAP, levels, glInternalFormat, image.width, image.height );
|
|
|
|
|
|
- if ( useTexStorage && allocateMemory ) {
|
|
|
+ }
|
|
|
|
|
|
- state.texStorage2D( _gl.TEXTURE_CUBE_MAP, levels, glInternalFormat, image.width, image.height );
|
|
|
+ for ( let i = 0; i < 6; i ++ ) {
|
|
|
|
|
|
- }
|
|
|
+ mipmaps = cubeImage[ i ].mipmaps;
|
|
|
|
|
|
- for ( let i = 0; i < 6; i ++ ) {
|
|
|
+ for ( let j = 0; j < mipmaps.length; j ++ ) {
|
|
|
|
|
|
- mipmaps = cubeImage[ i ].mipmaps;
|
|
|
+ const mipmap = mipmaps[ j ];
|
|
|
|
|
|
- for ( let j = 0; j < mipmaps.length; j ++ ) {
|
|
|
+ if ( texture.format !== RGBAFormat ) {
|
|
|
|
|
|
- const mipmap = mipmaps[ j ];
|
|
|
+ if ( glFormat !== null ) {
|
|
|
|
|
|
- if ( texture.format !== RGBAFormat ) {
|
|
|
+ if ( useTexStorage ) {
|
|
|
|
|
|
- if ( glFormat !== null ) {
|
|
|
+ state.compressedTexSubImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, j, 0, 0, mipmap.width, mipmap.height, glFormat, mipmap.data );
|
|
|
|
|
|
- if ( useTexStorage ) {
|
|
|
+ } else {
|
|
|
|
|
|
- state.compressedTexSubImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, j, 0, 0, mipmap.width, mipmap.height, glFormat, mipmap.data );
|
|
|
+ state.compressedTexImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, j, glInternalFormat, mipmap.width, mipmap.height, 0, mipmap.data );
|
|
|
+
|
|
|
+ }
|
|
|
|
|
|
} else {
|
|
|
|
|
|
- state.compressedTexImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, j, glInternalFormat, mipmap.width, mipmap.height, 0, mipmap.data );
|
|
|
+ console.warn( 'THREE.WebGLRenderer: Attempt to load unsupported compressed texture format in .setTextureCube()' );
|
|
|
|
|
|
}
|
|
|
|
|
|
} else {
|
|
|
|
|
|
- console.warn( 'THREE.WebGLRenderer: Attempt to load unsupported compressed texture format in .setTextureCube()' );
|
|
|
-
|
|
|
- }
|
|
|
+ if ( useTexStorage ) {
|
|
|
|
|
|
- } else {
|
|
|
+ state.texSubImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, j, 0, 0, mipmap.width, mipmap.height, glFormat, glType, mipmap.data );
|
|
|
|
|
|
- if ( useTexStorage ) {
|
|
|
-
|
|
|
- state.texSubImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, j, 0, 0, mipmap.width, mipmap.height, glFormat, glType, mipmap.data );
|
|
|
+ } else {
|
|
|
|
|
|
- } else {
|
|
|
+ state.texImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, j, glInternalFormat, mipmap.width, mipmap.height, 0, glFormat, glType, mipmap.data );
|
|
|
|
|
|
- state.texImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, j, glInternalFormat, mipmap.width, mipmap.height, 0, glFormat, glType, mipmap.data );
|
|
|
+ }
|
|
|
|
|
|
}
|
|
|
|
|
@@ -973,78 +1110,78 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils,
|
|
|
|
|
|
}
|
|
|
|
|
|
- }
|
|
|
+ } else {
|
|
|
|
|
|
- } else {
|
|
|
+ mipmaps = texture.mipmaps;
|
|
|
|
|
|
- mipmaps = texture.mipmaps;
|
|
|
+ if ( useTexStorage && allocateMemory ) {
|
|
|
|
|
|
- if ( useTexStorage && allocateMemory ) {
|
|
|
+ // TODO: Uniformly handle mipmap definitions
|
|
|
+ // Normal textures and compressed cube textures define base level + mips with their mipmap array
|
|
|
+ // Uncompressed cube textures use their mipmap array only for mips (no base level)
|
|
|
|
|
|
- // TODO: Uniformly handle mipmap definitions
|
|
|
- // Normal textures and compressed cube textures define base level + mips with their mipmap array
|
|
|
- // Uncompressed cube textures use their mipmap array only for mips (no base level)
|
|
|
+ if ( mipmaps.length > 0 ) levels ++;
|
|
|
|
|
|
- if ( mipmaps.length > 0 ) levels ++;
|
|
|
+ state.texStorage2D( _gl.TEXTURE_CUBE_MAP, levels, glInternalFormat, cubeImage[ 0 ].width, cubeImage[ 0 ].height );
|
|
|
|
|
|
- state.texStorage2D( _gl.TEXTURE_CUBE_MAP, levels, glInternalFormat, cubeImage[ 0 ].width, cubeImage[ 0 ].height );
|
|
|
+ }
|
|
|
|
|
|
- }
|
|
|
+ for ( let i = 0; i < 6; i ++ ) {
|
|
|
|
|
|
- for ( let i = 0; i < 6; i ++ ) {
|
|
|
+ if ( isDataTexture ) {
|
|
|
|
|
|
- if ( isDataTexture ) {
|
|
|
+ if ( useTexStorage ) {
|
|
|
|
|
|
- if ( useTexStorage ) {
|
|
|
+ state.texSubImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, 0, 0, cubeImage[ i ].width, cubeImage[ i ].height, glFormat, glType, cubeImage[ i ].data );
|
|
|
|
|
|
- state.texSubImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, 0, 0, cubeImage[ i ].width, cubeImage[ i ].height, glFormat, glType, cubeImage[ i ].data );
|
|
|
+ } else {
|
|
|
|
|
|
- } else {
|
|
|
+ state.texImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, glInternalFormat, cubeImage[ i ].width, cubeImage[ i ].height, 0, glFormat, glType, cubeImage[ i ].data );
|
|
|
|
|
|
- state.texImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, glInternalFormat, cubeImage[ i ].width, cubeImage[ i ].height, 0, glFormat, glType, cubeImage[ i ].data );
|
|
|
+ }
|
|
|
|
|
|
- }
|
|
|
+ for ( let j = 0; j < mipmaps.length; j ++ ) {
|
|
|
|
|
|
- for ( let j = 0; j < mipmaps.length; j ++ ) {
|
|
|
+ const mipmap = mipmaps[ j ];
|
|
|
+ const mipmapImage = mipmap.image[ i ].image;
|
|
|
|
|
|
- const mipmap = mipmaps[ j ];
|
|
|
- const mipmapImage = mipmap.image[ i ].image;
|
|
|
+ if ( useTexStorage ) {
|
|
|
|
|
|
- if ( useTexStorage ) {
|
|
|
+ state.texSubImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, j + 1, 0, 0, mipmapImage.width, mipmapImage.height, glFormat, glType, mipmapImage.data );
|
|
|
|
|
|
- state.texSubImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, j + 1, 0, 0, mipmapImage.width, mipmapImage.height, glFormat, glType, mipmapImage.data );
|
|
|
+ } else {
|
|
|
|
|
|
- } else {
|
|
|
+ state.texImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, j + 1, glInternalFormat, mipmapImage.width, mipmapImage.height, 0, glFormat, glType, mipmapImage.data );
|
|
|
|
|
|
- state.texImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, j + 1, glInternalFormat, mipmapImage.width, mipmapImage.height, 0, glFormat, glType, mipmapImage.data );
|
|
|
+ }
|
|
|
|
|
|
}
|
|
|
|
|
|
- }
|
|
|
+ } else {
|
|
|
|
|
|
- } else {
|
|
|
+ if ( useTexStorage ) {
|
|
|
|
|
|
- if ( useTexStorage ) {
|
|
|
+ state.texSubImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, 0, 0, glFormat, glType, cubeImage[ i ] );
|
|
|
|
|
|
- state.texSubImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, 0, 0, glFormat, glType, cubeImage[ i ] );
|
|
|
+ } else {
|
|
|
|
|
|
- } else {
|
|
|
+ state.texImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, glInternalFormat, glFormat, glType, cubeImage[ i ] );
|
|
|
|
|
|
- state.texImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, glInternalFormat, glFormat, glType, cubeImage[ i ] );
|
|
|
+ }
|
|
|
|
|
|
- }
|
|
|
+ for ( let j = 0; j < mipmaps.length; j ++ ) {
|
|
|
|
|
|
- for ( let j = 0; j < mipmaps.length; j ++ ) {
|
|
|
+ const mipmap = mipmaps[ j ];
|
|
|
|
|
|
- const mipmap = mipmaps[ j ];
|
|
|
+ if ( useTexStorage ) {
|
|
|
|
|
|
- if ( useTexStorage ) {
|
|
|
+ state.texSubImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, j + 1, 0, 0, glFormat, glType, mipmap.image[ i ] );
|
|
|
|
|
|
- state.texSubImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, j + 1, 0, 0, glFormat, glType, mipmap.image[ i ] );
|
|
|
+ } else {
|
|
|
|
|
|
- } else {
|
|
|
+ state.texImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, j + 1, glInternalFormat, glFormat, glType, mipmap.image[ i ] );
|
|
|
|
|
|
- state.texImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, j + 1, glInternalFormat, glFormat, glType, mipmap.image[ i ] );
|
|
|
+ }
|
|
|
|
|
|
}
|
|
|
|
|
@@ -1054,19 +1191,21 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils,
|
|
|
|
|
|
}
|
|
|
|
|
|
- }
|
|
|
+ if ( textureNeedsGenerateMipmaps( texture, supportsMips ) ) {
|
|
|
+
|
|
|
+ // We assume images for cube map have the same size.
|
|
|
+ generateMipmap( _gl.TEXTURE_CUBE_MAP );
|
|
|
+
|
|
|
+ }
|
|
|
|
|
|
- if ( textureNeedsGenerateMipmaps( texture, supportsMips ) ) {
|
|
|
+ source.__currentVersion = source.version;
|
|
|
|
|
|
- // We assume images for cube map have the same size.
|
|
|
- generateMipmap( _gl.TEXTURE_CUBE_MAP );
|
|
|
+ if ( texture.onUpdate ) texture.onUpdate( texture );
|
|
|
|
|
|
}
|
|
|
|
|
|
textureProperties.__version = texture.version;
|
|
|
|
|
|
- if ( texture.onUpdate ) texture.onUpdate( texture );
|
|
|
-
|
|
|
}
|
|
|
|
|
|
// Render targets
|