cesium/packages/engine/Source/Renderer/FramebufferManager.js

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

490 lines
16 KiB
JavaScript
Raw Permalink Normal View History

import Framebuffer from "./Framebuffer.js";
2022-01-07 05:33:54 +08:00
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 Frozen from "../Core/Frozen.js";
import defined from "../Core/defined.js";
2021-12-10 06:53:55 +08:00
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.
2021-12-22 03:18:15 +08:00
* @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.
2021-12-15 06:49:44 +08:00
*
2021-12-22 03:18:15 +08:00
* @exception {DeveloperError} Must enable at least one type of framebuffer attachment.
2021-12-15 06:49:44 +08:00
* @exception {DeveloperError} Cannot have both a depth and depth-stencil attachment.
*
* @private
* @constructor
*/
function FramebufferManager(options) {
options = options ?? Frozen.EMPTY_OBJECT;
2025-03-04 03:03:53 +08:00
this._numSamples = options.numSamples ?? 1;
this._colorAttachmentsLength = options.colorAttachmentsLength ?? 1;
2021-12-11 04:51:07 +08:00
2025-03-04 03:03:53 +08:00
this._color = options.color ?? true;
this._depth = options.depth ?? false;
this._depthStencil = options.depthStencil ?? false;
this._supportsDepthTexture = options.supportsDepthTexture ?? false;
2021-12-11 04:51:07 +08:00
//>>includeStart('debug', pragmas.debug);
2021-12-16 07:50:52 +08:00
if (!this._color && !this._depth && !this._depthStencil) {
throw new DeveloperError(
2021-12-22 03:18:15 +08:00
"Must enable at least one type of framebuffer attachment.",
2021-12-16 07:50:52 +08:00
);
}
2021-12-11 04:51:07 +08:00
if (this._depth && this._depthStencil) {
throw new DeveloperError(
"Cannot have both a depth and depth-stencil attachment.",
);
}
//>>includeEnd('debug');
2025-03-04 03:03:53 +08:00
this._createColorAttachments = options.createColorAttachments ?? true;
this._createDepthAttachments = options.createDepthAttachments ?? true;
2021-12-11 04:51:07 +08:00
2021-12-22 03:18:15 +08:00
this._pixelDatatype = options.pixelDatatype;
this._pixelFormat = options.pixelFormat;
2021-12-16 07:50:52 +08:00
this._width = undefined;
this._height = undefined;
this._framebuffer = undefined;
2022-01-20 02:42:09 +08:00
this._multisampleFramebuffer = undefined;
2021-12-16 07:50:52 +08:00
this._colorTextures = undefined;
if (this._color) {
this._colorTextures = new Array(this._colorAttachmentsLength);
2022-01-07 05:33:54 +08:00
this._colorRenderbuffers = new Array(this._colorAttachmentsLength);
2021-12-16 07:50:52 +08:00
}
2022-01-07 05:33:54 +08:00
this._colorRenderbuffer = undefined;
this._depthStencilRenderbuffer = undefined;
this._depthStencilTexture = undefined;
2021-12-11 04:51:07 +08:00
this._depthRenderbuffer = undefined;
2021-12-11 03:08:51 +08:00
this._depthTexture = undefined;
2021-12-18 06:19:05 +08:00
this._attachmentsDirty = false;
}
2021-12-10 06:53:55 +08:00
Object.defineProperties(FramebufferManager.prototype, {
framebuffer: {
get: function () {
2022-01-07 05:33:54 +08:00
if (this._numSamples > 1) {
return this._multisampleFramebuffer.getRenderFramebuffer();
2022-01-07 05:33:54 +08:00
}
2021-12-10 06:53:55 +08:00
return this._framebuffer;
},
},
numSamples: {
get: function () {
return this._numSamples;
},
},
2021-12-10 06:53:55 +08:00
status: {
get: function () {
return this.framebuffer.status;
2021-12-10 06:53:55 +08:00
},
},
});
2021-12-18 06:19:05 +08:00
FramebufferManager.prototype.isDirty = function (
width,
height,
2022-01-07 05:33:54 +08:00
numSamples,
2021-12-18 06:19:05 +08:00
pixelDatatype,
pixelFormat,
) {
2025-03-04 03:03:53 +08:00
numSamples = numSamples ?? 1;
2022-01-28 00:02:28 +08:00
const dimensionChanged = this._width !== width || this._height !== height;
const samplesChanged = this._numSamples !== numSamples;
const pixelChanged =
2021-12-18 06:19:05 +08:00
(defined(pixelDatatype) && this._pixelDatatype !== pixelDatatype) ||
(defined(pixelFormat) && this._pixelFormat !== pixelFormat);
2022-01-28 00:02:28 +08:00
const framebufferDefined =
2022-01-20 02:42:09 +08:00
numSamples === 1
? defined(this._framebuffer)
: defined(this._multisampleFramebuffer);
2021-12-18 06:19:05 +08:00
return (
this._attachmentsDirty ||
dimensionChanged ||
2022-01-07 05:33:54 +08:00
samplesChanged ||
2021-12-18 06:19:05 +08:00
pixelChanged ||
2022-01-20 02:42:09 +08:00
!framebufferDefined ||
2021-12-18 06:19:05 +08:00
(this._color && !defined(this._colorTextures[0]))
);
};
FramebufferManager.prototype.update = function (
context,
width,
height,
2022-01-07 05:33:54 +08:00
numSamples,
2021-12-16 08:13:17 +08:00
pixelDatatype,
pixelFormat,
) {
2021-12-10 06:53:55 +08:00
//>>includeStart('debug', pragmas.debug);
2021-12-16 07:50:52 +08:00
if (!defined(width) || !defined(height)) {
throw new DeveloperError("width and height must be defined.");
2021-12-10 06:53:55 +08:00
}
//>>includeEnd('debug');
2025-03-04 03:03:53 +08:00
numSamples = context.msaa ? (numSamples ?? 1) : 1;
pixelDatatype =
pixelDatatype ??
(this._color
? (this._pixelDatatype ?? PixelDatatype.UNSIGNED_BYTE)
: undefined);
pixelFormat =
pixelFormat ??
(this._color ? (this._pixelFormat ?? PixelFormat.RGBA) : undefined);
2022-01-07 05:33:54 +08:00
if (this.isDirty(width, height, numSamples, pixelDatatype, pixelFormat)) {
2021-12-18 06:19:05 +08:00
this.destroy();
2021-12-16 07:50:52 +08:00
this._width = width;
this._height = height;
2022-01-07 05:33:54 +08:00
this._numSamples = numSamples;
2021-12-16 07:50:52 +08:00
this._pixelDatatype = pixelDatatype;
2021-12-18 06:19:05 +08:00
this._pixelFormat = pixelFormat;
this._attachmentsDirty = false;
// Create color texture
2021-12-15 04:18:21 +08:00
if (this._color && this._createColorAttachments) {
2021-12-11 03:08:51 +08:00
for (let i = 0; i < this._colorAttachmentsLength; ++i) {
2021-12-16 07:50:52 +08:00
this._colorTextures[i] = new Texture({
context: context,
width: width,
height: height,
2021-12-16 08:13:17 +08:00
pixelFormat: pixelFormat,
2021-12-16 07:50:52 +08:00
pixelDatatype: pixelDatatype,
sampler: Sampler.NEAREST,
});
2022-01-07 05:33:54 +08:00
if (this._numSamples > 1) {
const format = RenderbufferFormat.getColorFormat(pixelDatatype);
2022-01-07 05:33:54 +08:00
this._colorRenderbuffers[i] = new Renderbuffer({
context: context,
width: width,
height: height,
format: format,
2022-01-07 05:33:54 +08:00
numSamples: this._numSamples,
});
}
2021-12-11 03:08:51 +08:00
}
2021-12-10 06:53:55 +08:00
}
// Create depth stencil texture or renderbuffer
2021-12-11 04:51:07 +08:00
if (this._depthStencil && this._createDepthAttachments) {
2021-12-17 00:57:40 +08:00
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,
});
2022-01-07 05:33:54 +08:00
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,
});
}
}
2021-12-11 03:08:51 +08:00
// Create depth texture
if (this._depth && this._createDepthAttachments) {
2021-12-17 00:57:40 +08:00
if (this._supportsDepthTexture && context.depthTexture) {
2021-12-11 04:51:07 +08:00
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,
});
}
2021-12-11 03:08:51 +08:00
}
2022-01-07 05:33:54 +08:00
if (this._numSamples > 1) {
this._multisampleFramebuffer = new MultisampleFramebuffer({
context: context,
width: this._width,
height: this._height,
2022-01-07 05:33:54 +08:00
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,
});
}
}
};
2021-12-10 06:53:55 +08:00
FramebufferManager.prototype.getColorTexture = function (index) {
2025-03-04 03:03:53 +08:00
index = index ?? 0;
2021-12-18 06:19:05 +08:00
//>>includeStart('debug', pragmas.debug);
if (index >= this._colorAttachmentsLength) {
throw new DeveloperError(
"index must be smaller than total number of color attachments.",
);
}
//>>includeEnd('debug');
2021-12-10 06:53:55 +08:00
return this._colorTextures[index];
};
FramebufferManager.prototype.setColorTexture = function (texture, index) {
2025-03-04 03:03:53 +08:00
index = index ?? 0;
2021-12-10 06:53:55 +08:00
//>>includeStart('debug', pragmas.debug);
if (this._createColorAttachments) {
throw new DeveloperError(
2021-12-16 07:50:52 +08:00
"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.",
2021-12-10 06:53:55 +08:00
);
}
//>>includeEnd('debug');
2021-12-22 03:18:15 +08:00
this._attachmentsDirty = texture !== this._colorTextures[index];
2021-12-10 06:53:55 +08:00
this._colorTextures[index] = texture;
2021-12-15 04:18:21 +08:00
};
2022-01-07 05:33:54 +08:00
FramebufferManager.prototype.getColorRenderbuffer = function (index) {
2025-03-04 03:03:53 +08:00
index = index ?? 0;
2022-01-07 05:33:54 +08:00
//>>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,
) {
2025-03-04 03:03:53 +08:00
index = index ?? 0;
2022-01-07 05:33:54 +08:00
//>>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;
};
2021-12-17 02:57:17 +08:00
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');
2021-12-22 03:18:15 +08:00
this._attachmentsDirty = renderbuffer !== this._depthRenderbuffer;
2021-12-17 02:57:17 +08:00
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');
2021-12-22 03:18:15 +08:00
this._attachmentsDirty = texture !== this._depthTexture;
2021-12-17 02:57:17 +08:00
this._depthTexture = texture;
};
2021-12-15 06:49:44 +08:00
FramebufferManager.prototype.getDepthStencilRenderbuffer = function () {
return this._depthStencilRenderbuffer;
};
2021-12-15 04:18:21 +08:00
FramebufferManager.prototype.setDepthStencilRenderbuffer = function (
renderbuffer,
) {
//>>includeStart('debug', pragmas.debug);
if (this._createDepthAttachments) {
throw new DeveloperError(
2021-12-16 07:50:52 +08:00
"createDepthAttachments must be false if setDepthStencilRenderbuffer is called.",
2021-12-15 04:18:21 +08:00
);
}
//>>includeEnd('debug');
2021-12-22 03:18:15 +08:00
this._attachmentsDirty = renderbuffer !== this._depthStencilRenderbuffer;
2021-12-15 04:18:21 +08:00
this._depthStencilRenderbuffer = renderbuffer;
2021-12-10 06:53:55 +08:00
};
2021-12-15 06:49:44 +08:00
FramebufferManager.prototype.getDepthStencilTexture = function () {
return this._depthStencilTexture;
};
2021-12-10 06:53:55 +08:00
FramebufferManager.prototype.setDepthStencilTexture = function (texture) {
//>>includeStart('debug', pragmas.debug);
2021-12-11 04:51:07 +08:00
if (this._createDepthAttachments) {
2021-12-10 06:53:55 +08:00
throw new DeveloperError(
2021-12-16 07:50:52 +08:00
"createDepthAttachments must be false if setDepthStencilTexture is called.",
2021-12-10 06:53:55 +08:00
);
}
//>>includeEnd('debug');
2021-12-22 03:18:15 +08:00
this._attachmentsDirty = texture !== this._depthStencilTexture;
2021-12-10 06:53:55 +08:00
this._depthStencilTexture = texture;
};
/**
* If using MSAA, resolve the stencil.
*
* @param {Context} context
* @param {boolean} blitStencil
*
* @private
*/
FramebufferManager.prototype.prepareTextures = function (context, blitStencil) {
2022-01-20 02:42:09 +08:00
if (this._numSamples > 1) {
this._multisampleFramebuffer.blitFramebuffers(context, blitStencil);
2022-01-20 02:42:09 +08:00
}
};
FramebufferManager.prototype.clear = function (
context,
clearCommand,
passState,
) {
const framebuffer = clearCommand.framebuffer;
clearCommand.framebuffer = this.framebuffer;
clearCommand.execute(context, passState);
clearCommand.framebuffer = framebuffer;
};
2021-12-15 04:18:21 +08:00
FramebufferManager.prototype.destroyFramebuffer = function () {
this._framebuffer = this._framebuffer && this._framebuffer.destroy();
2022-01-07 05:33:54 +08:00
this._multisampleFramebuffer =
this._multisampleFramebuffer && this._multisampleFramebuffer.destroy();
2021-12-15 04:18:21 +08:00
};
2021-12-18 06:19:05 +08:00
FramebufferManager.prototype.destroy = function () {
2022-01-22 02:17:07 +08:00
if (this._color) {
const colorTextures = this._colorTextures;
const colorRenderbuffers = this._colorRenderbuffers;
for (let i = 0; i < colorTextures.length; ++i) {
const texture = colorTextures[i];
2022-01-22 02:17:07 +08:00
if (this._createColorAttachments) {
if (defined(texture) && !texture.isDestroyed()) {
texture.destroy();
2022-01-22 02:17:07 +08:00
}
}
if (defined(texture) && texture.isDestroyed()) {
colorTextures[i] = undefined;
2021-12-16 07:50:52 +08:00
}
const renderbuffer = colorRenderbuffers[i];
2022-01-22 02:17:07 +08:00
if (this._createColorAttachments) {
if (defined(renderbuffer) && !renderbuffer.isDestroyed()) {
renderbuffer.destroy();
2022-01-22 02:17:07 +08:00
}
}
if (defined(renderbuffer) && renderbuffer.isDestroyed()) {
colorRenderbuffers[i] = undefined;
2022-01-07 05:33:54 +08:00
}
}
2021-12-10 06:53:55 +08:00
}
2022-01-22 02:17:07 +08:00
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;
}
2021-12-10 07:22:02 +08:00
}
2022-01-22 02:17:07 +08:00
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;
}
2021-12-11 03:08:51 +08:00
}
2021-12-15 04:18:21 +08:00
this.destroyFramebuffer();
};
export default FramebufferManager;