| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497 | import Framebuffer from "./Framebuffer.js";import MultisampleFramebuffer from "./MultisampleFramebuffer.js";import PixelDatatype from "./PixelDatatype.js";import Renderbuffer from "./Renderbuffer.js";import RenderbufferFormat from "./RenderbufferFormat.js";import Sampler from "./Sampler.js";import Texture from "./Texture.js";import defaultValue from "../Core/defaultValue.js";import defined from "../Core/defined.js";import DeveloperError from "../Core/DeveloperError.js";import PixelFormat from "../Core/PixelFormat.js";/** * Creates a wrapper object around a framebuffer and its resources. * * @param {Object} options Object with the following properties: * @param {Number} [options.numSamples=1] The multisampling rate of the render targets. Requires a WebGL2 context. * @param {Number} [options.colorAttachmentsLength=1] The number of color attachments this FramebufferManager will create. * @param {Boolean} [options.color=true] Whether the FramebufferManager will use color attachments. * @param {Boolean} [options.depth=false] Whether the FramebufferManager will use depth attachments. * @param {Boolean} [options.depthStencil=false] Whether the FramebufferManager will use depth-stencil attachments. * @param {Boolean} [options.supportsDepthTexture=false] Whether the FramebufferManager will create a depth texture when the extension is supported. * @param {Boolean} [options.createColorAttachments=true] Whether the FramebufferManager will construct its own color attachments. * @param {Boolean} [options.createDepthAttachments=true] Whether the FramebufferManager will construct its own depth attachments. * @param {PixelDatatype} [options.pixelDatatype=undefined] The default pixel datatype to use when creating color attachments. * @param {PixelFormat} [options.pixelFormat=undefined] The default pixel format to use when creating color attachments. * * @exception {DeveloperError} Must enable at least one type of framebuffer attachment. * @exception {DeveloperError} Cannot have both a depth and depth-stencil attachment. * * @private * @constructor */function FramebufferManager(options) {  options = defaultValue(options, defaultValue.EMPTY_OBJECT);  this._numSamples = defaultValue(options.numSamples, 1);  this._colorAttachmentsLength = defaultValue(    options.colorAttachmentsLength,    1  );  this._color = defaultValue(options.color, true);  this._depth = defaultValue(options.depth, false);  this._depthStencil = defaultValue(options.depthStencil, false);  this._supportsDepthTexture = defaultValue(    options.supportsDepthTexture,    false  );  //>>includeStart('debug', pragmas.debug);  if (!this._color && !this._depth && !this._depthStencil) {    throw new DeveloperError(      "Must enable at least one type of framebuffer attachment."    );  }  if (this._depth && this._depthStencil) {    throw new DeveloperError(      "Cannot have both a depth and depth-stencil attachment."    );  }  //>>includeEnd('debug');  this._createColorAttachments = defaultValue(    options.createColorAttachments,    true  );  this._createDepthAttachments = defaultValue(    options.createDepthAttachments,    true  );  this._pixelDatatype = options.pixelDatatype;  this._pixelFormat = options.pixelFormat;  this._width = undefined;  this._height = undefined;  this._framebuffer = undefined;  this._multisampleFramebuffer = undefined;  this._colorTextures = undefined;  if (this._color) {    this._colorTextures = new Array(this._colorAttachmentsLength);    this._colorRenderbuffers = new Array(this._colorAttachmentsLength);  }  this._colorRenderbuffer = undefined;  this._depthStencilRenderbuffer = undefined;  this._depthStencilTexture = undefined;  this._depthRenderbuffer = undefined;  this._depthTexture = undefined;  this._attachmentsDirty = false;}Object.defineProperties(FramebufferManager.prototype, {  framebuffer: {    get: function () {      if (this._numSamples > 1) {        return this._multisampleFramebuffer.getRenderFramebuffer();      }      return this._framebuffer;    },  },  numSamples: {    get: function () {      return this._numSamples;    },  },  status: {    get: function () {      return this.framebuffer.status;    },  },});FramebufferManager.prototype.isDirty = function (  width,  height,  numSamples,  pixelDatatype,  pixelFormat) {  numSamples = defaultValue(numSamples, 1);  const dimensionChanged = this._width !== width || this._height !== height;  const samplesChanged = this._numSamples !== numSamples;  const pixelChanged =    (defined(pixelDatatype) && this._pixelDatatype !== pixelDatatype) ||    (defined(pixelFormat) && this._pixelFormat !== pixelFormat);  const framebufferDefined =    numSamples === 1      ? defined(this._framebuffer)      : defined(this._multisampleFramebuffer);  return (    this._attachmentsDirty ||    dimensionChanged ||    samplesChanged ||    pixelChanged ||    !framebufferDefined ||    (this._color && !defined(this._colorTextures[0]))  );};FramebufferManager.prototype.update = function (  context,  width,  height,  numSamples,  pixelDatatype,  pixelFormat) {  //>>includeStart('debug', pragmas.debug);  if (!defined(width) || !defined(height)) {    throw new DeveloperError("width and height must be defined.");  }  //>>includeEnd('debug');  numSamples = context.msaa ? defaultValue(numSamples, 1) : 1;  pixelDatatype = defaultValue(    pixelDatatype,    this._color      ? defaultValue(this._pixelDatatype, PixelDatatype.UNSIGNED_BYTE)      : undefined  );  pixelFormat = defaultValue(    pixelFormat,    this._color ? defaultValue(this._pixelFormat, PixelFormat.RGBA) : undefined  );  if (this.isDirty(width, height, numSamples, pixelDatatype, pixelFormat)) {    this.destroy();    this._width = width;    this._height = height;    this._numSamples = numSamples;    this._pixelDatatype = pixelDatatype;    this._pixelFormat = pixelFormat;    this._attachmentsDirty = false;    // Create color texture    if (this._color && this._createColorAttachments) {      for (let i = 0; i < this._colorAttachmentsLength; ++i) {        this._colorTextures[i] = new Texture({          context: context,          width: width,          height: height,          pixelFormat: pixelFormat,          pixelDatatype: pixelDatatype,          sampler: Sampler.NEAREST,        });        if (this._numSamples > 1) {          const format = RenderbufferFormat.getColorFormat(pixelDatatype);          this._colorRenderbuffers[i] = new Renderbuffer({            context: context,            width: width,            height: height,            format: format,            numSamples: this._numSamples,          });        }      }    }    // Create depth stencil texture or renderbuffer    if (this._depthStencil && this._createDepthAttachments) {      if (this._supportsDepthTexture && context.depthTexture) {        this._depthStencilTexture = new Texture({          context: context,          width: width,          height: height,          pixelFormat: PixelFormat.DEPTH_STENCIL,          pixelDatatype: PixelDatatype.UNSIGNED_INT_24_8,          sampler: Sampler.NEAREST,        });        if (this._numSamples > 1) {          this._depthStencilRenderbuffer = new Renderbuffer({            context: context,            width: width,            height: height,            format: RenderbufferFormat.DEPTH24_STENCIL8,            numSamples: this._numSamples,          });        }      } else {        this._depthStencilRenderbuffer = new Renderbuffer({          context: context,          width: width,          height: height,          format: RenderbufferFormat.DEPTH_STENCIL,        });      }    }    // Create depth texture    if (this._depth && this._createDepthAttachments) {      if (this._supportsDepthTexture && context.depthTexture) {        this._depthTexture = new Texture({          context: context,          width: width,          height: height,          pixelFormat: PixelFormat.DEPTH_COMPONENT,          pixelDatatype: PixelDatatype.UNSIGNED_INT,          sampler: Sampler.NEAREST,        });      } else {        this._depthRenderbuffer = new Renderbuffer({          context: context,          width: width,          height: height,          format: RenderbufferFormat.DEPTH_COMPONENT16,        });      }    }    if (this._numSamples > 1) {      this._multisampleFramebuffer = new MultisampleFramebuffer({        context: context,        width: this._width,        height: this._height,        colorTextures: this._colorTextures,        colorRenderbuffers: this._colorRenderbuffers,        depthStencilTexture: this._depthStencilTexture,        depthStencilRenderbuffer: this._depthStencilRenderbuffer,        destroyAttachments: false,      });    } else {      this._framebuffer = new Framebuffer({        context: context,        colorTextures: this._colorTextures,        depthTexture: this._depthTexture,        depthRenderbuffer: this._depthRenderbuffer,        depthStencilTexture: this._depthStencilTexture,        depthStencilRenderbuffer: this._depthStencilRenderbuffer,        destroyAttachments: false,      });    }  }};FramebufferManager.prototype.getColorTexture = function (index) {  index = defaultValue(index, 0);  //>>includeStart('debug', pragmas.debug);  if (index >= this._colorAttachmentsLength) {    throw new DeveloperError(      "index must be smaller than total number of color attachments."    );  }  //>>includeEnd('debug');  return this._colorTextures[index];};FramebufferManager.prototype.setColorTexture = function (texture, index) {  index = defaultValue(index, 0);  //>>includeStart('debug', pragmas.debug);  if (this._createColorAttachments) {    throw new DeveloperError(      "createColorAttachments must be false if setColorTexture is called."    );  }  if (index >= this._colorAttachmentsLength) {    throw new DeveloperError(      "index must be smaller than total number of color attachments."    );  }  //>>includeEnd('debug');  this._attachmentsDirty = texture !== this._colorTextures[index];  this._colorTextures[index] = texture;};FramebufferManager.prototype.getColorRenderbuffer = function (index) {  index = defaultValue(index, 0);  //>>includeStart('debug', pragmas.debug);  if (index >= this._colorAttachmentsLength) {    throw new DeveloperError(      "index must be smaller than total number of color attachments."    );  }  //>>includeEnd('debug');  return this._colorRenderbuffers[index];};FramebufferManager.prototype.setColorRenderbuffer = function (  renderbuffer,  index) {  index = defaultValue(index, 0);  //>>includeStart('debug', pragmas.debug);  if (this._createColorAttachments) {    throw new DeveloperError(      "createColorAttachments must be false if setColorRenderbuffer is called."    );  }  if (index >= this._colorAttachmentsLength) {    throw new DeveloperError(      "index must be smaller than total number of color attachments."    );  }  //>>includeEnd('debug');  this._attachmentsDirty = renderbuffer !== this._colorRenderbuffers[index];  this._colorRenderbuffers[index] = renderbuffer;};FramebufferManager.prototype.getDepthRenderbuffer = function () {  return this._depthRenderbuffer;};FramebufferManager.prototype.setDepthRenderbuffer = function (renderbuffer) {  //>>includeStart('debug', pragmas.debug);  if (this._createDepthAttachments) {    throw new DeveloperError(      "createDepthAttachments must be false if setDepthRenderbuffer is called."    );  }  //>>includeEnd('debug');  this._attachmentsDirty = renderbuffer !== this._depthRenderbuffer;  this._depthRenderbuffer = renderbuffer;};FramebufferManager.prototype.getDepthTexture = function () {  return this._depthTexture;};FramebufferManager.prototype.setDepthTexture = function (texture) {  //>>includeStart('debug', pragmas.debug);  if (this._createDepthAttachments) {    throw new DeveloperError(      "createDepthAttachments must be false if setDepthTexture is called."    );  }  //>>includeEnd('debug');  this._attachmentsDirty = texture !== this._depthTexture;  this._depthTexture = texture;};FramebufferManager.prototype.getDepthStencilRenderbuffer = function () {  return this._depthStencilRenderbuffer;};FramebufferManager.prototype.setDepthStencilRenderbuffer = function (  renderbuffer) {  //>>includeStart('debug', pragmas.debug);  if (this._createDepthAttachments) {    throw new DeveloperError(      "createDepthAttachments must be false if setDepthStencilRenderbuffer is called."    );  }  //>>includeEnd('debug');  this._attachmentsDirty = renderbuffer !== this._depthStencilRenderbuffer;  this._depthStencilRenderbuffer = renderbuffer;};FramebufferManager.prototype.getDepthStencilTexture = function () {  return this._depthStencilTexture;};FramebufferManager.prototype.setDepthStencilTexture = function (texture) {  //>>includeStart('debug', pragmas.debug);  if (this._createDepthAttachments) {    throw new DeveloperError(      "createDepthAttachments must be false if setDepthStencilTexture is called."    );  }  //>>includeEnd('debug');  this._attachmentsDirty = texture !== this._depthStencilTexture;  this._depthStencilTexture = texture;};FramebufferManager.prototype.prepareTextures = function (context, blitStencil) {  if (this._numSamples > 1) {    this._multisampleFramebuffer.blitFramebuffers(context, blitStencil);  }};FramebufferManager.prototype.clear = function (  context,  clearCommand,  passState) {  const framebuffer = clearCommand.framebuffer;  clearCommand.framebuffer = this.framebuffer;  clearCommand.execute(context, passState);  clearCommand.framebuffer = framebuffer;};FramebufferManager.prototype.destroyFramebuffer = function () {  this._framebuffer = this._framebuffer && this._framebuffer.destroy();  this._multisampleFramebuffer =    this._multisampleFramebuffer && this._multisampleFramebuffer.destroy();};FramebufferManager.prototype.destroy = function () {  if (this._color) {    let i;    const length = this._colorTextures.length;    for (i = 0; i < length; ++i) {      const texture = this._colorTextures[i];      if (this._createColorAttachments) {        if (defined(texture) && !texture.isDestroyed()) {          this._colorTextures[i].destroy();          this._colorTextures[i] = undefined;        }      }      if (defined(texture) && texture.isDestroyed()) {        this._colorTextures[i] = undefined;      }      const renderbuffer = this._colorRenderbuffers[i];      if (this._createColorAttachments) {        if (defined(renderbuffer) && !renderbuffer.isDestroyed()) {          this._colorRenderbuffers[i].destroy();          this._colorRenderbuffers[i] = undefined;        }      }      if (defined(renderbuffer) && renderbuffer.isDestroyed()) {        this._colorRenderbuffers[i] = undefined;      }    }  }  if (this._depthStencil) {    if (this._createDepthAttachments) {      this._depthStencilTexture =        this._depthStencilTexture && this._depthStencilTexture.destroy();      this._depthStencilRenderbuffer =        this._depthStencilRenderbuffer &&        this._depthStencilRenderbuffer.destroy();    }    if (      defined(this._depthStencilTexture) &&      this._depthStencilTexture.isDestroyed()    ) {      this._depthStencilTexture = undefined;    }    if (      defined(this._depthStencilRenderbuffer) &&      this._depthStencilRenderbuffer.isDestroyed()    ) {      this._depthStencilRenderbuffer = undefined;    }  }  if (this._depth) {    if (this._createDepthAttachments) {      this._depthTexture = this._depthTexture && this._depthTexture.destroy();      this._depthRenderbuffer =        this._depthRenderbuffer && this._depthRenderbuffer.destroy();    }    if (defined(this._depthTexture) && this._depthTexture.isDestroyed()) {      this._depthTexture = undefined;    }    if (      defined(this._depthRenderbuffer) &&      this._depthRenderbuffer.isDestroyed()    ) {      this._depthRenderbuffer = undefined;    }  }  this.destroyFramebuffer();};export default FramebufferManager;
 |