playcanvas
Version:
PlayCanvas WebGL game engine
193 lines (190 loc) • 5.38 kB
JavaScript
import { PIXELFORMAT_DEPTH, PIXELFORMAT_DEPTH16, PIXELFORMAT_DEPTHSTENCIL, PIXELFORMAT_R32F, isSrgbPixelFormat } from './constants.js';
import { TextureUtils } from './texture-utils.js';
let id = 0;
class RenderTarget {
constructor(options = {}){
this.id = id++;
const device = options.colorBuffer?.device ?? options.colorBuffers?.[0].device ?? options.depthBuffer?.device ?? options.graphicsDevice;
this._device = device;
const { maxSamples } = this._device;
this._samples = Math.min(options.samples ?? 1, maxSamples);
if (device.isWebGPU) {
this._samples = this._samples > 1 ? maxSamples : 1;
}
this._colorBuffer = options.colorBuffer;
if (options.colorBuffer) {
this._colorBuffers = [
options.colorBuffer
];
}
this._depthBuffer = options.depthBuffer;
this._face = options.face ?? 0;
if (this._depthBuffer) {
const format = this._depthBuffer._format;
if (format === PIXELFORMAT_DEPTH || format === PIXELFORMAT_DEPTH16) {
this._depth = true;
this._stencil = false;
} else if (format === PIXELFORMAT_DEPTHSTENCIL) {
this._depth = true;
this._stencil = true;
} else if (format === PIXELFORMAT_R32F && this._depthBuffer.device.isWebGPU && this._samples > 1) {
this._depth = true;
this._stencil = false;
} else {
this._depth = false;
this._stencil = false;
}
} else {
this._depth = options.depth ?? true;
this._stencil = options.stencil ?? false;
}
if (options.colorBuffers) {
if (!this._colorBuffers) {
this._colorBuffers = [
...options.colorBuffers
];
this._colorBuffer = options.colorBuffers[0];
}
}
this.autoResolve = options.autoResolve ?? true;
this.name = options.name;
if (!this.name) {
this.name = this._colorBuffer?.name;
}
if (!this.name) {
this.name = this._depthBuffer?.name;
}
if (!this.name) {
this.name = 'Untitled';
}
this.flipY = options.flipY ?? false;
this._mipLevel = options.mipLevel ?? 0;
if (this._mipLevel > 0 && this._depth) {
this._mipLevel = 0;
}
this._mipmaps = options.mipLevel === undefined;
this.validateMrt();
this.impl = device.createRenderTargetImpl(this);
}
destroy() {
const device = this._device;
if (device) {
device.targets.delete(this);
if (device.renderTarget === this) {
device.setRenderTarget(null);
}
this.destroyFrameBuffers();
}
}
destroyFrameBuffers() {
const device = this._device;
if (device) {
this.impl.destroy(device);
}
}
destroyTextureBuffers() {
this._depthBuffer?.destroy();
this._depthBuffer = null;
this._colorBuffers?.forEach((colorBuffer)=>{
colorBuffer.destroy();
});
this._colorBuffers = null;
this._colorBuffer = null;
}
resize(width, height) {
if (this.width !== width || this.height !== height) {
if (this.mipLevel > 0) {
return;
}
const device = this._device;
this.destroyFrameBuffers();
if (device.renderTarget === this) {
device.setRenderTarget(null);
}
this._depthBuffer?.resize(width, height);
this._colorBuffers?.forEach((colorBuffer)=>{
colorBuffer.resize(width, height);
});
this.validateMrt();
this.impl = device.createRenderTargetImpl(this);
}
}
validateMrt() {}
init() {
this.impl.init(this._device, this);
}
get initialized() {
return this.impl.initialized;
}
get device() {
return this._device;
}
loseContext() {
this.impl.loseContext();
}
resolve(color = true, depth = !!this._depthBuffer) {
if (this._device && this._samples > 1) {
this.impl.resolve(this._device, this, color, depth);
}
}
copy(source, color, depth) {
if (!this._device) {
if (source._device) {
this._device = source._device;
} else {
return false;
}
}
const success = this._device.copyRenderTarget(source, this, color, depth);
return success;
}
get samples() {
return this._samples;
}
get depth() {
return this._depth;
}
get stencil() {
return this._stencil;
}
get colorBuffer() {
return this._colorBuffer;
}
getColorBuffer(index) {
return this._colorBuffers?.[index];
}
get depthBuffer() {
return this._depthBuffer;
}
get face() {
return this._face;
}
get mipLevel() {
return this._mipLevel;
}
get mipmaps() {
return this._mipmaps;
}
get width() {
let width = this._colorBuffer?.width || this._depthBuffer?.width || this._device.width;
if (this._mipLevel > 0) {
width = TextureUtils.calcLevelDimension(width, this._mipLevel);
}
return width;
}
get height() {
let height = this._colorBuffer?.height || this._depthBuffer?.height || this._device.height;
if (this._mipLevel > 0) {
height = TextureUtils.calcLevelDimension(height, this._mipLevel);
}
return height;
}
isColorBufferSrgb(index = 0) {
if (this.device.backBuffer === this) {
return isSrgbPixelFormat(this.device.backBufferFormat);
}
const colorBuffer = this.getColorBuffer(index);
return colorBuffer ? isSrgbPixelFormat(colorBuffer.format) : false;
}
}
export { RenderTarget };