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;
|