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,75 @@
declare global
{
namespace PixiMixins
{
// eslint-disable-next-line @typescript-eslint/no-empty-interface
interface ICanvas
{
}
// eslint-disable-next-line @typescript-eslint/no-empty-interface
interface RendererOptions
{
resolution?: number;
failIfMajorPerformanceCaveat?: boolean;
roundPixels?: boolean;
}
// eslint-disable-next-line @typescript-eslint/no-empty-interface
interface WebGLOptions
{
}
// eslint-disable-next-line @typescript-eslint/no-empty-interface
interface WebGPUOptions
{
}
// eslint-disable-next-line @typescript-eslint/no-empty-interface
interface RendererSystems
{
}
// eslint-disable-next-line @typescript-eslint/no-empty-interface
interface WebGLSystems
{
}
// eslint-disable-next-line @typescript-eslint/no-empty-interface
interface WebGPUSystems
{
}
// eslint-disable-next-line @typescript-eslint/no-empty-interface
interface CanvasSystems
{
}
// eslint-disable-next-line @typescript-eslint/no-empty-interface
interface RendererPipes
{
}
// eslint-disable-next-line @typescript-eslint/no-empty-interface
interface WebGLPipes
{
}
// eslint-disable-next-line @typescript-eslint/no-empty-interface
interface WebGPUPipes
{
}
// eslint-disable-next-line @typescript-eslint/no-empty-interface
interface CanvasPipes
{
}
}
}
export {};

View File

@@ -0,0 +1,23 @@
import { ExtensionType } from '../../../extensions/Extensions';
import type { Geometry } from '../../renderers/shared/geometry/Geometry';
import type { Shader } from '../../renderers/shared/shader/Shader';
import type { Batch } from '../shared/Batcher';
import type { BatcherAdaptor, BatcherPipe } from '../shared/BatcherPipe';
/**
* A BatcherAdaptor that uses WebGL to render batches.
* @memberof rendering
* @ignore
*/
export declare class GlBatchAdaptor implements BatcherAdaptor {
/** @ignore */
static extension: {
readonly type: readonly [ExtensionType.WebGLPipesAdaptor];
readonly name: "batch";
};
private _didUpload;
private readonly _tempState;
init(batcherPipe: BatcherPipe): void;
contextChange(): void;
start(batchPipe: BatcherPipe, geometry: Geometry, shader: Shader): void;
execute(batchPipe: BatcherPipe, batch: Batch): void;
}

View File

@@ -0,0 +1,45 @@
'use strict';
var Extensions = require('../../../extensions/Extensions.js');
var State = require('../../renderers/shared/state/State.js');
"use strict";
class GlBatchAdaptor {
constructor() {
this._didUpload = false;
this._tempState = State.State.for2d();
}
init(batcherPipe) {
batcherPipe.renderer.runners.contextChange.add(this);
}
contextChange() {
this._didUpload = false;
}
start(batchPipe, geometry, shader) {
const renderer = batchPipe.renderer;
renderer.shader.bind(shader, this._didUpload);
renderer.shader.updateUniformGroup(renderer.globalUniforms.uniformGroup);
renderer.geometry.bind(geometry, shader.glProgram);
}
execute(batchPipe, batch) {
const renderer = batchPipe.renderer;
this._didUpload = true;
this._tempState.blendMode = batch.blendMode;
renderer.state.set(this._tempState);
const textures = batch.textures.textures;
for (let i = 0; i < batch.textures.count; i++) {
renderer.texture.bind(textures[i], i);
}
renderer.geometry.draw("triangle-list", batch.size, batch.start);
}
}
/** @ignore */
GlBatchAdaptor.extension = {
type: [
Extensions.ExtensionType.WebGLPipesAdaptor
],
name: "batch"
};
exports.GlBatchAdaptor = GlBatchAdaptor;
//# sourceMappingURL=GlBatchAdaptor.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"GlBatchAdaptor.js","sources":["../../../../src/rendering/batcher/gl/GlBatchAdaptor.ts"],"sourcesContent":["import { ExtensionType } from '../../../extensions/Extensions';\nimport { State } from '../../renderers/shared/state/State';\n\nimport type { WebGLRenderer } from '../../renderers/gl/WebGLRenderer';\nimport type { Geometry } from '../../renderers/shared/geometry/Geometry';\nimport type { Shader } from '../../renderers/shared/shader/Shader';\nimport type { Batch } from '../shared/Batcher';\nimport type { BatcherAdaptor, BatcherPipe } from '../shared/BatcherPipe';\n\n/**\n * A BatcherAdaptor that uses WebGL to render batches.\n * @memberof rendering\n * @ignore\n */\nexport class GlBatchAdaptor implements BatcherAdaptor\n{\n /** @ignore */\n public static extension = {\n type: [\n ExtensionType.WebGLPipesAdaptor,\n ],\n name: 'batch',\n } as const;\n\n private _didUpload = false;\n private readonly _tempState = State.for2d();\n\n public init(batcherPipe: BatcherPipe): void\n {\n batcherPipe.renderer.runners.contextChange.add(this);\n }\n\n public contextChange(): void\n {\n this._didUpload = false;\n }\n\n public start(batchPipe: BatcherPipe, geometry: Geometry, shader: Shader): void\n {\n const renderer = batchPipe.renderer as WebGLRenderer;\n\n // only want to sync the shade ron its first bind!\n renderer.shader.bind(shader, this._didUpload);\n\n renderer.shader.updateUniformGroup(renderer.globalUniforms.uniformGroup);\n\n renderer.geometry.bind(geometry, shader.glProgram);\n }\n\n public execute(batchPipe: BatcherPipe, batch: Batch): void\n {\n const renderer = batchPipe.renderer as WebGLRenderer;\n\n this._didUpload = true;\n\n this._tempState.blendMode = batch.blendMode;\n\n renderer.state.set(this._tempState);\n\n const textures = batch.textures.textures;\n\n for (let i = 0; i < batch.textures.count; i++)\n {\n renderer.texture.bind(textures[i], i);\n }\n\n renderer.geometry.draw('triangle-list', batch.size, batch.start);\n }\n}\n"],"names":["State","ExtensionType"],"mappings":";;;;;;AAcO,MAAM,cACb,CAAA;AAAA,EADO,WAAA,GAAA;AAUH,IAAA,IAAA,CAAQ,UAAa,GAAA,KAAA,CAAA;AACrB,IAAiB,IAAA,CAAA,UAAA,GAAaA,YAAM,KAAM,EAAA,CAAA;AAAA,GAAA;AAAA,EAEnC,KAAK,WACZ,EAAA;AACI,IAAA,WAAA,CAAY,QAAS,CAAA,OAAA,CAAQ,aAAc,CAAA,GAAA,CAAI,IAAI,CAAA,CAAA;AAAA,GACvD;AAAA,EAEO,aACP,GAAA;AACI,IAAA,IAAA,CAAK,UAAa,GAAA,KAAA,CAAA;AAAA,GACtB;AAAA,EAEO,KAAA,CAAM,SAAwB,EAAA,QAAA,EAAoB,MACzD,EAAA;AACI,IAAA,MAAM,WAAW,SAAU,CAAA,QAAA,CAAA;AAG3B,IAAA,QAAA,CAAS,MAAO,CAAA,IAAA,CAAK,MAAQ,EAAA,IAAA,CAAK,UAAU,CAAA,CAAA;AAE5C,IAAA,QAAA,CAAS,MAAO,CAAA,kBAAA,CAAmB,QAAS,CAAA,cAAA,CAAe,YAAY,CAAA,CAAA;AAEvE,IAAA,QAAA,CAAS,QAAS,CAAA,IAAA,CAAK,QAAU,EAAA,MAAA,CAAO,SAAS,CAAA,CAAA;AAAA,GACrD;AAAA,EAEO,OAAA,CAAQ,WAAwB,KACvC,EAAA;AACI,IAAA,MAAM,WAAW,SAAU,CAAA,QAAA,CAAA;AAE3B,IAAA,IAAA,CAAK,UAAa,GAAA,IAAA,CAAA;AAElB,IAAK,IAAA,CAAA,UAAA,CAAW,YAAY,KAAM,CAAA,SAAA,CAAA;AAElC,IAAS,QAAA,CAAA,KAAA,CAAM,GAAI,CAAA,IAAA,CAAK,UAAU,CAAA,CAAA;AAElC,IAAM,MAAA,QAAA,GAAW,MAAM,QAAS,CAAA,QAAA,CAAA;AAEhC,IAAA,KAAA,IAAS,IAAI,CAAG,EAAA,CAAA,GAAI,KAAM,CAAA,QAAA,CAAS,OAAO,CAC1C,EAAA,EAAA;AACI,MAAA,QAAA,CAAS,OAAQ,CAAA,IAAA,CAAK,QAAS,CAAA,CAAC,GAAG,CAAC,CAAA,CAAA;AAAA,KACxC;AAEA,IAAA,QAAA,CAAS,SAAS,IAAK,CAAA,eAAA,EAAiB,KAAM,CAAA,IAAA,EAAM,MAAM,KAAK,CAAA,CAAA;AAAA,GACnE;AACJ,CAAA;AAAA;AAtDa,cAAA,CAGK,SAAY,GAAA;AAAA,EACtB,IAAM,EAAA;AAAA,IACFC,wBAAc,CAAA,iBAAA;AAAA,GAClB;AAAA,EACA,IAAM,EAAA,OAAA;AACV,CAAA;;;;"}

View File

@@ -0,0 +1,43 @@
import { ExtensionType } from '../../../extensions/Extensions.mjs';
import { State } from '../../renderers/shared/state/State.mjs';
"use strict";
class GlBatchAdaptor {
constructor() {
this._didUpload = false;
this._tempState = State.for2d();
}
init(batcherPipe) {
batcherPipe.renderer.runners.contextChange.add(this);
}
contextChange() {
this._didUpload = false;
}
start(batchPipe, geometry, shader) {
const renderer = batchPipe.renderer;
renderer.shader.bind(shader, this._didUpload);
renderer.shader.updateUniformGroup(renderer.globalUniforms.uniformGroup);
renderer.geometry.bind(geometry, shader.glProgram);
}
execute(batchPipe, batch) {
const renderer = batchPipe.renderer;
this._didUpload = true;
this._tempState.blendMode = batch.blendMode;
renderer.state.set(this._tempState);
const textures = batch.textures.textures;
for (let i = 0; i < batch.textures.count; i++) {
renderer.texture.bind(textures[i], i);
}
renderer.geometry.draw("triangle-list", batch.size, batch.start);
}
}
/** @ignore */
GlBatchAdaptor.extension = {
type: [
ExtensionType.WebGLPipesAdaptor
],
name: "batch"
};
export { GlBatchAdaptor };
//# sourceMappingURL=GlBatchAdaptor.mjs.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"GlBatchAdaptor.mjs","sources":["../../../../src/rendering/batcher/gl/GlBatchAdaptor.ts"],"sourcesContent":["import { ExtensionType } from '../../../extensions/Extensions';\nimport { State } from '../../renderers/shared/state/State';\n\nimport type { WebGLRenderer } from '../../renderers/gl/WebGLRenderer';\nimport type { Geometry } from '../../renderers/shared/geometry/Geometry';\nimport type { Shader } from '../../renderers/shared/shader/Shader';\nimport type { Batch } from '../shared/Batcher';\nimport type { BatcherAdaptor, BatcherPipe } from '../shared/BatcherPipe';\n\n/**\n * A BatcherAdaptor that uses WebGL to render batches.\n * @memberof rendering\n * @ignore\n */\nexport class GlBatchAdaptor implements BatcherAdaptor\n{\n /** @ignore */\n public static extension = {\n type: [\n ExtensionType.WebGLPipesAdaptor,\n ],\n name: 'batch',\n } as const;\n\n private _didUpload = false;\n private readonly _tempState = State.for2d();\n\n public init(batcherPipe: BatcherPipe): void\n {\n batcherPipe.renderer.runners.contextChange.add(this);\n }\n\n public contextChange(): void\n {\n this._didUpload = false;\n }\n\n public start(batchPipe: BatcherPipe, geometry: Geometry, shader: Shader): void\n {\n const renderer = batchPipe.renderer as WebGLRenderer;\n\n // only want to sync the shade ron its first bind!\n renderer.shader.bind(shader, this._didUpload);\n\n renderer.shader.updateUniformGroup(renderer.globalUniforms.uniformGroup);\n\n renderer.geometry.bind(geometry, shader.glProgram);\n }\n\n public execute(batchPipe: BatcherPipe, batch: Batch): void\n {\n const renderer = batchPipe.renderer as WebGLRenderer;\n\n this._didUpload = true;\n\n this._tempState.blendMode = batch.blendMode;\n\n renderer.state.set(this._tempState);\n\n const textures = batch.textures.textures;\n\n for (let i = 0; i < batch.textures.count; i++)\n {\n renderer.texture.bind(textures[i], i);\n }\n\n renderer.geometry.draw('triangle-list', batch.size, batch.start);\n }\n}\n"],"names":[],"mappings":";;;;AAcO,MAAM,cACb,CAAA;AAAA,EADO,WAAA,GAAA;AAUH,IAAA,IAAA,CAAQ,UAAa,GAAA,KAAA,CAAA;AACrB,IAAiB,IAAA,CAAA,UAAA,GAAa,MAAM,KAAM,EAAA,CAAA;AAAA,GAAA;AAAA,EAEnC,KAAK,WACZ,EAAA;AACI,IAAA,WAAA,CAAY,QAAS,CAAA,OAAA,CAAQ,aAAc,CAAA,GAAA,CAAI,IAAI,CAAA,CAAA;AAAA,GACvD;AAAA,EAEO,aACP,GAAA;AACI,IAAA,IAAA,CAAK,UAAa,GAAA,KAAA,CAAA;AAAA,GACtB;AAAA,EAEO,KAAA,CAAM,SAAwB,EAAA,QAAA,EAAoB,MACzD,EAAA;AACI,IAAA,MAAM,WAAW,SAAU,CAAA,QAAA,CAAA;AAG3B,IAAA,QAAA,CAAS,MAAO,CAAA,IAAA,CAAK,MAAQ,EAAA,IAAA,CAAK,UAAU,CAAA,CAAA;AAE5C,IAAA,QAAA,CAAS,MAAO,CAAA,kBAAA,CAAmB,QAAS,CAAA,cAAA,CAAe,YAAY,CAAA,CAAA;AAEvE,IAAA,QAAA,CAAS,QAAS,CAAA,IAAA,CAAK,QAAU,EAAA,MAAA,CAAO,SAAS,CAAA,CAAA;AAAA,GACrD;AAAA,EAEO,OAAA,CAAQ,WAAwB,KACvC,EAAA;AACI,IAAA,MAAM,WAAW,SAAU,CAAA,QAAA,CAAA;AAE3B,IAAA,IAAA,CAAK,UAAa,GAAA,IAAA,CAAA;AAElB,IAAK,IAAA,CAAA,UAAA,CAAW,YAAY,KAAM,CAAA,SAAA,CAAA;AAElC,IAAS,QAAA,CAAA,KAAA,CAAM,GAAI,CAAA,IAAA,CAAK,UAAU,CAAA,CAAA;AAElC,IAAM,MAAA,QAAA,GAAW,MAAM,QAAS,CAAA,QAAA,CAAA;AAEhC,IAAA,KAAA,IAAS,IAAI,CAAG,EAAA,CAAA,GAAI,KAAM,CAAA,QAAA,CAAS,OAAO,CAC1C,EAAA,EAAA;AACI,MAAA,QAAA,CAAS,OAAQ,CAAA,IAAA,CAAK,QAAS,CAAA,CAAC,GAAG,CAAC,CAAA,CAAA;AAAA,KACxC;AAEA,IAAA,QAAA,CAAS,SAAS,IAAK,CAAA,eAAA,EAAiB,KAAM,CAAA,IAAA,EAAM,MAAM,KAAK,CAAA,CAAA;AAAA,GACnE;AACJ,CAAA;AAAA;AAtDa,cAAA,CAGK,SAAY,GAAA;AAAA,EACtB,IAAM,EAAA;AAAA,IACF,aAAc,CAAA,iBAAA;AAAA,GAClB;AAAA,EACA,IAAM,EAAA,OAAA;AACV,CAAA;;;;"}

View File

@@ -0,0 +1,2 @@
import type { GlRenderingContext } from '../../../renderers/gl/context/GlRenderingContext';
export declare function checkMaxIfStatementsInShader(maxIfs: number, gl: GlRenderingContext): number;

View File

@@ -0,0 +1,47 @@
'use strict';
"use strict";
const fragTemplate = [
"precision mediump float;",
"void main(void){",
"float test = 0.1;",
"%forloop%",
"gl_FragColor = vec4(0.0);",
"}"
].join("\n");
function generateIfTestSrc(maxIfs) {
let src = "";
for (let i = 0; i < maxIfs; ++i) {
if (i > 0) {
src += "\nelse ";
}
if (i < maxIfs - 1) {
src += `if(test == ${i}.0){}`;
}
}
return src;
}
function checkMaxIfStatementsInShader(maxIfs, gl) {
if (maxIfs === 0) {
throw new Error("Invalid value of `0` passed to `checkMaxIfStatementsInShader`");
}
const shader = gl.createShader(gl.FRAGMENT_SHADER);
try {
while (true) {
const fragmentSrc = fragTemplate.replace(/%forloop%/gi, generateIfTestSrc(maxIfs));
gl.shaderSource(shader, fragmentSrc);
gl.compileShader(shader);
if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
maxIfs = maxIfs / 2 | 0;
} else {
break;
}
}
} finally {
gl.deleteShader(shader);
}
return maxIfs;
}
exports.checkMaxIfStatementsInShader = checkMaxIfStatementsInShader;
//# sourceMappingURL=checkMaxIfStatementsInShader.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"checkMaxIfStatementsInShader.js","sources":["../../../../../src/rendering/batcher/gl/utils/checkMaxIfStatementsInShader.ts"],"sourcesContent":["import type { GlRenderingContext } from '../../../renderers/gl/context/GlRenderingContext';\n\nconst fragTemplate = [\n 'precision mediump float;',\n 'void main(void){',\n 'float test = 0.1;',\n '%forloop%',\n 'gl_FragColor = vec4(0.0);',\n '}',\n].join('\\n');\n\nfunction generateIfTestSrc(maxIfs: number): string\n{\n let src = '';\n\n for (let i = 0; i < maxIfs; ++i)\n {\n if (i > 0)\n {\n src += '\\nelse ';\n }\n\n if (i < maxIfs - 1)\n {\n src += `if(test == ${i}.0){}`;\n }\n }\n\n return src;\n}\n\nexport function checkMaxIfStatementsInShader(maxIfs: number, gl: GlRenderingContext): number\n{\n if (maxIfs === 0)\n {\n throw new Error('Invalid value of `0` passed to `checkMaxIfStatementsInShader`');\n }\n\n const shader = gl.createShader(gl.FRAGMENT_SHADER);\n\n try\n {\n while (true) // eslint-disable-line no-constant-condition\n {\n const fragmentSrc = fragTemplate.replace(/%forloop%/gi, generateIfTestSrc(maxIfs));\n\n gl.shaderSource(shader, fragmentSrc);\n gl.compileShader(shader);\n\n if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS))\n {\n maxIfs = (maxIfs / 2) | 0;\n }\n else\n {\n // valid!\n break;\n }\n }\n }\n finally\n {\n gl.deleteShader(shader);\n }\n\n return maxIfs;\n}\n"],"names":[],"mappings":";;;AAEA,MAAM,YAAe,GAAA;AAAA,EACjB,0BAAA;AAAA,EACA,kBAAA;AAAA,EACA,mBAAA;AAAA,EACA,WAAA;AAAA,EACA,2BAAA;AAAA,EACA,GAAA;AACJ,CAAA,CAAE,KAAK,IAAI,CAAA,CAAA;AAEX,SAAS,kBAAkB,MAC3B,EAAA;AACI,EAAA,IAAI,GAAM,GAAA,EAAA,CAAA;AAEV,EAAA,KAAA,IAAS,CAAI,GAAA,CAAA,EAAG,CAAI,GAAA,MAAA,EAAQ,EAAE,CAC9B,EAAA;AACI,IAAA,IAAI,IAAI,CACR,EAAA;AACI,MAAO,GAAA,IAAA,SAAA,CAAA;AAAA,KACX;AAEA,IAAI,IAAA,CAAA,GAAI,SAAS,CACjB,EAAA;AACI,MAAA,GAAA,IAAO,cAAc,CAAC,CAAA,KAAA,CAAA,CAAA;AAAA,KAC1B;AAAA,GACJ;AAEA,EAAO,OAAA,GAAA,CAAA;AACX,CAAA;AAEgB,SAAA,4BAAA,CAA6B,QAAgB,EAC7D,EAAA;AACI,EAAA,IAAI,WAAW,CACf,EAAA;AACI,IAAM,MAAA,IAAI,MAAM,+DAA+D,CAAA,CAAA;AAAA,GACnF;AAEA,EAAA,MAAM,MAAS,GAAA,EAAA,CAAG,YAAa,CAAA,EAAA,CAAG,eAAe,CAAA,CAAA;AAEjD,EACA,IAAA;AACI,IAAA,OAAO,IACP,EAAA;AACI,MAAA,MAAM,cAAc,YAAa,CAAA,OAAA,CAAQ,aAAe,EAAA,iBAAA,CAAkB,MAAM,CAAC,CAAA,CAAA;AAEjF,MAAG,EAAA,CAAA,YAAA,CAAa,QAAQ,WAAW,CAAA,CAAA;AACnC,MAAA,EAAA,CAAG,cAAc,MAAM,CAAA,CAAA;AAEvB,MAAA,IAAI,CAAC,EAAG,CAAA,kBAAA,CAAmB,MAAQ,EAAA,EAAA,CAAG,cAAc,CACpD,EAAA;AACI,QAAA,MAAA,GAAU,SAAS,CAAK,GAAA,CAAA,CAAA;AAAA,OAG5B,MAAA;AAEI,QAAA,MAAA;AAAA,OACJ;AAAA,KACJ;AAAA,GAEJ,SAAA;AAEI,IAAA,EAAA,CAAG,aAAa,MAAM,CAAA,CAAA;AAAA,GAC1B;AAEA,EAAO,OAAA,MAAA,CAAA;AACX;;;;"}

View File

@@ -0,0 +1,45 @@
"use strict";
const fragTemplate = [
"precision mediump float;",
"void main(void){",
"float test = 0.1;",
"%forloop%",
"gl_FragColor = vec4(0.0);",
"}"
].join("\n");
function generateIfTestSrc(maxIfs) {
let src = "";
for (let i = 0; i < maxIfs; ++i) {
if (i > 0) {
src += "\nelse ";
}
if (i < maxIfs - 1) {
src += `if(test == ${i}.0){}`;
}
}
return src;
}
function checkMaxIfStatementsInShader(maxIfs, gl) {
if (maxIfs === 0) {
throw new Error("Invalid value of `0` passed to `checkMaxIfStatementsInShader`");
}
const shader = gl.createShader(gl.FRAGMENT_SHADER);
try {
while (true) {
const fragmentSrc = fragTemplate.replace(/%forloop%/gi, generateIfTestSrc(maxIfs));
gl.shaderSource(shader, fragmentSrc);
gl.compileShader(shader);
if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
maxIfs = maxIfs / 2 | 0;
} else {
break;
}
}
} finally {
gl.deleteShader(shader);
}
return maxIfs;
}
export { checkMaxIfStatementsInShader };
//# sourceMappingURL=checkMaxIfStatementsInShader.mjs.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"checkMaxIfStatementsInShader.mjs","sources":["../../../../../src/rendering/batcher/gl/utils/checkMaxIfStatementsInShader.ts"],"sourcesContent":["import type { GlRenderingContext } from '../../../renderers/gl/context/GlRenderingContext';\n\nconst fragTemplate = [\n 'precision mediump float;',\n 'void main(void){',\n 'float test = 0.1;',\n '%forloop%',\n 'gl_FragColor = vec4(0.0);',\n '}',\n].join('\\n');\n\nfunction generateIfTestSrc(maxIfs: number): string\n{\n let src = '';\n\n for (let i = 0; i < maxIfs; ++i)\n {\n if (i > 0)\n {\n src += '\\nelse ';\n }\n\n if (i < maxIfs - 1)\n {\n src += `if(test == ${i}.0){}`;\n }\n }\n\n return src;\n}\n\nexport function checkMaxIfStatementsInShader(maxIfs: number, gl: GlRenderingContext): number\n{\n if (maxIfs === 0)\n {\n throw new Error('Invalid value of `0` passed to `checkMaxIfStatementsInShader`');\n }\n\n const shader = gl.createShader(gl.FRAGMENT_SHADER);\n\n try\n {\n while (true) // eslint-disable-line no-constant-condition\n {\n const fragmentSrc = fragTemplate.replace(/%forloop%/gi, generateIfTestSrc(maxIfs));\n\n gl.shaderSource(shader, fragmentSrc);\n gl.compileShader(shader);\n\n if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS))\n {\n maxIfs = (maxIfs / 2) | 0;\n }\n else\n {\n // valid!\n break;\n }\n }\n }\n finally\n {\n gl.deleteShader(shader);\n }\n\n return maxIfs;\n}\n"],"names":[],"mappings":";AAEA,MAAM,YAAe,GAAA;AAAA,EACjB,0BAAA;AAAA,EACA,kBAAA;AAAA,EACA,mBAAA;AAAA,EACA,WAAA;AAAA,EACA,2BAAA;AAAA,EACA,GAAA;AACJ,CAAA,CAAE,KAAK,IAAI,CAAA,CAAA;AAEX,SAAS,kBAAkB,MAC3B,EAAA;AACI,EAAA,IAAI,GAAM,GAAA,EAAA,CAAA;AAEV,EAAA,KAAA,IAAS,CAAI,GAAA,CAAA,EAAG,CAAI,GAAA,MAAA,EAAQ,EAAE,CAC9B,EAAA;AACI,IAAA,IAAI,IAAI,CACR,EAAA;AACI,MAAO,GAAA,IAAA,SAAA,CAAA;AAAA,KACX;AAEA,IAAI,IAAA,CAAA,GAAI,SAAS,CACjB,EAAA;AACI,MAAA,GAAA,IAAO,cAAc,CAAC,CAAA,KAAA,CAAA,CAAA;AAAA,KAC1B;AAAA,GACJ;AAEA,EAAO,OAAA,GAAA,CAAA;AACX,CAAA;AAEgB,SAAA,4BAAA,CAA6B,QAAgB,EAC7D,EAAA;AACI,EAAA,IAAI,WAAW,CACf,EAAA;AACI,IAAM,MAAA,IAAI,MAAM,+DAA+D,CAAA,CAAA;AAAA,GACnF;AAEA,EAAA,MAAM,MAAS,GAAA,EAAA,CAAG,YAAa,CAAA,EAAA,CAAG,eAAe,CAAA,CAAA;AAEjD,EACA,IAAA;AACI,IAAA,OAAO,IACP,EAAA;AACI,MAAA,MAAM,cAAc,YAAa,CAAA,OAAA,CAAQ,aAAe,EAAA,iBAAA,CAAkB,MAAM,CAAC,CAAA,CAAA;AAEjF,MAAG,EAAA,CAAA,YAAA,CAAa,QAAQ,WAAW,CAAA,CAAA;AACnC,MAAA,EAAA,CAAG,cAAc,MAAM,CAAA,CAAA;AAEvB,MAAA,IAAI,CAAC,EAAG,CAAA,kBAAA,CAAmB,MAAQ,EAAA,EAAA,CAAG,cAAc,CACpD,EAAA;AACI,QAAA,MAAA,GAAU,SAAS,CAAK,GAAA,CAAA,CAAA;AAAA,OAG5B,MAAA;AAEI,QAAA,MAAA;AAAA,OACJ;AAAA,KACJ;AAAA,GAEJ,SAAA;AAEI,IAAA,EAAA,CAAG,aAAa,MAAM,CAAA,CAAA;AAAA,GAC1B;AAEA,EAAO,OAAA,MAAA,CAAA;AACX;;;;"}

View File

@@ -0,0 +1,8 @@
/**
* Returns the maximum number of textures that can be batched. This uses WebGL1's `MAX_TEXTURE_IMAGE_UNITS`.
* The response for this is that to get this info via WebGPU, we would need to make a context, which
* would make this function async, and we want to avoid that.
* @private
* @returns {number} The maximum number of textures that can be batched
*/
export declare function getMaxTexturesPerBatch(): number;

View File

@@ -0,0 +1,22 @@
'use strict';
var getTestContext = require('../../../renderers/gl/shader/program/getTestContext.js');
var checkMaxIfStatementsInShader = require('./checkMaxIfStatementsInShader.js');
"use strict";
let maxTexturesPerBatchCache = null;
function getMaxTexturesPerBatch() {
if (maxTexturesPerBatchCache)
return maxTexturesPerBatchCache;
const gl = getTestContext.getTestContext();
maxTexturesPerBatchCache = gl.getParameter(gl.MAX_TEXTURE_IMAGE_UNITS);
maxTexturesPerBatchCache = checkMaxIfStatementsInShader.checkMaxIfStatementsInShader(
maxTexturesPerBatchCache,
gl
);
gl.getExtension("WEBGL_lose_context")?.loseContext();
return maxTexturesPerBatchCache;
}
exports.getMaxTexturesPerBatch = getMaxTexturesPerBatch;
//# sourceMappingURL=maxRecommendedTextures.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"maxRecommendedTextures.js","sources":["../../../../../src/rendering/batcher/gl/utils/maxRecommendedTextures.ts"],"sourcesContent":["import { getTestContext } from '../../../renderers/gl/shader/program/getTestContext';\nimport { checkMaxIfStatementsInShader } from './checkMaxIfStatementsInShader';\n\nlet maxTexturesPerBatchCache: number | null = null;\n\n/**\n * Returns the maximum number of textures that can be batched. This uses WebGL1's `MAX_TEXTURE_IMAGE_UNITS`.\n * The response for this is that to get this info via WebGPU, we would need to make a context, which\n * would make this function async, and we want to avoid that.\n * @private\n * @returns {number} The maximum number of textures that can be batched\n */\nexport function getMaxTexturesPerBatch(): number\n{\n if (maxTexturesPerBatchCache) return maxTexturesPerBatchCache;\n\n const gl = getTestContext();\n\n // step 1: first check max textures the GPU can handle.\n maxTexturesPerBatchCache = gl.getParameter(gl.MAX_TEXTURE_IMAGE_UNITS);\n\n // step 2: check the maximum number of if statements the shader can have too..\n maxTexturesPerBatchCache = checkMaxIfStatementsInShader(\n maxTexturesPerBatchCache, gl);\n\n gl.getExtension('WEBGL_lose_context')?.loseContext();\n\n return maxTexturesPerBatchCache;\n}\n"],"names":["getTestContext","checkMaxIfStatementsInShader"],"mappings":";;;;;;AAGA,IAAI,wBAA0C,GAAA,IAAA,CAAA;AASvC,SAAS,sBAChB,GAAA;AACI,EAAI,IAAA,wBAAA;AAA0B,IAAO,OAAA,wBAAA,CAAA;AAErC,EAAA,MAAM,KAAKA,6BAAe,EAAA,CAAA;AAG1B,EAA2B,wBAAA,GAAA,EAAA,CAAG,YAAa,CAAA,EAAA,CAAG,uBAAuB,CAAA,CAAA;AAGrE,EAA2B,wBAAA,GAAAC,yDAAA;AAAA,IACvB,wBAAA;AAAA,IAA0B,EAAA;AAAA,GAAE,CAAA;AAEhC,EAAG,EAAA,CAAA,YAAA,CAAa,oBAAoB,CAAA,EAAG,WAAY,EAAA,CAAA;AAEnD,EAAO,OAAA,wBAAA,CAAA;AACX;;;;"}

View File

@@ -0,0 +1,20 @@
import { getTestContext } from '../../../renderers/gl/shader/program/getTestContext.mjs';
import { checkMaxIfStatementsInShader } from './checkMaxIfStatementsInShader.mjs';
"use strict";
let maxTexturesPerBatchCache = null;
function getMaxTexturesPerBatch() {
if (maxTexturesPerBatchCache)
return maxTexturesPerBatchCache;
const gl = getTestContext();
maxTexturesPerBatchCache = gl.getParameter(gl.MAX_TEXTURE_IMAGE_UNITS);
maxTexturesPerBatchCache = checkMaxIfStatementsInShader(
maxTexturesPerBatchCache,
gl
);
gl.getExtension("WEBGL_lose_context")?.loseContext();
return maxTexturesPerBatchCache;
}
export { getMaxTexturesPerBatch };
//# sourceMappingURL=maxRecommendedTextures.mjs.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"maxRecommendedTextures.mjs","sources":["../../../../../src/rendering/batcher/gl/utils/maxRecommendedTextures.ts"],"sourcesContent":["import { getTestContext } from '../../../renderers/gl/shader/program/getTestContext';\nimport { checkMaxIfStatementsInShader } from './checkMaxIfStatementsInShader';\n\nlet maxTexturesPerBatchCache: number | null = null;\n\n/**\n * Returns the maximum number of textures that can be batched. This uses WebGL1's `MAX_TEXTURE_IMAGE_UNITS`.\n * The response for this is that to get this info via WebGPU, we would need to make a context, which\n * would make this function async, and we want to avoid that.\n * @private\n * @returns {number} The maximum number of textures that can be batched\n */\nexport function getMaxTexturesPerBatch(): number\n{\n if (maxTexturesPerBatchCache) return maxTexturesPerBatchCache;\n\n const gl = getTestContext();\n\n // step 1: first check max textures the GPU can handle.\n maxTexturesPerBatchCache = gl.getParameter(gl.MAX_TEXTURE_IMAGE_UNITS);\n\n // step 2: check the maximum number of if statements the shader can have too..\n maxTexturesPerBatchCache = checkMaxIfStatementsInShader(\n maxTexturesPerBatchCache, gl);\n\n gl.getExtension('WEBGL_lose_context')?.loseContext();\n\n return maxTexturesPerBatchCache;\n}\n"],"names":[],"mappings":";;;;AAGA,IAAI,wBAA0C,GAAA,IAAA,CAAA;AASvC,SAAS,sBAChB,GAAA;AACI,EAAI,IAAA,wBAAA;AAA0B,IAAO,OAAA,wBAAA,CAAA;AAErC,EAAA,MAAM,KAAK,cAAe,EAAA,CAAA;AAG1B,EAA2B,wBAAA,GAAA,EAAA,CAAG,YAAa,CAAA,EAAA,CAAG,uBAAuB,CAAA,CAAA;AAGrE,EAA2B,wBAAA,GAAA,4BAAA;AAAA,IACvB,wBAAA;AAAA,IAA0B,EAAA;AAAA,GAAE,CAAA;AAEhC,EAAG,EAAA,CAAA,YAAA,CAAa,oBAAoB,CAAA,EAAG,WAAY,EAAA,CAAA;AAEnD,EAAO,OAAA,wBAAA,CAAA;AACX;;;;"}

View File

@@ -0,0 +1,21 @@
import { ExtensionType } from '../../../extensions/Extensions';
import type { Geometry } from '../../renderers/shared/geometry/Geometry';
import type { Shader } from '../../renderers/shared/shader/Shader';
import type { Batch } from '../shared/Batcher';
import type { BatcherAdaptor, BatcherPipe } from '../shared/BatcherPipe';
/**
* A BatcherAdaptor that uses the GPU to render batches.
* @memberof rendering
* @ignore
*/
export declare class GpuBatchAdaptor implements BatcherAdaptor {
/** @ignore */
static extension: {
readonly type: readonly [ExtensionType.WebGPUPipesAdaptor];
readonly name: "batch";
};
private _shader;
private _geometry;
start(batchPipe: BatcherPipe, geometry: Geometry, shader: Shader): void;
execute(batchPipe: BatcherPipe, batch: Batch): void;
}

View File

@@ -0,0 +1,61 @@
'use strict';
var Extensions = require('../../../extensions/Extensions.js');
var State = require('../../renderers/shared/state/State.js');
var getTextureBatchBindGroup = require('./getTextureBatchBindGroup.js');
"use strict";
const tempState = State.State.for2d();
class GpuBatchAdaptor {
start(batchPipe, geometry, shader) {
const renderer = batchPipe.renderer;
const encoder = renderer.encoder;
const program = shader.gpuProgram;
this._shader = shader;
this._geometry = geometry;
encoder.setGeometry(geometry, program);
tempState.blendMode = "normal";
renderer.pipeline.getPipeline(
geometry,
program,
tempState
);
const globalUniformsBindGroup = renderer.globalUniforms.bindGroup;
encoder.resetBindGroup(1);
encoder.setBindGroup(0, globalUniformsBindGroup, program);
}
execute(batchPipe, batch) {
const program = this._shader.gpuProgram;
const renderer = batchPipe.renderer;
const encoder = renderer.encoder;
if (!batch.bindGroup) {
const textureBatch = batch.textures;
batch.bindGroup = getTextureBatchBindGroup.getTextureBatchBindGroup(textureBatch.textures, textureBatch.count);
}
tempState.blendMode = batch.blendMode;
const gpuBindGroup = renderer.bindGroup.getBindGroup(
batch.bindGroup,
program,
1
);
const pipeline = renderer.pipeline.getPipeline(
this._geometry,
program,
tempState
);
batch.bindGroup._touch(renderer.textureGC.count);
encoder.setPipeline(pipeline);
encoder.renderPassEncoder.setBindGroup(1, gpuBindGroup);
encoder.renderPassEncoder.drawIndexed(batch.size, 1, batch.start);
}
}
/** @ignore */
GpuBatchAdaptor.extension = {
type: [
Extensions.ExtensionType.WebGPUPipesAdaptor
],
name: "batch"
};
exports.GpuBatchAdaptor = GpuBatchAdaptor;
//# sourceMappingURL=GpuBatchAdaptor.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,59 @@
import { ExtensionType } from '../../../extensions/Extensions.mjs';
import { State } from '../../renderers/shared/state/State.mjs';
import { getTextureBatchBindGroup } from './getTextureBatchBindGroup.mjs';
"use strict";
const tempState = State.for2d();
class GpuBatchAdaptor {
start(batchPipe, geometry, shader) {
const renderer = batchPipe.renderer;
const encoder = renderer.encoder;
const program = shader.gpuProgram;
this._shader = shader;
this._geometry = geometry;
encoder.setGeometry(geometry, program);
tempState.blendMode = "normal";
renderer.pipeline.getPipeline(
geometry,
program,
tempState
);
const globalUniformsBindGroup = renderer.globalUniforms.bindGroup;
encoder.resetBindGroup(1);
encoder.setBindGroup(0, globalUniformsBindGroup, program);
}
execute(batchPipe, batch) {
const program = this._shader.gpuProgram;
const renderer = batchPipe.renderer;
const encoder = renderer.encoder;
if (!batch.bindGroup) {
const textureBatch = batch.textures;
batch.bindGroup = getTextureBatchBindGroup(textureBatch.textures, textureBatch.count);
}
tempState.blendMode = batch.blendMode;
const gpuBindGroup = renderer.bindGroup.getBindGroup(
batch.bindGroup,
program,
1
);
const pipeline = renderer.pipeline.getPipeline(
this._geometry,
program,
tempState
);
batch.bindGroup._touch(renderer.textureGC.count);
encoder.setPipeline(pipeline);
encoder.renderPassEncoder.setBindGroup(1, gpuBindGroup);
encoder.renderPassEncoder.drawIndexed(batch.size, 1, batch.start);
}
}
/** @ignore */
GpuBatchAdaptor.extension = {
type: [
ExtensionType.WebGPUPipesAdaptor
],
name: "batch"
};
export { GpuBatchAdaptor };
//# sourceMappingURL=GpuBatchAdaptor.mjs.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,2 @@
/// <reference types="@webgpu/types" />
export declare function generateGPULayout(maxTextures: number): GPUBindGroupLayoutEntry[];

View File

@@ -0,0 +1,31 @@
'use strict';
"use strict";
function generateGPULayout(maxTextures) {
const gpuLayout = [];
let bindIndex = 0;
for (let i = 0; i < maxTextures; i++) {
gpuLayout[bindIndex] = {
texture: {
sampleType: "float",
viewDimension: "2d",
multisampled: false
},
binding: bindIndex,
visibility: GPUShaderStage.FRAGMENT
};
bindIndex++;
gpuLayout[bindIndex] = {
sampler: {
type: "filtering"
},
binding: bindIndex,
visibility: GPUShaderStage.FRAGMENT
};
bindIndex++;
}
return gpuLayout;
}
exports.generateGPULayout = generateGPULayout;
//# sourceMappingURL=generateGPULayout.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"generateGPULayout.js","sources":["../../../../src/rendering/batcher/gpu/generateGPULayout.ts"],"sourcesContent":["export function generateGPULayout(maxTextures: number): GPUBindGroupLayoutEntry[]\n{\n const gpuLayout: GPUBindGroupLayoutEntry[] = [];\n\n let bindIndex = 0;\n\n for (let i = 0; i < maxTextures; i++)\n {\n gpuLayout[bindIndex] = {\n texture: {\n sampleType: 'float',\n viewDimension: '2d',\n multisampled: false,\n },\n binding: bindIndex,\n visibility: GPUShaderStage.FRAGMENT,\n };\n bindIndex++;\n\n gpuLayout[bindIndex] = {\n sampler: {\n type: 'filtering',\n },\n binding: bindIndex,\n visibility: GPUShaderStage.FRAGMENT,\n };\n\n bindIndex++;\n }\n\n return gpuLayout;\n}\n"],"names":[],"mappings":";;;AAAO,SAAS,kBAAkB,WAClC,EAAA;AACI,EAAA,MAAM,YAAuC,EAAC,CAAA;AAE9C,EAAA,IAAI,SAAY,GAAA,CAAA,CAAA;AAEhB,EAAA,KAAA,IAAS,CAAI,GAAA,CAAA,EAAG,CAAI,GAAA,WAAA,EAAa,CACjC,EAAA,EAAA;AACI,IAAA,SAAA,CAAU,SAAS,CAAI,GAAA;AAAA,MACnB,OAAS,EAAA;AAAA,QACL,UAAY,EAAA,OAAA;AAAA,QACZ,aAAe,EAAA,IAAA;AAAA,QACf,YAAc,EAAA,KAAA;AAAA,OAClB;AAAA,MACA,OAAS,EAAA,SAAA;AAAA,MACT,YAAY,cAAe,CAAA,QAAA;AAAA,KAC/B,CAAA;AACA,IAAA,SAAA,EAAA,CAAA;AAEA,IAAA,SAAA,CAAU,SAAS,CAAI,GAAA;AAAA,MACnB,OAAS,EAAA;AAAA,QACL,IAAM,EAAA,WAAA;AAAA,OACV;AAAA,MACA,OAAS,EAAA,SAAA;AAAA,MACT,YAAY,cAAe,CAAA,QAAA;AAAA,KAC/B,CAAA;AAEA,IAAA,SAAA,EAAA,CAAA;AAAA,GACJ;AAEA,EAAO,OAAA,SAAA,CAAA;AACX;;;;"}

View File

@@ -0,0 +1,29 @@
"use strict";
function generateGPULayout(maxTextures) {
const gpuLayout = [];
let bindIndex = 0;
for (let i = 0; i < maxTextures; i++) {
gpuLayout[bindIndex] = {
texture: {
sampleType: "float",
viewDimension: "2d",
multisampled: false
},
binding: bindIndex,
visibility: GPUShaderStage.FRAGMENT
};
bindIndex++;
gpuLayout[bindIndex] = {
sampler: {
type: "filtering"
},
binding: bindIndex,
visibility: GPUShaderStage.FRAGMENT
};
bindIndex++;
}
return gpuLayout;
}
export { generateGPULayout };
//# sourceMappingURL=generateGPULayout.mjs.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"generateGPULayout.mjs","sources":["../../../../src/rendering/batcher/gpu/generateGPULayout.ts"],"sourcesContent":["export function generateGPULayout(maxTextures: number): GPUBindGroupLayoutEntry[]\n{\n const gpuLayout: GPUBindGroupLayoutEntry[] = [];\n\n let bindIndex = 0;\n\n for (let i = 0; i < maxTextures; i++)\n {\n gpuLayout[bindIndex] = {\n texture: {\n sampleType: 'float',\n viewDimension: '2d',\n multisampled: false,\n },\n binding: bindIndex,\n visibility: GPUShaderStage.FRAGMENT,\n };\n bindIndex++;\n\n gpuLayout[bindIndex] = {\n sampler: {\n type: 'filtering',\n },\n binding: bindIndex,\n visibility: GPUShaderStage.FRAGMENT,\n };\n\n bindIndex++;\n }\n\n return gpuLayout;\n}\n"],"names":[],"mappings":";AAAO,SAAS,kBAAkB,WAClC,EAAA;AACI,EAAA,MAAM,YAAuC,EAAC,CAAA;AAE9C,EAAA,IAAI,SAAY,GAAA,CAAA,CAAA;AAEhB,EAAA,KAAA,IAAS,CAAI,GAAA,CAAA,EAAG,CAAI,GAAA,WAAA,EAAa,CACjC,EAAA,EAAA;AACI,IAAA,SAAA,CAAU,SAAS,CAAI,GAAA;AAAA,MACnB,OAAS,EAAA;AAAA,QACL,UAAY,EAAA,OAAA;AAAA,QACZ,aAAe,EAAA,IAAA;AAAA,QACf,YAAc,EAAA,KAAA;AAAA,OAClB;AAAA,MACA,OAAS,EAAA,SAAA;AAAA,MACT,YAAY,cAAe,CAAA,QAAA;AAAA,KAC/B,CAAA;AACA,IAAA,SAAA,EAAA,CAAA;AAEA,IAAA,SAAA,CAAU,SAAS,CAAI,GAAA;AAAA,MACnB,OAAS,EAAA;AAAA,QACL,IAAM,EAAA,WAAA;AAAA,OACV;AAAA,MACA,OAAS,EAAA,SAAA;AAAA,MACT,YAAY,cAAe,CAAA,QAAA;AAAA,KAC/B,CAAA;AAEA,IAAA,SAAA,EAAA,CAAA;AAAA,GACJ;AAEA,EAAO,OAAA,SAAA,CAAA;AACX;;;;"}

View File

@@ -0,0 +1 @@
export declare function generateLayout(maxTextures: number): Record<string, number>;

View File

@@ -0,0 +1,15 @@
'use strict';
"use strict";
function generateLayout(maxTextures) {
const layout = {};
let bindIndex = 0;
for (let i = 0; i < maxTextures; i++) {
layout[`textureSource${i + 1}`] = bindIndex++;
layout[`textureSampler${i + 1}`] = bindIndex++;
}
return layout;
}
exports.generateLayout = generateLayout;
//# sourceMappingURL=generateLayout.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"generateLayout.js","sources":["../../../../src/rendering/batcher/gpu/generateLayout.ts"],"sourcesContent":["export function generateLayout(maxTextures: number): Record<string, number>\n{\n const layout: Record<string, number> = {};\n\n let bindIndex = 0;\n\n for (let i = 0; i < maxTextures; i++)\n {\n layout[`textureSource${i + 1}`] = bindIndex++;\n layout[`textureSampler${i + 1}`] = bindIndex++;\n }\n\n return layout;\n}\n"],"names":[],"mappings":";;;AAAO,SAAS,eAAe,WAC/B,EAAA;AACI,EAAA,MAAM,SAAiC,EAAC,CAAA;AAExC,EAAA,IAAI,SAAY,GAAA,CAAA,CAAA;AAEhB,EAAA,KAAA,IAAS,CAAI,GAAA,CAAA,EAAG,CAAI,GAAA,WAAA,EAAa,CACjC,EAAA,EAAA;AACI,IAAA,MAAA,CAAO,CAAgB,aAAA,EAAA,CAAA,GAAI,CAAC,CAAA,CAAE,CAAI,GAAA,SAAA,EAAA,CAAA;AAClC,IAAA,MAAA,CAAO,CAAiB,cAAA,EAAA,CAAA,GAAI,CAAC,CAAA,CAAE,CAAI,GAAA,SAAA,EAAA,CAAA;AAAA,GACvC;AAEA,EAAO,OAAA,MAAA,CAAA;AACX;;;;"}

View File

@@ -0,0 +1,13 @@
"use strict";
function generateLayout(maxTextures) {
const layout = {};
let bindIndex = 0;
for (let i = 0; i < maxTextures; i++) {
layout[`textureSource${i + 1}`] = bindIndex++;
layout[`textureSampler${i + 1}`] = bindIndex++;
}
return layout;
}
export { generateLayout };
//# sourceMappingURL=generateLayout.mjs.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"generateLayout.mjs","sources":["../../../../src/rendering/batcher/gpu/generateLayout.ts"],"sourcesContent":["export function generateLayout(maxTextures: number): Record<string, number>\n{\n const layout: Record<string, number> = {};\n\n let bindIndex = 0;\n\n for (let i = 0; i < maxTextures; i++)\n {\n layout[`textureSource${i + 1}`] = bindIndex++;\n layout[`textureSampler${i + 1}`] = bindIndex++;\n }\n\n return layout;\n}\n"],"names":[],"mappings":";AAAO,SAAS,eAAe,WAC/B,EAAA;AACI,EAAA,MAAM,SAAiC,EAAC,CAAA;AAExC,EAAA,IAAI,SAAY,GAAA,CAAA,CAAA;AAEhB,EAAA,KAAA,IAAS,CAAI,GAAA,CAAA,EAAG,CAAI,GAAA,WAAA,EAAa,CACjC,EAAA,EAAA;AACI,IAAA,MAAA,CAAO,CAAgB,aAAA,EAAA,CAAA,GAAI,CAAC,CAAA,CAAE,CAAI,GAAA,SAAA,EAAA,CAAA;AAClC,IAAA,MAAA,CAAO,CAAiB,cAAA,EAAA,CAAA,GAAI,CAAC,CAAA,CAAE,CAAI,GAAA,SAAA,EAAA,CAAA;AAAA,GACvC;AAEA,EAAO,OAAA,MAAA,CAAA;AACX;;;;"}

View File

@@ -0,0 +1,3 @@
import { BindGroup } from '../../renderers/gpu/shader/BindGroup';
import type { TextureSource } from '../../renderers/shared/texture/sources/TextureSource';
export declare function getTextureBatchBindGroup(textures: TextureSource[], size: number): BindGroup;

View File

@@ -0,0 +1,35 @@
'use strict';
var BindGroup = require('../../renderers/gpu/shader/BindGroup.js');
var Texture = require('../../renderers/shared/texture/Texture.js');
var maxRecommendedTextures = require('../gl/utils/maxRecommendedTextures.js');
"use strict";
const cachedGroups = {};
function getTextureBatchBindGroup(textures, size) {
let uid = 2166136261;
for (let i = 0; i < size; i++) {
uid ^= textures[i].uid;
uid = Math.imul(uid, 16777619);
uid >>>= 0;
}
return cachedGroups[uid] || generateTextureBatchBindGroup(textures, size, uid);
}
let maxTextures = 0;
function generateTextureBatchBindGroup(textures, size, key) {
const bindGroupResources = {};
let bindIndex = 0;
if (!maxTextures)
maxTextures = maxRecommendedTextures.getMaxTexturesPerBatch();
for (let i = 0; i < maxTextures; i++) {
const texture = i < size ? textures[i] : Texture.Texture.EMPTY.source;
bindGroupResources[bindIndex++] = texture.source;
bindGroupResources[bindIndex++] = texture.style;
}
const bindGroup = new BindGroup.BindGroup(bindGroupResources);
cachedGroups[key] = bindGroup;
return bindGroup;
}
exports.getTextureBatchBindGroup = getTextureBatchBindGroup;
//# sourceMappingURL=getTextureBatchBindGroup.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"getTextureBatchBindGroup.js","sources":["../../../../src/rendering/batcher/gpu/getTextureBatchBindGroup.ts"],"sourcesContent":["import { BindGroup } from '../../renderers/gpu/shader/BindGroup';\nimport { Texture } from '../../renderers/shared/texture/Texture';\nimport { getMaxTexturesPerBatch } from '../gl/utils/maxRecommendedTextures';\n\nimport type { TextureSource } from '../../renderers/shared/texture/sources/TextureSource';\n\nconst cachedGroups: Record<number, BindGroup> = {};\n\nexport function getTextureBatchBindGroup(textures: TextureSource[], size: number)\n{\n let uid = 2166136261; // FNV-1a 32-bit offset basis\n\n for (let i = 0; i < size; i++)\n {\n uid ^= textures[i].uid;\n uid = Math.imul(uid, 16777619);\n uid >>>= 0;\n }\n\n return cachedGroups[uid] || generateTextureBatchBindGroup(textures, size, uid);\n}\n\nlet maxTextures = 0;\n\nfunction generateTextureBatchBindGroup(textures: TextureSource[], size: number, key: number): BindGroup\n{\n const bindGroupResources: Record<string, any> = {};\n\n let bindIndex = 0;\n\n if (!maxTextures)maxTextures = getMaxTexturesPerBatch();\n\n for (let i = 0; i < maxTextures; i++)\n {\n const texture = i < size ? textures[i] : Texture.EMPTY.source;\n\n bindGroupResources[bindIndex++] = texture.source;\n bindGroupResources[bindIndex++] = texture.style;\n }\n\n // pad out with empty textures\n const bindGroup = new BindGroup(bindGroupResources);\n\n cachedGroups[key] = bindGroup;\n\n return bindGroup;\n}\n\n"],"names":["getMaxTexturesPerBatch","Texture","BindGroup"],"mappings":";;;;;;;AAMA,MAAM,eAA0C,EAAC,CAAA;AAEjC,SAAA,wBAAA,CAAyB,UAA2B,IACpE,EAAA;AACI,EAAA,IAAI,GAAM,GAAA,UAAA,CAAA;AAEV,EAAA,KAAA,IAAS,CAAI,GAAA,CAAA,EAAG,CAAI,GAAA,IAAA,EAAM,CAC1B,EAAA,EAAA;AACI,IAAO,GAAA,IAAA,QAAA,CAAS,CAAC,CAAE,CAAA,GAAA,CAAA;AACnB,IAAM,GAAA,GAAA,IAAA,CAAK,IAAK,CAAA,GAAA,EAAK,QAAQ,CAAA,CAAA;AAC7B,IAAS,GAAA,MAAA,CAAA,CAAA;AAAA,GACb;AAEA,EAAA,OAAO,aAAa,GAAG,CAAA,IAAK,6BAA8B,CAAA,QAAA,EAAU,MAAM,GAAG,CAAA,CAAA;AACjF,CAAA;AAEA,IAAI,WAAc,GAAA,CAAA,CAAA;AAElB,SAAS,6BAAA,CAA8B,QAA2B,EAAA,IAAA,EAAc,GAChF,EAAA;AACI,EAAA,MAAM,qBAA0C,EAAC,CAAA;AAEjD,EAAA,IAAI,SAAY,GAAA,CAAA,CAAA;AAEhB,EAAA,IAAI,CAAC,WAAA;AAAY,IAAA,WAAA,GAAcA,6CAAuB,EAAA,CAAA;AAEtD,EAAA,KAAA,IAAS,CAAI,GAAA,CAAA,EAAG,CAAI,GAAA,WAAA,EAAa,CACjC,EAAA,EAAA;AACI,IAAA,MAAM,UAAU,CAAI,GAAA,IAAA,GAAO,SAAS,CAAC,CAAA,GAAIC,gBAAQ,KAAM,CAAA,MAAA,CAAA;AAEvD,IAAmB,kBAAA,CAAA,SAAA,EAAW,IAAI,OAAQ,CAAA,MAAA,CAAA;AAC1C,IAAmB,kBAAA,CAAA,SAAA,EAAW,IAAI,OAAQ,CAAA,KAAA,CAAA;AAAA,GAC9C;AAGA,EAAM,MAAA,SAAA,GAAY,IAAIC,mBAAA,CAAU,kBAAkB,CAAA,CAAA;AAElD,EAAA,YAAA,CAAa,GAAG,CAAI,GAAA,SAAA,CAAA;AAEpB,EAAO,OAAA,SAAA,CAAA;AACX;;;;"}

View File

@@ -0,0 +1,33 @@
import { BindGroup } from '../../renderers/gpu/shader/BindGroup.mjs';
import { Texture } from '../../renderers/shared/texture/Texture.mjs';
import { getMaxTexturesPerBatch } from '../gl/utils/maxRecommendedTextures.mjs';
"use strict";
const cachedGroups = {};
function getTextureBatchBindGroup(textures, size) {
let uid = 2166136261;
for (let i = 0; i < size; i++) {
uid ^= textures[i].uid;
uid = Math.imul(uid, 16777619);
uid >>>= 0;
}
return cachedGroups[uid] || generateTextureBatchBindGroup(textures, size, uid);
}
let maxTextures = 0;
function generateTextureBatchBindGroup(textures, size, key) {
const bindGroupResources = {};
let bindIndex = 0;
if (!maxTextures)
maxTextures = getMaxTexturesPerBatch();
for (let i = 0; i < maxTextures; i++) {
const texture = i < size ? textures[i] : Texture.EMPTY.source;
bindGroupResources[bindIndex++] = texture.source;
bindGroupResources[bindIndex++] = texture.style;
}
const bindGroup = new BindGroup(bindGroupResources);
cachedGroups[key] = bindGroup;
return bindGroup;
}
export { getTextureBatchBindGroup };
//# sourceMappingURL=getTextureBatchBindGroup.mjs.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"getTextureBatchBindGroup.mjs","sources":["../../../../src/rendering/batcher/gpu/getTextureBatchBindGroup.ts"],"sourcesContent":["import { BindGroup } from '../../renderers/gpu/shader/BindGroup';\nimport { Texture } from '../../renderers/shared/texture/Texture';\nimport { getMaxTexturesPerBatch } from '../gl/utils/maxRecommendedTextures';\n\nimport type { TextureSource } from '../../renderers/shared/texture/sources/TextureSource';\n\nconst cachedGroups: Record<number, BindGroup> = {};\n\nexport function getTextureBatchBindGroup(textures: TextureSource[], size: number)\n{\n let uid = 2166136261; // FNV-1a 32-bit offset basis\n\n for (let i = 0; i < size; i++)\n {\n uid ^= textures[i].uid;\n uid = Math.imul(uid, 16777619);\n uid >>>= 0;\n }\n\n return cachedGroups[uid] || generateTextureBatchBindGroup(textures, size, uid);\n}\n\nlet maxTextures = 0;\n\nfunction generateTextureBatchBindGroup(textures: TextureSource[], size: number, key: number): BindGroup\n{\n const bindGroupResources: Record<string, any> = {};\n\n let bindIndex = 0;\n\n if (!maxTextures)maxTextures = getMaxTexturesPerBatch();\n\n for (let i = 0; i < maxTextures; i++)\n {\n const texture = i < size ? textures[i] : Texture.EMPTY.source;\n\n bindGroupResources[bindIndex++] = texture.source;\n bindGroupResources[bindIndex++] = texture.style;\n }\n\n // pad out with empty textures\n const bindGroup = new BindGroup(bindGroupResources);\n\n cachedGroups[key] = bindGroup;\n\n return bindGroup;\n}\n\n"],"names":[],"mappings":";;;;;AAMA,MAAM,eAA0C,EAAC,CAAA;AAEjC,SAAA,wBAAA,CAAyB,UAA2B,IACpE,EAAA;AACI,EAAA,IAAI,GAAM,GAAA,UAAA,CAAA;AAEV,EAAA,KAAA,IAAS,CAAI,GAAA,CAAA,EAAG,CAAI,GAAA,IAAA,EAAM,CAC1B,EAAA,EAAA;AACI,IAAO,GAAA,IAAA,QAAA,CAAS,CAAC,CAAE,CAAA,GAAA,CAAA;AACnB,IAAM,GAAA,GAAA,IAAA,CAAK,IAAK,CAAA,GAAA,EAAK,QAAQ,CAAA,CAAA;AAC7B,IAAS,GAAA,MAAA,CAAA,CAAA;AAAA,GACb;AAEA,EAAA,OAAO,aAAa,GAAG,CAAA,IAAK,6BAA8B,CAAA,QAAA,EAAU,MAAM,GAAG,CAAA,CAAA;AACjF,CAAA;AAEA,IAAI,WAAc,GAAA,CAAA,CAAA;AAElB,SAAS,6BAAA,CAA8B,QAA2B,EAAA,IAAA,EAAc,GAChF,EAAA;AACI,EAAA,MAAM,qBAA0C,EAAC,CAAA;AAEjD,EAAA,IAAI,SAAY,GAAA,CAAA,CAAA;AAEhB,EAAA,IAAI,CAAC,WAAA;AAAY,IAAA,WAAA,GAAc,sBAAuB,EAAA,CAAA;AAEtD,EAAA,KAAA,IAAS,CAAI,GAAA,CAAA,EAAG,CAAI,GAAA,WAAA,EAAa,CACjC,EAAA,EAAA;AACI,IAAA,MAAM,UAAU,CAAI,GAAA,IAAA,GAAO,SAAS,CAAC,CAAA,GAAI,QAAQ,KAAM,CAAA,MAAA,CAAA;AAEvD,IAAmB,kBAAA,CAAA,SAAA,EAAW,IAAI,OAAQ,CAAA,MAAA,CAAA;AAC1C,IAAmB,kBAAA,CAAA,SAAA,EAAW,IAAI,OAAQ,CAAA,KAAA,CAAA;AAAA,GAC9C;AAGA,EAAM,MAAA,SAAA,GAAY,IAAI,SAAA,CAAU,kBAAkB,CAAA,CAAA;AAElD,EAAA,YAAA,CAAa,GAAG,CAAI,GAAA,SAAA,CAAA;AAEpB,EAAO,OAAA,SAAA,CAAA;AACX;;;;"}

View File

@@ -0,0 +1,4 @@
import { Geometry } from '../../renderers/shared/geometry/Geometry';
export declare class BatchGeometry extends Geometry {
constructor();
}

View File

@@ -0,0 +1,60 @@
'use strict';
var Buffer = require('../../renderers/shared/buffer/Buffer.js');
var _const = require('../../renderers/shared/buffer/const.js');
var Geometry = require('../../renderers/shared/geometry/Geometry.js');
"use strict";
const placeHolderBufferData = new Float32Array(1);
const placeHolderIndexData = new Uint32Array(1);
class BatchGeometry extends Geometry.Geometry {
constructor() {
const vertexSize = 6;
const attributeBuffer = new Buffer.Buffer({
data: placeHolderBufferData,
label: "attribute-batch-buffer",
usage: _const.BufferUsage.VERTEX | _const.BufferUsage.COPY_DST,
shrinkToFit: false
});
const indexBuffer = new Buffer.Buffer({
data: placeHolderIndexData,
label: "index-batch-buffer",
usage: _const.BufferUsage.INDEX | _const.BufferUsage.COPY_DST,
// | BufferUsage.STATIC,
shrinkToFit: false
});
const stride = vertexSize * 4;
super({
attributes: {
aPosition: {
buffer: attributeBuffer,
format: "float32x2",
stride,
offset: 0
},
aUV: {
buffer: attributeBuffer,
format: "float32x2",
stride,
offset: 2 * 4
},
aColor: {
buffer: attributeBuffer,
format: "unorm8x4",
stride,
offset: 4 * 4
},
aTextureIdAndRound: {
buffer: attributeBuffer,
format: "uint16x2",
stride,
offset: 5 * 4
}
},
indexBuffer
});
}
}
exports.BatchGeometry = BatchGeometry;
//# sourceMappingURL=BatchGeometry.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"BatchGeometry.js","sources":["../../../../src/rendering/batcher/shared/BatchGeometry.ts"],"sourcesContent":["import { Buffer } from '../../renderers/shared/buffer/Buffer';\nimport { BufferUsage } from '../../renderers/shared/buffer/const';\nimport { Geometry } from '../../renderers/shared/geometry/Geometry';\n\nconst placeHolderBufferData = new Float32Array(1);\nconst placeHolderIndexData = new Uint32Array(1);\n\nexport class BatchGeometry extends Geometry\n{\n constructor()\n {\n const vertexSize = 6;\n\n const attributeBuffer = new Buffer({\n data: placeHolderBufferData,\n label: 'attribute-batch-buffer',\n usage: BufferUsage.VERTEX | BufferUsage.COPY_DST,\n shrinkToFit: false,\n });\n\n const indexBuffer = new Buffer({\n data: placeHolderIndexData,\n label: 'index-batch-buffer',\n usage: BufferUsage.INDEX | BufferUsage.COPY_DST, // | BufferUsage.STATIC,\n shrinkToFit: false,\n });\n\n const stride = vertexSize * 4;\n\n super({\n attributes: {\n aPosition: {\n buffer: attributeBuffer,\n format: 'float32x2',\n stride,\n offset: 0,\n },\n aUV: {\n buffer: attributeBuffer,\n format: 'float32x2',\n stride,\n offset: 2 * 4,\n },\n aColor: {\n buffer: attributeBuffer,\n format: 'unorm8x4',\n stride,\n offset: 4 * 4,\n },\n aTextureIdAndRound: {\n buffer: attributeBuffer,\n format: 'uint16x2',\n stride,\n offset: 5 * 4,\n },\n },\n indexBuffer\n });\n }\n}\n\n"],"names":["Geometry","Buffer","BufferUsage"],"mappings":";;;;;;;AAIA,MAAM,qBAAA,GAAwB,IAAI,YAAA,CAAa,CAAC,CAAA,CAAA;AAChD,MAAM,oBAAA,GAAuB,IAAI,WAAA,CAAY,CAAC,CAAA,CAAA;AAEvC,MAAM,sBAAsBA,iBACnC,CAAA;AAAA,EACI,WACA,GAAA;AACI,IAAA,MAAM,UAAa,GAAA,CAAA,CAAA;AAEnB,IAAM,MAAA,eAAA,GAAkB,IAAIC,aAAO,CAAA;AAAA,MAC/B,IAAM,EAAA,qBAAA;AAAA,MACN,KAAO,EAAA,wBAAA;AAAA,MACP,KAAA,EAAOC,kBAAY,CAAA,MAAA,GAASA,kBAAY,CAAA,QAAA;AAAA,MACxC,WAAa,EAAA,KAAA;AAAA,KAChB,CAAA,CAAA;AAED,IAAM,MAAA,WAAA,GAAc,IAAID,aAAO,CAAA;AAAA,MAC3B,IAAM,EAAA,oBAAA;AAAA,MACN,KAAO,EAAA,oBAAA;AAAA,MACP,KAAA,EAAOC,kBAAY,CAAA,KAAA,GAAQA,kBAAY,CAAA,QAAA;AAAA;AAAA,MACvC,WAAa,EAAA,KAAA;AAAA,KAChB,CAAA,CAAA;AAED,IAAA,MAAM,SAAS,UAAa,GAAA,CAAA,CAAA;AAE5B,IAAM,KAAA,CAAA;AAAA,MACF,UAAY,EAAA;AAAA,QACR,SAAW,EAAA;AAAA,UACP,MAAQ,EAAA,eAAA;AAAA,UACR,MAAQ,EAAA,WAAA;AAAA,UACR,MAAA;AAAA,UACA,MAAQ,EAAA,CAAA;AAAA,SACZ;AAAA,QACA,GAAK,EAAA;AAAA,UACD,MAAQ,EAAA,eAAA;AAAA,UACR,MAAQ,EAAA,WAAA;AAAA,UACR,MAAA;AAAA,UACA,QAAQ,CAAI,GAAA,CAAA;AAAA,SAChB;AAAA,QACA,MAAQ,EAAA;AAAA,UACJ,MAAQ,EAAA,eAAA;AAAA,UACR,MAAQ,EAAA,UAAA;AAAA,UACR,MAAA;AAAA,UACA,QAAQ,CAAI,GAAA,CAAA;AAAA,SAChB;AAAA,QACA,kBAAoB,EAAA;AAAA,UAChB,MAAQ,EAAA,eAAA;AAAA,UACR,MAAQ,EAAA,UAAA;AAAA,UACR,MAAA;AAAA,UACA,QAAQ,CAAI,GAAA,CAAA;AAAA,SAChB;AAAA,OACJ;AAAA,MACA,WAAA;AAAA,KACH,CAAA,CAAA;AAAA,GACL;AACJ;;;;"}

View File

@@ -0,0 +1,58 @@
import { Buffer } from '../../renderers/shared/buffer/Buffer.mjs';
import { BufferUsage } from '../../renderers/shared/buffer/const.mjs';
import { Geometry } from '../../renderers/shared/geometry/Geometry.mjs';
"use strict";
const placeHolderBufferData = new Float32Array(1);
const placeHolderIndexData = new Uint32Array(1);
class BatchGeometry extends Geometry {
constructor() {
const vertexSize = 6;
const attributeBuffer = new Buffer({
data: placeHolderBufferData,
label: "attribute-batch-buffer",
usage: BufferUsage.VERTEX | BufferUsage.COPY_DST,
shrinkToFit: false
});
const indexBuffer = new Buffer({
data: placeHolderIndexData,
label: "index-batch-buffer",
usage: BufferUsage.INDEX | BufferUsage.COPY_DST,
// | BufferUsage.STATIC,
shrinkToFit: false
});
const stride = vertexSize * 4;
super({
attributes: {
aPosition: {
buffer: attributeBuffer,
format: "float32x2",
stride,
offset: 0
},
aUV: {
buffer: attributeBuffer,
format: "float32x2",
stride,
offset: 2 * 4
},
aColor: {
buffer: attributeBuffer,
format: "unorm8x4",
stride,
offset: 4 * 4
},
aTextureIdAndRound: {
buffer: attributeBuffer,
format: "uint16x2",
stride,
offset: 5 * 4
}
},
indexBuffer
});
}
}
export { BatchGeometry };
//# sourceMappingURL=BatchGeometry.mjs.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"BatchGeometry.mjs","sources":["../../../../src/rendering/batcher/shared/BatchGeometry.ts"],"sourcesContent":["import { Buffer } from '../../renderers/shared/buffer/Buffer';\nimport { BufferUsage } from '../../renderers/shared/buffer/const';\nimport { Geometry } from '../../renderers/shared/geometry/Geometry';\n\nconst placeHolderBufferData = new Float32Array(1);\nconst placeHolderIndexData = new Uint32Array(1);\n\nexport class BatchGeometry extends Geometry\n{\n constructor()\n {\n const vertexSize = 6;\n\n const attributeBuffer = new Buffer({\n data: placeHolderBufferData,\n label: 'attribute-batch-buffer',\n usage: BufferUsage.VERTEX | BufferUsage.COPY_DST,\n shrinkToFit: false,\n });\n\n const indexBuffer = new Buffer({\n data: placeHolderIndexData,\n label: 'index-batch-buffer',\n usage: BufferUsage.INDEX | BufferUsage.COPY_DST, // | BufferUsage.STATIC,\n shrinkToFit: false,\n });\n\n const stride = vertexSize * 4;\n\n super({\n attributes: {\n aPosition: {\n buffer: attributeBuffer,\n format: 'float32x2',\n stride,\n offset: 0,\n },\n aUV: {\n buffer: attributeBuffer,\n format: 'float32x2',\n stride,\n offset: 2 * 4,\n },\n aColor: {\n buffer: attributeBuffer,\n format: 'unorm8x4',\n stride,\n offset: 4 * 4,\n },\n aTextureIdAndRound: {\n buffer: attributeBuffer,\n format: 'uint16x2',\n stride,\n offset: 5 * 4,\n },\n },\n indexBuffer\n });\n }\n}\n\n"],"names":[],"mappings":";;;;;AAIA,MAAM,qBAAA,GAAwB,IAAI,YAAA,CAAa,CAAC,CAAA,CAAA;AAChD,MAAM,oBAAA,GAAuB,IAAI,WAAA,CAAY,CAAC,CAAA,CAAA;AAEvC,MAAM,sBAAsB,QACnC,CAAA;AAAA,EACI,WACA,GAAA;AACI,IAAA,MAAM,UAAa,GAAA,CAAA,CAAA;AAEnB,IAAM,MAAA,eAAA,GAAkB,IAAI,MAAO,CAAA;AAAA,MAC/B,IAAM,EAAA,qBAAA;AAAA,MACN,KAAO,EAAA,wBAAA;AAAA,MACP,KAAA,EAAO,WAAY,CAAA,MAAA,GAAS,WAAY,CAAA,QAAA;AAAA,MACxC,WAAa,EAAA,KAAA;AAAA,KAChB,CAAA,CAAA;AAED,IAAM,MAAA,WAAA,GAAc,IAAI,MAAO,CAAA;AAAA,MAC3B,IAAM,EAAA,oBAAA;AAAA,MACN,KAAO,EAAA,oBAAA;AAAA,MACP,KAAA,EAAO,WAAY,CAAA,KAAA,GAAQ,WAAY,CAAA,QAAA;AAAA;AAAA,MACvC,WAAa,EAAA,KAAA;AAAA,KAChB,CAAA,CAAA;AAED,IAAA,MAAM,SAAS,UAAa,GAAA,CAAA,CAAA;AAE5B,IAAM,KAAA,CAAA;AAAA,MACF,UAAY,EAAA;AAAA,QACR,SAAW,EAAA;AAAA,UACP,MAAQ,EAAA,eAAA;AAAA,UACR,MAAQ,EAAA,WAAA;AAAA,UACR,MAAA;AAAA,UACA,MAAQ,EAAA,CAAA;AAAA,SACZ;AAAA,QACA,GAAK,EAAA;AAAA,UACD,MAAQ,EAAA,eAAA;AAAA,UACR,MAAQ,EAAA,WAAA;AAAA,UACR,MAAA;AAAA,UACA,QAAQ,CAAI,GAAA,CAAA;AAAA,SAChB;AAAA,QACA,MAAQ,EAAA;AAAA,UACJ,MAAQ,EAAA,eAAA;AAAA,UACR,MAAQ,EAAA,UAAA;AAAA,UACR,MAAA;AAAA,UACA,QAAQ,CAAI,GAAA,CAAA;AAAA,SAChB;AAAA,QACA,kBAAoB,EAAA;AAAA,UAChB,MAAQ,EAAA,eAAA;AAAA,UACR,MAAQ,EAAA,UAAA;AAAA,UACR,MAAA;AAAA,UACA,QAAQ,CAAI,GAAA,CAAA;AAAA,SAChB;AAAA,OACJ;AAAA,MACA,WAAA;AAAA,KACH,CAAA,CAAA;AAAA,GACL;AACJ;;;;"}

View File

@@ -0,0 +1,16 @@
import type { TextureSource } from '../../renderers/shared/texture/sources/TextureSource';
/**
* Used by the batcher to build texture batches. Holds list of textures and their respective locations.
* @memberof rendering
*/
export declare class BatchTextureArray {
/** Inside textures array. */
textures: TextureSource[];
/** Respective locations for textures. */
ids: Record<number, number>;
/** Number of filled elements. */
count: number;
constructor();
/** Clear the textures and their locations. */
clear(): void;
}

View File

@@ -0,0 +1,23 @@
'use strict';
"use strict";
class BatchTextureArray {
constructor() {
/** Respective locations for textures. */
this.ids = /* @__PURE__ */ Object.create(null);
this.textures = [];
this.count = 0;
}
/** Clear the textures and their locations. */
clear() {
for (let i = 0; i < this.count; i++) {
const t = this.textures[i];
this.textures[i] = null;
this.ids[t.uid] = null;
}
this.count = 0;
}
}
exports.BatchTextureArray = BatchTextureArray;
//# sourceMappingURL=BatchTextureArray.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"BatchTextureArray.js","sources":["../../../../src/rendering/batcher/shared/BatchTextureArray.ts"],"sourcesContent":["import type { TextureSource } from '../../renderers/shared/texture/sources/TextureSource';\n\n/**\n * Used by the batcher to build texture batches. Holds list of textures and their respective locations.\n * @memberof rendering\n */\nexport class BatchTextureArray\n{\n /** Inside textures array. */\n public textures: TextureSource[];\n\n /** Respective locations for textures. */\n public ids: Record<number, number> = Object.create(null);\n\n /** Number of filled elements. */\n public count: number;\n\n constructor()\n {\n this.textures = [];\n this.count = 0;\n }\n\n /** Clear the textures and their locations. */\n public clear(): void\n {\n for (let i = 0; i < this.count; i++)\n {\n const t = this.textures[i];\n\n this.textures[i] = null;\n this.ids[t.uid] = null;\n }\n\n this.count = 0;\n }\n}\n"],"names":[],"mappings":";;;AAMO,MAAM,iBACb,CAAA;AAAA,EAUI,WACA,GAAA;AANA;AAAA,IAAO,IAAA,CAAA,GAAA,mBAAqC,MAAA,CAAA,MAAA,CAAO,IAAI,CAAA,CAAA;AAOnD,IAAA,IAAA,CAAK,WAAW,EAAC,CAAA;AACjB,IAAA,IAAA,CAAK,KAAQ,GAAA,CAAA,CAAA;AAAA,GACjB;AAAA;AAAA,EAGO,KACP,GAAA;AACI,IAAA,KAAA,IAAS,CAAI,GAAA,CAAA,EAAG,CAAI,GAAA,IAAA,CAAK,OAAO,CAChC,EAAA,EAAA;AACI,MAAM,MAAA,CAAA,GAAI,IAAK,CAAA,QAAA,CAAS,CAAC,CAAA,CAAA;AAEzB,MAAK,IAAA,CAAA,QAAA,CAAS,CAAC,CAAI,GAAA,IAAA,CAAA;AACnB,MAAK,IAAA,CAAA,GAAA,CAAI,CAAE,CAAA,GAAG,CAAI,GAAA,IAAA,CAAA;AAAA,KACtB;AAEA,IAAA,IAAA,CAAK,KAAQ,GAAA,CAAA,CAAA;AAAA,GACjB;AACJ;;;;"}

View File

@@ -0,0 +1,21 @@
"use strict";
class BatchTextureArray {
constructor() {
/** Respective locations for textures. */
this.ids = /* @__PURE__ */ Object.create(null);
this.textures = [];
this.count = 0;
}
/** Clear the textures and their locations. */
clear() {
for (let i = 0; i < this.count; i++) {
const t = this.textures[i];
this.textures[i] = null;
this.ids[t.uid] = null;
}
this.count = 0;
}
}
export { BatchTextureArray };
//# sourceMappingURL=BatchTextureArray.mjs.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"BatchTextureArray.mjs","sources":["../../../../src/rendering/batcher/shared/BatchTextureArray.ts"],"sourcesContent":["import type { TextureSource } from '../../renderers/shared/texture/sources/TextureSource';\n\n/**\n * Used by the batcher to build texture batches. Holds list of textures and their respective locations.\n * @memberof rendering\n */\nexport class BatchTextureArray\n{\n /** Inside textures array. */\n public textures: TextureSource[];\n\n /** Respective locations for textures. */\n public ids: Record<number, number> = Object.create(null);\n\n /** Number of filled elements. */\n public count: number;\n\n constructor()\n {\n this.textures = [];\n this.count = 0;\n }\n\n /** Clear the textures and their locations. */\n public clear(): void\n {\n for (let i = 0; i < this.count; i++)\n {\n const t = this.textures[i];\n\n this.textures[i] = null;\n this.ids[t.uid] = null;\n }\n\n this.count = 0;\n }\n}\n"],"names":[],"mappings":";AAMO,MAAM,iBACb,CAAA;AAAA,EAUI,WACA,GAAA;AANA;AAAA,IAAO,IAAA,CAAA,GAAA,mBAAqC,MAAA,CAAA,MAAA,CAAO,IAAI,CAAA,CAAA;AAOnD,IAAA,IAAA,CAAK,WAAW,EAAC,CAAA;AACjB,IAAA,IAAA,CAAK,KAAQ,GAAA,CAAA,CAAA;AAAA,GACjB;AAAA;AAAA,EAGO,KACP,GAAA;AACI,IAAA,KAAA,IAAS,CAAI,GAAA,CAAA,EAAG,CAAI,GAAA,IAAA,CAAK,OAAO,CAChC,EAAA,EAAA;AACI,MAAM,MAAA,CAAA,GAAI,IAAK,CAAA,QAAA,CAAS,CAAC,CAAA,CAAA;AAEzB,MAAK,IAAA,CAAA,QAAA,CAAS,CAAC,CAAI,GAAA,IAAA,CAAA;AACnB,MAAK,IAAA,CAAA,GAAA,CAAI,CAAE,CAAA,GAAG,CAAI,GAAA,IAAA,CAAA;AAAA,KACtB;AAEA,IAAA,IAAA,CAAK,KAAQ,GAAA,CAAA,CAAA;AAAA,GACjB;AACJ;;;;"}

View File

@@ -0,0 +1,272 @@
/// <reference types="@webgpu/types" />
import { ViewableBuffer } from '../../../utils/data/ViewableBuffer';
import { type BLEND_MODES } from '../../renderers/shared/state/const';
import { BatchTextureArray } from './BatchTextureArray';
import type { BoundsData } from '../../../scene/container/bounds/Bounds';
import type { BindGroup } from '../../renderers/gpu/shader/BindGroup';
import type { Geometry, IndexBufferArray } from '../../renderers/shared/geometry/Geometry';
import type { Instruction } from '../../renderers/shared/instructions/Instruction';
import type { InstructionSet } from '../../renderers/shared/instructions/InstructionSet';
import type { Shader } from '../../renderers/shared/shader/Shader';
import type { Texture } from '../../renderers/shared/texture/Texture';
export type BatchAction = 'startBatch' | 'renderBatch';
/**
* A batch pool is used to store batches when they are not currently in use.
* @memberof rendering
*/
export declare class Batch implements Instruction {
renderPipeId: string;
action: BatchAction;
start: number;
size: number;
textures: BatchTextureArray;
blendMode: BLEND_MODES;
canBundle: boolean;
/**
* breaking rules slightly here in the name of performance..
* storing references to these bindgroups here is just faster for access!
* keeps a reference to the GPU bind group to set when rendering this batch for WebGPU. Will be null is using WebGL.
*/
gpuBindGroup: GPUBindGroup;
/**
* breaking rules slightly here in the name of performance..
* storing references to these bindgroups here is just faster for access!
* keeps a reference to the bind group to set when rendering this batch for WebGPU. Will be null if using WebGl.
*/
bindGroup: BindGroup;
batcher: Batcher;
destroy(): void;
}
/**
* Represents an element that can be batched for rendering.
* @interface
* @memberof rendering
*/
export interface BatchableElement {
/**
* The name of the batcher to use. Must be registered.
* @type {string}
*/
batcherName: string;
/**
* The texture to be used for rendering.
* @type {Texture}
*/
texture: Texture;
/**
* The blend mode to be applied.
* @type {BLEND_MODES}
*/
blendMode: BLEND_MODES;
/**
* The size of the index data.
* @type {number}
*/
indexSize: number;
/**
* The size of the attribute data.
* @type {number}
*/
attributeSize: number;
/**
* Whether the element should be packed as a quad for better performance.
* @type {boolean}
*/
packAsQuad: boolean;
/**
* The texture ID, stored for efficient updating.
* @type {number}
* @private
*/
_textureId: number;
/**
* The starting position in the attribute buffer.
* @type {number}
* @private
*/
_attributeStart: number;
/**
* The starting position in the index buffer.
* @type {number}
* @private
*/
_indexStart: number;
/**
* Reference to the batcher.
* @type {Batcher}
* @private
*/
_batcher: Batcher;
/**
* Reference to the batch.
* @type {Batch}
* @private
*/
_batch: Batch;
}
/**
* Represents a batchable quad element.
* @extends BatchableElement
* @memberof rendering
*/
export interface BatchableQuadElement extends BatchableElement {
/**
* Indicates that this element should be packed as a quad.
* @type {true}
*/
packAsQuad: true;
/**
* The size of the attribute data for this quad element.
* @type {4}
*/
attributeSize: 4;
/**
* The size of the index data for this quad element.
* @type {6}
*/
indexSize: 6;
/**
* The bounds data for this quad element.
* @type {BoundsData}
*/
bounds: BoundsData;
}
/**
* Represents a batchable mesh element.
* @extends BatchableElement
* @memberof rendering
*/
export interface BatchableMeshElement extends BatchableElement {
/**
* The UV coordinates of the mesh.
* @type {number[] | Float32Array}
*/
uvs: number[] | Float32Array;
/**
* The vertex positions of the mesh.
* @type {number[] | Float32Array}
*/
positions: number[] | Float32Array;
/**
* The indices of the mesh.
* @type {number[] | Uint16Array | Uint32Array}
*/
indices: number[] | Uint16Array | Uint32Array;
/**
* The offset in the index buffer.
* @type {number}
*/
indexOffset: number;
/**
* The offset in the attribute buffer.
* @type {number}
*/
attributeOffset: number;
/**
* Indicates that this element should not be packed as a quad.
* @type {false}
*/
packAsQuad: false;
}
/**
* The options for the batcher.
* @memberof rendering
*/
export interface BatcherOptions {
/** The maximum number of textures per batch. */
maxTextures?: number;
attributesInitialSize?: number;
indicesInitialSize?: number;
}
/**
* A batcher is used to batch together objects with the same texture.
* It is an abstract class that must be extended. see DefaultBatcher for an example.
* @memberof rendering
*/
export declare abstract class Batcher {
static defaultOptions: Partial<BatcherOptions>;
/** unique id for this batcher */
readonly uid: number;
/** The buffer containing attribute data for all elements in the batch. */
attributeBuffer: ViewableBuffer;
/** The buffer containing index data for all elements in the batch. */
indexBuffer: IndexBufferArray;
/** The current size of the attribute data in the batch. */
attributeSize: number;
/** The current size of the index data in the batch. */
indexSize: number;
/** The total number of elements currently in the batch. */
elementSize: number;
/** The starting index of elements in the current batch. */
elementStart: number;
/** Indicates whether the batch data has been modified and needs updating. */
dirty: boolean;
/** The current index of the batch being processed. */
batchIndex: number;
/** An array of all batches created during the current rendering process. */
batches: Batch[];
private _elements;
private _batchIndexStart;
private _batchIndexSize;
/** The maximum number of textures per batch. */
readonly maxTextures: number;
/** The name of the batcher. Must be implemented by subclasses. */
abstract name: string;
/** The vertex size of the batcher. Must be implemented by subclasses. */
protected abstract vertexSize: number;
/** The geometry used by this batcher. Must be implemented by subclasses. */
abstract geometry: Geometry;
/**
* The shader used by this batcher. Must be implemented by subclasses.
* this can be shared by multiple batchers of the same type.
*/
abstract shader: Shader;
/**
* Packs the attributes of a BatchableMeshElement into the provided views.
* Must be implemented by subclasses.
* @param element - The BatchableMeshElement to pack.
* @param float32View - The Float32Array view to pack into.
* @param uint32View - The Uint32Array view to pack into.
* @param index - The starting index in the views.
* @param textureId - The texture ID to use.
*/
abstract packAttributes(element: BatchableMeshElement, float32View: Float32Array, uint32View: Uint32Array, index: number, textureId: number): void;
/**
* Packs the attributes of a BatchableQuadElement into the provided views.
* Must be implemented by subclasses.
* @param element - The BatchableQuadElement to pack.
* @param float32View - The Float32Array view to pack into.
* @param uint32View - The Uint32Array view to pack into.
* @param index - The starting index in the views.
* @param textureId - The texture ID to use.
*/
abstract packQuadAttributes(element: BatchableQuadElement, float32View: Float32Array, uint32View: Uint32Array, index: number, textureId: number): void;
constructor(options?: BatcherOptions);
begin(): void;
add(batchableObject: BatchableElement): void;
checkAndUpdateTexture(batchableObject: BatchableElement, texture: Texture): boolean;
updateElement(batchableObject: BatchableElement): void;
/**
* breaks the batcher. This happens when a batch gets too big,
* or we need to switch to a different type of rendering (a filter for example)
* @param instructionSet
*/
break(instructionSet: InstructionSet): void;
private _finishBatch;
finish(instructionSet: InstructionSet): void;
/**
* Resizes the attribute buffer to the given size (1 = 1 float32)
* @param size - the size in vertices to ensure (not bytes!)
*/
ensureAttributeBuffer(size: number): void;
/**
* Resizes the index buffer to the given size (1 = 1 float32)
* @param size - the size in vertices to ensure (not bytes!)
*/
ensureIndexBuffer(size: number): void;
private _resizeAttributeBuffer;
private _resizeIndexBuffer;
packQuadIndex(indexBuffer: IndexBufferArray, index: number, indicesOffset: number): void;
packIndex(element: BatchableMeshElement, indexBuffer: IndexBufferArray, index: number, indicesOffset: number): void;
destroy(): void;
}

View File

@@ -0,0 +1,341 @@
'use strict';
var uid = require('../../../utils/data/uid.js');
var ViewableBuffer = require('../../../utils/data/ViewableBuffer.js');
var fastCopy = require('../../renderers/shared/buffer/utils/fastCopy.js');
var getAdjustedBlendModeBlend = require('../../renderers/shared/state/getAdjustedBlendModeBlend.js');
var maxRecommendedTextures = require('../gl/utils/maxRecommendedTextures.js');
var BatchTextureArray = require('./BatchTextureArray.js');
"use strict";
class Batch {
constructor() {
this.renderPipeId = "batch";
this.action = "startBatch";
// TODO - eventually this could be useful for flagging batches as dirty and then only rebuilding those ones
// public elementStart = 0;
// public elementSize = 0;
// for drawing..
this.start = 0;
this.size = 0;
this.textures = new BatchTextureArray.BatchTextureArray();
this.blendMode = "normal";
this.canBundle = true;
}
destroy() {
this.textures = null;
this.gpuBindGroup = null;
this.bindGroup = null;
this.batcher = null;
}
}
const batchPool = [];
let batchPoolIndex = 0;
function getBatchFromPool() {
return batchPoolIndex > 0 ? batchPool[--batchPoolIndex] : new Batch();
}
function returnBatchToPool(batch) {
batchPool[batchPoolIndex++] = batch;
}
let BATCH_TICK = 0;
const _Batcher = class _Batcher {
constructor(options = {}) {
/** unique id for this batcher */
this.uid = uid.uid("batcher");
/** Indicates whether the batch data has been modified and needs updating. */
this.dirty = true;
/** The current index of the batch being processed. */
this.batchIndex = 0;
/** An array of all batches created during the current rendering process. */
this.batches = [];
this._elements = [];
_Batcher.defaultOptions.maxTextures = _Batcher.defaultOptions.maxTextures ?? maxRecommendedTextures.getMaxTexturesPerBatch();
options = { ..._Batcher.defaultOptions, ...options };
const { maxTextures, attributesInitialSize, indicesInitialSize } = options;
this.attributeBuffer = new ViewableBuffer.ViewableBuffer(attributesInitialSize * 4);
this.indexBuffer = new Uint16Array(indicesInitialSize);
this.maxTextures = maxTextures;
}
begin() {
this.elementSize = 0;
this.elementStart = 0;
this.indexSize = 0;
this.attributeSize = 0;
for (let i = 0; i < this.batchIndex; i++) {
returnBatchToPool(this.batches[i]);
}
this.batchIndex = 0;
this._batchIndexStart = 0;
this._batchIndexSize = 0;
this.dirty = true;
}
add(batchableObject) {
this._elements[this.elementSize++] = batchableObject;
batchableObject._indexStart = this.indexSize;
batchableObject._attributeStart = this.attributeSize;
batchableObject._batcher = this;
this.indexSize += batchableObject.indexSize;
this.attributeSize += batchableObject.attributeSize * this.vertexSize;
}
checkAndUpdateTexture(batchableObject, texture) {
const textureId = batchableObject._batch.textures.ids[texture._source.uid];
if (!textureId && textureId !== 0)
return false;
batchableObject._textureId = textureId;
batchableObject.texture = texture;
return true;
}
updateElement(batchableObject) {
this.dirty = true;
const attributeBuffer = this.attributeBuffer;
if (batchableObject.packAsQuad) {
this.packQuadAttributes(
batchableObject,
attributeBuffer.float32View,
attributeBuffer.uint32View,
batchableObject._attributeStart,
batchableObject._textureId
);
} else {
this.packAttributes(
batchableObject,
attributeBuffer.float32View,
attributeBuffer.uint32View,
batchableObject._attributeStart,
batchableObject._textureId
);
}
}
/**
* breaks the batcher. This happens when a batch gets too big,
* or we need to switch to a different type of rendering (a filter for example)
* @param instructionSet
*/
break(instructionSet) {
const elements = this._elements;
if (!elements[this.elementStart])
return;
let batch = getBatchFromPool();
let textureBatch = batch.textures;
textureBatch.clear();
const firstElement = elements[this.elementStart];
let blendMode = getAdjustedBlendModeBlend.getAdjustedBlendModeBlend(firstElement.blendMode, firstElement.texture._source);
if (this.attributeSize * 4 > this.attributeBuffer.size) {
this._resizeAttributeBuffer(this.attributeSize * 4);
}
if (this.indexSize > this.indexBuffer.length) {
this._resizeIndexBuffer(this.indexSize);
}
const f32 = this.attributeBuffer.float32View;
const u32 = this.attributeBuffer.uint32View;
const indexBuffer = this.indexBuffer;
let size = this._batchIndexSize;
let start = this._batchIndexStart;
let action = "startBatch";
const maxTextures = this.maxTextures;
for (let i = this.elementStart; i < this.elementSize; ++i) {
const element = elements[i];
elements[i] = null;
const texture = element.texture;
const source = texture._source;
const adjustedBlendMode = getAdjustedBlendModeBlend.getAdjustedBlendModeBlend(element.blendMode, source);
const breakRequired = blendMode !== adjustedBlendMode;
if (source._batchTick === BATCH_TICK && !breakRequired) {
element._textureId = source._textureBindLocation;
size += element.indexSize;
if (element.packAsQuad) {
this.packQuadAttributes(
element,
f32,
u32,
element._attributeStart,
element._textureId
);
this.packQuadIndex(
indexBuffer,
element._indexStart,
element._attributeStart / this.vertexSize
);
} else {
this.packAttributes(
element,
f32,
u32,
element._attributeStart,
element._textureId
);
this.packIndex(
element,
indexBuffer,
element._indexStart,
element._attributeStart / this.vertexSize
);
}
element._batch = batch;
continue;
}
source._batchTick = BATCH_TICK;
if (textureBatch.count >= maxTextures || breakRequired) {
this._finishBatch(
batch,
start,
size - start,
textureBatch,
blendMode,
instructionSet,
action
);
action = "renderBatch";
start = size;
blendMode = adjustedBlendMode;
batch = getBatchFromPool();
textureBatch = batch.textures;
textureBatch.clear();
++BATCH_TICK;
}
element._textureId = source._textureBindLocation = textureBatch.count;
textureBatch.ids[source.uid] = textureBatch.count;
textureBatch.textures[textureBatch.count++] = source;
element._batch = batch;
size += element.indexSize;
if (element.packAsQuad) {
this.packQuadAttributes(
element,
f32,
u32,
element._attributeStart,
element._textureId
);
this.packQuadIndex(
indexBuffer,
element._indexStart,
element._attributeStart / this.vertexSize
);
} else {
this.packAttributes(
element,
f32,
u32,
element._attributeStart,
element._textureId
);
this.packIndex(
element,
indexBuffer,
element._indexStart,
element._attributeStart / this.vertexSize
);
}
}
if (textureBatch.count > 0) {
this._finishBatch(
batch,
start,
size - start,
textureBatch,
blendMode,
instructionSet,
action
);
start = size;
++BATCH_TICK;
}
this.elementStart = this.elementSize;
this._batchIndexStart = start;
this._batchIndexSize = size;
}
_finishBatch(batch, indexStart, indexSize, textureBatch, blendMode, instructionSet, action) {
batch.gpuBindGroup = null;
batch.bindGroup = null;
batch.action = action;
batch.batcher = this;
batch.textures = textureBatch;
batch.blendMode = blendMode;
batch.start = indexStart;
batch.size = indexSize;
++BATCH_TICK;
this.batches[this.batchIndex++] = batch;
instructionSet.add(batch);
}
finish(instructionSet) {
this.break(instructionSet);
}
/**
* Resizes the attribute buffer to the given size (1 = 1 float32)
* @param size - the size in vertices to ensure (not bytes!)
*/
ensureAttributeBuffer(size) {
if (size * 4 <= this.attributeBuffer.size)
return;
this._resizeAttributeBuffer(size * 4);
}
/**
* Resizes the index buffer to the given size (1 = 1 float32)
* @param size - the size in vertices to ensure (not bytes!)
*/
ensureIndexBuffer(size) {
if (size <= this.indexBuffer.length)
return;
this._resizeIndexBuffer(size);
}
_resizeAttributeBuffer(size) {
const newSize = Math.max(size, this.attributeBuffer.size * 2);
const newArrayBuffer = new ViewableBuffer.ViewableBuffer(newSize);
fastCopy.fastCopy(this.attributeBuffer.rawBinaryData, newArrayBuffer.rawBinaryData);
this.attributeBuffer = newArrayBuffer;
}
_resizeIndexBuffer(size) {
const indexBuffer = this.indexBuffer;
let newSize = Math.max(size, indexBuffer.length * 1.5);
newSize += newSize % 2;
const newIndexBuffer = newSize > 65535 ? new Uint32Array(newSize) : new Uint16Array(newSize);
if (newIndexBuffer.BYTES_PER_ELEMENT !== indexBuffer.BYTES_PER_ELEMENT) {
for (let i = 0; i < indexBuffer.length; i++) {
newIndexBuffer[i] = indexBuffer[i];
}
} else {
fastCopy.fastCopy(indexBuffer.buffer, newIndexBuffer.buffer);
}
this.indexBuffer = newIndexBuffer;
}
packQuadIndex(indexBuffer, index, indicesOffset) {
indexBuffer[index] = indicesOffset + 0;
indexBuffer[index + 1] = indicesOffset + 1;
indexBuffer[index + 2] = indicesOffset + 2;
indexBuffer[index + 3] = indicesOffset + 0;
indexBuffer[index + 4] = indicesOffset + 2;
indexBuffer[index + 5] = indicesOffset + 3;
}
packIndex(element, indexBuffer, index, indicesOffset) {
const indices = element.indices;
const size = element.indexSize;
const indexOffset = element.indexOffset;
const attributeOffset = element.attributeOffset;
for (let i = 0; i < size; i++) {
indexBuffer[index++] = indicesOffset + indices[i + indexOffset] - attributeOffset;
}
}
destroy() {
for (let i = 0; i < this.batches.length; i++) {
returnBatchToPool(this.batches[i]);
}
this.batches = null;
for (let i = 0; i < this._elements.length; i++) {
this._elements[i]._batch = null;
}
this._elements = null;
this.indexBuffer = null;
this.attributeBuffer.destroy();
this.attributeBuffer = null;
}
};
_Batcher.defaultOptions = {
maxTextures: null,
attributesInitialSize: 4,
indicesInitialSize: 6
};
let Batcher = _Batcher;
exports.Batch = Batch;
exports.Batcher = Batcher;
//# sourceMappingURL=Batcher.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,338 @@
import { uid } from '../../../utils/data/uid.mjs';
import { ViewableBuffer } from '../../../utils/data/ViewableBuffer.mjs';
import { fastCopy } from '../../renderers/shared/buffer/utils/fastCopy.mjs';
import { getAdjustedBlendModeBlend } from '../../renderers/shared/state/getAdjustedBlendModeBlend.mjs';
import { getMaxTexturesPerBatch } from '../gl/utils/maxRecommendedTextures.mjs';
import { BatchTextureArray } from './BatchTextureArray.mjs';
"use strict";
class Batch {
constructor() {
this.renderPipeId = "batch";
this.action = "startBatch";
// TODO - eventually this could be useful for flagging batches as dirty and then only rebuilding those ones
// public elementStart = 0;
// public elementSize = 0;
// for drawing..
this.start = 0;
this.size = 0;
this.textures = new BatchTextureArray();
this.blendMode = "normal";
this.canBundle = true;
}
destroy() {
this.textures = null;
this.gpuBindGroup = null;
this.bindGroup = null;
this.batcher = null;
}
}
const batchPool = [];
let batchPoolIndex = 0;
function getBatchFromPool() {
return batchPoolIndex > 0 ? batchPool[--batchPoolIndex] : new Batch();
}
function returnBatchToPool(batch) {
batchPool[batchPoolIndex++] = batch;
}
let BATCH_TICK = 0;
const _Batcher = class _Batcher {
constructor(options = {}) {
/** unique id for this batcher */
this.uid = uid("batcher");
/** Indicates whether the batch data has been modified and needs updating. */
this.dirty = true;
/** The current index of the batch being processed. */
this.batchIndex = 0;
/** An array of all batches created during the current rendering process. */
this.batches = [];
this._elements = [];
_Batcher.defaultOptions.maxTextures = _Batcher.defaultOptions.maxTextures ?? getMaxTexturesPerBatch();
options = { ..._Batcher.defaultOptions, ...options };
const { maxTextures, attributesInitialSize, indicesInitialSize } = options;
this.attributeBuffer = new ViewableBuffer(attributesInitialSize * 4);
this.indexBuffer = new Uint16Array(indicesInitialSize);
this.maxTextures = maxTextures;
}
begin() {
this.elementSize = 0;
this.elementStart = 0;
this.indexSize = 0;
this.attributeSize = 0;
for (let i = 0; i < this.batchIndex; i++) {
returnBatchToPool(this.batches[i]);
}
this.batchIndex = 0;
this._batchIndexStart = 0;
this._batchIndexSize = 0;
this.dirty = true;
}
add(batchableObject) {
this._elements[this.elementSize++] = batchableObject;
batchableObject._indexStart = this.indexSize;
batchableObject._attributeStart = this.attributeSize;
batchableObject._batcher = this;
this.indexSize += batchableObject.indexSize;
this.attributeSize += batchableObject.attributeSize * this.vertexSize;
}
checkAndUpdateTexture(batchableObject, texture) {
const textureId = batchableObject._batch.textures.ids[texture._source.uid];
if (!textureId && textureId !== 0)
return false;
batchableObject._textureId = textureId;
batchableObject.texture = texture;
return true;
}
updateElement(batchableObject) {
this.dirty = true;
const attributeBuffer = this.attributeBuffer;
if (batchableObject.packAsQuad) {
this.packQuadAttributes(
batchableObject,
attributeBuffer.float32View,
attributeBuffer.uint32View,
batchableObject._attributeStart,
batchableObject._textureId
);
} else {
this.packAttributes(
batchableObject,
attributeBuffer.float32View,
attributeBuffer.uint32View,
batchableObject._attributeStart,
batchableObject._textureId
);
}
}
/**
* breaks the batcher. This happens when a batch gets too big,
* or we need to switch to a different type of rendering (a filter for example)
* @param instructionSet
*/
break(instructionSet) {
const elements = this._elements;
if (!elements[this.elementStart])
return;
let batch = getBatchFromPool();
let textureBatch = batch.textures;
textureBatch.clear();
const firstElement = elements[this.elementStart];
let blendMode = getAdjustedBlendModeBlend(firstElement.blendMode, firstElement.texture._source);
if (this.attributeSize * 4 > this.attributeBuffer.size) {
this._resizeAttributeBuffer(this.attributeSize * 4);
}
if (this.indexSize > this.indexBuffer.length) {
this._resizeIndexBuffer(this.indexSize);
}
const f32 = this.attributeBuffer.float32View;
const u32 = this.attributeBuffer.uint32View;
const indexBuffer = this.indexBuffer;
let size = this._batchIndexSize;
let start = this._batchIndexStart;
let action = "startBatch";
const maxTextures = this.maxTextures;
for (let i = this.elementStart; i < this.elementSize; ++i) {
const element = elements[i];
elements[i] = null;
const texture = element.texture;
const source = texture._source;
const adjustedBlendMode = getAdjustedBlendModeBlend(element.blendMode, source);
const breakRequired = blendMode !== adjustedBlendMode;
if (source._batchTick === BATCH_TICK && !breakRequired) {
element._textureId = source._textureBindLocation;
size += element.indexSize;
if (element.packAsQuad) {
this.packQuadAttributes(
element,
f32,
u32,
element._attributeStart,
element._textureId
);
this.packQuadIndex(
indexBuffer,
element._indexStart,
element._attributeStart / this.vertexSize
);
} else {
this.packAttributes(
element,
f32,
u32,
element._attributeStart,
element._textureId
);
this.packIndex(
element,
indexBuffer,
element._indexStart,
element._attributeStart / this.vertexSize
);
}
element._batch = batch;
continue;
}
source._batchTick = BATCH_TICK;
if (textureBatch.count >= maxTextures || breakRequired) {
this._finishBatch(
batch,
start,
size - start,
textureBatch,
blendMode,
instructionSet,
action
);
action = "renderBatch";
start = size;
blendMode = adjustedBlendMode;
batch = getBatchFromPool();
textureBatch = batch.textures;
textureBatch.clear();
++BATCH_TICK;
}
element._textureId = source._textureBindLocation = textureBatch.count;
textureBatch.ids[source.uid] = textureBatch.count;
textureBatch.textures[textureBatch.count++] = source;
element._batch = batch;
size += element.indexSize;
if (element.packAsQuad) {
this.packQuadAttributes(
element,
f32,
u32,
element._attributeStart,
element._textureId
);
this.packQuadIndex(
indexBuffer,
element._indexStart,
element._attributeStart / this.vertexSize
);
} else {
this.packAttributes(
element,
f32,
u32,
element._attributeStart,
element._textureId
);
this.packIndex(
element,
indexBuffer,
element._indexStart,
element._attributeStart / this.vertexSize
);
}
}
if (textureBatch.count > 0) {
this._finishBatch(
batch,
start,
size - start,
textureBatch,
blendMode,
instructionSet,
action
);
start = size;
++BATCH_TICK;
}
this.elementStart = this.elementSize;
this._batchIndexStart = start;
this._batchIndexSize = size;
}
_finishBatch(batch, indexStart, indexSize, textureBatch, blendMode, instructionSet, action) {
batch.gpuBindGroup = null;
batch.bindGroup = null;
batch.action = action;
batch.batcher = this;
batch.textures = textureBatch;
batch.blendMode = blendMode;
batch.start = indexStart;
batch.size = indexSize;
++BATCH_TICK;
this.batches[this.batchIndex++] = batch;
instructionSet.add(batch);
}
finish(instructionSet) {
this.break(instructionSet);
}
/**
* Resizes the attribute buffer to the given size (1 = 1 float32)
* @param size - the size in vertices to ensure (not bytes!)
*/
ensureAttributeBuffer(size) {
if (size * 4 <= this.attributeBuffer.size)
return;
this._resizeAttributeBuffer(size * 4);
}
/**
* Resizes the index buffer to the given size (1 = 1 float32)
* @param size - the size in vertices to ensure (not bytes!)
*/
ensureIndexBuffer(size) {
if (size <= this.indexBuffer.length)
return;
this._resizeIndexBuffer(size);
}
_resizeAttributeBuffer(size) {
const newSize = Math.max(size, this.attributeBuffer.size * 2);
const newArrayBuffer = new ViewableBuffer(newSize);
fastCopy(this.attributeBuffer.rawBinaryData, newArrayBuffer.rawBinaryData);
this.attributeBuffer = newArrayBuffer;
}
_resizeIndexBuffer(size) {
const indexBuffer = this.indexBuffer;
let newSize = Math.max(size, indexBuffer.length * 1.5);
newSize += newSize % 2;
const newIndexBuffer = newSize > 65535 ? new Uint32Array(newSize) : new Uint16Array(newSize);
if (newIndexBuffer.BYTES_PER_ELEMENT !== indexBuffer.BYTES_PER_ELEMENT) {
for (let i = 0; i < indexBuffer.length; i++) {
newIndexBuffer[i] = indexBuffer[i];
}
} else {
fastCopy(indexBuffer.buffer, newIndexBuffer.buffer);
}
this.indexBuffer = newIndexBuffer;
}
packQuadIndex(indexBuffer, index, indicesOffset) {
indexBuffer[index] = indicesOffset + 0;
indexBuffer[index + 1] = indicesOffset + 1;
indexBuffer[index + 2] = indicesOffset + 2;
indexBuffer[index + 3] = indicesOffset + 0;
indexBuffer[index + 4] = indicesOffset + 2;
indexBuffer[index + 5] = indicesOffset + 3;
}
packIndex(element, indexBuffer, index, indicesOffset) {
const indices = element.indices;
const size = element.indexSize;
const indexOffset = element.indexOffset;
const attributeOffset = element.attributeOffset;
for (let i = 0; i < size; i++) {
indexBuffer[index++] = indicesOffset + indices[i + indexOffset] - attributeOffset;
}
}
destroy() {
for (let i = 0; i < this.batches.length; i++) {
returnBatchToPool(this.batches[i]);
}
this.batches = null;
for (let i = 0; i < this._elements.length; i++) {
this._elements[i]._batch = null;
}
this._elements = null;
this.indexBuffer = null;
this.attributeBuffer.destroy();
this.attributeBuffer = null;
}
};
_Batcher.defaultOptions = {
maxTextures: null,
attributesInitialSize: 4,
indicesInitialSize: 6
};
let Batcher = _Batcher;
export { Batch, Batcher };
//# sourceMappingURL=Batcher.mjs.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,46 @@
import { ExtensionType } from '../../../extensions/Extensions';
import { State } from '../../renderers/shared/state/State';
import type { Geometry } from '../../renderers/shared/geometry/Geometry';
import type { InstructionSet } from '../../renderers/shared/instructions/InstructionSet';
import type { BatchPipe, InstructionPipe } from '../../renderers/shared/instructions/RenderPipe';
import type { Shader } from '../../renderers/shared/shader/Shader';
import type { Renderer } from '../../renderers/types';
import type { Batch, BatchableElement, Batcher } from './Batcher';
export interface BatcherAdaptor {
start(batchPipe: BatcherPipe, geometry: Geometry, shader: Shader): void;
init?(batchPipe: BatcherPipe): void;
execute(batchPipe: BatcherPipe, batch: Batch): void;
contextChange?(): void;
}
/**
* A pipe that batches elements into batches and sends them to the renderer.
*
* You can install new Batchers using ExtensionType.Batcher. Each render group will
* have a default batcher and any required ones will be created on demand.
* @memberof rendering
*/
export declare class BatcherPipe implements InstructionPipe<Batch>, BatchPipe {
/** @ignore */
static extension: {
readonly type: readonly [ExtensionType.WebGLPipes, ExtensionType.WebGPUPipes, ExtensionType.CanvasPipes];
readonly name: "batch";
};
state: State;
renderer: Renderer;
private readonly _batchersByInstructionSet;
private _adaptor;
/** A record of all active batchers, keyed by their names */
private _activeBatches;
/** The currently active batcher being used to batch elements */
private _activeBatch;
static _availableBatchers: Record<string, new () => Batcher>;
static getBatcher(name: string): Batcher;
constructor(renderer: Renderer, adaptor: BatcherAdaptor);
buildStart(instructionSet: InstructionSet): void;
addToBatch(batchableObject: BatchableElement, instructionSet: InstructionSet): void;
break(instructionSet: InstructionSet): void;
buildEnd(instructionSet: InstructionSet): void;
upload(instructionSet: InstructionSet): void;
execute(batch: Batch): void;
destroy(): void;
}

View File

@@ -0,0 +1,103 @@
'use strict';
var Extensions = require('../../../extensions/Extensions.js');
var State = require('../../renderers/shared/state/State.js');
var DefaultBatcher = require('./DefaultBatcher.js');
"use strict";
const _BatcherPipe = class _BatcherPipe {
constructor(renderer, adaptor) {
this.state = State.State.for2d();
this._batchersByInstructionSet = /* @__PURE__ */ Object.create(null);
/** A record of all active batchers, keyed by their names */
this._activeBatches = /* @__PURE__ */ Object.create(null);
this.renderer = renderer;
this._adaptor = adaptor;
this._adaptor.init?.(this);
}
static getBatcher(name) {
return new this._availableBatchers[name]();
}
buildStart(instructionSet) {
let batchers = this._batchersByInstructionSet[instructionSet.uid];
if (!batchers) {
batchers = this._batchersByInstructionSet[instructionSet.uid] = /* @__PURE__ */ Object.create(null);
batchers.default || (batchers.default = new DefaultBatcher.DefaultBatcher());
}
this._activeBatches = batchers;
this._activeBatch = this._activeBatches.default;
for (const i in this._activeBatches) {
this._activeBatches[i].begin();
}
}
addToBatch(batchableObject, instructionSet) {
if (this._activeBatch.name !== batchableObject.batcherName) {
this._activeBatch.break(instructionSet);
let batch = this._activeBatches[batchableObject.batcherName];
if (!batch) {
batch = this._activeBatches[batchableObject.batcherName] = _BatcherPipe.getBatcher(batchableObject.batcherName);
batch.begin();
}
this._activeBatch = batch;
}
this._activeBatch.add(batchableObject);
}
break(instructionSet) {
this._activeBatch.break(instructionSet);
}
buildEnd(instructionSet) {
this._activeBatch.break(instructionSet);
const batches = this._activeBatches;
for (const i in batches) {
const batch = batches[i];
const geometry = batch.geometry;
geometry.indexBuffer.setDataWithSize(batch.indexBuffer, batch.indexSize, true);
geometry.buffers[0].setDataWithSize(batch.attributeBuffer.float32View, batch.attributeSize, false);
}
}
upload(instructionSet) {
const batchers = this._batchersByInstructionSet[instructionSet.uid];
for (const i in batchers) {
const batcher = batchers[i];
const geometry = batcher.geometry;
if (batcher.dirty) {
batcher.dirty = false;
geometry.buffers[0].update(batcher.attributeSize * 4);
}
}
}
execute(batch) {
if (batch.action === "startBatch") {
const batcher = batch.batcher;
const geometry = batcher.geometry;
const shader = batcher.shader;
this._adaptor.start(this, geometry, shader);
}
this._adaptor.execute(this, batch);
}
destroy() {
this.state = null;
this.renderer = null;
this._adaptor = null;
for (const i in this._activeBatches) {
this._activeBatches[i].destroy();
}
this._activeBatches = null;
}
};
/** @ignore */
_BatcherPipe.extension = {
type: [
Extensions.ExtensionType.WebGLPipes,
Extensions.ExtensionType.WebGPUPipes,
Extensions.ExtensionType.CanvasPipes
],
name: "batch"
};
_BatcherPipe._availableBatchers = /* @__PURE__ */ Object.create(null);
let BatcherPipe = _BatcherPipe;
Extensions.extensions.handleByMap(Extensions.ExtensionType.Batcher, BatcherPipe._availableBatchers);
Extensions.extensions.add(DefaultBatcher.DefaultBatcher);
exports.BatcherPipe = BatcherPipe;
//# sourceMappingURL=BatcherPipe.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,101 @@
import { ExtensionType, extensions } from '../../../extensions/Extensions.mjs';
import { State } from '../../renderers/shared/state/State.mjs';
import { DefaultBatcher } from './DefaultBatcher.mjs';
"use strict";
const _BatcherPipe = class _BatcherPipe {
constructor(renderer, adaptor) {
this.state = State.for2d();
this._batchersByInstructionSet = /* @__PURE__ */ Object.create(null);
/** A record of all active batchers, keyed by their names */
this._activeBatches = /* @__PURE__ */ Object.create(null);
this.renderer = renderer;
this._adaptor = adaptor;
this._adaptor.init?.(this);
}
static getBatcher(name) {
return new this._availableBatchers[name]();
}
buildStart(instructionSet) {
let batchers = this._batchersByInstructionSet[instructionSet.uid];
if (!batchers) {
batchers = this._batchersByInstructionSet[instructionSet.uid] = /* @__PURE__ */ Object.create(null);
batchers.default || (batchers.default = new DefaultBatcher());
}
this._activeBatches = batchers;
this._activeBatch = this._activeBatches.default;
for (const i in this._activeBatches) {
this._activeBatches[i].begin();
}
}
addToBatch(batchableObject, instructionSet) {
if (this._activeBatch.name !== batchableObject.batcherName) {
this._activeBatch.break(instructionSet);
let batch = this._activeBatches[batchableObject.batcherName];
if (!batch) {
batch = this._activeBatches[batchableObject.batcherName] = _BatcherPipe.getBatcher(batchableObject.batcherName);
batch.begin();
}
this._activeBatch = batch;
}
this._activeBatch.add(batchableObject);
}
break(instructionSet) {
this._activeBatch.break(instructionSet);
}
buildEnd(instructionSet) {
this._activeBatch.break(instructionSet);
const batches = this._activeBatches;
for (const i in batches) {
const batch = batches[i];
const geometry = batch.geometry;
geometry.indexBuffer.setDataWithSize(batch.indexBuffer, batch.indexSize, true);
geometry.buffers[0].setDataWithSize(batch.attributeBuffer.float32View, batch.attributeSize, false);
}
}
upload(instructionSet) {
const batchers = this._batchersByInstructionSet[instructionSet.uid];
for (const i in batchers) {
const batcher = batchers[i];
const geometry = batcher.geometry;
if (batcher.dirty) {
batcher.dirty = false;
geometry.buffers[0].update(batcher.attributeSize * 4);
}
}
}
execute(batch) {
if (batch.action === "startBatch") {
const batcher = batch.batcher;
const geometry = batcher.geometry;
const shader = batcher.shader;
this._adaptor.start(this, geometry, shader);
}
this._adaptor.execute(this, batch);
}
destroy() {
this.state = null;
this.renderer = null;
this._adaptor = null;
for (const i in this._activeBatches) {
this._activeBatches[i].destroy();
}
this._activeBatches = null;
}
};
/** @ignore */
_BatcherPipe.extension = {
type: [
ExtensionType.WebGLPipes,
ExtensionType.WebGPUPipes,
ExtensionType.CanvasPipes
],
name: "batch"
};
_BatcherPipe._availableBatchers = /* @__PURE__ */ Object.create(null);
let BatcherPipe = _BatcherPipe;
extensions.handleByMap(ExtensionType.Batcher, BatcherPipe._availableBatchers);
extensions.add(DefaultBatcher);
export { BatcherPipe };
//# sourceMappingURL=BatcherPipe.mjs.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,81 @@
import { ExtensionType } from '../../../extensions/Extensions';
import { Batcher } from './Batcher';
import { BatchGeometry } from './BatchGeometry';
import type { Matrix } from '../../../maths/matrix/Matrix';
import type { Shader } from '../../renderers/shared/shader/Shader';
import type { BatchableMeshElement, BatchableQuadElement } from './Batcher';
/**
* Represents the common elements for default batch rendering.
* This interface defines the properties that are used by the DefaultBatcher
* to render elements efficiently in a batch.
* @memberof rendering
*/
export interface DefaultBatchElements {
/**
* The color of the element that will be multiplied with the texture color.
* This is typically represented as a 32-bit integer in RGBA format.
*/
color: number;
/**
* Determines whether the element should be rounded to the nearest pixel.
* - 0: No rounding (default)
* - 1: Round to nearest pixel
* This can help with visual consistency, especially for pixel art styles.
*/
roundPixels: 0 | 1;
/**
* The transform matrix of the element.
* This matrix represents the position, scale, rotation, and skew of the element.
*/
transform: Matrix;
}
/**
* Represents a batchable quad element with default batch properties.
* @memberof rendering
*/
export interface DefaultBatchableQuadElement extends BatchableQuadElement, DefaultBatchElements {
}
/**
* Represents a batchable mesh element with default batch properties.
* @memberof rendering
*/
export interface DefaultBatchableMeshElement extends BatchableMeshElement, DefaultBatchElements {
}
/**
* The default batcher is used to batch quads and meshes. This batcher will batch the following elements:
* - tints
* - roundPixels
* - texture
* - transform
* @memberof rendering
*/
export declare class DefaultBatcher extends Batcher {
/** @ignore */
static extension: {
readonly type: readonly [ExtensionType.Batcher];
readonly name: "default";
};
geometry: BatchGeometry;
shader: Shader;
name: "default";
/** The size of one attribute. 1 = 32 bit. x, y, u, v, color, textureIdAndRound -> total = 6 */
vertexSize: number;
/**
* Packs the attributes of a DefaultBatchableMeshElement into the provided views.
* @param element - The DefaultBatchableMeshElement to pack.
* @param float32View - The Float32Array view to pack into.
* @param uint32View - The Uint32Array view to pack into.
* @param index - The starting index in the views.
* @param textureId - The texture ID to use.
*/
packAttributes(element: DefaultBatchableMeshElement, float32View: Float32Array, uint32View: Uint32Array, index: number, textureId: number): void;
/**
* Packs the attributes of a DefaultBatchableQuadElement into the provided views.
* @param element - The DefaultBatchableQuadElement to pack.
* @param float32View - The Float32Array view to pack into.
* @param uint32View - The Uint32Array view to pack into.
* @param index - The starting index in the views.
* @param textureId - The texture ID to use.
*/
packQuadAttributes(element: DefaultBatchableQuadElement, float32View: Float32Array, uint32View: Uint32Array, index: number, textureId: number): void;
}

View File

@@ -0,0 +1,113 @@
'use strict';
var Extensions = require('../../../extensions/Extensions.js');
var Batcher = require('./Batcher.js');
var BatchGeometry = require('./BatchGeometry.js');
var DefaultShader = require('./DefaultShader.js');
"use strict";
let defaultShader = null;
const _DefaultBatcher = class _DefaultBatcher extends Batcher.Batcher {
constructor() {
super(...arguments);
this.geometry = new BatchGeometry.BatchGeometry();
this.shader = defaultShader || (defaultShader = new DefaultShader.DefaultShader(this.maxTextures));
this.name = _DefaultBatcher.extension.name;
/** The size of one attribute. 1 = 32 bit. x, y, u, v, color, textureIdAndRound -> total = 6 */
this.vertexSize = 6;
}
/**
* Packs the attributes of a DefaultBatchableMeshElement into the provided views.
* @param element - The DefaultBatchableMeshElement to pack.
* @param float32View - The Float32Array view to pack into.
* @param uint32View - The Uint32Array view to pack into.
* @param index - The starting index in the views.
* @param textureId - The texture ID to use.
*/
packAttributes(element, float32View, uint32View, index, textureId) {
const textureIdAndRound = textureId << 16 | element.roundPixels & 65535;
const wt = element.transform;
const a = wt.a;
const b = wt.b;
const c = wt.c;
const d = wt.d;
const tx = wt.tx;
const ty = wt.ty;
const { positions, uvs } = element;
const argb = element.color;
const offset = element.attributeOffset;
const end = offset + element.attributeSize;
for (let i = offset; i < end; i++) {
const i2 = i * 2;
const x = positions[i2];
const y = positions[i2 + 1];
float32View[index++] = a * x + c * y + tx;
float32View[index++] = d * y + b * x + ty;
float32View[index++] = uvs[i2];
float32View[index++] = uvs[i2 + 1];
uint32View[index++] = argb;
uint32View[index++] = textureIdAndRound;
}
}
/**
* Packs the attributes of a DefaultBatchableQuadElement into the provided views.
* @param element - The DefaultBatchableQuadElement to pack.
* @param float32View - The Float32Array view to pack into.
* @param uint32View - The Uint32Array view to pack into.
* @param index - The starting index in the views.
* @param textureId - The texture ID to use.
*/
packQuadAttributes(element, float32View, uint32View, index, textureId) {
const texture = element.texture;
const wt = element.transform;
const a = wt.a;
const b = wt.b;
const c = wt.c;
const d = wt.d;
const tx = wt.tx;
const ty = wt.ty;
const bounds = element.bounds;
const w0 = bounds.maxX;
const w1 = bounds.minX;
const h0 = bounds.maxY;
const h1 = bounds.minY;
const uvs = texture.uvs;
const argb = element.color;
const textureIdAndRound = textureId << 16 | element.roundPixels & 65535;
float32View[index + 0] = a * w1 + c * h1 + tx;
float32View[index + 1] = d * h1 + b * w1 + ty;
float32View[index + 2] = uvs.x0;
float32View[index + 3] = uvs.y0;
uint32View[index + 4] = argb;
uint32View[index + 5] = textureIdAndRound;
float32View[index + 6] = a * w0 + c * h1 + tx;
float32View[index + 7] = d * h1 + b * w0 + ty;
float32View[index + 8] = uvs.x1;
float32View[index + 9] = uvs.y1;
uint32View[index + 10] = argb;
uint32View[index + 11] = textureIdAndRound;
float32View[index + 12] = a * w0 + c * h0 + tx;
float32View[index + 13] = d * h0 + b * w0 + ty;
float32View[index + 14] = uvs.x2;
float32View[index + 15] = uvs.y2;
uint32View[index + 16] = argb;
uint32View[index + 17] = textureIdAndRound;
float32View[index + 18] = a * w1 + c * h0 + tx;
float32View[index + 19] = d * h0 + b * w1 + ty;
float32View[index + 20] = uvs.x3;
float32View[index + 21] = uvs.y3;
uint32View[index + 22] = argb;
uint32View[index + 23] = textureIdAndRound;
}
};
/** @ignore */
_DefaultBatcher.extension = {
type: [
Extensions.ExtensionType.Batcher
],
name: "default"
};
let DefaultBatcher = _DefaultBatcher;
exports.DefaultBatcher = DefaultBatcher;
//# sourceMappingURL=DefaultBatcher.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,111 @@
import { ExtensionType } from '../../../extensions/Extensions.mjs';
import { Batcher } from './Batcher.mjs';
import { BatchGeometry } from './BatchGeometry.mjs';
import { DefaultShader } from './DefaultShader.mjs';
"use strict";
let defaultShader = null;
const _DefaultBatcher = class _DefaultBatcher extends Batcher {
constructor() {
super(...arguments);
this.geometry = new BatchGeometry();
this.shader = defaultShader || (defaultShader = new DefaultShader(this.maxTextures));
this.name = _DefaultBatcher.extension.name;
/** The size of one attribute. 1 = 32 bit. x, y, u, v, color, textureIdAndRound -> total = 6 */
this.vertexSize = 6;
}
/**
* Packs the attributes of a DefaultBatchableMeshElement into the provided views.
* @param element - The DefaultBatchableMeshElement to pack.
* @param float32View - The Float32Array view to pack into.
* @param uint32View - The Uint32Array view to pack into.
* @param index - The starting index in the views.
* @param textureId - The texture ID to use.
*/
packAttributes(element, float32View, uint32View, index, textureId) {
const textureIdAndRound = textureId << 16 | element.roundPixels & 65535;
const wt = element.transform;
const a = wt.a;
const b = wt.b;
const c = wt.c;
const d = wt.d;
const tx = wt.tx;
const ty = wt.ty;
const { positions, uvs } = element;
const argb = element.color;
const offset = element.attributeOffset;
const end = offset + element.attributeSize;
for (let i = offset; i < end; i++) {
const i2 = i * 2;
const x = positions[i2];
const y = positions[i2 + 1];
float32View[index++] = a * x + c * y + tx;
float32View[index++] = d * y + b * x + ty;
float32View[index++] = uvs[i2];
float32View[index++] = uvs[i2 + 1];
uint32View[index++] = argb;
uint32View[index++] = textureIdAndRound;
}
}
/**
* Packs the attributes of a DefaultBatchableQuadElement into the provided views.
* @param element - The DefaultBatchableQuadElement to pack.
* @param float32View - The Float32Array view to pack into.
* @param uint32View - The Uint32Array view to pack into.
* @param index - The starting index in the views.
* @param textureId - The texture ID to use.
*/
packQuadAttributes(element, float32View, uint32View, index, textureId) {
const texture = element.texture;
const wt = element.transform;
const a = wt.a;
const b = wt.b;
const c = wt.c;
const d = wt.d;
const tx = wt.tx;
const ty = wt.ty;
const bounds = element.bounds;
const w0 = bounds.maxX;
const w1 = bounds.minX;
const h0 = bounds.maxY;
const h1 = bounds.minY;
const uvs = texture.uvs;
const argb = element.color;
const textureIdAndRound = textureId << 16 | element.roundPixels & 65535;
float32View[index + 0] = a * w1 + c * h1 + tx;
float32View[index + 1] = d * h1 + b * w1 + ty;
float32View[index + 2] = uvs.x0;
float32View[index + 3] = uvs.y0;
uint32View[index + 4] = argb;
uint32View[index + 5] = textureIdAndRound;
float32View[index + 6] = a * w0 + c * h1 + tx;
float32View[index + 7] = d * h1 + b * w0 + ty;
float32View[index + 8] = uvs.x1;
float32View[index + 9] = uvs.y1;
uint32View[index + 10] = argb;
uint32View[index + 11] = textureIdAndRound;
float32View[index + 12] = a * w0 + c * h0 + tx;
float32View[index + 13] = d * h0 + b * w0 + ty;
float32View[index + 14] = uvs.x2;
float32View[index + 15] = uvs.y2;
uint32View[index + 16] = argb;
uint32View[index + 17] = textureIdAndRound;
float32View[index + 18] = a * w1 + c * h0 + tx;
float32View[index + 19] = d * h0 + b * w1 + ty;
float32View[index + 20] = uvs.x3;
float32View[index + 21] = uvs.y3;
uint32View[index + 22] = argb;
uint32View[index + 23] = textureIdAndRound;
}
};
/** @ignore */
_DefaultBatcher.extension = {
type: [
ExtensionType.Batcher
],
name: "default"
};
let DefaultBatcher = _DefaultBatcher;
export { DefaultBatcher };
//# sourceMappingURL=DefaultBatcher.mjs.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,13 @@
import { Shader } from '../../renderers/shared/shader/Shader';
/**
* DefaultShader is a specialized shader class designed for batch rendering.
* It extends the base Shader class and provides functionality for handling
* color, texture batching, and pixel rounding in both WebGL and WebGPU contexts.
*
* It is used by the default batcher
* @extends Shader
* @memberof rendering
*/
export declare class DefaultShader extends Shader {
constructor(maxTextures: number);
}

View File

@@ -0,0 +1,40 @@
'use strict';
var compileHighShaderToProgram = require('../../high-shader/compileHighShaderToProgram.js');
var colorBit = require('../../high-shader/shader-bits/colorBit.js');
var generateTextureBatchBit = require('../../high-shader/shader-bits/generateTextureBatchBit.js');
var roundPixelsBit = require('../../high-shader/shader-bits/roundPixelsBit.js');
var getBatchSamplersUniformGroup = require('../../renderers/gl/shader/getBatchSamplersUniformGroup.js');
var Shader = require('../../renderers/shared/shader/Shader.js');
"use strict";
class DefaultShader extends Shader.Shader {
constructor(maxTextures) {
const glProgram = compileHighShaderToProgram.compileHighShaderGlProgram({
name: "batch",
bits: [
colorBit.colorBitGl,
generateTextureBatchBit.generateTextureBatchBitGl(maxTextures),
roundPixelsBit.roundPixelsBitGl
]
});
const gpuProgram = compileHighShaderToProgram.compileHighShaderGpuProgram({
name: "batch",
bits: [
colorBit.colorBit,
generateTextureBatchBit.generateTextureBatchBit(maxTextures),
roundPixelsBit.roundPixelsBit
]
});
super({
glProgram,
gpuProgram,
resources: {
batchSamplers: getBatchSamplersUniformGroup.getBatchSamplersUniformGroup(maxTextures)
}
});
}
}
exports.DefaultShader = DefaultShader;
//# sourceMappingURL=DefaultShader.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"DefaultShader.js","sources":["../../../../src/rendering/batcher/shared/DefaultShader.ts"],"sourcesContent":["import { compileHighShaderGlProgram, compileHighShaderGpuProgram } from '../../high-shader/compileHighShaderToProgram';\nimport { colorBit, colorBitGl } from '../../high-shader/shader-bits/colorBit';\nimport { generateTextureBatchBit, generateTextureBatchBitGl } from '../../high-shader/shader-bits/generateTextureBatchBit';\nimport { roundPixelsBit, roundPixelsBitGl } from '../../high-shader/shader-bits/roundPixelsBit';\nimport { getBatchSamplersUniformGroup } from '../../renderers/gl/shader/getBatchSamplersUniformGroup';\nimport { Shader } from '../../renderers/shared/shader/Shader';\n\n/**\n * DefaultShader is a specialized shader class designed for batch rendering.\n * It extends the base Shader class and provides functionality for handling\n * color, texture batching, and pixel rounding in both WebGL and WebGPU contexts.\n *\n * It is used by the default batcher\n * @extends Shader\n * @memberof rendering\n */\nexport class DefaultShader extends Shader\n{\n constructor(maxTextures: number)\n {\n const glProgram = compileHighShaderGlProgram({\n name: 'batch',\n bits: [\n colorBitGl,\n generateTextureBatchBitGl(maxTextures),\n roundPixelsBitGl,\n ]\n });\n\n const gpuProgram = compileHighShaderGpuProgram({\n name: 'batch',\n bits: [\n colorBit,\n generateTextureBatchBit(maxTextures),\n roundPixelsBit,\n ]\n });\n\n super({\n glProgram,\n gpuProgram,\n resources: {\n batchSamplers: getBatchSamplersUniformGroup(maxTextures),\n }\n });\n }\n}\n"],"names":["Shader","compileHighShaderGlProgram","colorBitGl","generateTextureBatchBitGl","roundPixelsBitGl","compileHighShaderGpuProgram","colorBit","generateTextureBatchBit","roundPixelsBit","getBatchSamplersUniformGroup"],"mappings":";;;;;;;;;;AAgBO,MAAM,sBAAsBA,aACnC,CAAA;AAAA,EACI,YAAY,WACZ,EAAA;AACI,IAAA,MAAM,YAAYC,qDAA2B,CAAA;AAAA,MACzC,IAAM,EAAA,OAAA;AAAA,MACN,IAAM,EAAA;AAAA,QACFC,mBAAA;AAAA,QACAC,kDAA0B,WAAW,CAAA;AAAA,QACrCC,+BAAA;AAAA,OACJ;AAAA,KACH,CAAA,CAAA;AAED,IAAA,MAAM,aAAaC,sDAA4B,CAAA;AAAA,MAC3C,IAAM,EAAA,OAAA;AAAA,MACN,IAAM,EAAA;AAAA,QACFC,iBAAA;AAAA,QACAC,gDAAwB,WAAW,CAAA;AAAA,QACnCC,6BAAA;AAAA,OACJ;AAAA,KACH,CAAA,CAAA;AAED,IAAM,KAAA,CAAA;AAAA,MACF,SAAA;AAAA,MACA,UAAA;AAAA,MACA,SAAW,EAAA;AAAA,QACP,aAAA,EAAeC,0DAA6B,WAAW,CAAA;AAAA,OAC3D;AAAA,KACH,CAAA,CAAA;AAAA,GACL;AACJ;;;;"}

View File

@@ -0,0 +1,38 @@
import { compileHighShaderGlProgram, compileHighShaderGpuProgram } from '../../high-shader/compileHighShaderToProgram.mjs';
import { colorBitGl, colorBit } from '../../high-shader/shader-bits/colorBit.mjs';
import { generateTextureBatchBitGl, generateTextureBatchBit } from '../../high-shader/shader-bits/generateTextureBatchBit.mjs';
import { roundPixelsBitGl, roundPixelsBit } from '../../high-shader/shader-bits/roundPixelsBit.mjs';
import { getBatchSamplersUniformGroup } from '../../renderers/gl/shader/getBatchSamplersUniformGroup.mjs';
import { Shader } from '../../renderers/shared/shader/Shader.mjs';
"use strict";
class DefaultShader extends Shader {
constructor(maxTextures) {
const glProgram = compileHighShaderGlProgram({
name: "batch",
bits: [
colorBitGl,
generateTextureBatchBitGl(maxTextures),
roundPixelsBitGl
]
});
const gpuProgram = compileHighShaderGpuProgram({
name: "batch",
bits: [
colorBit,
generateTextureBatchBit(maxTextures),
roundPixelsBit
]
});
super({
glProgram,
gpuProgram,
resources: {
batchSamplers: getBatchSamplersUniformGroup(maxTextures)
}
});
}
}
export { DefaultShader };
//# sourceMappingURL=DefaultShader.mjs.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"DefaultShader.mjs","sources":["../../../../src/rendering/batcher/shared/DefaultShader.ts"],"sourcesContent":["import { compileHighShaderGlProgram, compileHighShaderGpuProgram } from '../../high-shader/compileHighShaderToProgram';\nimport { colorBit, colorBitGl } from '../../high-shader/shader-bits/colorBit';\nimport { generateTextureBatchBit, generateTextureBatchBitGl } from '../../high-shader/shader-bits/generateTextureBatchBit';\nimport { roundPixelsBit, roundPixelsBitGl } from '../../high-shader/shader-bits/roundPixelsBit';\nimport { getBatchSamplersUniformGroup } from '../../renderers/gl/shader/getBatchSamplersUniformGroup';\nimport { Shader } from '../../renderers/shared/shader/Shader';\n\n/**\n * DefaultShader is a specialized shader class designed for batch rendering.\n * It extends the base Shader class and provides functionality for handling\n * color, texture batching, and pixel rounding in both WebGL and WebGPU contexts.\n *\n * It is used by the default batcher\n * @extends Shader\n * @memberof rendering\n */\nexport class DefaultShader extends Shader\n{\n constructor(maxTextures: number)\n {\n const glProgram = compileHighShaderGlProgram({\n name: 'batch',\n bits: [\n colorBitGl,\n generateTextureBatchBitGl(maxTextures),\n roundPixelsBitGl,\n ]\n });\n\n const gpuProgram = compileHighShaderGpuProgram({\n name: 'batch',\n bits: [\n colorBit,\n generateTextureBatchBit(maxTextures),\n roundPixelsBit,\n ]\n });\n\n super({\n glProgram,\n gpuProgram,\n resources: {\n batchSamplers: getBatchSamplersUniformGroup(maxTextures),\n }\n });\n }\n}\n"],"names":[],"mappings":";;;;;;;;AAgBO,MAAM,sBAAsB,MACnC,CAAA;AAAA,EACI,YAAY,WACZ,EAAA;AACI,IAAA,MAAM,YAAY,0BAA2B,CAAA;AAAA,MACzC,IAAM,EAAA,OAAA;AAAA,MACN,IAAM,EAAA;AAAA,QACF,UAAA;AAAA,QACA,0BAA0B,WAAW,CAAA;AAAA,QACrC,gBAAA;AAAA,OACJ;AAAA,KACH,CAAA,CAAA;AAED,IAAA,MAAM,aAAa,2BAA4B,CAAA;AAAA,MAC3C,IAAM,EAAA,OAAA;AAAA,MACN,IAAM,EAAA;AAAA,QACF,QAAA;AAAA,QACA,wBAAwB,WAAW,CAAA;AAAA,QACnC,cAAA;AAAA,OACJ;AAAA,KACH,CAAA,CAAA;AAED,IAAM,KAAA,CAAA;AAAA,MACF,SAAA;AAAA,MACA,UAAA;AAAA,MACA,SAAW,EAAA;AAAA,QACP,aAAA,EAAe,6BAA6B,WAAW,CAAA;AAAA,OAC3D;AAAA,KACH,CAAA,CAAA;AAAA,GACL;AACJ;;;;"}

View File

@@ -0,0 +1,11 @@
import { GlProgram } from '../renderers/gl/shader/GlProgram';
import { GpuProgram } from '../renderers/gpu/shader/GpuProgram';
import type { HighShaderBit } from './compiler/types';
export declare function compileHighShaderGpuProgram({ bits, name }: {
bits: HighShaderBit[];
name: string;
}): GpuProgram;
export declare function compileHighShaderGlProgram({ bits, name }: {
bits: HighShaderBit[];
name: string;
}): GlProgram;

View File

@@ -0,0 +1,51 @@
'use strict';
var GlProgram = require('../renderers/gl/shader/GlProgram.js');
var GpuProgram = require('../renderers/gpu/shader/GpuProgram.js');
var compileHighShader = require('./compiler/compileHighShader.js');
var defaultProgramTemplate = require('./defaultProgramTemplate.js');
var globalUniformsBit = require('./shader-bits/globalUniformsBit.js');
"use strict";
function compileHighShaderGpuProgram({ bits, name }) {
const source = compileHighShader.compileHighShader({
template: {
fragment: defaultProgramTemplate.fragmentGPUTemplate,
vertex: defaultProgramTemplate.vertexGPUTemplate
},
bits: [
globalUniformsBit.globalUniformsBit,
...bits
]
});
return GpuProgram.GpuProgram.from({
name,
vertex: {
source: source.vertex,
entryPoint: "main"
},
fragment: {
source: source.fragment,
entryPoint: "main"
}
});
}
function compileHighShaderGlProgram({ bits, name }) {
return new GlProgram.GlProgram({
name,
...compileHighShader.compileHighShaderGl({
template: {
vertex: defaultProgramTemplate.vertexGlTemplate,
fragment: defaultProgramTemplate.fragmentGlTemplate
},
bits: [
globalUniformsBit.globalUniformsBitGl,
...bits
]
})
});
}
exports.compileHighShaderGlProgram = compileHighShaderGlProgram;
exports.compileHighShaderGpuProgram = compileHighShaderGpuProgram;
//# sourceMappingURL=compileHighShaderToProgram.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"compileHighShaderToProgram.js","sources":["../../../src/rendering/high-shader/compileHighShaderToProgram.ts"],"sourcesContent":["import { GlProgram } from '../renderers/gl/shader/GlProgram';\nimport { GpuProgram } from '../renderers/gpu/shader/GpuProgram';\nimport { compileHighShader, compileHighShaderGl } from './compiler/compileHighShader';\nimport { fragmentGlTemplate, fragmentGPUTemplate, vertexGlTemplate, vertexGPUTemplate } from './defaultProgramTemplate';\nimport { globalUniformsBit, globalUniformsBitGl } from './shader-bits/globalUniformsBit';\n\nimport type { HighShaderBit } from './compiler/types';\n\nexport function compileHighShaderGpuProgram({ bits, name }: {bits: HighShaderBit[], name: string}): GpuProgram\n{\n const source = compileHighShader({\n template: {\n fragment: fragmentGPUTemplate,\n vertex: vertexGPUTemplate,\n },\n bits: [\n globalUniformsBit,\n ...bits,\n ]\n });\n\n return GpuProgram.from({\n name,\n vertex: {\n source: source.vertex,\n entryPoint: 'main',\n },\n fragment: {\n source: source.fragment,\n entryPoint: 'main',\n },\n });\n}\n\nexport function compileHighShaderGlProgram({ bits, name }: {bits: HighShaderBit[], name: string}): GlProgram\n{\n return new GlProgram({\n name,\n ...compileHighShaderGl({\n template: {\n vertex: vertexGlTemplate,\n fragment: fragmentGlTemplate,\n },\n bits: [\n globalUniformsBitGl,\n ...bits,\n ]\n })\n });\n}\n"],"names":["compileHighShader","fragmentGPUTemplate","vertexGPUTemplate","globalUniformsBit","GpuProgram","GlProgram","compileHighShaderGl","vertexGlTemplate","fragmentGlTemplate","globalUniformsBitGl"],"mappings":";;;;;;;;;AAQO,SAAS,2BAA4B,CAAA,EAAE,IAAM,EAAA,IAAA,EACpD,EAAA;AACI,EAAA,MAAM,SAASA,mCAAkB,CAAA;AAAA,IAC7B,QAAU,EAAA;AAAA,MACN,QAAU,EAAAC,0CAAA;AAAA,MACV,MAAQ,EAAAC,wCAAA;AAAA,KACZ;AAAA,IACA,IAAM,EAAA;AAAA,MACFC,mCAAA;AAAA,MACA,GAAG,IAAA;AAAA,KACP;AAAA,GACH,CAAA,CAAA;AAED,EAAA,OAAOC,sBAAW,IAAK,CAAA;AAAA,IACnB,IAAA;AAAA,IACA,MAAQ,EAAA;AAAA,MACJ,QAAQ,MAAO,CAAA,MAAA;AAAA,MACf,UAAY,EAAA,MAAA;AAAA,KAChB;AAAA,IACA,QAAU,EAAA;AAAA,MACN,QAAQ,MAAO,CAAA,QAAA;AAAA,MACf,UAAY,EAAA,MAAA;AAAA,KAChB;AAAA,GACH,CAAA,CAAA;AACL,CAAA;AAEO,SAAS,0BAA2B,CAAA,EAAE,IAAM,EAAA,IAAA,EACnD,EAAA;AACI,EAAA,OAAO,IAAIC,mBAAU,CAAA;AAAA,IACjB,IAAA;AAAA,IACA,GAAGC,qCAAoB,CAAA;AAAA,MACnB,QAAU,EAAA;AAAA,QACN,MAAQ,EAAAC,uCAAA;AAAA,QACR,QAAU,EAAAC,yCAAA;AAAA,OACd;AAAA,MACA,IAAM,EAAA;AAAA,QACFC,qCAAA;AAAA,QACA,GAAG,IAAA;AAAA,OACP;AAAA,KACH,CAAA;AAAA,GACJ,CAAA,CAAA;AACL;;;;;"}

View File

@@ -0,0 +1,48 @@
import { GlProgram } from '../renderers/gl/shader/GlProgram.mjs';
import { GpuProgram } from '../renderers/gpu/shader/GpuProgram.mjs';
import { compileHighShader, compileHighShaderGl } from './compiler/compileHighShader.mjs';
import { fragmentGPUTemplate, vertexGPUTemplate, vertexGlTemplate, fragmentGlTemplate } from './defaultProgramTemplate.mjs';
import { globalUniformsBit, globalUniformsBitGl } from './shader-bits/globalUniformsBit.mjs';
"use strict";
function compileHighShaderGpuProgram({ bits, name }) {
const source = compileHighShader({
template: {
fragment: fragmentGPUTemplate,
vertex: vertexGPUTemplate
},
bits: [
globalUniformsBit,
...bits
]
});
return GpuProgram.from({
name,
vertex: {
source: source.vertex,
entryPoint: "main"
},
fragment: {
source: source.fragment,
entryPoint: "main"
}
});
}
function compileHighShaderGlProgram({ bits, name }) {
return new GlProgram({
name,
...compileHighShaderGl({
template: {
vertex: vertexGlTemplate,
fragment: fragmentGlTemplate
},
bits: [
globalUniformsBitGl,
...bits
]
})
});
}
export { compileHighShaderGlProgram, compileHighShaderGpuProgram };
//# sourceMappingURL=compileHighShaderToProgram.mjs.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"compileHighShaderToProgram.mjs","sources":["../../../src/rendering/high-shader/compileHighShaderToProgram.ts"],"sourcesContent":["import { GlProgram } from '../renderers/gl/shader/GlProgram';\nimport { GpuProgram } from '../renderers/gpu/shader/GpuProgram';\nimport { compileHighShader, compileHighShaderGl } from './compiler/compileHighShader';\nimport { fragmentGlTemplate, fragmentGPUTemplate, vertexGlTemplate, vertexGPUTemplate } from './defaultProgramTemplate';\nimport { globalUniformsBit, globalUniformsBitGl } from './shader-bits/globalUniformsBit';\n\nimport type { HighShaderBit } from './compiler/types';\n\nexport function compileHighShaderGpuProgram({ bits, name }: {bits: HighShaderBit[], name: string}): GpuProgram\n{\n const source = compileHighShader({\n template: {\n fragment: fragmentGPUTemplate,\n vertex: vertexGPUTemplate,\n },\n bits: [\n globalUniformsBit,\n ...bits,\n ]\n });\n\n return GpuProgram.from({\n name,\n vertex: {\n source: source.vertex,\n entryPoint: 'main',\n },\n fragment: {\n source: source.fragment,\n entryPoint: 'main',\n },\n });\n}\n\nexport function compileHighShaderGlProgram({ bits, name }: {bits: HighShaderBit[], name: string}): GlProgram\n{\n return new GlProgram({\n name,\n ...compileHighShaderGl({\n template: {\n vertex: vertexGlTemplate,\n fragment: fragmentGlTemplate,\n },\n bits: [\n globalUniformsBitGl,\n ...bits,\n ]\n })\n });\n}\n"],"names":[],"mappings":";;;;;;;AAQO,SAAS,2BAA4B,CAAA,EAAE,IAAM,EAAA,IAAA,EACpD,EAAA;AACI,EAAA,MAAM,SAAS,iBAAkB,CAAA;AAAA,IAC7B,QAAU,EAAA;AAAA,MACN,QAAU,EAAA,mBAAA;AAAA,MACV,MAAQ,EAAA,iBAAA;AAAA,KACZ;AAAA,IACA,IAAM,EAAA;AAAA,MACF,iBAAA;AAAA,MACA,GAAG,IAAA;AAAA,KACP;AAAA,GACH,CAAA,CAAA;AAED,EAAA,OAAO,WAAW,IAAK,CAAA;AAAA,IACnB,IAAA;AAAA,IACA,MAAQ,EAAA;AAAA,MACJ,QAAQ,MAAO,CAAA,MAAA;AAAA,MACf,UAAY,EAAA,MAAA;AAAA,KAChB;AAAA,IACA,QAAU,EAAA;AAAA,MACN,QAAQ,MAAO,CAAA,QAAA;AAAA,MACf,UAAY,EAAA,MAAA;AAAA,KAChB;AAAA,GACH,CAAA,CAAA;AACL,CAAA;AAEO,SAAS,0BAA2B,CAAA,EAAE,IAAM,EAAA,IAAA,EACnD,EAAA;AACI,EAAA,OAAO,IAAI,SAAU,CAAA;AAAA,IACjB,IAAA;AAAA,IACA,GAAG,mBAAoB,CAAA;AAAA,MACnB,QAAU,EAAA;AAAA,QACN,MAAQ,EAAA,gBAAA;AAAA,QACR,QAAU,EAAA,kBAAA;AAAA,OACd;AAAA,MACA,IAAM,EAAA;AAAA,QACF,mBAAA;AAAA,QACA,GAAG,IAAA;AAAA,OACP;AAAA,KACH,CAAA;AAAA,GACJ,CAAA,CAAA;AACL;;;;"}

View File

@@ -0,0 +1,19 @@
import type { HighShaderBit, HighShaderSource } from './types';
/** A high template consists of vertex and fragment source */
export interface HighShaderTemplate {
name?: string;
fragment: string;
vertex: string;
}
export interface CompileHighShaderOptions {
template: HighShaderTemplate;
bits: HighShaderBit[];
}
/**
* This function will take a HighShader template, some High fragments and then merge them in to a shader source.
* @param options
* @param options.template
* @param options.bits
*/
export declare function compileHighShader({ template, bits }: CompileHighShaderOptions): HighShaderSource;
export declare function compileHighShaderGl({ template, bits }: CompileHighShaderOptions): HighShaderSource;

View File

@@ -0,0 +1,68 @@
'use strict';
var addBits = require('./utils/addBits.js');
var compileHooks = require('./utils/compileHooks.js');
var compileInputs = require('./utils/compileInputs.js');
var compileOutputs = require('./utils/compileOutputs.js');
var injectBits = require('./utils/injectBits.js');
"use strict";
const cacheMap = /* @__PURE__ */ Object.create(null);
const bitCacheMap = /* @__PURE__ */ new Map();
let CACHE_UID = 0;
function compileHighShader({
template,
bits
}) {
const cacheId = generateCacheId(template, bits);
if (cacheMap[cacheId])
return cacheMap[cacheId];
const { vertex, fragment } = compileInputsAndOutputs(template, bits);
cacheMap[cacheId] = compileBits(vertex, fragment, bits);
return cacheMap[cacheId];
}
function compileHighShaderGl({
template,
bits
}) {
const cacheId = generateCacheId(template, bits);
if (cacheMap[cacheId])
return cacheMap[cacheId];
cacheMap[cacheId] = compileBits(template.vertex, template.fragment, bits);
return cacheMap[cacheId];
}
function compileInputsAndOutputs(template, bits) {
const vertexFragments = bits.map((shaderBit) => shaderBit.vertex).filter((v) => !!v);
const fragmentFragments = bits.map((shaderBit) => shaderBit.fragment).filter((v) => !!v);
let compiledVertex = compileInputs.compileInputs(vertexFragments, template.vertex, true);
compiledVertex = compileOutputs.compileOutputs(vertexFragments, compiledVertex);
const compiledFragment = compileInputs.compileInputs(fragmentFragments, template.fragment, true);
return {
vertex: compiledVertex,
fragment: compiledFragment
};
}
function generateCacheId(template, bits) {
return bits.map((highFragment) => {
if (!bitCacheMap.has(highFragment)) {
bitCacheMap.set(highFragment, CACHE_UID++);
}
return bitCacheMap.get(highFragment);
}).sort((a, b) => a - b).join("-") + template.vertex + template.fragment;
}
function compileBits(vertex, fragment, bits) {
const vertexParts = compileHooks.compileHooks(vertex);
const fragmentParts = compileHooks.compileHooks(fragment);
bits.forEach((shaderBit) => {
addBits.addBits(shaderBit.vertex, vertexParts, shaderBit.name);
addBits.addBits(shaderBit.fragment, fragmentParts, shaderBit.name);
});
return {
vertex: injectBits.injectBits(vertex, vertexParts),
fragment: injectBits.injectBits(fragment, fragmentParts)
};
}
exports.compileHighShader = compileHighShader;
exports.compileHighShaderGl = compileHighShaderGl;
//# sourceMappingURL=compileHighShader.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,65 @@
import { addBits } from './utils/addBits.mjs';
import { compileHooks } from './utils/compileHooks.mjs';
import { compileInputs } from './utils/compileInputs.mjs';
import { compileOutputs } from './utils/compileOutputs.mjs';
import { injectBits } from './utils/injectBits.mjs';
"use strict";
const cacheMap = /* @__PURE__ */ Object.create(null);
const bitCacheMap = /* @__PURE__ */ new Map();
let CACHE_UID = 0;
function compileHighShader({
template,
bits
}) {
const cacheId = generateCacheId(template, bits);
if (cacheMap[cacheId])
return cacheMap[cacheId];
const { vertex, fragment } = compileInputsAndOutputs(template, bits);
cacheMap[cacheId] = compileBits(vertex, fragment, bits);
return cacheMap[cacheId];
}
function compileHighShaderGl({
template,
bits
}) {
const cacheId = generateCacheId(template, bits);
if (cacheMap[cacheId])
return cacheMap[cacheId];
cacheMap[cacheId] = compileBits(template.vertex, template.fragment, bits);
return cacheMap[cacheId];
}
function compileInputsAndOutputs(template, bits) {
const vertexFragments = bits.map((shaderBit) => shaderBit.vertex).filter((v) => !!v);
const fragmentFragments = bits.map((shaderBit) => shaderBit.fragment).filter((v) => !!v);
let compiledVertex = compileInputs(vertexFragments, template.vertex, true);
compiledVertex = compileOutputs(vertexFragments, compiledVertex);
const compiledFragment = compileInputs(fragmentFragments, template.fragment, true);
return {
vertex: compiledVertex,
fragment: compiledFragment
};
}
function generateCacheId(template, bits) {
return bits.map((highFragment) => {
if (!bitCacheMap.has(highFragment)) {
bitCacheMap.set(highFragment, CACHE_UID++);
}
return bitCacheMap.get(highFragment);
}).sort((a, b) => a - b).join("-") + template.vertex + template.fragment;
}
function compileBits(vertex, fragment, bits) {
const vertexParts = compileHooks(vertex);
const fragmentParts = compileHooks(fragment);
bits.forEach((shaderBit) => {
addBits(shaderBit.vertex, vertexParts, shaderBit.name);
addBits(shaderBit.fragment, fragmentParts, shaderBit.name);
});
return {
vertex: injectBits(vertex, vertexParts),
fragment: injectBits(fragment, fragmentParts)
};
}
export { compileHighShader, compileHighShaderGl };
//# sourceMappingURL=compileHighShader.mjs.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,41 @@
/** the vertex source code, an obj */
export type Vertex = {
/** stick uniforms and functions in here all headers will be compiled at the top of the shader */
header?: string;
/** code will be added at the start of the shader */
start?: string;
/** code will be run here before lighting happens */
main?: string;
/** code here will to modify anything before it is passed to the fragment shader */
end?: string;
};
export type Fragment = {
/** stick uniforms and functions in here all headers will be compiled at the top of the shader */
header?: string;
/** code will be added at the start of the shader */
start?: string;
/** code will be run here before lighting happens */
main?: string;
/** code here will to modify anything before it is passed to the fragment shader */
end?: string;
};
/**
* HighShaderBit is a part of a shader.
* it is used to compile HighShaders.
*
* Internally shaders are made up of many of these.
* You can even write your own and compile them in.
*/
export interface HighShaderBit {
/** used to make the shader easier to understand! */
name?: string;
/** the snippets of vertex code */
vertex?: Vertex;
/** the snippets of fragment code */
fragment?: Fragment;
}
/** source code to compile a shader. this can be directly used by pixi and should be good to go! */
export interface HighShaderSource {
fragment: string;
vertex: string;
}

View File

@@ -0,0 +1,4 @@
'use strict';
"use strict";
//# sourceMappingURL=types.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"types.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;"}

View File

@@ -0,0 +1,2 @@
"use strict";
//# sourceMappingURL=types.mjs.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"types.mjs","sources":[],"sourcesContent":[],"names":[],"mappings":""}

View File

@@ -0,0 +1,7 @@
/**
* takes the HighFragment source parts and adds them to the hook hash
* @param srcParts - the hash of hook arrays
* @param parts - the code to inject into the hooks
* @param name - optional the name of the part to add
*/
export declare function addBits(srcParts: Record<string, string>, parts: Record<string, string[]>, name?: string): void;

View File

@@ -0,0 +1,28 @@
'use strict';
var warn = require('../../../../utils/logging/warn.js');
"use strict";
function addBits(srcParts, parts, name) {
if (srcParts) {
for (const i in srcParts) {
const id = i.toLocaleLowerCase();
const part = parts[id];
if (part) {
let sanitisedPart = srcParts[i];
if (i === "header") {
sanitisedPart = sanitisedPart.replace(/@in\s+[^;]+;\s*/g, "").replace(/@out\s+[^;]+;\s*/g, "");
}
if (name) {
part.push(`//----${name}----//`);
}
part.push(sanitisedPart);
} else {
warn.warn(`${i} placement hook does not exist in shader`);
}
}
}
}
exports.addBits = addBits;
//# sourceMappingURL=addBits.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"addBits.js","sources":["../../../../../src/rendering/high-shader/compiler/utils/addBits.ts"],"sourcesContent":["import { warn } from '../../../../utils/logging/warn';\n\n/**\n * takes the HighFragment source parts and adds them to the hook hash\n * @param srcParts - the hash of hook arrays\n * @param parts - the code to inject into the hooks\n * @param name - optional the name of the part to add\n */\nexport function addBits(srcParts: Record<string, string>, parts: Record<string, string[]>, name?: string)\n{\n if (srcParts)\n {\n for (const i in srcParts)\n {\n const id = i.toLocaleLowerCase();\n\n const part = parts[id];\n\n if (part)\n {\n let sanitisedPart = srcParts[i];\n\n if (i === 'header')\n {\n sanitisedPart = sanitisedPart\n .replace(/@in\\s+[^;]+;\\s*/g, '')\n .replace(/@out\\s+[^;]+;\\s*/g, '');\n }\n\n if (name)\n {\n part.push(`//----${name}----//`);\n }\n part.push(sanitisedPart);\n }\n\n else\n {\n // #if _DEBUG\n warn(`${i} placement hook does not exist in shader`);\n // #endif\n }\n }\n }\n}\n"],"names":["warn"],"mappings":";;;;;AAQgB,SAAA,OAAA,CAAQ,QAAkC,EAAA,KAAA,EAAiC,IAC3F,EAAA;AACI,EAAA,IAAI,QACJ,EAAA;AACI,IAAA,KAAA,MAAW,KAAK,QAChB,EAAA;AACI,MAAM,MAAA,EAAA,GAAK,EAAE,iBAAkB,EAAA,CAAA;AAE/B,MAAM,MAAA,IAAA,GAAO,MAAM,EAAE,CAAA,CAAA;AAErB,MAAA,IAAI,IACJ,EAAA;AACI,QAAI,IAAA,aAAA,GAAgB,SAAS,CAAC,CAAA,CAAA;AAE9B,QAAA,IAAI,MAAM,QACV,EAAA;AACI,UAAA,aAAA,GAAgB,cACX,OAAQ,CAAA,kBAAA,EAAoB,EAAE,CAC9B,CAAA,OAAA,CAAQ,qBAAqB,EAAE,CAAA,CAAA;AAAA,SACxC;AAEA,QAAA,IAAI,IACJ,EAAA;AACI,UAAK,IAAA,CAAA,IAAA,CAAK,CAAS,MAAA,EAAA,IAAI,CAAQ,MAAA,CAAA,CAAA,CAAA;AAAA,SACnC;AACA,QAAA,IAAA,CAAK,KAAK,aAAa,CAAA,CAAA;AAAA,OAI3B,MAAA;AAEI,QAAKA,SAAA,CAAA,CAAA,EAAG,CAAC,CAA0C,wCAAA,CAAA,CAAA,CAAA;AAAA,OAEvD;AAAA,KACJ;AAAA,GACJ;AACJ;;;;"}

View File

@@ -0,0 +1,26 @@
import { warn } from '../../../../utils/logging/warn.mjs';
"use strict";
function addBits(srcParts, parts, name) {
if (srcParts) {
for (const i in srcParts) {
const id = i.toLocaleLowerCase();
const part = parts[id];
if (part) {
let sanitisedPart = srcParts[i];
if (i === "header") {
sanitisedPart = sanitisedPart.replace(/@in\s+[^;]+;\s*/g, "").replace(/@out\s+[^;]+;\s*/g, "");
}
if (name) {
part.push(`//----${name}----//`);
}
part.push(sanitisedPart);
} else {
warn(`${i} placement hook does not exist in shader`);
}
}
}
}
export { addBits };
//# sourceMappingURL=addBits.mjs.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"addBits.mjs","sources":["../../../../../src/rendering/high-shader/compiler/utils/addBits.ts"],"sourcesContent":["import { warn } from '../../../../utils/logging/warn';\n\n/**\n * takes the HighFragment source parts and adds them to the hook hash\n * @param srcParts - the hash of hook arrays\n * @param parts - the code to inject into the hooks\n * @param name - optional the name of the part to add\n */\nexport function addBits(srcParts: Record<string, string>, parts: Record<string, string[]>, name?: string)\n{\n if (srcParts)\n {\n for (const i in srcParts)\n {\n const id = i.toLocaleLowerCase();\n\n const part = parts[id];\n\n if (part)\n {\n let sanitisedPart = srcParts[i];\n\n if (i === 'header')\n {\n sanitisedPart = sanitisedPart\n .replace(/@in\\s+[^;]+;\\s*/g, '')\n .replace(/@out\\s+[^;]+;\\s*/g, '');\n }\n\n if (name)\n {\n part.push(`//----${name}----//`);\n }\n part.push(sanitisedPart);\n }\n\n else\n {\n // #if _DEBUG\n warn(`${i} placement hook does not exist in shader`);\n // #endif\n }\n }\n }\n}\n"],"names":[],"mappings":";;;AAQgB,SAAA,OAAA,CAAQ,QAAkC,EAAA,KAAA,EAAiC,IAC3F,EAAA;AACI,EAAA,IAAI,QACJ,EAAA;AACI,IAAA,KAAA,MAAW,KAAK,QAChB,EAAA;AACI,MAAM,MAAA,EAAA,GAAK,EAAE,iBAAkB,EAAA,CAAA;AAE/B,MAAM,MAAA,IAAA,GAAO,MAAM,EAAE,CAAA,CAAA;AAErB,MAAA,IAAI,IACJ,EAAA;AACI,QAAI,IAAA,aAAA,GAAgB,SAAS,CAAC,CAAA,CAAA;AAE9B,QAAA,IAAI,MAAM,QACV,EAAA;AACI,UAAA,aAAA,GAAgB,cACX,OAAQ,CAAA,kBAAA,EAAoB,EAAE,CAC9B,CAAA,OAAA,CAAQ,qBAAqB,EAAE,CAAA,CAAA;AAAA,SACxC;AAEA,QAAA,IAAI,IACJ,EAAA;AACI,UAAK,IAAA,CAAA,IAAA,CAAK,CAAS,MAAA,EAAA,IAAI,CAAQ,MAAA,CAAA,CAAA,CAAA;AAAA,SACnC;AACA,QAAA,IAAA,CAAK,KAAK,aAAa,CAAA,CAAA;AAAA,OAI3B,MAAA;AAEI,QAAK,IAAA,CAAA,CAAA,EAAG,CAAC,CAA0C,wCAAA,CAAA,CAAA,CAAA;AAAA,OAEvD;AAAA,KACJ;AAAA,GACJ;AACJ;;;;"}

View File

@@ -0,0 +1,6 @@
export declare const findHooksRx: RegExp;
/**
* takes a program string and returns an hash mapping the hooks to empty arrays
* @param programSrc - the program containing hooks
*/
export declare function compileHooks(programSrc: string): Record<string, string[]>;

View File

@@ -0,0 +1,16 @@
'use strict';
"use strict";
const findHooksRx = /\{\{(.*?)\}\}/g;
function compileHooks(programSrc) {
const parts = {};
const partMatches = programSrc.match(findHooksRx)?.map((hook) => hook.replace(/[{()}]/g, "")) ?? [];
partMatches.forEach((hook) => {
parts[hook] = [];
});
return parts;
}
exports.compileHooks = compileHooks;
exports.findHooksRx = findHooksRx;
//# sourceMappingURL=compileHooks.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"compileHooks.js","sources":["../../../../../src/rendering/high-shader/compiler/utils/compileHooks.ts"],"sourcesContent":["export const findHooksRx = /\\{\\{(.*?)\\}\\}/g;\n\n/**\n * takes a program string and returns an hash mapping the hooks to empty arrays\n * @param programSrc - the program containing hooks\n */\nexport function compileHooks(programSrc: string): Record<string, string[]>\n{\n const parts: Record<string, string[]> = {};\n\n const partMatches = programSrc\n .match(findHooksRx)\n ?.map((hook) => hook.replace(/[{()}]/g, '')) ?? [];\n\n partMatches.forEach((hook) =>\n {\n parts[hook] = [];\n });\n\n return parts;\n}\n"],"names":[],"mappings":";;;AAAO,MAAM,WAAc,GAAA,iBAAA;AAMpB,SAAS,aAAa,UAC7B,EAAA;AACI,EAAA,MAAM,QAAkC,EAAC,CAAA;AAEzC,EAAA,MAAM,WAAc,GAAA,UAAA,CACf,KAAM,CAAA,WAAW,GAChB,GAAI,CAAA,CAAC,IAAS,KAAA,IAAA,CAAK,OAAQ,CAAA,SAAA,EAAW,EAAE,CAAC,KAAK,EAAC,CAAA;AAErD,EAAY,WAAA,CAAA,OAAA,CAAQ,CAAC,IACrB,KAAA;AACI,IAAM,KAAA,CAAA,IAAI,IAAI,EAAC,CAAA;AAAA,GAClB,CAAA,CAAA;AAED,EAAO,OAAA,KAAA,CAAA;AACX;;;;;"}

View File

@@ -0,0 +1,13 @@
"use strict";
const findHooksRx = /\{\{(.*?)\}\}/g;
function compileHooks(programSrc) {
const parts = {};
const partMatches = programSrc.match(findHooksRx)?.map((hook) => hook.replace(/[{()}]/g, "")) ?? [];
partMatches.forEach((hook) => {
parts[hook] = [];
});
return parts;
}
export { compileHooks, findHooksRx };
//# sourceMappingURL=compileHooks.mjs.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"compileHooks.mjs","sources":["../../../../../src/rendering/high-shader/compiler/utils/compileHooks.ts"],"sourcesContent":["export const findHooksRx = /\\{\\{(.*?)\\}\\}/g;\n\n/**\n * takes a program string and returns an hash mapping the hooks to empty arrays\n * @param programSrc - the program containing hooks\n */\nexport function compileHooks(programSrc: string): Record<string, string[]>\n{\n const parts: Record<string, string[]> = {};\n\n const partMatches = programSrc\n .match(findHooksRx)\n ?.map((hook) => hook.replace(/[{()}]/g, '')) ?? [];\n\n partMatches.forEach((hook) =>\n {\n parts[hook] = [];\n });\n\n return parts;\n}\n"],"names":[],"mappings":";AAAO,MAAM,WAAc,GAAA,iBAAA;AAMpB,SAAS,aAAa,UAC7B,EAAA;AACI,EAAA,MAAM,QAAkC,EAAC,CAAA;AAEzC,EAAA,MAAM,WAAc,GAAA,UAAA,CACf,KAAM,CAAA,WAAW,GAChB,GAAI,CAAA,CAAC,IAAS,KAAA,IAAA,CAAK,OAAQ,CAAA,SAAA,EAAW,EAAE,CAAC,KAAK,EAAC,CAAA;AAErD,EAAY,WAAA,CAAA,OAAA,CAAQ,CAAC,IACrB,KAAA;AACI,IAAM,KAAA,CAAA,IAAI,IAAI,EAAC,CAAA;AAAA,GAClB,CAAA,CAAA;AAED,EAAO,OAAA,KAAA,CAAA;AACX;;;;"}

View File

@@ -0,0 +1 @@
export declare function compileInputs(fragments: any[], template: string, sort?: boolean): string;

View File

@@ -0,0 +1,32 @@
'use strict';
"use strict";
function extractInputs(fragmentSource, out) {
let match;
const regex = /@in\s+([^;]+);/g;
while ((match = regex.exec(fragmentSource)) !== null) {
out.push(match[1]);
}
}
function compileInputs(fragments, template, sort = false) {
const results = [];
extractInputs(template, results);
fragments.forEach((fragment) => {
if (fragment.header) {
extractInputs(fragment.header, results);
}
});
const mainInput = results;
if (sort) {
mainInput.sort();
}
const finalString = mainInput.map((inValue, i) => ` @location(${i}) ${inValue},`).join("\n");
let cleanedString = template.replace(/@in\s+[^;]+;\s*/g, "");
cleanedString = cleanedString.replace("{{in}}", `
${finalString}
`);
return cleanedString;
}
exports.compileInputs = compileInputs;
//# sourceMappingURL=compileInputs.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"compileInputs.js","sources":["../../../../../src/rendering/high-shader/compiler/utils/compileInputs.ts"],"sourcesContent":["function extractInputs(fragmentSource: string, out: string[])\n{\n let match;\n const regex = /@in\\s+([^;]+);/g;\n\n while ((match = regex.exec(fragmentSource)) !== null)\n {\n out.push(match[1]);\n }\n}\n\nexport function compileInputs(fragments: any[], template: string, sort = false)\n{\n // get all the inputs from the fragments..\n const results: string[] = [];\n\n extractInputs(template, results);\n\n fragments.forEach((fragment) =>\n {\n if (fragment.header)\n {\n extractInputs(fragment.header, results);\n }\n });\n\n // build the input:\n const mainInput = results;\n\n if (sort)\n {\n mainInput.sort();\n }\n\n const finalString = mainInput\n .map((inValue, i) => ` @location(${i}) ${inValue},`)\n .join('\\n');\n\n // Remove lines from original string\n let cleanedString = template.replace(/@in\\s+[^;]+;\\s*/g, '');\n\n cleanedString = cleanedString.replace('{{in}}', `\\n${finalString}\\n`);\n\n return cleanedString;\n}\n"],"names":[],"mappings":";;;AAAA,SAAS,aAAA,CAAc,gBAAwB,GAC/C,EAAA;AACI,EAAI,IAAA,KAAA,CAAA;AACJ,EAAA,MAAM,KAAQ,GAAA,iBAAA,CAAA;AAEd,EAAA,OAAA,CAAQ,KAAQ,GAAA,KAAA,CAAM,IAAK,CAAA,cAAc,OAAO,IAChD,EAAA;AACI,IAAI,GAAA,CAAA,IAAA,CAAK,KAAM,CAAA,CAAC,CAAC,CAAA,CAAA;AAAA,GACrB;AACJ,CAAA;AAEO,SAAS,aAAc,CAAA,SAAA,EAAkB,QAAkB,EAAA,IAAA,GAAO,KACzE,EAAA;AAEI,EAAA,MAAM,UAAoB,EAAC,CAAA;AAE3B,EAAA,aAAA,CAAc,UAAU,OAAO,CAAA,CAAA;AAE/B,EAAU,SAAA,CAAA,OAAA,CAAQ,CAAC,QACnB,KAAA;AACI,IAAA,IAAI,SAAS,MACb,EAAA;AACI,MAAc,aAAA,CAAA,QAAA,CAAS,QAAQ,OAAO,CAAA,CAAA;AAAA,KAC1C;AAAA,GACH,CAAA,CAAA;AAGD,EAAA,MAAM,SAAY,GAAA,OAAA,CAAA;AAElB,EAAA,IAAI,IACJ,EAAA;AACI,IAAA,SAAA,CAAU,IAAK,EAAA,CAAA;AAAA,GACnB;AAEA,EAAA,MAAM,WAAc,GAAA,SAAA,CACf,GAAI,CAAA,CAAC,OAAS,EAAA,CAAA,KAAM,CAAoB,iBAAA,EAAA,CAAC,CAAK,EAAA,EAAA,OAAO,CAAG,CAAA,CAAA,CAAA,CACxD,KAAK,IAAI,CAAA,CAAA;AAGd,EAAA,IAAI,aAAgB,GAAA,QAAA,CAAS,OAAQ,CAAA,kBAAA,EAAoB,EAAE,CAAA,CAAA;AAE3D,EAAgB,aAAA,GAAA,aAAA,CAAc,QAAQ,QAAU,EAAA,CAAA;AAAA,EAAK,WAAW,CAAA;AAAA,CAAI,CAAA,CAAA;AAEpE,EAAO,OAAA,aAAA,CAAA;AACX;;;;"}

View File

@@ -0,0 +1,30 @@
"use strict";
function extractInputs(fragmentSource, out) {
let match;
const regex = /@in\s+([^;]+);/g;
while ((match = regex.exec(fragmentSource)) !== null) {
out.push(match[1]);
}
}
function compileInputs(fragments, template, sort = false) {
const results = [];
extractInputs(template, results);
fragments.forEach((fragment) => {
if (fragment.header) {
extractInputs(fragment.header, results);
}
});
const mainInput = results;
if (sort) {
mainInput.sort();
}
const finalString = mainInput.map((inValue, i) => ` @location(${i}) ${inValue},`).join("\n");
let cleanedString = template.replace(/@in\s+[^;]+;\s*/g, "");
cleanedString = cleanedString.replace("{{in}}", `
${finalString}
`);
return cleanedString;
}
export { compileInputs };
//# sourceMappingURL=compileInputs.mjs.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"compileInputs.mjs","sources":["../../../../../src/rendering/high-shader/compiler/utils/compileInputs.ts"],"sourcesContent":["function extractInputs(fragmentSource: string, out: string[])\n{\n let match;\n const regex = /@in\\s+([^;]+);/g;\n\n while ((match = regex.exec(fragmentSource)) !== null)\n {\n out.push(match[1]);\n }\n}\n\nexport function compileInputs(fragments: any[], template: string, sort = false)\n{\n // get all the inputs from the fragments..\n const results: string[] = [];\n\n extractInputs(template, results);\n\n fragments.forEach((fragment) =>\n {\n if (fragment.header)\n {\n extractInputs(fragment.header, results);\n }\n });\n\n // build the input:\n const mainInput = results;\n\n if (sort)\n {\n mainInput.sort();\n }\n\n const finalString = mainInput\n .map((inValue, i) => ` @location(${i}) ${inValue},`)\n .join('\\n');\n\n // Remove lines from original string\n let cleanedString = template.replace(/@in\\s+[^;]+;\\s*/g, '');\n\n cleanedString = cleanedString.replace('{{in}}', `\\n${finalString}\\n`);\n\n return cleanedString;\n}\n"],"names":[],"mappings":";AAAA,SAAS,aAAA,CAAc,gBAAwB,GAC/C,EAAA;AACI,EAAI,IAAA,KAAA,CAAA;AACJ,EAAA,MAAM,KAAQ,GAAA,iBAAA,CAAA;AAEd,EAAA,OAAA,CAAQ,KAAQ,GAAA,KAAA,CAAM,IAAK,CAAA,cAAc,OAAO,IAChD,EAAA;AACI,IAAI,GAAA,CAAA,IAAA,CAAK,KAAM,CAAA,CAAC,CAAC,CAAA,CAAA;AAAA,GACrB;AACJ,CAAA;AAEO,SAAS,aAAc,CAAA,SAAA,EAAkB,QAAkB,EAAA,IAAA,GAAO,KACzE,EAAA;AAEI,EAAA,MAAM,UAAoB,EAAC,CAAA;AAE3B,EAAA,aAAA,CAAc,UAAU,OAAO,CAAA,CAAA;AAE/B,EAAU,SAAA,CAAA,OAAA,CAAQ,CAAC,QACnB,KAAA;AACI,IAAA,IAAI,SAAS,MACb,EAAA;AACI,MAAc,aAAA,CAAA,QAAA,CAAS,QAAQ,OAAO,CAAA,CAAA;AAAA,KAC1C;AAAA,GACH,CAAA,CAAA;AAGD,EAAA,MAAM,SAAY,GAAA,OAAA,CAAA;AAElB,EAAA,IAAI,IACJ,EAAA;AACI,IAAA,SAAA,CAAU,IAAK,EAAA,CAAA;AAAA,GACnB;AAEA,EAAA,MAAM,WAAc,GAAA,SAAA,CACf,GAAI,CAAA,CAAC,OAAS,EAAA,CAAA,KAAM,CAAoB,iBAAA,EAAA,CAAC,CAAK,EAAA,EAAA,OAAO,CAAG,CAAA,CAAA,CAAA,CACxD,KAAK,IAAI,CAAA,CAAA;AAGd,EAAA,IAAI,aAAgB,GAAA,QAAA,CAAS,OAAQ,CAAA,kBAAA,EAAoB,EAAE,CAAA,CAAA;AAE3D,EAAgB,aAAA,GAAA,aAAA,CAAc,QAAQ,QAAU,EAAA,CAAA;AAAA,EAAK,WAAW,CAAA;AAAA,CAAI,CAAA,CAAA;AAEpE,EAAO,OAAA,aAAA,CAAA;AACX;;;;"}

View File

@@ -0,0 +1 @@
export declare function compileOutputs(fragments: any[], template: string): string;

View File

@@ -0,0 +1,52 @@
'use strict';
"use strict";
function extractOutputs(fragmentSource, out) {
let match;
const regex = /@out\s+([^;]+);/g;
while ((match = regex.exec(fragmentSource)) !== null) {
out.push(match[1]);
}
}
function extractVariableName(value) {
const regex = /\b(\w+)\s*:/g;
const match = regex.exec(value);
return match ? match[1] : "";
}
function stripVariable(value) {
const regex = /@.*?\s+/g;
return value.replace(regex, "");
}
function compileOutputs(fragments, template) {
const results = [];
extractOutputs(template, results);
fragments.forEach((fragment) => {
if (fragment.header) {
extractOutputs(fragment.header, results);
}
});
let index = 0;
const mainStruct = results.sort().map((inValue) => {
if (inValue.indexOf("builtin") > -1) {
return inValue;
}
return `@location(${index++}) ${inValue}`;
}).join(",\n");
const mainStart = results.sort().map((inValue) => ` var ${stripVariable(inValue)};`).join("\n");
const mainEnd = `return VSOutput(
${results.sort().map((inValue) => ` ${extractVariableName(inValue)}`).join(",\n")});`;
let compiledCode = template.replace(/@out\s+[^;]+;\s*/g, "");
compiledCode = compiledCode.replace("{{struct}}", `
${mainStruct}
`);
compiledCode = compiledCode.replace("{{start}}", `
${mainStart}
`);
compiledCode = compiledCode.replace("{{return}}", `
${mainEnd}
`);
return compiledCode;
}
exports.compileOutputs = compileOutputs;
//# sourceMappingURL=compileOutputs.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"compileOutputs.js","sources":["../../../../../src/rendering/high-shader/compiler/utils/compileOutputs.ts"],"sourcesContent":["function extractOutputs(fragmentSource: string, out: string[])\n{\n let match;\n const regex = /@out\\s+([^;]+);/g;\n\n while ((match = regex.exec(fragmentSource)) !== null)\n {\n out.push(match[1]);\n }\n}\n\nfunction extractVariableName(value: string)\n{\n const regex = /\\b(\\w+)\\s*:/g;\n\n const match = regex.exec(value);\n\n return match ? match[1] : '';\n}\n\nfunction stripVariable(value: string)\n{\n const regex = /@.*?\\s+/g;\n\n return value.replace(regex, '');\n}\n\nexport function compileOutputs(fragments: any[], template: string)\n{\n // get all the inputs from the fragments..\n const results: string[] = [];\n\n extractOutputs(template, results);\n\n fragments.forEach((fragment) =>\n {\n if (fragment.header)\n {\n extractOutputs(fragment.header, results);\n }\n });\n\n let index = 0;\n\n // generate the output struct\n const mainStruct = results\n .sort()\n .map((inValue) =>\n {\n if (inValue.indexOf('builtin') > -1)\n {\n return inValue;\n }\n\n return `@location(${index++}) ${inValue}`;\n })\n .join(',\\n');\n\n // generate the variables we will set:\n const mainStart = results\n .sort()\n .map((inValue) => ` var ${stripVariable(inValue)};`)\n .join('\\n');\n\n // generate the return object\n const mainEnd = `return VSOutput(\n ${results\n .sort()\n .map((inValue) => ` ${extractVariableName(inValue)}`)\n .join(',\\n')});`;\n\n // Remove lines from original string\n let compiledCode = template.replace(/@out\\s+[^;]+;\\s*/g, '');\n\n compiledCode = compiledCode.replace('{{struct}}', `\\n${mainStruct}\\n`);\n compiledCode = compiledCode.replace('{{start}}', `\\n${mainStart}\\n`);\n compiledCode = compiledCode.replace('{{return}}', `\\n${mainEnd}\\n`);\n\n return compiledCode;\n}\n"],"names":[],"mappings":";;;AAAA,SAAS,cAAA,CAAe,gBAAwB,GAChD,EAAA;AACI,EAAI,IAAA,KAAA,CAAA;AACJ,EAAA,MAAM,KAAQ,GAAA,kBAAA,CAAA;AAEd,EAAA,OAAA,CAAQ,KAAQ,GAAA,KAAA,CAAM,IAAK,CAAA,cAAc,OAAO,IAChD,EAAA;AACI,IAAI,GAAA,CAAA,IAAA,CAAK,KAAM,CAAA,CAAC,CAAC,CAAA,CAAA;AAAA,GACrB;AACJ,CAAA;AAEA,SAAS,oBAAoB,KAC7B,EAAA;AACI,EAAA,MAAM,KAAQ,GAAA,cAAA,CAAA;AAEd,EAAM,MAAA,KAAA,GAAQ,KAAM,CAAA,IAAA,CAAK,KAAK,CAAA,CAAA;AAE9B,EAAO,OAAA,KAAA,GAAQ,KAAM,CAAA,CAAC,CAAI,GAAA,EAAA,CAAA;AAC9B,CAAA;AAEA,SAAS,cAAc,KACvB,EAAA;AACI,EAAA,MAAM,KAAQ,GAAA,UAAA,CAAA;AAEd,EAAO,OAAA,KAAA,CAAM,OAAQ,CAAA,KAAA,EAAO,EAAE,CAAA,CAAA;AAClC,CAAA;AAEgB,SAAA,cAAA,CAAe,WAAkB,QACjD,EAAA;AAEI,EAAA,MAAM,UAAoB,EAAC,CAAA;AAE3B,EAAA,cAAA,CAAe,UAAU,OAAO,CAAA,CAAA;AAEhC,EAAU,SAAA,CAAA,OAAA,CAAQ,CAAC,QACnB,KAAA;AACI,IAAA,IAAI,SAAS,MACb,EAAA;AACI,MAAe,cAAA,CAAA,QAAA,CAAS,QAAQ,OAAO,CAAA,CAAA;AAAA,KAC3C;AAAA,GACH,CAAA,CAAA;AAED,EAAA,IAAI,KAAQ,GAAA,CAAA,CAAA;AAGZ,EAAA,MAAM,aAAa,OACd,CAAA,IAAA,EACA,CAAA,GAAA,CAAI,CAAC,OACN,KAAA;AACI,IAAA,IAAI,OAAQ,CAAA,OAAA,CAAQ,SAAS,CAAA,GAAI,CACjC,CAAA,EAAA;AACI,MAAO,OAAA,OAAA,CAAA;AAAA,KACX;AAEA,IAAO,OAAA,CAAA,UAAA,EAAa,KAAO,EAAA,CAAA,EAAA,EAAK,OAAO,CAAA,CAAA,CAAA;AAAA,GAC1C,CACA,CAAA,IAAA,CAAK,KAAK,CAAA,CAAA;AAGf,EAAA,MAAM,SAAY,GAAA,OAAA,CACb,IAAK,EAAA,CACL,IAAI,CAAC,OAAA,KAAY,CAAc,WAAA,EAAA,aAAA,CAAc,OAAO,CAAC,CAAG,CAAA,CAAA,CAAA,CACxD,KAAK,IAAI,CAAA,CAAA;AAGd,EAAA,MAAM,OAAU,GAAA,CAAA;AAAA,gBAAA,EACF,OACT,CAAA,IAAA,EACA,CAAA,GAAA,CAAI,CAAC,OAAY,KAAA,CAAA,CAAA,EAAI,mBAAoB,CAAA,OAAO,CAAC,CAAA,CAAE,CACnD,CAAA,IAAA,CAAK,KAAK,CAAC,CAAA,EAAA,CAAA,CAAA;AAGhB,EAAA,IAAI,YAAe,GAAA,QAAA,CAAS,OAAQ,CAAA,mBAAA,EAAqB,EAAE,CAAA,CAAA;AAE3D,EAAe,YAAA,GAAA,YAAA,CAAa,QAAQ,YAAc,EAAA,CAAA;AAAA,EAAK,UAAU,CAAA;AAAA,CAAI,CAAA,CAAA;AACrE,EAAe,YAAA,GAAA,YAAA,CAAa,QAAQ,WAAa,EAAA,CAAA;AAAA,EAAK,SAAS,CAAA;AAAA,CAAI,CAAA,CAAA;AACnE,EAAe,YAAA,GAAA,YAAA,CAAa,QAAQ,YAAc,EAAA,CAAA;AAAA,EAAK,OAAO,CAAA;AAAA,CAAI,CAAA,CAAA;AAElE,EAAO,OAAA,YAAA,CAAA;AACX;;;;"}

View File

@@ -0,0 +1,50 @@
"use strict";
function extractOutputs(fragmentSource, out) {
let match;
const regex = /@out\s+([^;]+);/g;
while ((match = regex.exec(fragmentSource)) !== null) {
out.push(match[1]);
}
}
function extractVariableName(value) {
const regex = /\b(\w+)\s*:/g;
const match = regex.exec(value);
return match ? match[1] : "";
}
function stripVariable(value) {
const regex = /@.*?\s+/g;
return value.replace(regex, "");
}
function compileOutputs(fragments, template) {
const results = [];
extractOutputs(template, results);
fragments.forEach((fragment) => {
if (fragment.header) {
extractOutputs(fragment.header, results);
}
});
let index = 0;
const mainStruct = results.sort().map((inValue) => {
if (inValue.indexOf("builtin") > -1) {
return inValue;
}
return `@location(${index++}) ${inValue}`;
}).join(",\n");
const mainStart = results.sort().map((inValue) => ` var ${stripVariable(inValue)};`).join("\n");
const mainEnd = `return VSOutput(
${results.sort().map((inValue) => ` ${extractVariableName(inValue)}`).join(",\n")});`;
let compiledCode = template.replace(/@out\s+[^;]+;\s*/g, "");
compiledCode = compiledCode.replace("{{struct}}", `
${mainStruct}
`);
compiledCode = compiledCode.replace("{{start}}", `
${mainStart}
`);
compiledCode = compiledCode.replace("{{return}}", `
${mainEnd}
`);
return compiledCode;
}
export { compileOutputs };
//# sourceMappingURL=compileOutputs.mjs.map

Some files were not shown because too many files have changed in this diff Show More