Implementation
void uploadCubeTexture(Map<String, dynamic> textureProperties, Texture texture, int slot) {
if (texture.image.length != 6) return;
final forceUpload = initTexture(textureProperties, texture);
final source = texture.source;
state.activeTexture(WebGL.TEXTURE0 + slot);
state.bindTexture(WebGL.TEXTURE_CUBE_MAP, textureProperties['__webglTexture']);
if (source.version != source.currentVersion || forceUpload) {
_gl.pixelStorei(WebGL.UNPACK_ALIGNMENT, texture.unpackAlignment);
if (kIsWeb) {
_gl.pixelStorei(WebGL.UNPACK_FLIP_Y_WEBGL, texture.flipY ? 1 : 0);
_gl.pixelStorei(WebGL.UNPACK_PREMULTIPLY_ALPHA_WEBGL, texture.premultiplyAlpha ? 1 : 0);
_gl.pixelStorei(WebGL.UNPACK_COLORSPACE_CONVERSION_WEBGL, WebGL.NONE);
}
final isCompressed = (texture.isCompressedTexture || texture is CompressedTexture);
final isDataTexture = (texture.image[0] != null && texture is DataTexture);
final isCubeTexture = (texture.image[0] != null && texture is CubeTexture);
final cubeImage = [];
for (int i = 0; i < 6; i++) {
if (!isCompressed && !isDataTexture) {
cubeImage.add(texture.image[i]);
}
else {
cubeImage.add(isDataTexture ? texture.image[i].image : texture.image[i]);
}
cubeImage[i] = verifyColorSpace(texture, cubeImage[i]);
}
final 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);
final useTexStorage = (isWebGL2 && texture is! VideoTexture);
final allocateMemory = (textureProperties['__version'] == null);
int levels = getMipLevels(texture, image, supportsMips);
setTextureParameters(WebGL.TEXTURE_CUBE_MAP, texture, supportsMips);
dynamic mipmaps;
if (isCompressed) {
if (useTexStorage && allocateMemory) {
state.texStorage2D(WebGL.TEXTURE_CUBE_MAP, levels, glInternalFormat, image.width, image.height);
}
for (int i = 0; i < 6; i++) {
mipmaps = cubeImage[i].mipmaps;
for (int j = 0; j < mipmaps.length; j++) {
final mipmap = mipmaps[j];
if (texture.format != RGBAFormat) {
if (glFormat != null) {
if (useTexStorage) {
state.compressedTexSubImage2D(WebGL.TEXTURE_CUBE_MAP_POSITIVE_X + i, j, 0, 0, mipmap.width, mipmap.height, glFormat, mipmap.data);
} else {
state.compressedTexImage2D(WebGL.TEXTURE_CUBE_MAP_POSITIVE_X + i, j, glInternalFormat, mipmap.width, mipmap.height, 0, mipmap.data);
}
} else {
console.warning('WebGLRenderer: Attempt to load unsupported compressed texture format in .setTextureCube()');
}
} else {
if (useTexStorage) {
state.texSubImage2D(WebGL.TEXTURE_CUBE_MAP_POSITIVE_X + i, j, 0, 0, mipmap.width, mipmap.height, glFormat,
glType, mipmap.data);
} else {
state.texImage2D(WebGL.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(WebGL.TEXTURE_CUBE_MAP, levels, glInternalFormat, cubeImage[0].width, cubeImage[0].height);
}
for (int i = 0; i < 6; i++) {
if (isDataTexture || isCubeTexture) {
if (useTexStorage) {
if(kIsWeb){
state.texSubImage2DNoSize(WebGL.TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, 0, 0, glFormat, glType, cubeImage[i].data);
}
else{
state.texSubImage2D(WebGL.TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, 0, 0, cubeImage[i].width, cubeImage[i].height, glFormat, glType, cubeImage[i].data);
}
}
else {
if(kIsWeb){
state.texImage2DNoSize(WebGL.TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, glInternalFormat, glFormat, glType, cubeImage[i].data);
}
else{
state.texImage2D(WebGL.TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, glInternalFormat, cubeImage[i].width,cubeImage[i].height, 0, glFormat, glType, cubeImage[i].data);
}
}
for (int j = 0; j < mipmaps.length; j++) {
final mipmap = mipmaps[j];
final mipmapImage = mipmap.image[i].image;
if (useTexStorage) {
state.texSubImage2D(WebGL.TEXTURE_CUBE_MAP_POSITIVE_X + i, j + 1, 0, 0, mipmapImage.width,
mipmapImage.height, glFormat, glType, mipmapImage.data);
} else {
state.texImage2D(WebGL.TEXTURE_CUBE_MAP_POSITIVE_X + i, j + 1, glInternalFormat, mipmapImage.width,
mipmapImage.height, 0, glFormat, glType, mipmapImage.data);
}
}
}
else {
if (useTexStorage) {
state.texSubImage2DIf(WebGL.TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, 0, 0, glFormat, glType, cubeImage[i]);
} else {
state.texImage2DIf(
WebGL.TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, glInternalFormat, glFormat, glType, cubeImage[i]);
}
for (int j = 0; j < mipmaps.length; j++) {
final mipmap = mipmaps[j];
if (useTexStorage) {
state.texSubImage2DIf(
WebGL.TEXTURE_CUBE_MAP_POSITIVE_X + i, j + 1, 0, 0, glFormat, glType, mipmap.image[i]);
} else {
state.texImage2DIf(
WebGL.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(WebGL.TEXTURE_CUBE_MAP);
}
source.currentVersion = source.version;
if (texture.onUpdate != null) texture.onUpdate!(texture);
}
textureProperties['__version'] = texture.version;
}