function createFramebufferInfo(gl, attachments, width, height) {
    var target = gl.FRAMEBUFFER;
    var fb = gl.createFramebuffer();
    gl.bindFramebuffer(target, fb);
    width  = width  || gl.drawingBufferWidth;
    height = height || gl.drawingBufferHeight;
    attachments = attachments || defaultAttachments;
    var colorAttachmentCount = 0;
    var framebufferInfo = {
      framebuffer: fb,
      attachments: [],
      width: width,
      height: height,
    };
    attachments.forEach(function(attachmentOptions) {
      var attachment = attachmentOptions.attachment;
      var format = attachmentOptions.format;
      var attachmentPoint = getAttachmentPointForFormat(format);
      if (!attachmentPoint) {
        attachmentPoint = COLOR_ATTACHMENT0 + colorAttachmentCount++;
      }
      if (!attachment) {
        if (isRenderbufferFormat(format)) {
          attachment = gl.createRenderbuffer();
          gl.bindRenderbuffer(gl.RENDERBUFFER, attachment);
          gl.renderbufferStorage(gl.RENDERBUFFER, format, width, height);
        } else {
          var textureOptions = utils.shallowCopy(attachmentOptions);
          textureOptions.width = width;
          textureOptions.height = height;
          if (textureOptions.auto === undefined) {
            textureOptions.auto = false;
            textureOptions.min = textureOptions.min || gl.LINEAR;
            textureOptions.mag = textureOptions.mag || gl.LINEAR;
            textureOptions.wrapS = textureOptions.wrapS || textureOptions.wrap || gl.CLAMP_TO_EDGE;
            textureOptions.wrapT = textureOptions.wrapT || textureOptions.wrap || gl.CLAMP_TO_EDGE;
          }
          attachment = textures.createTexture(gl, textureOptions);
        }
      }
      if (attachment instanceof WebGLRenderbuffer) {
        gl.framebufferRenderbuffer(target, attachmentPoint, gl.RENDERBUFFER, attachment);
      } else if (attachment instanceof WebGLTexture) {
        gl.framebufferTexture2D(
            target,
            attachmentPoint,
            attachmentOptions.texTarget || gl.TEXTURE_2D,
            attachment,
            attachmentOptions.level || 0);
      } else {
        throw "unknown attachment type";
      }
      framebufferInfo.attachments.push(attachment);
    });
    return framebufferInfo;
  }
Creates a framebuffer and attachments.

This returns a {@link module:twgl.FramebufferInfo} because it needs to return the attachments as well as the framebuffer.

The simplest usage

    // create an RGBA/UNSIGNED_BYTE texture and DEPTH_STENCIL renderbuffer
    var fbi = twgl.createFramebufferInfo(gl);

More complex usage

    // create an RGB565 renderbuffer and a STENCIL_INDEX8 renderbuffer
    var attachments = [
      { format: RGB565, mag: NEAREST },
      { format: STENCIL_INDEX8 },
    ]
    var fbi = twgl.createFramebufferInfo(gl, attachments);

Passing in a specific size

    var width = 256;
    var height = 256;
    var fbi = twgl.createFramebufferInfo(gl, attachments, width, height);

**Note!!** It is up to you to check if the framebuffer is renderable by calling `gl.checkFramebufferStatus`.
[WebGL only guarantees 3 combinations of attachments work](https://www.khronos.org/registry/webgl/specs/latest/1.0/#6.6).

@param {WebGLRenderingContext} gl the WebGLRenderingContext
@param {module:twgl.AttachmentOptions[]} [attachments] which attachments to create. If not provided the default is a framebuffer with an
   `RGBA`, `UNSIGNED_BYTE` texture `COLOR_ATTACHMENT0` and a `DEPTH_STENCIL` renderbuffer `DEPTH_STENCIL_ATTACHMENT`.
@param {number} [width] the width for the attachments. Default = size of drawingBuffer
@param {number} [height] the height for the attachments. Defautt = size of drawingBuffer
@return {module:twgl.FramebufferInfo} the framebuffer and attachments.
@memberOf module:twgl/framebuffers