123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324 |
- /*global define*/
- define([
- '../Core/defaultValue',
- '../Core/defined',
- '../Core/defineProperties',
- '../Core/destroyObject',
- '../Core/DeveloperError',
- '../Core/PixelFormat'
- ], function(
- defaultValue,
- defined,
- defineProperties,
- destroyObject,
- DeveloperError,
- PixelFormat) {
- "use strict";
- function attachTexture(framebuffer, attachment, texture) {
- var gl = framebuffer._gl;
- gl.framebufferTexture2D(gl.FRAMEBUFFER, attachment, texture._target, texture._texture, 0);
- }
- function attachRenderbuffer(framebuffer, attachment, renderbuffer) {
- var gl = framebuffer._gl;
- gl.framebufferRenderbuffer(gl.FRAMEBUFFER, attachment, gl.RENDERBUFFER, renderbuffer._getRenderbuffer());
- }
- /**
- * @private
- */
- var Framebuffer = function(gl, maximumColorAttachments, options) {
- options = defaultValue(options, defaultValue.EMPTY_OBJECT);
- this._gl = gl;
- this._framebuffer = gl.createFramebuffer();
- this._colorTextures = [];
- this._colorRenderbuffers = [];
- this._activeColorAttachments = [];
- this._depthTexture = undefined;
- this._depthRenderbuffer = undefined;
- this._stencilRenderbuffer = undefined;
- this._depthStencilTexture = undefined;
- this._depthStencilRenderbuffer = undefined;
- /**
- * When true, the framebuffer owns its attachments so they will be destroyed when
- * {@link Framebuffer#destroy} is called or when a new attachment is assigned
- * to an attachment point.
- *
- * @type {Boolean}
- * @default true
- *
- * @see Framebuffer#destroy
- */
- this.destroyAttachments = defaultValue(options.destroyAttachments, true);
- // Throw if a texture and renderbuffer are attached to the same point. This won't
- // cause a WebGL error (because only one will be attached), but is likely a developer error.
- //>>includeStart('debug', pragmas.debug);
- if (defined(options.colorTextures) && defined(options.colorRenderbuffers)) {
- throw new DeveloperError('Cannot have both color texture and color renderbuffer attachments.');
- }
- if (defined(options.depthTexture) && defined(options.depthRenderbuffer)) {
- throw new DeveloperError('Cannot have both a depth texture and depth renderbuffer attachment.');
- }
- if (defined(options.depthStencilTexture) && defined(options.depthStencilRenderbuffer)) {
- throw new DeveloperError('Cannot have both a depth-stencil texture and depth-stencil renderbuffer attachment.');
- }
- //>>includeEnd('debug');
- // Avoid errors defined in Section 6.5 of the WebGL spec
- var depthAttachment = (defined(options.depthTexture) || defined(options.depthRenderbuffer));
- var depthStencilAttachment = (defined(options.depthStencilTexture) || defined(options.depthStencilRenderbuffer));
- //>>includeStart('debug', pragmas.debug);
- if (depthAttachment && depthStencilAttachment) {
- throw new DeveloperError('Cannot have both a depth and depth-stencil attachment.');
- }
- if (defined(options.stencilRenderbuffer) && depthStencilAttachment) {
- throw new DeveloperError('Cannot have both a stencil and depth-stencil attachment.');
- }
- if (depthAttachment && defined(options.stencilRenderbuffer)) {
- throw new DeveloperError('Cannot have both a depth and stencil attachment.');
- }
- //>>includeEnd('debug');
- ///////////////////////////////////////////////////////////////////
- this._bind();
- var texture;
- var renderbuffer;
- var i;
- var length;
- var attachmentEnum;
- if (defined(options.colorTextures)) {
- var textures = options.colorTextures;
- length = this._colorTextures.length = this._activeColorAttachments.length = textures.length;
- //>>includeStart('debug', pragmas.debug);
- if (length > maximumColorAttachments) {
- throw new DeveloperError('The number of color attachments exceeds the number supported.');
- }
- //>>includeEnd('debug');
- for (i = 0; i < length; ++i) {
- texture = textures[i];
- //>>includeStart('debug', pragmas.debug);
- if (!PixelFormat.isColorFormat(texture.pixelFormat)) {
- throw new DeveloperError('The color-texture pixel-format must be a color format.');
- }
- //>>includeEnd('debug');
- attachmentEnum = this._gl.COLOR_ATTACHMENT0 + i;
- attachTexture(this, attachmentEnum, texture);
- this._activeColorAttachments[i] = attachmentEnum;
- this._colorTextures[i] = texture;
- }
- }
- if (defined(options.colorRenderbuffers)) {
- var renderbuffers = options.colorRenderbuffers;
- length = this._colorRenderbuffers.length = this._activeColorAttachments.length = renderbuffers.length;
- //>>includeStart('debug', pragmas.debug);
- if (length > maximumColorAttachments) {
- throw new DeveloperError('The number of color attachments exceeds the number supported.');
- }
- //>>includeEnd('debug');
- for (i = 0; i < length; ++i) {
- renderbuffer = renderbuffers[i];
- attachmentEnum = this._gl.COLOR_ATTACHMENT0 + i;
- attachRenderbuffer(this, attachmentEnum, renderbuffer);
- this._activeColorAttachments[i] = attachmentEnum;
- this._colorRenderbuffers[i] = renderbuffer;
- }
- }
- if (defined(options.depthTexture)) {
- texture = options.depthTexture;
- //>>includeStart('debug', pragmas.debug);
- if (texture.pixelFormat !== PixelFormat.DEPTH_COMPONENT) {
- throw new DeveloperError('The depth-texture pixel-format must be DEPTH_COMPONENT.');
- }
- //>>includeEnd('debug');
- attachTexture(this, this._gl.DEPTH_ATTACHMENT, texture);
- this._depthTexture = texture;
- }
- if (defined(options.depthRenderbuffer)) {
- renderbuffer = options.depthRenderbuffer;
- attachRenderbuffer(this, this._gl.DEPTH_ATTACHMENT, renderbuffer);
- this._depthRenderbuffer = renderbuffer;
- }
- if (defined(options.stencilRenderbuffer)) {
- renderbuffer = options.stencilRenderbuffer;
- attachRenderbuffer(this, this._gl.STENCIL_ATTACHMENT, renderbuffer);
- this._stencilRenderbuffer = renderbuffer;
- }
- if (defined(options.depthStencilTexture)) {
- texture = options.depthStencilTexture;
- //>>includeStart('debug', pragmas.debug);
- if (texture.pixelFormat !== PixelFormat.DEPTH_STENCIL) {
- throw new DeveloperError('The depth-stencil pixel-format must be DEPTH_STENCIL.');
- }
- //>>includeEnd('debug');
- attachTexture(this, this._gl.DEPTH_STENCIL_ATTACHMENT, texture);
- this._depthStencilTexture = texture;
- }
- if (defined(options.depthStencilRenderbuffer)) {
- renderbuffer = options.depthStencilRenderbuffer;
- attachRenderbuffer(this, this._gl.DEPTH_STENCIL_ATTACHMENT, renderbuffer);
- this._depthStencilRenderbuffer = renderbuffer;
- }
- this._unBind();
- };
- defineProperties(Framebuffer.prototype, {
- /**
- * The status of the framebuffer. If the status is not WebGLRenderingContext.COMPLETE,
- * a {@link DeveloperError} will be thrown when attempting to render to the framebuffer.
- * @memberof Framebuffer.prototype
- * @type {Number}
- */
- status : {
- get : function() {
- this._bind();
- var status = this._gl.checkFramebufferStatus(this._gl.FRAMEBUFFER);
- this._unBind();
- return status;
- }
- },
- numberOfColorAttachments : {
- get : function() {
- return this._activeColorAttachments.length;
- }
- },
- depthTexture: {
- get : function() {
- return this._depthTexture;
- }
- },
- depthRenderbuffer: {
- get : function() {
- return this._depthRenderbuffer;
- }
- },
- stencilRenderbuffer : {
- get : function() {
- return this._stencilRenderbuffer;
- }
- },
- depthStencilTexture : {
- get : function() {
- return this._depthStencilTexture;
- }
- },
- depthStencilRenderbuffer : {
- get : function() {
- return this._depthStencilRenderbuffer;
- }
- },
- /**
- * True if the framebuffer has a depth attachment. Depth attachments include
- * depth and depth-stencil textures, and depth and depth-stencil renderbuffers. When
- * rendering to a framebuffer, a depth attachment is required for the depth test to have effect.
- * @memberof Framebuffer.prototype
- * @type {Boolean}
- */
- hasDepthAttachment : {
- get : function() {
- return !!(this.depthTexture || this.depthRenderbuffer || this.depthStencilTexture || this.depthStencilRenderbuffer);
- }
- }
- });
- Framebuffer.prototype._bind = function() {
- var gl = this._gl;
- gl.bindFramebuffer(gl.FRAMEBUFFER, this._framebuffer);
- };
- Framebuffer.prototype._unBind = function() {
- var gl = this._gl;
- gl.bindFramebuffer(gl.FRAMEBUFFER, null);
- };
- Framebuffer.prototype._getActiveColorAttachments = function() {
- return this._activeColorAttachments;
- };
- Framebuffer.prototype.getColorTexture = function(index) {
- //>>includeStart('debug', pragmas.debug);
- if (!defined(index) || index < 0 || index >= this._colorTextures.length) {
- throw new DeveloperError('index is required, must be greater than or equal to zero and must be less than the number of color attachments.');
- }
- //>>includeEnd('debug');
- return this._colorTextures[index];
- };
- Framebuffer.prototype.getColorRenderbuffer = function(index) {
- //>>includeStart('debug', pragmas.debug);
- if (!defined(index) || index < 0 || index >= this._colorRenderbuffers.length) {
- throw new DeveloperError('index is required, must be greater than or equal to zero and must be less than the number of color attachments.');
- }
- //>>includeEnd('debug');
- return this._colorRenderbuffers[index];
- };
- Framebuffer.prototype.isDestroyed = function() {
- return false;
- };
- Framebuffer.prototype.destroy = function() {
- if (this.destroyAttachments) {
- // If the color texture is a cube map face, it is owned by the cube map, and will not be destroyed.
- var i = 0;
- var textures = this._colorTextures;
- var length = textures.length;
- for (; i < length; ++i) {
- var texture = textures[i];
- if (defined(texture)) {
- texture.destroy();
- }
- }
- var renderbuffers = this._colorRenderbuffers;
- length = renderbuffers.length;
- for (i = 0; i < length; ++i) {
- var renderbuffer = renderbuffers[i];
- if (defined(renderbuffer)) {
- renderbuffer.destroy();
- }
- }
- this._depthTexture = this._depthTexture && this._depthTexture.destroy();
- this._depthRenderbuffer = this._depthRenderbuffer && this._depthRenderbuffer.destroy();
- this._stencilRenderbuffer = this._stencilRenderbuffer && this._stencilRenderbuffer.destroy();
- this._depthStencilTexture = this._depthStencilTexture && this._depthStencilTexture.destroy();
- this._depthStencilRenderbuffer = this._depthStencilRenderbuffer && this._depthStencilRenderbuffer.destroy();
- }
- this._gl.deleteFramebuffer(this._framebuffer);
- return destroyObject(this);
- };
- return Framebuffer;
- });
|