Files
nothoughts/node_modules/pixi.js/lib/scene/sprite-tiling/TilingSpritePipe.mjs
2025-08-04 18:57:35 +02:00

164 lines
6.4 KiB
JavaScript

import { ExtensionType } from '../../extensions/Extensions.mjs';
import { getAdjustedBlendModeBlend } from '../../rendering/renderers/shared/state/getAdjustedBlendModeBlend.mjs';
import { State } from '../../rendering/renderers/shared/state/State.mjs';
import { RendererType } from '../../rendering/renderers/types.mjs';
import { color32BitToUniform } from '../graphics/gpu/colorToUniform.mjs';
import { BatchableMesh } from '../mesh/shared/BatchableMesh.mjs';
import { MeshGeometry } from '../mesh/shared/MeshGeometry.mjs';
import { TilingSpriteShader } from './shader/TilingSpriteShader.mjs';
import { QuadGeometry } from './utils/QuadGeometry.mjs';
import { setPositions } from './utils/setPositions.mjs';
import { setUvs } from './utils/setUvs.mjs';
"use strict";
const sharedQuad = new QuadGeometry();
class TilingSpritePipe {
constructor(renderer) {
this._state = State.default2d;
this._tilingSpriteDataHash = /* @__PURE__ */ Object.create(null);
this._destroyRenderableBound = this.destroyRenderable.bind(this);
this._renderer = renderer;
}
validateRenderable(renderable) {
const tilingSpriteData = this._getTilingSpriteData(renderable);
const couldBatch = tilingSpriteData.canBatch;
this._updateCanBatch(renderable);
const canBatch = tilingSpriteData.canBatch;
if (canBatch && canBatch === couldBatch) {
const { batchableMesh } = tilingSpriteData;
if (batchableMesh && batchableMesh.texture._source !== renderable.texture._source) {
return !batchableMesh._batcher.checkAndUpdateTexture(batchableMesh, renderable.texture);
}
}
return couldBatch !== canBatch;
}
addRenderable(tilingSprite, instructionSet) {
const batcher = this._renderer.renderPipes.batch;
this._updateCanBatch(tilingSprite);
const tilingSpriteData = this._getTilingSpriteData(tilingSprite);
const { geometry, canBatch } = tilingSpriteData;
if (canBatch) {
tilingSpriteData.batchableMesh || (tilingSpriteData.batchableMesh = new BatchableMesh());
const batchableMesh = tilingSpriteData.batchableMesh;
if (tilingSprite._didTilingSpriteUpdate) {
tilingSprite._didTilingSpriteUpdate = false;
this._updateBatchableMesh(tilingSprite);
batchableMesh.geometry = geometry;
batchableMesh.renderable = tilingSprite;
batchableMesh.transform = tilingSprite.groupTransform;
batchableMesh.texture = tilingSprite._texture;
}
batchableMesh.roundPixels = this._renderer._roundPixels | tilingSprite._roundPixels;
batcher.addToBatch(batchableMesh, instructionSet);
} else {
batcher.break(instructionSet);
tilingSpriteData.shader || (tilingSpriteData.shader = new TilingSpriteShader());
this.updateRenderable(tilingSprite);
instructionSet.add(tilingSprite);
}
}
execute(tilingSprite) {
const { shader } = this._tilingSpriteDataHash[tilingSprite.uid];
shader.groups[0] = this._renderer.globalUniforms.bindGroup;
const localUniforms = shader.resources.localUniforms.uniforms;
localUniforms.uTransformMatrix = tilingSprite.groupTransform;
localUniforms.uRound = this._renderer._roundPixels | tilingSprite._roundPixels;
color32BitToUniform(
tilingSprite.groupColorAlpha,
localUniforms.uColor,
0
);
this._state.blendMode = getAdjustedBlendModeBlend(tilingSprite.groupBlendMode, tilingSprite.texture._source);
this._renderer.encoder.draw({
geometry: sharedQuad,
shader,
state: this._state
});
}
updateRenderable(tilingSprite) {
const tilingSpriteData = this._getTilingSpriteData(tilingSprite);
const { canBatch } = tilingSpriteData;
if (canBatch) {
const { batchableMesh } = tilingSpriteData;
if (tilingSprite._didTilingSpriteUpdate)
this._updateBatchableMesh(tilingSprite);
batchableMesh._batcher.updateElement(batchableMesh);
} else if (tilingSprite._didTilingSpriteUpdate) {
const { shader } = tilingSpriteData;
shader.updateUniforms(
tilingSprite.width,
tilingSprite.height,
tilingSprite._tileTransform.matrix,
tilingSprite.anchor.x,
tilingSprite.anchor.y,
tilingSprite.texture
);
}
tilingSprite._didTilingSpriteUpdate = false;
}
destroyRenderable(tilingSprite) {
const tilingSpriteData = this._getTilingSpriteData(tilingSprite);
tilingSpriteData.batchableMesh = null;
tilingSpriteData.shader?.destroy();
this._tilingSpriteDataHash[tilingSprite.uid] = null;
tilingSprite.off("destroyed", this._destroyRenderableBound);
}
_getTilingSpriteData(renderable) {
return this._tilingSpriteDataHash[renderable.uid] || this._initTilingSpriteData(renderable);
}
_initTilingSpriteData(tilingSprite) {
const geometry = new MeshGeometry({
indices: sharedQuad.indices,
positions: sharedQuad.positions.slice(),
uvs: sharedQuad.uvs.slice()
});
this._tilingSpriteDataHash[tilingSprite.uid] = {
canBatch: true,
renderable: tilingSprite,
geometry
};
tilingSprite.on("destroyed", this._destroyRenderableBound);
return this._tilingSpriteDataHash[tilingSprite.uid];
}
_updateBatchableMesh(tilingSprite) {
const renderableData = this._getTilingSpriteData(tilingSprite);
const { geometry } = renderableData;
const style = tilingSprite.texture.source.style;
if (style.addressMode !== "repeat") {
style.addressMode = "repeat";
style.update();
}
setUvs(tilingSprite, geometry.uvs);
setPositions(tilingSprite, geometry.positions);
}
destroy() {
for (const i in this._tilingSpriteDataHash) {
this.destroyRenderable(this._tilingSpriteDataHash[i].renderable);
}
this._tilingSpriteDataHash = null;
this._renderer = null;
}
_updateCanBatch(tilingSprite) {
const renderableData = this._getTilingSpriteData(tilingSprite);
const texture = tilingSprite.texture;
let _nonPowOf2wrapping = true;
if (this._renderer.type === RendererType.WEBGL) {
_nonPowOf2wrapping = this._renderer.context.supports.nonPowOf2wrapping;
}
renderableData.canBatch = texture.textureMatrix.isSimple && (_nonPowOf2wrapping || texture.source.isPowerOfTwo);
return renderableData.canBatch;
}
}
/** @ignore */
TilingSpritePipe.extension = {
type: [
ExtensionType.WebGLPipes,
ExtensionType.WebGPUPipes,
ExtensionType.CanvasPipes
],
name: "tilingSprite"
};
export { TilingSpritePipe };
//# sourceMappingURL=TilingSpritePipe.mjs.map