src/textures.js
function createTextures(gl, textureOptions, callback) {
  callback = callback || noop;
  let numDownloading = 0;
  const errors = [];
  const textures = {};
  const images = {};

  function callCallbackIfReady() {
    if (numDownloading === 0) {
      setTimeout(function() {
        callback(errors.length ? errors : undefined, textures, images);
      }, 0);
    }
  }

  Object.keys(textureOptions).forEach(function(name) {
    const options = textureOptions[name];
    let onLoadFn;
    if (isAsyncSrc(options.src)) {
      onLoadFn = function(err, tex, img) {
        images[name] = img;
        --numDownloading;
        if (err) {
          errors.push(err);
        }
        callCallbackIfReady();
      };
      ++numDownloading;
    }
    textures[name] = createTexture(gl, options, onLoadFn);
  });

  // queue the callback if there are no images to download.
  // We do this because if your code is structured to wait for
  // images to download but then you comment out all the async
  // images your code would break.
  callCallbackIfReady();

  return textures;
}
function createTextures(gl, textureOptions, callback) {
  callback = callback || noop;
  let numDownloading = 0;
  const errors = [];
  const textures = {};
  const images = {};

  function callCallbackIfReady() {
    if (numDownloading === 0) {
      setTimeout(function() {
        callback(errors.length ? errors : undefined, textures, images);
      }, 0);
    }
  }

  Object.keys(textureOptions).forEach(function(name) {
    const options = textureOptions[name];
    let onLoadFn;
    if (isAsyncSrc(options.src)) {
      onLoadFn = function(err, tex, img) {
        images[name] = img;
        --numDownloading;
        if (err) {
          errors.push(err);
        }
        callCallbackIfReady();
      };
      ++numDownloading;
    }
    textures[name] = createTexture(gl, options, onLoadFn);
  });

  // queue the callback if there are no images to download.
  // We do this because if your code is structured to wait for
  // images to download but then you comment out all the async
  // images your code would break.
  callCallbackIfReady();

  return textures;
}
function createTextures ( gl , textureOptions , callback ) { callback = callback || noop ; let numDownloading = 0 ; const errors = [ ] ; const textures = { } ; const images = { } ; function callCallbackIfReady ( ) { if ( numDownloading === 0 ) { setTimeout ( function ( ) { callback ( errors . length ? errors : undefined , textures , images ) ; } , 0 ) ; } } Object . keys ( textureOptions ) . forEach ( function ( name ) { const options = textureOptions [ name ] ; let onLoadFn ; if ( isAsyncSrc ( options . src ) ) { onLoadFn = function ( err , tex , img ) { images [ name ] = img ; -- numDownloading ; if ( err ) { errors . push ( err ) ; } callCallbackIfReady ( ) ; } ; ++ numDownloading ; } textures [ name ] = createTexture ( gl , options , onLoadFn ) ; } ) ; // queue the callback if there are no images to download. // We do this because if your code is structured to wait for // images to download but then you comment out all the async // images your code would break. callCallbackIfReady ( ) ; return textures ; }
Creates a bunch of textures based on the passed in options.

Example:

const textures = twgl.createTextures(gl, {
// a power of 2 image
hftIcon: { src: "images/hft-icon-16.png", mag: gl.NEAREST },
// a non-power of 2 image
clover: { src: "images/clover.jpg" },
// From a canvas
fromCanvas: { src: ctx.canvas },
// A cubemap from 6 images
yokohama: {
target: gl.TEXTURE_CUBE_MAP,
src: [
'images/yokohama/posx.jpg',
'images/yokohama/negx.jpg',
'images/yokohama/posy.jpg',
'images/yokohama/negy.jpg',
'images/yokohama/posz.jpg',
'images/yokohama/negz.jpg',
],
},
// A cubemap from 1 image (can be 1x6, 2x3, 3x2, 6x1)
goldengate: {
target: gl.TEXTURE_CUBE_MAP,
src: 'images/goldengate.jpg',
},
// A 2x2 pixel texture from a JavaScript array
checker: {
mag: gl.NEAREST,
min: gl.LINEAR,
src: [
255,255,255,255,
192,192,192,255,
192,192,192,255,
255,255,255,255,
],
},
// a 1x2 pixel texture from a typed array.
stripe: {
mag: gl.NEAREST,
min: gl.LINEAR,
format: gl.LUMINANCE,
src: new Uint8Array([
255,
128,
255,
128,
255,
128,
255,
128,
]),
width: 1,
},
});

Now

*   `textures.hftIcon` will be a 2d texture
*   `textures.clover` will be a 2d texture
*   `textures.fromCanvas` will be a 2d texture
*   `textures.yohohama` will be a cubemap texture
*   `textures.goldengate` will be a cubemap texture
*   `textures.checker` will be a 2d texture
*   `textures.stripe` will be a 2d texture

@param {WebGLRenderingContext} gl the WebGLRenderingContext
@param {Object.<string,module:twgl.TextureOptions>} options A object of TextureOptions one per texture.
@param {module:twgl.TexturesReadyCallback} [callback] A callback called when all textures have been downloaded.
@return {Object.<string,WebGLTexture>} the created textures by name
@memberOf module:twgl/textures
Creates a bunch of textures based on the passed in options .