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.texSubImage2D_IF(_gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, 0,
0, glFormat, glType, cubeImage[i]);
} else {
state.texImage2D_IF(_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.texSubImage2D_IF(_gl.TEXTURE_CUBE_MAP_POSITIVE_X + i,
j + 1, 0, 0, glFormat, glType, mipmap.image[i]);
} else {
state.texImage2D_IF(_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;
}