This commit is contained in:
Akko
2025-08-04 18:57:35 +02:00
parent 8cf6e78a79
commit 9495868c2e
5030 changed files with 518594 additions and 17609 deletions

View File

@@ -0,0 +1,78 @@
import { ExtensionType } from '../../../../extensions/Extensions';
import { Matrix } from '../../../../maths/matrix/Matrix';
import { BindGroup } from '../../gpu/shader/BindGroup';
import { type Renderer, RendererType } from '../../types';
import { UniformGroup } from '../shader/UniformGroup';
import type { PointData } from '../../../../maths/point/PointData';
import type { GlRenderTargetSystem } from '../../gl/renderTarget/GlRenderTargetSystem';
import type { GpuRenderTargetSystem } from '../../gpu/renderTarget/GpuRenderTargetSystem';
import type { UboSystem } from '../shader/UboSystem';
import type { System } from '../system/System';
export type GlobalUniformGroup = UniformGroup<{
uProjectionMatrix: {
value: Matrix;
type: 'mat3x3<f32>';
};
uWorldTransformMatrix: {
value: Matrix;
type: 'mat3x3<f32>';
};
uWorldColorAlpha: {
value: Float32Array;
type: 'vec4<f32>';
};
uResolution: {
value: number[];
type: 'vec2<f32>';
};
}>;
export interface GlobalUniformOptions {
size?: number[];
projectionMatrix?: Matrix;
worldTransformMatrix?: Matrix;
worldColor?: number;
offset?: PointData;
}
export interface GlobalUniformData {
projectionMatrix: Matrix;
worldTransformMatrix: Matrix;
worldColor: number;
resolution: number[];
offset: PointData;
bindGroup: BindGroup;
}
export interface GlobalUniformRenderer {
renderTarget: GlRenderTargetSystem | GpuRenderTargetSystem;
renderPipes: Renderer['renderPipes'];
ubo: UboSystem;
type: RendererType;
}
/**
* System plugin to the renderer to manage global uniforms for the renderer.
* @memberof rendering
*/
export declare class GlobalUniformSystem implements System {
/** @ignore */
static extension: {
readonly type: readonly [ExtensionType.WebGLSystem, ExtensionType.WebGPUSystem, ExtensionType.CanvasSystem];
readonly name: "globalUniforms";
};
private readonly _renderer;
private _stackIndex;
private _globalUniformDataStack;
private readonly _uniformsPool;
private readonly _activeUniforms;
private readonly _bindGroupPool;
private readonly _activeBindGroups;
private _currentGlobalUniformData;
constructor(renderer: GlobalUniformRenderer);
reset(): void;
start(options: GlobalUniformOptions): void;
bind({ size, projectionMatrix, worldTransformMatrix, worldColor, offset, }: GlobalUniformOptions): void;
push(options: GlobalUniformOptions): void;
pop(): void;
get bindGroup(): BindGroup;
get uniformGroup(): UniformGroup<any>;
private _createUniforms;
destroy(): void;
}

View File

@@ -0,0 +1,127 @@
'use strict';
var Extensions = require('../../../../extensions/Extensions.js');
var Matrix = require('../../../../maths/matrix/Matrix.js');
var Point = require('../../../../maths/point/Point.js');
var colorToUniform = require('../../../../scene/graphics/gpu/colorToUniform.js');
var BindGroup = require('../../gpu/shader/BindGroup.js');
var types = require('../../types.js');
var UniformGroup = require('../shader/UniformGroup.js');
"use strict";
class GlobalUniformSystem {
constructor(renderer) {
this._stackIndex = 0;
this._globalUniformDataStack = [];
this._uniformsPool = [];
this._activeUniforms = [];
this._bindGroupPool = [];
this._activeBindGroups = [];
this._renderer = renderer;
}
reset() {
this._stackIndex = 0;
for (let i = 0; i < this._activeUniforms.length; i++) {
this._uniformsPool.push(this._activeUniforms[i]);
}
for (let i = 0; i < this._activeBindGroups.length; i++) {
this._bindGroupPool.push(this._activeBindGroups[i]);
}
this._activeUniforms.length = 0;
this._activeBindGroups.length = 0;
}
start(options) {
this.reset();
this.push(options);
}
bind({
size,
projectionMatrix,
worldTransformMatrix,
worldColor,
offset
}) {
const renderTarget = this._renderer.renderTarget.renderTarget;
const currentGlobalUniformData = this._stackIndex ? this._globalUniformDataStack[this._stackIndex - 1] : {
projectionData: renderTarget,
worldTransformMatrix: new Matrix.Matrix(),
worldColor: 4294967295,
offset: new Point.Point()
};
const globalUniformData = {
projectionMatrix: projectionMatrix || this._renderer.renderTarget.projectionMatrix,
resolution: size || renderTarget.size,
worldTransformMatrix: worldTransformMatrix || currentGlobalUniformData.worldTransformMatrix,
worldColor: worldColor || currentGlobalUniformData.worldColor,
offset: offset || currentGlobalUniformData.offset,
bindGroup: null
};
const uniformGroup = this._uniformsPool.pop() || this._createUniforms();
this._activeUniforms.push(uniformGroup);
const uniforms = uniformGroup.uniforms;
uniforms.uProjectionMatrix = globalUniformData.projectionMatrix;
uniforms.uResolution = globalUniformData.resolution;
uniforms.uWorldTransformMatrix.copyFrom(globalUniformData.worldTransformMatrix);
uniforms.uWorldTransformMatrix.tx -= globalUniformData.offset.x;
uniforms.uWorldTransformMatrix.ty -= globalUniformData.offset.y;
colorToUniform.color32BitToUniform(
globalUniformData.worldColor,
uniforms.uWorldColorAlpha,
0
);
uniformGroup.update();
let bindGroup;
if (this._renderer.renderPipes.uniformBatch) {
bindGroup = this._renderer.renderPipes.uniformBatch.getUniformBindGroup(uniformGroup, false);
} else {
bindGroup = this._bindGroupPool.pop() || new BindGroup.BindGroup();
this._activeBindGroups.push(bindGroup);
bindGroup.setResource(uniformGroup, 0);
}
globalUniformData.bindGroup = bindGroup;
this._currentGlobalUniformData = globalUniformData;
}
push(options) {
this.bind(options);
this._globalUniformDataStack[this._stackIndex++] = this._currentGlobalUniformData;
}
pop() {
this._currentGlobalUniformData = this._globalUniformDataStack[--this._stackIndex - 1];
if (this._renderer.type === types.RendererType.WEBGL) {
this._currentGlobalUniformData.bindGroup.resources[0].update();
}
}
get bindGroup() {
return this._currentGlobalUniformData.bindGroup;
}
get uniformGroup() {
return this._currentGlobalUniformData.bindGroup.resources[0];
}
_createUniforms() {
const globalUniforms = new UniformGroup.UniformGroup({
uProjectionMatrix: { value: new Matrix.Matrix(), type: "mat3x3<f32>" },
uWorldTransformMatrix: { value: new Matrix.Matrix(), type: "mat3x3<f32>" },
// TODO - someone smart - set this to be a unorm8x4 rather than a vec4<f32>
uWorldColorAlpha: { value: new Float32Array(4), type: "vec4<f32>" },
uResolution: { value: [0, 0], type: "vec2<f32>" }
}, {
isStatic: true
});
return globalUniforms;
}
destroy() {
this._renderer = null;
}
}
/** @ignore */
GlobalUniformSystem.extension = {
type: [
Extensions.ExtensionType.WebGLSystem,
Extensions.ExtensionType.WebGPUSystem,
Extensions.ExtensionType.CanvasSystem
],
name: "globalUniforms"
};
exports.GlobalUniformSystem = GlobalUniformSystem;
//# sourceMappingURL=GlobalUniformSystem.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,125 @@
import { ExtensionType } from '../../../../extensions/Extensions.mjs';
import { Matrix } from '../../../../maths/matrix/Matrix.mjs';
import { Point } from '../../../../maths/point/Point.mjs';
import { color32BitToUniform } from '../../../../scene/graphics/gpu/colorToUniform.mjs';
import { BindGroup } from '../../gpu/shader/BindGroup.mjs';
import { RendererType } from '../../types.mjs';
import { UniformGroup } from '../shader/UniformGroup.mjs';
"use strict";
class GlobalUniformSystem {
constructor(renderer) {
this._stackIndex = 0;
this._globalUniformDataStack = [];
this._uniformsPool = [];
this._activeUniforms = [];
this._bindGroupPool = [];
this._activeBindGroups = [];
this._renderer = renderer;
}
reset() {
this._stackIndex = 0;
for (let i = 0; i < this._activeUniforms.length; i++) {
this._uniformsPool.push(this._activeUniforms[i]);
}
for (let i = 0; i < this._activeBindGroups.length; i++) {
this._bindGroupPool.push(this._activeBindGroups[i]);
}
this._activeUniforms.length = 0;
this._activeBindGroups.length = 0;
}
start(options) {
this.reset();
this.push(options);
}
bind({
size,
projectionMatrix,
worldTransformMatrix,
worldColor,
offset
}) {
const renderTarget = this._renderer.renderTarget.renderTarget;
const currentGlobalUniformData = this._stackIndex ? this._globalUniformDataStack[this._stackIndex - 1] : {
projectionData: renderTarget,
worldTransformMatrix: new Matrix(),
worldColor: 4294967295,
offset: new Point()
};
const globalUniformData = {
projectionMatrix: projectionMatrix || this._renderer.renderTarget.projectionMatrix,
resolution: size || renderTarget.size,
worldTransformMatrix: worldTransformMatrix || currentGlobalUniformData.worldTransformMatrix,
worldColor: worldColor || currentGlobalUniformData.worldColor,
offset: offset || currentGlobalUniformData.offset,
bindGroup: null
};
const uniformGroup = this._uniformsPool.pop() || this._createUniforms();
this._activeUniforms.push(uniformGroup);
const uniforms = uniformGroup.uniforms;
uniforms.uProjectionMatrix = globalUniformData.projectionMatrix;
uniforms.uResolution = globalUniformData.resolution;
uniforms.uWorldTransformMatrix.copyFrom(globalUniformData.worldTransformMatrix);
uniforms.uWorldTransformMatrix.tx -= globalUniformData.offset.x;
uniforms.uWorldTransformMatrix.ty -= globalUniformData.offset.y;
color32BitToUniform(
globalUniformData.worldColor,
uniforms.uWorldColorAlpha,
0
);
uniformGroup.update();
let bindGroup;
if (this._renderer.renderPipes.uniformBatch) {
bindGroup = this._renderer.renderPipes.uniformBatch.getUniformBindGroup(uniformGroup, false);
} else {
bindGroup = this._bindGroupPool.pop() || new BindGroup();
this._activeBindGroups.push(bindGroup);
bindGroup.setResource(uniformGroup, 0);
}
globalUniformData.bindGroup = bindGroup;
this._currentGlobalUniformData = globalUniformData;
}
push(options) {
this.bind(options);
this._globalUniformDataStack[this._stackIndex++] = this._currentGlobalUniformData;
}
pop() {
this._currentGlobalUniformData = this._globalUniformDataStack[--this._stackIndex - 1];
if (this._renderer.type === RendererType.WEBGL) {
this._currentGlobalUniformData.bindGroup.resources[0].update();
}
}
get bindGroup() {
return this._currentGlobalUniformData.bindGroup;
}
get uniformGroup() {
return this._currentGlobalUniformData.bindGroup.resources[0];
}
_createUniforms() {
const globalUniforms = new UniformGroup({
uProjectionMatrix: { value: new Matrix(), type: "mat3x3<f32>" },
uWorldTransformMatrix: { value: new Matrix(), type: "mat3x3<f32>" },
// TODO - someone smart - set this to be a unorm8x4 rather than a vec4<f32>
uWorldColorAlpha: { value: new Float32Array(4), type: "vec4<f32>" },
uResolution: { value: [0, 0], type: "vec2<f32>" }
}, {
isStatic: true
});
return globalUniforms;
}
destroy() {
this._renderer = null;
}
}
/** @ignore */
GlobalUniformSystem.extension = {
type: [
ExtensionType.WebGLSystem,
ExtensionType.WebGPUSystem,
ExtensionType.CanvasSystem
],
name: "globalUniforms"
};
export { GlobalUniformSystem };
//# sourceMappingURL=GlobalUniformSystem.mjs.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,78 @@
import { TextureSource } from '../texture/sources/TextureSource';
import type { BindableTexture } from '../texture/Texture';
/**
* Options for creating a render target.
* @memberof rendering
*/
export interface RenderTargetOptions {
/** the width of the RenderTarget */
width?: number;
/** the height of the RenderTarget */
height?: number;
/** the resolution of the RenderTarget */
resolution?: number;
/** an array of textures, or a number indicating how many color textures there should be */
colorTextures?: BindableTexture[] | number;
/** should this render target have a stencil buffer? */
stencil?: boolean;
/** should this render target have a depth buffer? */
depth?: boolean;
/** a depth stencil texture that the depth and stencil outputs will be written to */
depthStencilTexture?: BindableTexture | boolean;
/** should this render target be antialiased? */
antialias?: boolean;
/** is this a root element, true if this is gl context owners render target */
isRoot?: boolean;
}
/**
* A class that describes what the renderers are rendering to.
* This can be as simple as a Texture, or as complex as a multi-texture, multi-sampled render target.
* Support for stencil and depth buffers is also included.
*
* If you need something more complex than a Texture to render to, you should use this class.
* Under the hood, all textures you render to have a RenderTarget created on their behalf.
* @memberof rendering
*/
export declare class RenderTarget {
/** The default options for a render target */
static defaultOptions: RenderTargetOptions;
/** unique id for this render target */
readonly uid: number;
/**
* An array of textures that can be written to by the GPU - mostly this has one texture in Pixi, but you could
* write to multiple if required! (eg deferred lighting)
*/
colorTextures: TextureSource[];
/** the stencil and depth buffer will right to this texture in WebGPU */
depthStencilTexture: TextureSource;
/** if true, will ensure a stencil buffer is added. For WebGPU, this will automatically create a depthStencilTexture */
stencil: boolean;
/** if true, will ensure a depth buffer is added. For WebGPU, this will automatically create a depthStencilTexture */
depth: boolean;
dirtyId: number;
isRoot: boolean;
private readonly _size;
/** if true, then when the render target is destroyed, it will destroy all the textures that were created for it. */
private readonly _managedColorTextures;
/**
* @param [descriptor] - Options for creating a render target.
*/
constructor(descriptor?: RenderTargetOptions);
get size(): [number, number];
get width(): number;
get height(): number;
get pixelWidth(): number;
get pixelHeight(): number;
get resolution(): number;
get colorTexture(): TextureSource;
protected onSourceResize(source: TextureSource): void;
/**
* This will ensure a depthStencil texture is created for this render target.
* Most likely called by the mask system to make sure we have stencil buffer added.
* @internal
* @ignore
*/
ensureDepthStencilTexture(): void;
resize(width: number, height: number, resolution?: number, skipColorTexture?: boolean): void;
destroy(): void;
}

View File

@@ -0,0 +1,149 @@
'use strict';
var uid = require('../../../../utils/data/uid.js');
var TextureSource = require('../texture/sources/TextureSource.js');
var Texture = require('../texture/Texture.js');
"use strict";
const _RenderTarget = class _RenderTarget {
/**
* @param [descriptor] - Options for creating a render target.
*/
constructor(descriptor = {}) {
/** unique id for this render target */
this.uid = uid.uid("renderTarget");
/**
* An array of textures that can be written to by the GPU - mostly this has one texture in Pixi, but you could
* write to multiple if required! (eg deferred lighting)
*/
this.colorTextures = [];
this.dirtyId = 0;
this.isRoot = false;
this._size = new Float32Array(2);
/** if true, then when the render target is destroyed, it will destroy all the textures that were created for it. */
this._managedColorTextures = false;
descriptor = { ..._RenderTarget.defaultOptions, ...descriptor };
this.stencil = descriptor.stencil;
this.depth = descriptor.depth;
this.isRoot = descriptor.isRoot;
if (typeof descriptor.colorTextures === "number") {
this._managedColorTextures = true;
for (let i = 0; i < descriptor.colorTextures; i++) {
this.colorTextures.push(
new TextureSource.TextureSource({
width: descriptor.width,
height: descriptor.height,
resolution: descriptor.resolution,
antialias: descriptor.antialias
})
);
}
} else {
this.colorTextures = [...descriptor.colorTextures.map((texture) => texture.source)];
const colorSource = this.colorTexture.source;
this.resize(colorSource.width, colorSource.height, colorSource._resolution);
}
this.colorTexture.source.on("resize", this.onSourceResize, this);
if (descriptor.depthStencilTexture || this.stencil) {
if (descriptor.depthStencilTexture instanceof Texture.Texture || descriptor.depthStencilTexture instanceof TextureSource.TextureSource) {
this.depthStencilTexture = descriptor.depthStencilTexture.source;
} else {
this.ensureDepthStencilTexture();
}
}
}
get size() {
const _size = this._size;
_size[0] = this.pixelWidth;
_size[1] = this.pixelHeight;
return _size;
}
get width() {
return this.colorTexture.source.width;
}
get height() {
return this.colorTexture.source.height;
}
get pixelWidth() {
return this.colorTexture.source.pixelWidth;
}
get pixelHeight() {
return this.colorTexture.source.pixelHeight;
}
get resolution() {
return this.colorTexture.source._resolution;
}
get colorTexture() {
return this.colorTextures[0];
}
onSourceResize(source) {
this.resize(source.width, source.height, source._resolution, true);
}
/**
* This will ensure a depthStencil texture is created for this render target.
* Most likely called by the mask system to make sure we have stencil buffer added.
* @internal
* @ignore
*/
ensureDepthStencilTexture() {
if (!this.depthStencilTexture) {
this.depthStencilTexture = new TextureSource.TextureSource({
width: this.width,
height: this.height,
resolution: this.resolution,
format: "depth24plus-stencil8",
autoGenerateMipmaps: false,
antialias: false,
mipLevelCount: 1
// sampleCount: handled by the render target system..
});
}
}
resize(width, height, resolution = this.resolution, skipColorTexture = false) {
this.dirtyId++;
this.colorTextures.forEach((colorTexture, i) => {
if (skipColorTexture && i === 0)
return;
colorTexture.source.resize(width, height, resolution);
});
if (this.depthStencilTexture) {
this.depthStencilTexture.source.resize(width, height, resolution);
}
}
destroy() {
this.colorTexture.source.off("resize", this.onSourceResize, this);
if (this._managedColorTextures) {
this.colorTextures.forEach((texture) => {
texture.destroy();
});
}
if (this.depthStencilTexture) {
this.depthStencilTexture.destroy();
delete this.depthStencilTexture;
}
}
};
/** The default options for a render target */
_RenderTarget.defaultOptions = {
/** the width of the RenderTarget */
width: 0,
/** the height of the RenderTarget */
height: 0,
/** the resolution of the RenderTarget */
resolution: 1,
/** an array of textures, or a number indicating how many color textures there should be */
colorTextures: 1,
/** should this render target have a stencil buffer? */
stencil: false,
/** should this render target have a depth buffer? */
depth: false,
/** should this render target be antialiased? */
antialias: false,
// save on perf by default!
/** is this a root element, true if this is gl context owners render target */
isRoot: false
};
let RenderTarget = _RenderTarget;
exports.RenderTarget = RenderTarget;
//# sourceMappingURL=RenderTarget.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,147 @@
import { uid } from '../../../../utils/data/uid.mjs';
import { TextureSource } from '../texture/sources/TextureSource.mjs';
import { Texture } from '../texture/Texture.mjs';
"use strict";
const _RenderTarget = class _RenderTarget {
/**
* @param [descriptor] - Options for creating a render target.
*/
constructor(descriptor = {}) {
/** unique id for this render target */
this.uid = uid("renderTarget");
/**
* An array of textures that can be written to by the GPU - mostly this has one texture in Pixi, but you could
* write to multiple if required! (eg deferred lighting)
*/
this.colorTextures = [];
this.dirtyId = 0;
this.isRoot = false;
this._size = new Float32Array(2);
/** if true, then when the render target is destroyed, it will destroy all the textures that were created for it. */
this._managedColorTextures = false;
descriptor = { ..._RenderTarget.defaultOptions, ...descriptor };
this.stencil = descriptor.stencil;
this.depth = descriptor.depth;
this.isRoot = descriptor.isRoot;
if (typeof descriptor.colorTextures === "number") {
this._managedColorTextures = true;
for (let i = 0; i < descriptor.colorTextures; i++) {
this.colorTextures.push(
new TextureSource({
width: descriptor.width,
height: descriptor.height,
resolution: descriptor.resolution,
antialias: descriptor.antialias
})
);
}
} else {
this.colorTextures = [...descriptor.colorTextures.map((texture) => texture.source)];
const colorSource = this.colorTexture.source;
this.resize(colorSource.width, colorSource.height, colorSource._resolution);
}
this.colorTexture.source.on("resize", this.onSourceResize, this);
if (descriptor.depthStencilTexture || this.stencil) {
if (descriptor.depthStencilTexture instanceof Texture || descriptor.depthStencilTexture instanceof TextureSource) {
this.depthStencilTexture = descriptor.depthStencilTexture.source;
} else {
this.ensureDepthStencilTexture();
}
}
}
get size() {
const _size = this._size;
_size[0] = this.pixelWidth;
_size[1] = this.pixelHeight;
return _size;
}
get width() {
return this.colorTexture.source.width;
}
get height() {
return this.colorTexture.source.height;
}
get pixelWidth() {
return this.colorTexture.source.pixelWidth;
}
get pixelHeight() {
return this.colorTexture.source.pixelHeight;
}
get resolution() {
return this.colorTexture.source._resolution;
}
get colorTexture() {
return this.colorTextures[0];
}
onSourceResize(source) {
this.resize(source.width, source.height, source._resolution, true);
}
/**
* This will ensure a depthStencil texture is created for this render target.
* Most likely called by the mask system to make sure we have stencil buffer added.
* @internal
* @ignore
*/
ensureDepthStencilTexture() {
if (!this.depthStencilTexture) {
this.depthStencilTexture = new TextureSource({
width: this.width,
height: this.height,
resolution: this.resolution,
format: "depth24plus-stencil8",
autoGenerateMipmaps: false,
antialias: false,
mipLevelCount: 1
// sampleCount: handled by the render target system..
});
}
}
resize(width, height, resolution = this.resolution, skipColorTexture = false) {
this.dirtyId++;
this.colorTextures.forEach((colorTexture, i) => {
if (skipColorTexture && i === 0)
return;
colorTexture.source.resize(width, height, resolution);
});
if (this.depthStencilTexture) {
this.depthStencilTexture.source.resize(width, height, resolution);
}
}
destroy() {
this.colorTexture.source.off("resize", this.onSourceResize, this);
if (this._managedColorTextures) {
this.colorTextures.forEach((texture) => {
texture.destroy();
});
}
if (this.depthStencilTexture) {
this.depthStencilTexture.destroy();
delete this.depthStencilTexture;
}
}
};
/** The default options for a render target */
_RenderTarget.defaultOptions = {
/** the width of the RenderTarget */
width: 0,
/** the height of the RenderTarget */
height: 0,
/** the resolution of the RenderTarget */
resolution: 1,
/** an array of textures, or a number indicating how many color textures there should be */
colorTextures: 1,
/** should this render target have a stencil buffer? */
stencil: false,
/** should this render target have a depth buffer? */
depth: false,
/** should this render target be antialiased? */
antialias: false,
// save on perf by default!
/** is this a root element, true if this is gl context owners render target */
isRoot: false
};
let RenderTarget = _RenderTarget;
export { RenderTarget };
//# sourceMappingURL=RenderTarget.mjs.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,242 @@
import { Matrix } from '../../../../maths/matrix/Matrix';
import { Rectangle } from '../../../../maths/shapes/Rectangle';
import { CLEAR } from '../../gl/const';
import { SystemRunner } from '../system/SystemRunner';
import { TextureSource } from '../texture/sources/TextureSource';
import { Texture } from '../texture/Texture';
import { RenderTarget } from './RenderTarget';
import type { RgbaArray } from '../../../../color/Color';
import type { ICanvas } from '../../../../environment/canvas/ICanvas';
import type { CLEAR_OR_BOOL } from '../../gl/const';
import type { GlRenderTarget } from '../../gl/GlRenderTarget';
import type { GpuRenderTarget } from '../../gpu/renderTarget/GpuRenderTarget';
import type { Renderer } from '../../types';
import type { System } from '../system/System';
import type { BindableTexture } from '../texture/Texture';
/**
* A render surface is a texture, canvas, or render target
* @memberof rendering
* @see environment.ICanvas
* @see rendering.Texture
* @see rendering.RenderTarget
*/
export type RenderSurface = ICanvas | BindableTexture | RenderTarget;
/**
* An adaptor interface for RenderTargetSystem to support WebGL and WebGPU.
* This is used internally by the renderer, and is not intended to be used directly.
* @ignore
*/
export interface RenderTargetAdaptor<RENDER_TARGET extends GlRenderTarget | GpuRenderTarget> {
init(
/** the renderer */
renderer: Renderer,
/** the render target system */
renderTargetSystem: RenderTargetSystem<RENDER_TARGET>): void;
/** A function copies the contents of a render surface to a texture */
copyToTexture(
/** the render surface to copy from */
sourceRenderSurfaceTexture: RenderTarget,
/** the texture to copy to */
destinationTexture: Texture,
/** the origin of the copy */
originSrc: {
x: number;
y: number;
},
/** the size of the copy */
size: {
width: number;
height: number;
},
/** the destination origin (top left to paste from!) */
originDest?: {
x: number;
y: number;
}): Texture;
/** starts a render pass on the render target */
startRenderPass(
/** the render target to start the render pass on */
renderTarget: RenderTarget, clear: CLEAR_OR_BOOL,
/** the color to clear to */
clearColor?: RgbaArray,
/** the viewport to use */
viewport?: Rectangle): void;
/** clears the current render target to the specified color */
clear(
/** the render target to clear */
renderTarget: RenderTarget,
/** the clear mode to use. Can be true or a CLEAR number 'COLOR | DEPTH | STENCIL' 0b111 */
clear: CLEAR_OR_BOOL,
/** the color to clear to */
clearColor?: RgbaArray,
/** the viewport to use */
viewport?: Rectangle): void;
/** finishes the current render pass */
finishRenderPass(renderTarget: RenderTarget): void;
/** called after the render pass is finished */
postrender?(renderTarget: RenderTarget): void;
/**
* initializes a gpu render target. Both renderers use this function to initialize a gpu render target
* Its different type of object depending on the renderer.
*/
initGpuRenderTarget(
/** the render target to initialize */
renderTarget: RenderTarget): RENDER_TARGET;
/** called when a render target is resized */
resizeGpuRenderTarget(
/** the render target to resize */
renderTarget: RenderTarget): void;
/** destroys the gpu render target */
destroyGpuRenderTarget(
/** the render target to destroy */
gpuRenderTarget: RENDER_TARGET): void;
}
/**
* A system that manages render targets. A render target is essentially a place where the shaders can color in the pixels.
* The render target system is responsible for binding the render target to the renderer, and managing the viewport.
* Render targets can be pushed and popped.
*
* To make it easier, you can also bind textures and canvases too. This will automatically create a render target for you.
* The render target itself is a lot more powerful than just a texture or canvas,
* as it can have multiple textures attached to it.
* It will also give ou fine grain control over the stencil buffer / depth texture.
* @example
*
* ```js
*
* // create a render target
* const renderTarget = new RenderTarget({
* colorTextures: [new TextureSource({ width: 100, height: 100 })],
* });
*
* // bind the render target
* renderer.renderTarget.bind(renderTarget);
*
* // draw something!
* ```
* @memberof rendering
*/
export declare class RenderTargetSystem<RENDER_TARGET extends GlRenderTarget | GpuRenderTarget> implements System {
/** When rendering of a scene begins, this is where the root render surface is stored */
rootRenderTarget: RenderTarget;
/** This is the root viewport for the render pass*/
rootViewPort: Rectangle;
/** A boolean that lets the dev know if the current render pass is rendering to the screen. Used by some plugins */
renderingToScreen: boolean;
/** the current active render target */
renderTarget: RenderTarget;
/** the current active render surface that the render target is created from */
renderSurface: RenderSurface;
/** the current viewport that the gpu is using */
readonly viewport: Rectangle;
/**
* a runner that lets systems know if the active render target has changed.
* Eg the Stencil System needs to know so it can manage the stencil buffer
*/
readonly onRenderTargetChange: SystemRunner;
/** the projection matrix that is used by the shaders based on the active render target and the viewport */
readonly projectionMatrix: Matrix;
/** the default clear color for render targets */
readonly defaultClearColor: RgbaArray;
/** a reference to the adaptor that interfaces with WebGL / WebGP */
readonly adaptor: RenderTargetAdaptor<RENDER_TARGET>;
/**
* a hash that stores the render target for a given render surface. When you pass in a texture source,
* a render target is created for it. This map stores and makes it easy to retrieve the render target
*/
private readonly _renderSurfaceToRenderTargetHash;
/** A hash that stores a gpu render target for a given render target. */
private _gpuRenderTargetHash;
/**
* A stack that stores the render target and frame that is currently being rendered to.
* When push is called, the current render target is stored in this stack.
* When pop is called, the previous render target is restored.
*/
private readonly _renderTargetStack;
/** A reference to the renderer */
private readonly _renderer;
constructor(renderer: Renderer);
/** called when dev wants to finish a render pass */
finishRenderPass(): void;
/**
* called when the renderer starts to render a scene.
* @param options
* @param options.target - the render target to render to
* @param options.clear - the clear mode to use. Can be true or a CLEAR number 'COLOR | DEPTH | STENCIL' 0b111
* @param options.clearColor - the color to clear to
* @param options.frame - the frame to render to
*/
renderStart({ target, clear, clearColor, frame }: {
target: RenderSurface;
clear: CLEAR_OR_BOOL;
clearColor: RgbaArray;
frame?: Rectangle;
}): void;
postrender(): void;
/**
* Binding a render surface! This is the main function of the render target system.
* It will take the RenderSurface (which can be a texture, canvas, or render target) and bind it to the renderer.
* Once bound all draw calls will be rendered to the render surface.
*
* If a frame is not provide and the render surface is a texture, the frame of the texture will be used.
* @param renderSurface - the render surface to bind
* @param clear - the clear mode to use. Can be true or a CLEAR number 'COLOR | DEPTH | STENCIL' 0b111
* @param clearColor - the color to clear to
* @param frame - the frame to render to
* @returns the render target that was bound
*/
bind(renderSurface: RenderSurface, clear?: CLEAR_OR_BOOL, clearColor?: RgbaArray, frame?: Rectangle): RenderTarget;
clear(target?: RenderSurface, clear?: CLEAR_OR_BOOL, clearColor?: RgbaArray): void;
protected contextChange(): void;
/**
* Push a render surface to the renderer. This will bind the render surface to the renderer,
* @param renderSurface - the render surface to push
* @param clear - the clear mode to use. Can be true or a CLEAR number 'COLOR | DEPTH | STENCIL' 0b111
* @param clearColor - the color to clear to
* @param frame - the frame to use when rendering to the render surface
*/
push(renderSurface: RenderSurface, clear?: CLEAR | boolean, clearColor?: RgbaArray, frame?: Rectangle): RenderTarget;
/** Pops the current render target from the renderer and restores the previous render target. */
pop(): void;
/**
* Gets the render target from the provide render surface. Eg if its a texture,
* it will return the render target for the texture.
* If its a render target, it will return the same render target.
* @param renderSurface - the render surface to get the render target for
* @returns the render target for the render surface
*/
getRenderTarget(renderSurface: RenderSurface): RenderTarget;
/**
* Copies a render surface to another texture
* @param sourceRenderSurfaceTexture - the render surface to copy from
* @param destinationTexture - the texture to copy to
* @param originSrc - the origin of the copy
* @param originSrc.x - the x origin of the copy
* @param originSrc.y - the y origin of the copy
* @param size - the size of the copy
* @param size.width - the width of the copy
* @param size.height - the height of the copy
* @param originDest - the destination origin (top left to paste from!)
* @param originDest.x - the x origin of the paste
* @param originDest.y - the y origin of the paste
*/
copyToTexture(sourceRenderSurfaceTexture: RenderTarget, destinationTexture: Texture, originSrc: {
x: number;
y: number;
}, size: {
width: number;
height: number;
}, originDest: {
x: number;
y: number;
}): Texture<TextureSource<any>>;
/**
* ensures that we have a depth stencil buffer available to render to
* This is used by the mask system to make sure we have a stencil buffer.
*/
ensureDepthStencil(): void;
/** nukes the render target system */
destroy(): void;
private _initRenderTarget;
getGpuRenderTarget(renderTarget: RenderTarget): RENDER_TARGET;
}

View File

@@ -0,0 +1,274 @@
'use strict';
var Matrix = require('../../../../maths/matrix/Matrix.js');
var Rectangle = require('../../../../maths/shapes/Rectangle.js');
var _const = require('../../gl/const.js');
var calculateProjection = require('../../gpu/renderTarget/calculateProjection.js');
var SystemRunner = require('../system/SystemRunner.js');
var CanvasSource = require('../texture/sources/CanvasSource.js');
var TextureSource = require('../texture/sources/TextureSource.js');
var Texture = require('../texture/Texture.js');
var getCanvasTexture = require('../texture/utils/getCanvasTexture.js');
var isRenderingToScreen = require('./isRenderingToScreen.js');
var RenderTarget = require('./RenderTarget.js');
"use strict";
class RenderTargetSystem {
constructor(renderer) {
/** This is the root viewport for the render pass*/
this.rootViewPort = new Rectangle.Rectangle();
/** the current viewport that the gpu is using */
this.viewport = new Rectangle.Rectangle();
/**
* a runner that lets systems know if the active render target has changed.
* Eg the Stencil System needs to know so it can manage the stencil buffer
*/
this.onRenderTargetChange = new SystemRunner.SystemRunner("onRenderTargetChange");
/** the projection matrix that is used by the shaders based on the active render target and the viewport */
this.projectionMatrix = new Matrix.Matrix();
/** the default clear color for render targets */
this.defaultClearColor = [0, 0, 0, 0];
/**
* a hash that stores the render target for a given render surface. When you pass in a texture source,
* a render target is created for it. This map stores and makes it easy to retrieve the render target
*/
this._renderSurfaceToRenderTargetHash = /* @__PURE__ */ new Map();
/** A hash that stores a gpu render target for a given render target. */
this._gpuRenderTargetHash = /* @__PURE__ */ Object.create(null);
/**
* A stack that stores the render target and frame that is currently being rendered to.
* When push is called, the current render target is stored in this stack.
* When pop is called, the previous render target is restored.
*/
this._renderTargetStack = [];
this._renderer = renderer;
}
/** called when dev wants to finish a render pass */
finishRenderPass() {
this.adaptor.finishRenderPass(this.renderTarget);
}
/**
* called when the renderer starts to render a scene.
* @param options
* @param options.target - the render target to render to
* @param options.clear - the clear mode to use. Can be true or a CLEAR number 'COLOR | DEPTH | STENCIL' 0b111
* @param options.clearColor - the color to clear to
* @param options.frame - the frame to render to
*/
renderStart({
target,
clear,
clearColor,
frame
}) {
this._renderTargetStack.length = 0;
this.push(
target,
clear,
clearColor,
frame
);
this.rootViewPort.copyFrom(this.viewport);
this.rootRenderTarget = this.renderTarget;
this.renderingToScreen = isRenderingToScreen.isRenderingToScreen(this.rootRenderTarget);
}
postrender() {
this.adaptor.postrender?.(this.rootRenderTarget);
}
/**
* Binding a render surface! This is the main function of the render target system.
* It will take the RenderSurface (which can be a texture, canvas, or render target) and bind it to the renderer.
* Once bound all draw calls will be rendered to the render surface.
*
* If a frame is not provide and the render surface is a texture, the frame of the texture will be used.
* @param renderSurface - the render surface to bind
* @param clear - the clear mode to use. Can be true or a CLEAR number 'COLOR | DEPTH | STENCIL' 0b111
* @param clearColor - the color to clear to
* @param frame - the frame to render to
* @returns the render target that was bound
*/
bind(renderSurface, clear = true, clearColor, frame) {
const renderTarget = this.getRenderTarget(renderSurface);
const didChange = this.renderTarget !== renderTarget;
this.renderTarget = renderTarget;
this.renderSurface = renderSurface;
const gpuRenderTarget = this.getGpuRenderTarget(renderTarget);
if (renderTarget.pixelWidth !== gpuRenderTarget.width || renderTarget.pixelHeight !== gpuRenderTarget.height) {
this.adaptor.resizeGpuRenderTarget(renderTarget);
gpuRenderTarget.width = renderTarget.pixelWidth;
gpuRenderTarget.height = renderTarget.pixelHeight;
}
const source = renderTarget.colorTexture;
const viewport = this.viewport;
const pixelWidth = source.pixelWidth;
const pixelHeight = source.pixelHeight;
if (!frame && renderSurface instanceof Texture.Texture) {
frame = renderSurface.frame;
}
if (frame) {
const resolution = source._resolution;
viewport.x = frame.x * resolution + 0.5 | 0;
viewport.y = frame.y * resolution + 0.5 | 0;
viewport.width = frame.width * resolution + 0.5 | 0;
viewport.height = frame.height * resolution + 0.5 | 0;
} else {
viewport.x = 0;
viewport.y = 0;
viewport.width = pixelWidth;
viewport.height = pixelHeight;
}
calculateProjection.calculateProjection(
this.projectionMatrix,
0,
0,
viewport.width / source.resolution,
viewport.height / source.resolution,
!renderTarget.isRoot
);
this.adaptor.startRenderPass(renderTarget, clear, clearColor, viewport);
if (didChange) {
this.onRenderTargetChange.emit(renderTarget);
}
return renderTarget;
}
clear(target, clear = _const.CLEAR.ALL, clearColor) {
if (!clear)
return;
if (target) {
target = this.getRenderTarget(target);
}
this.adaptor.clear(
target || this.renderTarget,
clear,
clearColor,
this.viewport
);
}
contextChange() {
this._gpuRenderTargetHash = /* @__PURE__ */ Object.create(null);
}
/**
* Push a render surface to the renderer. This will bind the render surface to the renderer,
* @param renderSurface - the render surface to push
* @param clear - the clear mode to use. Can be true or a CLEAR number 'COLOR | DEPTH | STENCIL' 0b111
* @param clearColor - the color to clear to
* @param frame - the frame to use when rendering to the render surface
*/
push(renderSurface, clear = _const.CLEAR.ALL, clearColor, frame) {
const renderTarget = this.bind(renderSurface, clear, clearColor, frame);
this._renderTargetStack.push({
renderTarget,
frame
});
return renderTarget;
}
/** Pops the current render target from the renderer and restores the previous render target. */
pop() {
this._renderTargetStack.pop();
const currentRenderTargetData = this._renderTargetStack[this._renderTargetStack.length - 1];
this.bind(currentRenderTargetData.renderTarget, false, null, currentRenderTargetData.frame);
}
/**
* Gets the render target from the provide render surface. Eg if its a texture,
* it will return the render target for the texture.
* If its a render target, it will return the same render target.
* @param renderSurface - the render surface to get the render target for
* @returns the render target for the render surface
*/
getRenderTarget(renderSurface) {
if (renderSurface.isTexture) {
renderSurface = renderSurface.source;
}
return this._renderSurfaceToRenderTargetHash.get(renderSurface) ?? this._initRenderTarget(renderSurface);
}
/**
* Copies a render surface to another texture
* @param sourceRenderSurfaceTexture - the render surface to copy from
* @param destinationTexture - the texture to copy to
* @param originSrc - the origin of the copy
* @param originSrc.x - the x origin of the copy
* @param originSrc.y - the y origin of the copy
* @param size - the size of the copy
* @param size.width - the width of the copy
* @param size.height - the height of the copy
* @param originDest - the destination origin (top left to paste from!)
* @param originDest.x - the x origin of the paste
* @param originDest.y - the y origin of the paste
*/
copyToTexture(sourceRenderSurfaceTexture, destinationTexture, originSrc, size, originDest) {
if (originSrc.x < 0) {
size.width += originSrc.x;
originDest.x -= originSrc.x;
originSrc.x = 0;
}
if (originSrc.y < 0) {
size.height += originSrc.y;
originDest.y -= originSrc.y;
originSrc.y = 0;
}
const { pixelWidth, pixelHeight } = sourceRenderSurfaceTexture;
size.width = Math.min(size.width, pixelWidth - originSrc.x);
size.height = Math.min(size.height, pixelHeight - originSrc.y);
return this.adaptor.copyToTexture(
sourceRenderSurfaceTexture,
destinationTexture,
originSrc,
size,
originDest
);
}
/**
* ensures that we have a depth stencil buffer available to render to
* This is used by the mask system to make sure we have a stencil buffer.
*/
ensureDepthStencil() {
if (!this.renderTarget.stencil) {
this.renderTarget.stencil = true;
this.adaptor.startRenderPass(this.renderTarget, false, null, this.viewport);
}
}
/** nukes the render target system */
destroy() {
this._renderer = null;
this._renderSurfaceToRenderTargetHash.forEach((renderTarget, key) => {
if (renderTarget !== key) {
renderTarget.destroy();
}
});
this._renderSurfaceToRenderTargetHash.clear();
this._gpuRenderTargetHash = /* @__PURE__ */ Object.create(null);
}
_initRenderTarget(renderSurface) {
let renderTarget = null;
if (CanvasSource.CanvasSource.test(renderSurface)) {
renderSurface = getCanvasTexture.getCanvasTexture(renderSurface).source;
}
if (renderSurface instanceof RenderTarget.RenderTarget) {
renderTarget = renderSurface;
} else if (renderSurface instanceof TextureSource.TextureSource) {
renderTarget = new RenderTarget.RenderTarget({
colorTextures: [renderSurface]
});
if (CanvasSource.CanvasSource.test(renderSurface.source.resource)) {
renderTarget.isRoot = true;
}
renderSurface.once("destroy", () => {
renderTarget.destroy();
this._renderSurfaceToRenderTargetHash.delete(renderSurface);
const gpuRenderTarget = this._gpuRenderTargetHash[renderTarget.uid];
if (gpuRenderTarget) {
this._gpuRenderTargetHash[renderTarget.uid] = null;
this.adaptor.destroyGpuRenderTarget(gpuRenderTarget);
}
});
}
this._renderSurfaceToRenderTargetHash.set(renderSurface, renderTarget);
return renderTarget;
}
getGpuRenderTarget(renderTarget) {
return this._gpuRenderTargetHash[renderTarget.uid] || (this._gpuRenderTargetHash[renderTarget.uid] = this.adaptor.initGpuRenderTarget(renderTarget));
}
}
exports.RenderTargetSystem = RenderTargetSystem;
//# sourceMappingURL=RenderTargetSystem.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,272 @@
import { Matrix } from '../../../../maths/matrix/Matrix.mjs';
import { Rectangle } from '../../../../maths/shapes/Rectangle.mjs';
import { CLEAR } from '../../gl/const.mjs';
import { calculateProjection } from '../../gpu/renderTarget/calculateProjection.mjs';
import { SystemRunner } from '../system/SystemRunner.mjs';
import { CanvasSource } from '../texture/sources/CanvasSource.mjs';
import { TextureSource } from '../texture/sources/TextureSource.mjs';
import { Texture } from '../texture/Texture.mjs';
import { getCanvasTexture } from '../texture/utils/getCanvasTexture.mjs';
import { isRenderingToScreen } from './isRenderingToScreen.mjs';
import { RenderTarget } from './RenderTarget.mjs';
"use strict";
class RenderTargetSystem {
constructor(renderer) {
/** This is the root viewport for the render pass*/
this.rootViewPort = new Rectangle();
/** the current viewport that the gpu is using */
this.viewport = new Rectangle();
/**
* a runner that lets systems know if the active render target has changed.
* Eg the Stencil System needs to know so it can manage the stencil buffer
*/
this.onRenderTargetChange = new SystemRunner("onRenderTargetChange");
/** the projection matrix that is used by the shaders based on the active render target and the viewport */
this.projectionMatrix = new Matrix();
/** the default clear color for render targets */
this.defaultClearColor = [0, 0, 0, 0];
/**
* a hash that stores the render target for a given render surface. When you pass in a texture source,
* a render target is created for it. This map stores and makes it easy to retrieve the render target
*/
this._renderSurfaceToRenderTargetHash = /* @__PURE__ */ new Map();
/** A hash that stores a gpu render target for a given render target. */
this._gpuRenderTargetHash = /* @__PURE__ */ Object.create(null);
/**
* A stack that stores the render target and frame that is currently being rendered to.
* When push is called, the current render target is stored in this stack.
* When pop is called, the previous render target is restored.
*/
this._renderTargetStack = [];
this._renderer = renderer;
}
/** called when dev wants to finish a render pass */
finishRenderPass() {
this.adaptor.finishRenderPass(this.renderTarget);
}
/**
* called when the renderer starts to render a scene.
* @param options
* @param options.target - the render target to render to
* @param options.clear - the clear mode to use. Can be true or a CLEAR number 'COLOR | DEPTH | STENCIL' 0b111
* @param options.clearColor - the color to clear to
* @param options.frame - the frame to render to
*/
renderStart({
target,
clear,
clearColor,
frame
}) {
this._renderTargetStack.length = 0;
this.push(
target,
clear,
clearColor,
frame
);
this.rootViewPort.copyFrom(this.viewport);
this.rootRenderTarget = this.renderTarget;
this.renderingToScreen = isRenderingToScreen(this.rootRenderTarget);
}
postrender() {
this.adaptor.postrender?.(this.rootRenderTarget);
}
/**
* Binding a render surface! This is the main function of the render target system.
* It will take the RenderSurface (which can be a texture, canvas, or render target) and bind it to the renderer.
* Once bound all draw calls will be rendered to the render surface.
*
* If a frame is not provide and the render surface is a texture, the frame of the texture will be used.
* @param renderSurface - the render surface to bind
* @param clear - the clear mode to use. Can be true or a CLEAR number 'COLOR | DEPTH | STENCIL' 0b111
* @param clearColor - the color to clear to
* @param frame - the frame to render to
* @returns the render target that was bound
*/
bind(renderSurface, clear = true, clearColor, frame) {
const renderTarget = this.getRenderTarget(renderSurface);
const didChange = this.renderTarget !== renderTarget;
this.renderTarget = renderTarget;
this.renderSurface = renderSurface;
const gpuRenderTarget = this.getGpuRenderTarget(renderTarget);
if (renderTarget.pixelWidth !== gpuRenderTarget.width || renderTarget.pixelHeight !== gpuRenderTarget.height) {
this.adaptor.resizeGpuRenderTarget(renderTarget);
gpuRenderTarget.width = renderTarget.pixelWidth;
gpuRenderTarget.height = renderTarget.pixelHeight;
}
const source = renderTarget.colorTexture;
const viewport = this.viewport;
const pixelWidth = source.pixelWidth;
const pixelHeight = source.pixelHeight;
if (!frame && renderSurface instanceof Texture) {
frame = renderSurface.frame;
}
if (frame) {
const resolution = source._resolution;
viewport.x = frame.x * resolution + 0.5 | 0;
viewport.y = frame.y * resolution + 0.5 | 0;
viewport.width = frame.width * resolution + 0.5 | 0;
viewport.height = frame.height * resolution + 0.5 | 0;
} else {
viewport.x = 0;
viewport.y = 0;
viewport.width = pixelWidth;
viewport.height = pixelHeight;
}
calculateProjection(
this.projectionMatrix,
0,
0,
viewport.width / source.resolution,
viewport.height / source.resolution,
!renderTarget.isRoot
);
this.adaptor.startRenderPass(renderTarget, clear, clearColor, viewport);
if (didChange) {
this.onRenderTargetChange.emit(renderTarget);
}
return renderTarget;
}
clear(target, clear = CLEAR.ALL, clearColor) {
if (!clear)
return;
if (target) {
target = this.getRenderTarget(target);
}
this.adaptor.clear(
target || this.renderTarget,
clear,
clearColor,
this.viewport
);
}
contextChange() {
this._gpuRenderTargetHash = /* @__PURE__ */ Object.create(null);
}
/**
* Push a render surface to the renderer. This will bind the render surface to the renderer,
* @param renderSurface - the render surface to push
* @param clear - the clear mode to use. Can be true or a CLEAR number 'COLOR | DEPTH | STENCIL' 0b111
* @param clearColor - the color to clear to
* @param frame - the frame to use when rendering to the render surface
*/
push(renderSurface, clear = CLEAR.ALL, clearColor, frame) {
const renderTarget = this.bind(renderSurface, clear, clearColor, frame);
this._renderTargetStack.push({
renderTarget,
frame
});
return renderTarget;
}
/** Pops the current render target from the renderer and restores the previous render target. */
pop() {
this._renderTargetStack.pop();
const currentRenderTargetData = this._renderTargetStack[this._renderTargetStack.length - 1];
this.bind(currentRenderTargetData.renderTarget, false, null, currentRenderTargetData.frame);
}
/**
* Gets the render target from the provide render surface. Eg if its a texture,
* it will return the render target for the texture.
* If its a render target, it will return the same render target.
* @param renderSurface - the render surface to get the render target for
* @returns the render target for the render surface
*/
getRenderTarget(renderSurface) {
if (renderSurface.isTexture) {
renderSurface = renderSurface.source;
}
return this._renderSurfaceToRenderTargetHash.get(renderSurface) ?? this._initRenderTarget(renderSurface);
}
/**
* Copies a render surface to another texture
* @param sourceRenderSurfaceTexture - the render surface to copy from
* @param destinationTexture - the texture to copy to
* @param originSrc - the origin of the copy
* @param originSrc.x - the x origin of the copy
* @param originSrc.y - the y origin of the copy
* @param size - the size of the copy
* @param size.width - the width of the copy
* @param size.height - the height of the copy
* @param originDest - the destination origin (top left to paste from!)
* @param originDest.x - the x origin of the paste
* @param originDest.y - the y origin of the paste
*/
copyToTexture(sourceRenderSurfaceTexture, destinationTexture, originSrc, size, originDest) {
if (originSrc.x < 0) {
size.width += originSrc.x;
originDest.x -= originSrc.x;
originSrc.x = 0;
}
if (originSrc.y < 0) {
size.height += originSrc.y;
originDest.y -= originSrc.y;
originSrc.y = 0;
}
const { pixelWidth, pixelHeight } = sourceRenderSurfaceTexture;
size.width = Math.min(size.width, pixelWidth - originSrc.x);
size.height = Math.min(size.height, pixelHeight - originSrc.y);
return this.adaptor.copyToTexture(
sourceRenderSurfaceTexture,
destinationTexture,
originSrc,
size,
originDest
);
}
/**
* ensures that we have a depth stencil buffer available to render to
* This is used by the mask system to make sure we have a stencil buffer.
*/
ensureDepthStencil() {
if (!this.renderTarget.stencil) {
this.renderTarget.stencil = true;
this.adaptor.startRenderPass(this.renderTarget, false, null, this.viewport);
}
}
/** nukes the render target system */
destroy() {
this._renderer = null;
this._renderSurfaceToRenderTargetHash.forEach((renderTarget, key) => {
if (renderTarget !== key) {
renderTarget.destroy();
}
});
this._renderSurfaceToRenderTargetHash.clear();
this._gpuRenderTargetHash = /* @__PURE__ */ Object.create(null);
}
_initRenderTarget(renderSurface) {
let renderTarget = null;
if (CanvasSource.test(renderSurface)) {
renderSurface = getCanvasTexture(renderSurface).source;
}
if (renderSurface instanceof RenderTarget) {
renderTarget = renderSurface;
} else if (renderSurface instanceof TextureSource) {
renderTarget = new RenderTarget({
colorTextures: [renderSurface]
});
if (CanvasSource.test(renderSurface.source.resource)) {
renderTarget.isRoot = true;
}
renderSurface.once("destroy", () => {
renderTarget.destroy();
this._renderSurfaceToRenderTargetHash.delete(renderSurface);
const gpuRenderTarget = this._gpuRenderTargetHash[renderTarget.uid];
if (gpuRenderTarget) {
this._gpuRenderTargetHash[renderTarget.uid] = null;
this.adaptor.destroyGpuRenderTarget(gpuRenderTarget);
}
});
}
this._renderSurfaceToRenderTargetHash.set(renderSurface, renderTarget);
return renderTarget;
}
getGpuRenderTarget(renderTarget) {
return this._gpuRenderTargetHash[renderTarget.uid] || (this._gpuRenderTargetHash[renderTarget.uid] = this.adaptor.initGpuRenderTarget(renderTarget));
}
}
export { RenderTargetSystem };
//# sourceMappingURL=RenderTargetSystem.mjs.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,8 @@
import type { RenderTarget } from './RenderTarget';
/**
* Checks if the render target is viewable on the screen
* Basically, is it a canvas element and is that canvas element in the DOM
* @param renderTarget - the render target to check
* @returns true if the render target is viewable on the screen
*/
export declare function isRenderingToScreen(renderTarget: RenderTarget): boolean;

View File

@@ -0,0 +1,10 @@
'use strict';
"use strict";
function isRenderingToScreen(renderTarget) {
const resource = renderTarget.colorTexture.source.resource;
return globalThis.HTMLCanvasElement && resource instanceof HTMLCanvasElement && document.body.contains(resource);
}
exports.isRenderingToScreen = isRenderingToScreen;
//# sourceMappingURL=isRenderingToScreen.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"isRenderingToScreen.js","sources":["../../../../../src/rendering/renderers/shared/renderTarget/isRenderingToScreen.ts"],"sourcesContent":["import type { RenderTarget } from './RenderTarget';\n\n/**\n * Checks if the render target is viewable on the screen\n * Basically, is it a canvas element and is that canvas element in the DOM\n * @param renderTarget - the render target to check\n * @returns true if the render target is viewable on the screen\n */\nexport function isRenderingToScreen(renderTarget: RenderTarget): boolean\n{\n const resource = renderTarget.colorTexture.source.resource;\n\n return ((globalThis.HTMLCanvasElement && resource instanceof HTMLCanvasElement) && document.body.contains(resource));\n}\n"],"names":[],"mappings":";;;AAQO,SAAS,oBAAoB,YACpC,EAAA;AACI,EAAM,MAAA,QAAA,GAAW,YAAa,CAAA,YAAA,CAAa,MAAO,CAAA,QAAA,CAAA;AAElD,EAAA,OAAS,WAAW,iBAAqB,IAAA,QAAA,YAAoB,qBAAsB,QAAS,CAAA,IAAA,CAAK,SAAS,QAAQ,CAAA,CAAA;AACtH;;;;"}

View File

@@ -0,0 +1,8 @@
"use strict";
function isRenderingToScreen(renderTarget) {
const resource = renderTarget.colorTexture.source.resource;
return globalThis.HTMLCanvasElement && resource instanceof HTMLCanvasElement && document.body.contains(resource);
}
export { isRenderingToScreen };
//# sourceMappingURL=isRenderingToScreen.mjs.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"isRenderingToScreen.mjs","sources":["../../../../../src/rendering/renderers/shared/renderTarget/isRenderingToScreen.ts"],"sourcesContent":["import type { RenderTarget } from './RenderTarget';\n\n/**\n * Checks if the render target is viewable on the screen\n * Basically, is it a canvas element and is that canvas element in the DOM\n * @param renderTarget - the render target to check\n * @returns true if the render target is viewable on the screen\n */\nexport function isRenderingToScreen(renderTarget: RenderTarget): boolean\n{\n const resource = renderTarget.colorTexture.source.resource;\n\n return ((globalThis.HTMLCanvasElement && resource instanceof HTMLCanvasElement) && document.body.contains(resource));\n}\n"],"names":[],"mappings":";AAQO,SAAS,oBAAoB,YACpC,EAAA;AACI,EAAM,MAAA,QAAA,GAAW,YAAa,CAAA,YAAA,CAAa,MAAO,CAAA,QAAA,CAAA;AAElD,EAAA,OAAS,WAAW,iBAAqB,IAAA,QAAA,YAAoB,qBAAsB,QAAS,CAAA,IAAA,CAAK,SAAS,QAAQ,CAAA,CAAA;AACtH;;;;"}

View File

@@ -0,0 +1,11 @@
import { Rectangle } from '../../../../maths/shapes/Rectangle';
import type { TextureSource } from '../texture/sources/TextureSource';
/**
* Takes a Texture source and a normalised frame
* and returns a viewport for that frame.
* @param viewport - The viewport rectangle to set.
* @param source - The source to get the pixel width and height from.
* @param frame - The frame to get the viewport from.
* @returns the passed in viewport.
*/
export declare function viewportFromFrame(viewport: Rectangle, source: TextureSource, frame?: Rectangle): Rectangle;

View File

@@ -0,0 +1,19 @@
'use strict';
var Rectangle = require('../../../../maths/shapes/Rectangle.js');
"use strict";
const fullFrame = new Rectangle.Rectangle(0, 0, 1, 1);
function viewportFromFrame(viewport, source, frame) {
frame || (frame = fullFrame);
const pixelWidth = source.pixelWidth;
const pixelHeight = source.pixelHeight;
viewport.x = frame.x * pixelWidth | 0;
viewport.y = frame.y * pixelHeight | 0;
viewport.width = frame.width * pixelWidth | 0;
viewport.height = frame.height * pixelHeight | 0;
return viewport;
}
exports.viewportFromFrame = viewportFromFrame;
//# sourceMappingURL=viewportFromFrame.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"viewportFromFrame.js","sources":["../../../../../src/rendering/renderers/shared/renderTarget/viewportFromFrame.ts"],"sourcesContent":["import { Rectangle } from '../../../../maths/shapes/Rectangle';\n\nimport type { TextureSource } from '../texture/sources/TextureSource';\n\nconst fullFrame = new Rectangle(0, 0, 1, 1);\n\n/**\n * Takes a Texture source and a normalised frame\n * and returns a viewport for that frame.\n * @param viewport - The viewport rectangle to set.\n * @param source - The source to get the pixel width and height from.\n * @param frame - The frame to get the viewport from.\n * @returns the passed in viewport.\n */\nexport function viewportFromFrame(\n viewport: Rectangle,\n source: TextureSource,\n frame?: Rectangle\n)\n{\n frame ||= fullFrame;\n\n const pixelWidth = source.pixelWidth;\n const pixelHeight = source.pixelHeight;\n\n viewport.x = (frame.x * pixelWidth) | 0;\n viewport.y = (frame.y * pixelHeight) | 0;\n viewport.width = (frame.width * pixelWidth) | 0;\n viewport.height = (frame.height * pixelHeight) | 0;\n\n return viewport;\n}\n"],"names":["Rectangle"],"mappings":";;;;;AAIA,MAAM,YAAY,IAAIA,mBAAA,CAAU,CAAG,EAAA,CAAA,EAAG,GAAG,CAAC,CAAA,CAAA;AAU1B,SAAA,iBAAA,CACZ,QACA,EAAA,MAAA,EACA,KAEJ,EAAA;AACI,EAAU,KAAA,KAAA,KAAA,GAAA,SAAA,CAAA,CAAA;AAEV,EAAA,MAAM,aAAa,MAAO,CAAA,UAAA,CAAA;AAC1B,EAAA,MAAM,cAAc,MAAO,CAAA,WAAA,CAAA;AAE3B,EAAS,QAAA,CAAA,CAAA,GAAK,KAAM,CAAA,CAAA,GAAI,UAAc,GAAA,CAAA,CAAA;AACtC,EAAS,QAAA,CAAA,CAAA,GAAK,KAAM,CAAA,CAAA,GAAI,WAAe,GAAA,CAAA,CAAA;AACvC,EAAS,QAAA,CAAA,KAAA,GAAS,KAAM,CAAA,KAAA,GAAQ,UAAc,GAAA,CAAA,CAAA;AAC9C,EAAS,QAAA,CAAA,MAAA,GAAU,KAAM,CAAA,MAAA,GAAS,WAAe,GAAA,CAAA,CAAA;AAEjD,EAAO,OAAA,QAAA,CAAA;AACX;;;;"}

View File

@@ -0,0 +1,17 @@
import { Rectangle } from '../../../../maths/shapes/Rectangle.mjs';
"use strict";
const fullFrame = new Rectangle(0, 0, 1, 1);
function viewportFromFrame(viewport, source, frame) {
frame || (frame = fullFrame);
const pixelWidth = source.pixelWidth;
const pixelHeight = source.pixelHeight;
viewport.x = frame.x * pixelWidth | 0;
viewport.y = frame.y * pixelHeight | 0;
viewport.width = frame.width * pixelWidth | 0;
viewport.height = frame.height * pixelHeight | 0;
return viewport;
}
export { viewportFromFrame };
//# sourceMappingURL=viewportFromFrame.mjs.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"viewportFromFrame.mjs","sources":["../../../../../src/rendering/renderers/shared/renderTarget/viewportFromFrame.ts"],"sourcesContent":["import { Rectangle } from '../../../../maths/shapes/Rectangle';\n\nimport type { TextureSource } from '../texture/sources/TextureSource';\n\nconst fullFrame = new Rectangle(0, 0, 1, 1);\n\n/**\n * Takes a Texture source and a normalised frame\n * and returns a viewport for that frame.\n * @param viewport - The viewport rectangle to set.\n * @param source - The source to get the pixel width and height from.\n * @param frame - The frame to get the viewport from.\n * @returns the passed in viewport.\n */\nexport function viewportFromFrame(\n viewport: Rectangle,\n source: TextureSource,\n frame?: Rectangle\n)\n{\n frame ||= fullFrame;\n\n const pixelWidth = source.pixelWidth;\n const pixelHeight = source.pixelHeight;\n\n viewport.x = (frame.x * pixelWidth) | 0;\n viewport.y = (frame.y * pixelHeight) | 0;\n viewport.width = (frame.width * pixelWidth) | 0;\n viewport.height = (frame.height * pixelHeight) | 0;\n\n return viewport;\n}\n"],"names":[],"mappings":";;;AAIA,MAAM,YAAY,IAAI,SAAA,CAAU,CAAG,EAAA,CAAA,EAAG,GAAG,CAAC,CAAA,CAAA;AAU1B,SAAA,iBAAA,CACZ,QACA,EAAA,MAAA,EACA,KAEJ,EAAA;AACI,EAAU,KAAA,KAAA,KAAA,GAAA,SAAA,CAAA,CAAA;AAEV,EAAA,MAAM,aAAa,MAAO,CAAA,UAAA,CAAA;AAC1B,EAAA,MAAM,cAAc,MAAO,CAAA,WAAA,CAAA;AAE3B,EAAS,QAAA,CAAA,CAAA,GAAK,KAAM,CAAA,CAAA,GAAI,UAAc,GAAA,CAAA,CAAA;AACtC,EAAS,QAAA,CAAA,CAAA,GAAK,KAAM,CAAA,CAAA,GAAI,WAAe,GAAA,CAAA,CAAA;AACvC,EAAS,QAAA,CAAA,KAAA,GAAS,KAAM,CAAA,KAAA,GAAQ,UAAc,GAAA,CAAA,CAAA;AAC9C,EAAS,QAAA,CAAA,MAAA,GAAU,KAAM,CAAA,MAAA,GAAS,WAAe,GAAA,CAAA,CAAA;AAEjD,EAAO,OAAA,QAAA,CAAA;AACX;;;;"}