uploadTexture method

void uploadTexture(
  1. Map<String, dynamic> textureProperties,
  2. Texture texture,
  3. dynamic slot
)

Implementation

void uploadTexture(Map<String, dynamic> textureProperties, Texture texture, slot) {
  var textureType = _gl.TEXTURE_2D;

  if (texture is DataArrayTexture) textureType = _gl.TEXTURE_2D_ARRAY;
  if (texture is Data3DTexture) textureType = _gl.TEXTURE_3D;

  var forceUpload = initTexture(textureProperties, texture);
  var source = texture.source;

  state.activeTexture(_gl.TEXTURE0 + slot);
  state.bindTexture(textureType, 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 needsPowerOfTwo = textureNeedsPowerOfTwo(texture) && isPowerOfTwo(texture.image) == false;
    var image = resizeImage(texture.image, needsPowerOfTwo, false, maxTextureSize);
    image = verifyColorSpace(texture, image);

    var supportsMips = isPowerOfTwo(image) || isWebGL2, glFormat = utils.convert(texture.format, texture.encoding);

    var glType = utils.convert(texture.type),
        glInternalFormat =
            getInternalFormat(texture.internalFormat, glFormat, glType, texture.encoding, texture is VideoTexture);

    setTextureParameters(textureType, texture, supportsMips);

    var mipmap;
    var mipmaps = texture.mipmaps;

    var useTexStorage = (isWebGL2 && texture is! VideoTexture);
    var allocateMemory = (textureProperties["__version"] == null) || (forceUpload == true);
    var levels = getMipLevels(texture, image, supportsMips);

    if (texture is DepthTexture) {
      // populate depth texture with dummy data

      glInternalFormat = _gl.DEPTH_COMPONENT;

      if (isWebGL2) {
        if (texture.type == FloatType) {
          glInternalFormat = _gl.DEPTH_COMPONENT32F;
        } else if (texture.type == UnsignedIntType) {
          glInternalFormat = _gl.DEPTH_COMPONENT24;
        } else if (texture.type == UnsignedInt248Type) {
          glInternalFormat = _gl.DEPTH24_STENCIL8;
        } else {
          glInternalFormat = _gl.DEPTH_COMPONENT16; // WebGL2 requires sized internalformat for glTexImage2D

        }
      } else {
        if (texture.type == FloatType) {
          console.error('WebGLRenderer: Floating point depth texture requires WebGL2.');
        }
      }

      // validation checks for WebGL 1

      if (texture.format == DepthFormat && glInternalFormat == _gl.DEPTH_COMPONENT) {
        // 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.');

          texture.type = UnsignedIntType;
          glType = utils.convert(texture.type);
        }
      }

      if (texture.format == DepthStencilFormat && glInternalFormat == _gl.DEPTH_COMPONENT) {
        // Depth stencil textures need the DEPTH_STENCIL internal format
        // (https://www.khronos.org/registry/webgl/extensions/WEBGL_depth_texture/)
        glInternalFormat = _gl.DEPTH_STENCIL;

        // 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) {
          console.warn('three.WebGLRenderer: Use UnsignedInt248Type for DepthStencilFormat DepthTexture.');

          texture.type = UnsignedInt248Type;
          glType = utils.convert(texture.type);
        }
      }

      //
      if (allocateMemory) {
        if (useTexStorage) {
          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, null);
        }
      }
    } else if (texture is DataTexture) {
      // 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

      if (mipmaps.isNotEmpty && supportsMips) {
        if (useTexStorage && allocateMemory) {
          state.texStorage2D(_gl.TEXTURE_2D, levels, glInternalFormat, mipmaps[0].width, mipmaps[0].height);
        }

        for (var i = 0, il = mipmaps.length; i < il; i++) {
          mipmap = mipmaps[i];

          if (useTexStorage) {
            state.texSubImage2D(_gl.TEXTURE_2D, i, 0, 0, mipmap.width, mipmap.height, glFormat, glType, mipmap.data);
          } else {
            state.texImage2D(
                _gl.TEXTURE_2D, i, glInternalFormat, mipmap.width, mipmap.height, 0, glFormat, glType, mipmap.data);
          }
        }

        texture.generateMipmaps = false;
      } else {
        if (useTexStorage) {
          if (allocateMemory) {
            state.texStorage2D(_gl.TEXTURE_2D, levels, glInternalFormat, image.width.toInt(), image.height.toInt());
          }

          state.texSubImage2D(_gl.TEXTURE_2D, 0, 0, 0, image.width, image.height, glFormat, glType, image.data);
        } else {
          state.texImage2D(
              _gl.TEXTURE_2D, 0, glInternalFormat, image.width, image.height, 0, glFormat, glType, image.data);
        }
      }
    } else if (texture is CompressedTexture) {
      if (useTexStorage && allocateMemory) {
        state.texStorage2D(_gl.TEXTURE_2D, levels, glInternalFormat, mipmaps[0].width, mipmaps[0].height);
      }

      for (var i = 0, il = mipmaps.length; i < il; i++) {
        mipmap = mipmaps[i];

        if (texture.format != RGBAFormat) {
          if (glFormat != null) {
            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) {
            state.texSubImage2D(_gl.TEXTURE_2D, i, 0, 0, mipmap.width, mipmap.height, glFormat, glType, mipmap.data);
          } else {
            state.texImage2D(
                _gl.TEXTURE_2D, i, glInternalFormat, mipmap.width, mipmap.height, 0, glFormat, glType, mipmap.data);
          }
        }
      }
    } else if (texture is DataArrayTexture) {
      if (useTexStorage) {
        if (allocateMemory) {
          state.texStorage3D(_gl.TEXTURE_2D_ARRAY, levels, glInternalFormat, image.width, image.height, image.depth);
        }

        state.texSubImage3D(
            _gl.TEXTURE_2D_ARRAY, 0, 0, 0, 0, image.width, image.height, image.depth, glFormat, glType, image.data);
      } else {
        state.texImage3D(_gl.TEXTURE_2D_ARRAY, 0, glInternalFormat, image.width, image.height, image.depth, 0,
            glFormat, glType, image.data);
      }
    } else if (texture is Data3DTexture) {
      if (useTexStorage) {
        if (allocateMemory) {
          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 {
        state.texImage3D(_gl.TEXTURE_3D, 0, glInternalFormat, image.width, image.height, image.depth, 0, glFormat,
            glType, image.data);
      }
    } else if (texture is FramebufferTexture) {
      if (allocateMemory) {
        if (useTexStorage) {
          state.texStorage2D(_gl.TEXTURE_2D, levels, glInternalFormat, image.width, image.height);
        } else if (allocateMemory) {
          var width = image.width, height = image.height;

          for (var i = 0; i < levels; i++) {
            state.texImage2D(_gl.TEXTURE_2D, i, glInternalFormat, width, height, 0, glFormat, glType, null);

            width >>= 1;
            height >>= 1;
          }
        }
      }
    } else {
      // regular Texture (image, video, canvas)

      // 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

      if (mipmaps.isNotEmpty && supportsMips) {
        if (useTexStorage && allocateMemory) {
          state.texStorage2D(_gl.TEXTURE_2D, levels, glInternalFormat, mipmaps[0].width, mipmaps[0].height);
        }

        for (var i = 0, il = mipmaps.length; i < il; i++) {
          mipmap = mipmaps[i];

          if (useTexStorage) {
            state.texSubImage2DIf(_gl.TEXTURE_2D, i, 0, 0, glFormat, glType, mipmap);
          } else {
            state.texImage2DIf(_gl.TEXTURE_2D, i, glInternalFormat, glFormat, glType, mipmap);
          }
        }

        texture.generateMipmaps = false;
      } else {
        if (useTexStorage) {
          if (allocateMemory) {
            state.texStorage2D(_gl.TEXTURE_2D, levels, glInternalFormat, image.width.toInt(), image.height.toInt());
          }

          state.texSubImage2DIf(_gl.TEXTURE_2D, 0, 0, 0, glFormat, glType, image);
        } else {
          state.texImage2DIf(_gl.TEXTURE_2D, 0, glInternalFormat, glFormat, glType, image);
        }
      }
    }

    if (textureNeedsGenerateMipmaps(texture, supportsMips)) {
      generateMipmap(textureType);
    }

    source.currentVersion = source.version;

    if (texture.onUpdate != null) texture.onUpdate!(texture);
  }

  textureProperties["__version"] = texture.version;
}