File: lib/glutils/FrameBuffer.js
var Class = require('klasse');
var Texture = require('../Texture');
var FrameBuffer = new Class({
/**
* Creates a new Frame Buffer Object with the given width and height.
*
* If width and height are non-numbers, this method expects the
* first parameter to be a Texture object which should be acted upon.
* In this case, the FrameBuffer does not "own" the texture, and so it
* won't dispose of it upon destruction. This is an advanced version of the
* constructor that assumes the user is giving us a valid Texture that can be bound (i.e.
* no async Image textures).
*
* @class FrameBuffer
* @constructor
* @param {[type]} width [description]
* @param {[type]} height [description]
* @param {[type]} filter [description]
* @return {[type]} [description]
*/
initialize: function FrameBuffer(context, width, height, format) { //TODO: depth component
if (typeof context !== "object")
throw "GL context not specified to FrameBuffer";
/**
* The underlying ID of the GL frame buffer object.
*
* @property {WebGLFramebuffer} id
*/
this.id = null;
/**
* The WebGLContext backed by this frame buffer.
*
* @property {WebGLContext} context
*/
this.context = context;
/**
* The Texture backed by this frame buffer.
*
* @property {Texture} Texture
*/
//this Texture is now managed.
this.texture = new Texture(context, width, height, format);
//This is maanged by WebGLContext
this.context.addManagedObject(this);
this.create();
},
/**
* A read-only property which returns the width of the backing texture.
*
* @readOnly
* @property width
* @type {Number}
*/
width: {
get: function() {
return this.texture.width
}
},
/**
* A read-only property which returns the height of the backing texture.
*
* @readOnly
* @property height
* @type {Number}
*/
height: {
get: function() {
return this.texture.height;
}
},
/**
* Called during initialization to setup the frame buffer; also called on
* context restore. Users will not need to call this directly.
*
* @method create
*/
create: function() {
this.gl = this.context.gl;
var gl = this.gl;
var tex = this.texture;
//we assume the texture has already had create() called on it
//since it was added as a managed object prior to this FrameBuffer
tex.bind();
this.id = gl.createFramebuffer();
gl.bindFramebuffer(gl.FRAMEBUFFER, this.id);
gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, tex.target, tex.id, 0);
var result = gl.checkFramebufferStatus(gl.FRAMEBUFFER);
if (result != gl.FRAMEBUFFER_COMPLETE) {
this.destroy(); //destroy our resources before leaving this function..
var err = "Framebuffer not complete";
switch (result) {
case gl.FRAMEBUFFER_UNSUPPORTED:
throw new Error(err + ": unsupported");
case gl.INCOMPLETE_DIMENSIONS:
throw new Error(err + ": incomplete dimensions");
case gl.INCOMPLETE_ATTACHMENT:
throw new Error(err + ": incomplete attachment");
case gl.INCOMPLETE_MISSING_ATTACHMENT:
throw new Error(err + ": missing attachment");
default:
throw new Error(err);
}
}
gl.bindFramebuffer(gl.FRAMEBUFFER, null);
},
/**
* Destroys this frame buffer. Using this object after destroying it will have
* undefined results.
* @method destroy
*/
destroy: function() {
var gl = this.gl;
if (this.texture)
this.texture.destroy();
if (this.id && this.gl)
this.gl.deleteFramebuffer(this.id);
if (this.context)
this.context.removeManagedObject(this);
this.id = null;
this.gl = null;
this.texture = null;
this.context = null;
},
/**
* Binds this framebuffer and sets the viewport to the expected size.
* @method begin
*/
begin: function() {
var gl = this.gl;
gl.viewport(0, 0, this.texture.width, this.texture.height);
gl.bindFramebuffer(gl.FRAMEBUFFER, this.id);
},
/**
* Binds the default frame buffer (the screen) and sets the viewport back
* to the size of the WebGLContext.
*
* @method end
*/
end: function() {
var gl = this.gl;
gl.viewport(0, 0, this.context.width, this.context.height);
gl.bindFramebuffer(gl.FRAMEBUFFER, null);
}
});
module.exports = FrameBuffer;