cesium/packages/engine/Source/Scene/EdgeFramebuffer.js

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

246 lines
6.8 KiB
JavaScript
Raw Permalink Normal View History

2025-08-06 23:31:29 +08:00
import defined from "../Core/defined.js";
import destroyObject from "../Core/destroyObject.js";
import PixelFormat from "../Core/PixelFormat.js";
2025-08-27 04:50:54 +08:00
import Color from "../Core/Color.js";
2025-08-06 23:31:29 +08:00
import PixelDatatype from "../Renderer/PixelDatatype.js";
import FramebufferManager from "../Renderer/FramebufferManager.js";
2025-08-27 04:50:54 +08:00
import ClearCommand from "../Renderer/ClearCommand.js";
2025-08-06 23:31:29 +08:00
/**
* Creates and manages framebuffers for edge visibility rendering.
*
* @param {Object} options Object with the following properties:
*
* @alias EdgeFramebuffer
* @constructor
*
* @private
*/
function EdgeFramebuffer(options) {
options = options || {};
2025-08-23 06:33:18 +08:00
// Create framebuffer manager with multiple render targets (MRT)
2025-09-18 08:29:21 +08:00
// Color attachment 0: edge color output (visualization / debug)
// Color attachment 1: R: edge type, G: featureId (metadata / ids)
// Color attachment 2: packed depth (czm_packDepth) for edge fragments
2025-08-06 23:31:29 +08:00
this._framebufferManager = new FramebufferManager({
2025-09-18 08:29:21 +08:00
colorAttachmentsLength: 3, // MRT: Color + ID + Depth (packed RGBA)
2025-08-25 12:26:00 +08:00
createColorAttachments: true,
2025-08-06 23:31:29 +08:00
depthStencil: true,
supportsDepthTexture: true,
2025-08-25 12:26:00 +08:00
color: true,
2025-08-06 23:31:29 +08:00
});
this._framebuffer = undefined;
this._colorTexture = undefined;
this._idTexture = undefined;
2025-09-18 08:29:21 +08:00
this._depthTexture = undefined; // packed depth color attachment (location = 2)
2025-08-06 23:31:29 +08:00
this._depthStencilTexture = undefined;
2025-08-27 04:50:54 +08:00
this._clearCommand = new ClearCommand({
color: new Color(0.0, 0.0, 0.0, 0.0),
depth: 1.0,
stencil: 0,
owner: this,
});
2025-08-06 23:31:29 +08:00
}
Object.defineProperties(EdgeFramebuffer.prototype, {
/**
* Gets the framebuffer for edge rendering.
* @memberof EdgeFramebuffer.prototype
* @type {Framebuffer}
* @readonly
*/
framebuffer: {
get: function () {
return this._framebuffer;
},
},
/**
* Gets the color texture.
* @memberof EdgeFramebuffer.prototype
* @type {Texture}
* @readonly
*/
colorTexture: {
get: function () {
return this._colorTexture;
},
},
/**
2025-08-28 13:12:12 +08:00
* Gets the ID texture.
2025-08-06 23:31:29 +08:00
* @memberof EdgeFramebuffer.prototype
* @type {Texture}
* @readonly
*/
idTexture: {
get: function () {
return this._idTexture;
},
},
2025-09-18 08:29:21 +08:00
/**
* Gets the packed depth texture written during the edge pass.
* @memberof EdgeFramebuffer.prototype
* @type {Texture}
* @readonly
*/
depthTexture: {
get: function () {
return this._depthTexture;
},
},
2025-08-06 23:31:29 +08:00
/**
* Gets the depth-stencil texture.
* @memberof EdgeFramebuffer.prototype
* @type {Texture}
* @readonly
*/
depthStencilTexture: {
get: function () {
return this._depthStencilTexture;
},
},
});
/**
* Updates the framebuffer.
*
* @param {Context} context The context.
* @param {Viewport} viewport The viewport.
* @param {boolean} hdr Whether HDR is enabled.
2025-08-23 06:33:18 +08:00
* @param {Texture} [existingColorTexture] Optional existing color texture to reuse.
* @param {Texture} [existingDepthTexture] Optional existing depth texture to reuse.
2025-08-06 23:31:29 +08:00
*
* @returns {boolean} True if the framebuffer was updated; otherwise, false.
*/
EdgeFramebuffer.prototype.update = function (
context,
viewport,
hdr,
2025-08-23 06:33:18 +08:00
existingColorTexture,
existingDepthTexture,
2025-08-06 23:31:29 +08:00
) {
const width = viewport.width;
const height = viewport.height;
const pixelDatatype = hdr
? context.halfFloatingPointTexture
? PixelDatatype.HALF_FLOAT
: PixelDatatype.FLOAT
: PixelDatatype.UNSIGNED_BYTE;
const changed = this._framebufferManager.update(
context,
width,
height,
2025-08-26 08:32:32 +08:00
1, // No MSAA
2025-08-06 23:31:29 +08:00
pixelDatatype,
2025-08-25 12:26:00 +08:00
PixelFormat.RGBA,
2025-08-06 23:31:29 +08:00
);
// Always assign framebuffer if FramebufferManager has one
if (this._framebufferManager.framebuffer) {
this._framebuffer = this._framebufferManager.framebuffer;
2025-08-23 06:33:18 +08:00
// Get the textures from the framebuffer manager or use existing ones
this._colorTexture = defined(existingColorTexture)
? existingColorTexture
: this._framebufferManager.getColorTexture(0); // Color attachment 0
this._idTexture = this._framebufferManager.getColorTexture(1); // Color attachment 1: ID texture
2025-09-18 08:29:21 +08:00
this._depthTexture = this._framebufferManager.getColorTexture(2); // Color attachment 2: packed depth
2025-08-23 06:33:18 +08:00
this._depthStencilTexture = defined(existingDepthTexture)
? existingDepthTexture
: this._framebufferManager.getDepthStencilTexture();
2025-08-06 23:31:29 +08:00
}
return changed;
};
/**
2025-08-27 04:50:54 +08:00
* Clears the framebuffer using ClearCommand.
* @deprecated Use getClearCommand() instead for proper MRT clearing.
2025-08-06 23:31:29 +08:00
*
* @param {Context} context The context.
* @param {PassState} passState The pass state.
* @param {Color} clearColor The clear color.
*/
EdgeFramebuffer.prototype.clear = function (context, passState, clearColor) {
2025-08-27 04:50:54 +08:00
const clearCommand = this.getClearCommand(clearColor);
clearCommand.execute(context, passState);
};
/**
* Gets the clear command for this framebuffer.
*
* @param {Color} [clearColor] The clear color to use. If undefined, uses the default.
* @returns {ClearCommand} The clear command.
*/
EdgeFramebuffer.prototype.getClearCommand = function (clearColor) {
this._clearCommand.framebuffer = this._framebuffer;
if (defined(clearColor)) {
Color.clone(clearColor, this._clearCommand.color);
2025-08-27 03:58:45 +08:00
}
2025-08-06 23:31:29 +08:00
2025-08-27 04:50:54 +08:00
return this._clearCommand;
2025-08-06 23:31:29 +08:00
};
/**
* Gets the edge framebuffer, creating it if necessary.
*
* @param {Context} context The context.
* @param {Viewport} viewport The viewport.
2025-08-23 06:33:18 +08:00
* @param {Texture} [existingColorTexture] Optional existing color texture to reuse.
* @param {Texture} [existingDepthTexture] Optional existing depth texture to reuse.
2025-08-06 23:31:29 +08:00
*
* @returns {Framebuffer} The edge framebuffer.
*/
EdgeFramebuffer.prototype.getFramebuffer = function (
context,
viewport,
2025-08-23 06:33:18 +08:00
existingColorTexture,
existingDepthTexture,
2025-08-06 23:31:29 +08:00
) {
2025-08-23 06:33:18 +08:00
this.update(
context,
viewport,
false,
existingColorTexture,
existingDepthTexture,
);
2025-08-06 23:31:29 +08:00
return this._framebuffer;
};
/**
* Returns true if this object was destroyed; otherwise, false.
*
* @returns {boolean} True if this object was destroyed; otherwise, false.
*/
EdgeFramebuffer.prototype.isDestroyed = function () {
return false;
};
/**
* Destroys the WebGL resources held by this object. Destroying an object allows for deterministic
* release of WebGL resources, instead of relying on the garbage collector to destroy this object.
* <br /><br />
* Once an object is destroyed, it should not be used; calling any function other than
* <code>isDestroyed</code> will result in a {@link DeveloperError} exception. Therefore,
* assign the return value (<code>undefined</code>) to the object as done in the example.
*
* @exception {DeveloperError} This object was destroyed, i.e., destroy() was called.
*/
EdgeFramebuffer.prototype.destroy = function () {
this._framebufferManager =
this._framebufferManager && this._framebufferManager.destroy();
2025-08-27 04:50:54 +08:00
this._clearCommand = undefined;
2025-08-06 23:31:29 +08:00
return destroyObject(this);
};
export default EdgeFramebuffer;