Implementation
void uploadCubeTexture(Map<String, dynamic> textureProperties, Texture texture, slot) {
if (texture.image.length != 6) return;
var forceUpload = initTexture(textureProperties, texture);
var source = texture.source;
state.activeTexture(_gl.TEXTURE0 + slot);
state.bindTexture(_gl.TEXTURE_CUBE_MAP, textureProperties['__webglTexture']);
if (source.version != source.currentVersion || forceUpload == true) {
_gl.pixelStorei(_gl.UNPACK_FLIP_Y_WEBGL, texture.flipY ? 1 : 0);
_gl.pixelStorei(_gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, texture.premultiplyAlpha ? 1 : 0);
_gl.pixelStorei(_gl.UNPACK_ALIGNMENT, texture.unpackAlignment);
if (kIsWeb) {
_gl.pixelStorei(_gl.UNPACK_COLORSPACE_CONVERSION_WEBGL, _gl.NONE);
}
var isCompressed = (texture.isCompressedTexture || texture.image[0].isCompressedTexture);
var isDataTexture = (texture.image[0] && texture.image[0].isDataTexture);
var cubeImage = [];
for (var i = 0; i < 6; i++) {
if (!isCompressed && !isDataTexture) {
cubeImage[i] = resizeImage(texture.image[i], false, true, maxCubemapSize);
} else {
cubeImage[i] = isDataTexture ? texture.image[i].image : texture.image[i];
}
cubeImage[i] = verifyColorSpace(texture, cubeImage[i]);
}
var 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);
var useTexStorage = (isWebGL2 && texture.isVideoTexture != true);
var allocateMemory = (textureProperties['__version'] == null);
var levels = getMipLevels(texture, image, supportsMips);
setTextureParameters(_gl.TEXTURE_CUBE_MAP, texture, supportsMips);
var mipmaps;
if (isCompressed) {
if (useTexStorage && allocateMemory) {
state.texStorage2D(_gl.TEXTURE_CUBE_MAP, levels, glInternalFormat, image.width, image.height);
}
for (var i = 0; i < 6; i++) {
mipmaps = cubeImage[i].mipmaps;
for (var j = 0; j < mipmaps.length; j++) {
var mipmap = mipmaps[j];
if (texture.format != RGBAFormat) {
if (glFormat != null) {
if (useTexStorage) {
state.compressedTexSubImage2D(
_gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, j, 0, 0, mipmap.width, mipmap.height, glFormat, mipmap.data);
} else {
state.compressedTexImage2D(_gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, j, glInternalFormat, mipmap.width,
mipmap.height, 0, mipmap.data);
}
} else {
console.warn(
'three.WebGLRenderer: Attempt to load unsupported compressed texture format in .setTextureCube()');
}
} else {
if (useTexStorage) {
state.texSubImage2D(_gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, j, 0, 0, mipmap.width, mipmap.height, glFormat,
glType, mipmap.data);
} else {
state.texImage2D(_gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, j, glInternalFormat, mipmap.width, mipmap.height,
0, glFormat, glType, mipmap.data);
}
}
}
}
} else {
mipmaps = texture.mipmaps;
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)
if (mipmaps.length > 0) levels++;
state.texStorage2D(_gl.TEXTURE_CUBE_MAP, levels, glInternalFormat, cubeImage[0].width, cubeImage[0].height);
}
for (var i = 0; i < 6; i++) {
if (isDataTexture) {
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);
} else {
state.texImage2D(_gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, glInternalFormat, cubeImage[i].width,
cubeImage[i].height, 0, glFormat, glType, cubeImage[i].data);
}
for (var j = 0; j < mipmaps.length; j++) {
var mipmap = mipmaps[j];
var mipmapImage = mipmap.image[i].image;
if (useTexStorage) {
state.texSubImage2D(_gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, j + 1, 0, 0, mipmapImage.width,
mipmapImage.height, glFormat, glType, mipmapImage.data);
} else {
state.texImage2D(_gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, j + 1, glInternalFormat, mipmapImage.width,
mipmapImage.height, 0, glFormat, glType, mipmapImage.data);
}
}
} else {
if (useTexStorage) {
state.texSubImage2DIf(_gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, 0, 0, glFormat, glType, cubeImage[i]);
} else {
state.texImage2DIf(
_gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, glInternalFormat, glFormat, glType, cubeImage[i]);
}
for (var j = 0; j < mipmaps.length; j++) {
var mipmap = mipmaps[j];
if (useTexStorage) {
state.texSubImage2DIf(
_gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, j + 1, 0, 0, glFormat, glType, mipmap.image[i]);
} else {
state.texImage2DIf(
_gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, j + 1, glInternalFormat, glFormat, glType, mipmap.image[i]);
}
}
}
}
}
if (textureNeedsGenerateMipmaps(texture, supportsMips)) {
// We assume images for cube map have the same size.
generateMipmap(_gl.TEXTURE_CUBE_MAP);
}
source.currentVersion = source.version;
if (texture.onUpdate != null) texture.onUpdate!(texture);
}
textureProperties['__version'] = texture.version;
}