Initial
This commit is contained in:
174
resources/app/client/pixi/webgl/extensions/batch-renderer.js
Normal file
174
resources/app/client/pixi/webgl/extensions/batch-renderer.js
Normal file
@@ -0,0 +1,174 @@
|
||||
/**
|
||||
* A batch renderer with a customizable data transfer function to packed geometries.
|
||||
* @extends PIXI.AbstractBatchRenderer
|
||||
*/
|
||||
class BatchRenderer extends PIXI.BatchRenderer {
|
||||
|
||||
/**
|
||||
* The batch shader generator class.
|
||||
* @type {typeof BatchShaderGenerator}
|
||||
*/
|
||||
static shaderGeneratorClass = BatchShaderGenerator;
|
||||
|
||||
/* -------------------------------------------- */
|
||||
|
||||
/**
|
||||
* The default uniform values for the batch shader.
|
||||
* @type {object | (maxTextures: number) => object}
|
||||
*/
|
||||
static defaultUniforms = {};
|
||||
|
||||
/* -------------------------------------------- */
|
||||
|
||||
/**
|
||||
* The PackInterleavedGeometry function provided by the sampler.
|
||||
* @type {Function|undefined}
|
||||
* @protected
|
||||
*/
|
||||
_packInterleavedGeometry;
|
||||
|
||||
/* -------------------------------------------- */
|
||||
|
||||
/**
|
||||
* The update function provided by the sampler and that is called just before a flush.
|
||||
* @type {(batchRenderer: BatchRenderer) => void | undefined}
|
||||
* @protected
|
||||
*/
|
||||
_preRenderBatch;
|
||||
|
||||
/* -------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Get the uniforms bound to this abstract batch renderer.
|
||||
* @returns {object|undefined}
|
||||
*/
|
||||
get uniforms() {
|
||||
return this._shader?.uniforms;
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
|
||||
/**
|
||||
* The number of reserved texture units that the shader generator should not use (maximum 4).
|
||||
* @param {number} val
|
||||
* @protected
|
||||
*/
|
||||
set reservedTextureUnits(val) {
|
||||
// Some checks before...
|
||||
if ( typeof val !== "number" ) {
|
||||
throw new Error("BatchRenderer#reservedTextureUnits must be a number!");
|
||||
}
|
||||
if ( (val < 0) || (val > 4) ) {
|
||||
throw new Error("BatchRenderer#reservedTextureUnits must be positive and can't exceed 4.");
|
||||
}
|
||||
this.#reservedTextureUnits = val;
|
||||
}
|
||||
|
||||
/**
|
||||
* Number of reserved texture units reserved by the batch shader that cannot be used by the batch renderer.
|
||||
* @returns {number}
|
||||
*/
|
||||
get reservedTextureUnits() {
|
||||
return this.#reservedTextureUnits;
|
||||
}
|
||||
|
||||
#reservedTextureUnits = 0;
|
||||
|
||||
/* -------------------------------------------- */
|
||||
|
||||
/** @override */
|
||||
setShaderGenerator({
|
||||
vertex=this.constructor.defaultVertexSrc,
|
||||
fragment=this.constructor.defaultFragmentTemplate,
|
||||
uniforms=this.constructor.defaultUniforms
|
||||
}={}) {
|
||||
this.shaderGenerator = new this.constructor.shaderGeneratorClass(vertex, fragment, uniforms);
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
|
||||
/**
|
||||
* This override allows to allocate a given number of texture units reserved for a custom batched shader.
|
||||
* These reserved texture units won't be used to batch textures for PIXI.Sprite or SpriteMesh.
|
||||
* @override
|
||||
*/
|
||||
contextChange() {
|
||||
const gl = this.renderer.gl;
|
||||
|
||||
// First handle legacy environment
|
||||
if ( PIXI.settings.PREFER_ENV === PIXI.ENV.WEBGL_LEGACY ) this.maxTextures = 1;
|
||||
else
|
||||
{
|
||||
// Step 1: first check max texture units the GPU can handle
|
||||
const gpuMaxTex = Math.min(gl.getParameter(gl.MAX_TEXTURE_IMAGE_UNITS), 65536);
|
||||
|
||||
// Step 2: Remove the number of reserved texture units that could be used by a custom batch shader
|
||||
const batchMaxTex = gpuMaxTex - this.#reservedTextureUnits;
|
||||
|
||||
// Step 3: Checking if remainder of texture units is at least 1. Should never happens on GPU < than 20 years old!
|
||||
if ( batchMaxTex < 1 ) {
|
||||
const msg = "Impossible to allocate the required number of texture units in contextChange#BatchRenderer. "
|
||||
+ "Your GPU should handle at least 8 texture units. Currently, it is supporting: "
|
||||
+ `${gpuMaxTex} texture units.`;
|
||||
throw new Error(msg);
|
||||
}
|
||||
|
||||
// Step 4: Check with the maximum number of textures of the setting (webGL specifications)
|
||||
this.maxTextures = Math.min(batchMaxTex, PIXI.settings.SPRITE_MAX_TEXTURES);
|
||||
|
||||
// Step 5: Check the maximum number of if statements the shader can have too..
|
||||
this.maxTextures = PIXI.checkMaxIfStatementsInShader(this.maxTextures, gl);
|
||||
}
|
||||
|
||||
// Generate the batched shader
|
||||
this._shader = this.shaderGenerator?.generateShader(this.maxTextures) ?? null;
|
||||
|
||||
// Initialize packed geometries
|
||||
for ( let i = 0; i < this._packedGeometryPoolSize; i++ ) {
|
||||
this._packedGeometries[i] = new (this.geometryClass)();
|
||||
}
|
||||
this.initFlushBuffers();
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
|
||||
/** @inheritdoc */
|
||||
onPrerender() {
|
||||
if ( !this.shaderGenerator ) this.setShaderGenerator();
|
||||
this._shader ??= this.shaderGenerator.generateShader(this.maxTextures);
|
||||
super.onPrerender();
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
|
||||
/** @override */
|
||||
start() {
|
||||
this._preRenderBatch?.(this);
|
||||
super.start();
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
|
||||
/** @override */
|
||||
packInterleavedGeometry(element, attributeBuffer, indexBuffer, aIndex, iIndex) {
|
||||
// If we have a specific function to pack data into geometry, we call it
|
||||
if ( this._packInterleavedGeometry ) {
|
||||
this._packInterleavedGeometry(element, attributeBuffer, indexBuffer, aIndex, iIndex);
|
||||
return;
|
||||
}
|
||||
// Otherwise, we call the parent method, with the classic packing
|
||||
super.packInterleavedGeometry(element, attributeBuffer, indexBuffer, aIndex, iIndex);
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Verify if a PIXI plugin exists. Check by name.
|
||||
* @param {string} name The name of the pixi plugin to check.
|
||||
* @returns {boolean} True if the plugin exists, false otherwise.
|
||||
*/
|
||||
static hasPlugin(name) {
|
||||
return Object.keys(PIXI.Renderer.__plugins).some(k => k === name);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user