Skip to content

Commit

Permalink
WIP on textures and bitmap font issues
Browse files Browse the repository at this point in the history
Our texture atlases seem to be getting corrupted.  This will show up as either
the Bitmap Fonts getting messed up, or leaking into the background tiles.

I've tried commenting out the minimap for now, and also doing some other
cleanups around the code to isolate whether textures are getting destroyed
propertly.
  • Loading branch information
bhousel committed Sep 23, 2024
1 parent 8307eee commit 665391e
Show file tree
Hide file tree
Showing 11 changed files with 79 additions and 46 deletions.
5 changes: 3 additions & 2 deletions modules/core/UiSystem.js
Original file line number Diff line number Diff line change
Expand Up @@ -250,8 +250,9 @@ export class UiSystem extends AbstractSystem {
.attr('class', 'select-trap')
.text('t');

overMapEnter
.call(uiMapInMap(context));
// not yet
// overMapEnter
// .call(uiMapInMap(context));

overMapEnter
.call(uiMap3dViewer(context));
Expand Down
2 changes: 1 addition & 1 deletion modules/pixi/AbstractFeature.js
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ export class AbstractFeature {
this.context = null;

if (this.halo) {
this.halo.destroy({ children: true });
this.halo.destroy();
this.halo = null;
}

Expand Down
2 changes: 1 addition & 1 deletion modules/pixi/PixiFeatureLine.js
Original file line number Diff line number Diff line change
Expand Up @@ -368,7 +368,7 @@ export class PixiFeatureLine extends AbstractFeature {
}
} else {
if (this.halo) {
this.halo.destroy({ children: true });
this.halo.destroy();
this.halo = null;
}
}
Expand Down
4 changes: 2 additions & 2 deletions modules/pixi/PixiFeaturePoint.js
Original file line number Diff line number Diff line change
Expand Up @@ -283,7 +283,7 @@ export class PixiFeaturePoint extends AbstractFeature {

// Recalculate hitArea, grow it if too small
const MINSIZE = 20;
// In v8, getLocalBounds now returns a Bounds, not a Rectangle.
// In v8, getLocalBounds now returns a Bounds, not a Rectangle.
// The Rectangle is wrapped within the bounds object.
const rect = this.marker.getLocalBounds().rectangle.clone();

Expand Down Expand Up @@ -369,7 +369,7 @@ export class PixiFeaturePoint extends AbstractFeature {

} else {
if (this.halo) {
this.halo.destroy({ children: true });
this.halo.destroy();
this.halo = null;
}
}
Expand Down
2 changes: 1 addition & 1 deletion modules/pixi/PixiFeaturePolygon.js
Original file line number Diff line number Diff line change
Expand Up @@ -494,7 +494,7 @@ export class PixiFeaturePolygon extends AbstractFeature {

} else {
if (this.halo) {
this.halo.destroy({ children: true });
this.halo.destroy();
this.halo = null;
}
}
Expand Down
44 changes: 32 additions & 12 deletions modules/pixi/PixiLayerBackgroundTiles.js
Original file line number Diff line number Diff line change
Expand Up @@ -225,7 +225,7 @@ export class PixiLayerBackgroundTiles extends AbstractLayer {
tile.sprite.texture = textureManager.allocate('tile', tile.sprite.label, w, h, tile.image);

tile.loaded = true;
tile.image = null; // image is copied to the atlas, we can free it
tile.image = null; // reference to `image` is held by the atlas, we can null it
map.deferredRedraw();
};

Expand Down Expand Up @@ -265,17 +265,34 @@ export class PixiLayerBackgroundTiles extends AbstractLayer {
tile.debug = new PIXI.Graphics();
tile.debug.label = `debug-${tileID}`;
tile.debug.eventMode = 'none';
tile.debug.sortableChildren = false;
debugContainer.addChild(tile.debug);
}

const label = new PIXI.BitmapText(tileID, { fontName: 'debug' });
label.label = `label-${tileID}`;
label.tint = DEBUGCOLOR;
label.position.set(2, 2);
tile.debug.addChild(label);
if (!tile.text) {
tile.text = new PIXI.BitmapText({
text: tileID,
style: {
fontFamily: 'rapid-debug',
fontSize: 14
}
});
// tile.text = new PIXI.BitmapText({
// text: tileID,
// style: {
// fontFamily: 'Arial',
// fontSize: 14,
// fill: 0xffffff
// }
// });

tile.text.label = `label-${tileID}`;
tile.text.tint = DEBUGCOLOR;
tile.text.eventMode = 'none';
debugContainer.addChild(tile.text);
}

tile.debug.position.set(x, y - size); // left, top
tile.debug.position.set(x, y - size); // left, top
tile.text.position.set(x + 2, y - size + 2); // left, top
tile.debug
.clear()
.rect(0, 0, size, size)
Expand Down Expand Up @@ -341,20 +358,23 @@ export class PixiLayerBackgroundTiles extends AbstractLayer {
const textureManager = this.renderer.textures;

if (tile.sprite) {
tile.sprite.texture = null;
if (tile.loaded) {
textureManager.free('tile', tile.sprite.label);
}
tile.sprite.destroy({ children: true, texture: false, baseTexture: false });
tile.sprite.destroy({ texture: true, textureSource: false });
}

if (tile.debug) {
tile.debug.destroy({ children: true });
tile.debug.destroy();
}
if (tile.text) {
tile.text.destroy();
}

tile.image = null;
tile.sprite = null;
tile.debug = null;
tile.text = null;
}


Expand All @@ -369,7 +389,7 @@ export class PixiLayerBackgroundTiles extends AbstractLayer {
let sourceContainer = groupContainer.getChildByLabel(sourceID);
if (!sourceContainer) {
sourceContainer = new PIXI.Container();
sourceContainer.label= sourceID;
sourceContainer.label = sourceID;
sourceContainer.eventMode = 'none';
sourceContainer.sortableChildren = true;
groupContainer.addChild(sourceContainer);
Expand Down
1 change: 0 additions & 1 deletion modules/pixi/PixiLayerCustomData.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import * as PIXI from 'pixi.js';
import { gpx, kml } from '@tmcw/togeojson';
import geojsonRewind from '@mapbox/geojson-rewind';
import { parse as wktParse } from 'wkt';
Expand Down
34 changes: 23 additions & 11 deletions modules/pixi/PixiLayerLabels.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,22 +9,22 @@ import { getLineSegments, /*getDebugBBox,*/ lineToPoly } from './helpers.js';
const MINZOOM = 12;

const TEXT_NORMAL = {
fill: 0x333333,
fill: { color: 0x333333 },
fontFamily: 'Arial, Helvetica, sans-serif',
fontSize: 11,
fontWeight: 600,
lineJoin: 'round',
stroke:({width:2.7, color:'0xffffff'})
stroke: { width: 2.7, color: 0xffffff }
};

const TEXT_ITALIC = {
fill: 0x333333,
fill: { color: 0x333333 },
fontFamily: 'Arial, Helvetica, sans-serif',
fontSize: 11,
fontStyle: 'italic',
fontWeight: 600,
lineJoin: 'round',
stroke:({width:2.7, color:'0xffffff'})
stroke: { width: 2.7, color: 0xffffff }
};


Expand Down Expand Up @@ -106,9 +106,21 @@ export class PixiLayerLabels extends AbstractLayer {
this._labelOffset = new PIXI.Point();

// For ascii-only labels, we can use PIXI.BitmapText to avoid generating label textures
// BitmapFont.install('label-normal', TEXT_NORMAL, { chars: BitmapFont.ASCII, padding: 0, resolution: 2 });
PIXI.BitmapFontManager.install({
name: 'label-normal',
style: TEXT_NORMAL,
chars: PIXI.BitmapFontManager.ASCII,
padding: 0,
resolution: 1
});
// not actually used
// PIXI.BitmapFont.from('label-italic', TEXT_ITALIC, { chars: PIXI.BitmapFont.ASCII, padding: 0, resolution: 2 });
// PIXI.BitmapFontManager.from({
// name: 'label-italic',
// style: TEXT_ITALIC,
// chars: PIXI.BitmapFontManager.ASCII,
// padding: 0,
// resolution: 1
// });

// For all other labels, generate it on the fly in a PIXI.Text or PIXI.Sprite
this._textStyleNormal = new PIXI.TextStyle(TEXT_NORMAL);
Expand All @@ -127,7 +139,7 @@ export class PixiLayerLabels extends AbstractLayer {
this.debugContainer.removeChildren();

for (const dObj of this._dObjs.values()) {
dObj.destroy({ children: true, texture: false, baseTexture: false });
dObj.destroy();
}
for (const label of this._labels.values()) {
label.dObjID = null;
Expand Down Expand Up @@ -192,7 +204,7 @@ export class PixiLayerLabels extends AbstractLayer {
for (const dObjID of dObjIDs) {
const dObj = this._dObjs.get(dObjID);
if (dObj) {
dObj.destroy({ children: true, texture: false, baseTexture: false });
dObj.destroy();
}
this._dObjs.delete(dObjID);
}
Expand Down Expand Up @@ -455,7 +467,7 @@ export class PixiLayerLabels extends AbstractLayer {
if (/^[\x20-\x7E]*$/.test(feature.label)) { // is it in the printable ASCII range?
labelObj = new PIXI.BitmapText({
text: feature.label,
style: { fontName: 'label-normal' }
style: { fontFamily: 'label-normal' }
});
// labelObj.updateText(); // force update it so its texture is ready to be reused on a sprite
labelObj.label = feature.label;
Expand Down Expand Up @@ -688,7 +700,7 @@ for (let i = 0; i < bufferdata.inner.length / 2; ++i) {
}

// if (!picked) {
// labelObj.destroy({ children: true }); // didn't place it
// labelObj.destroy(); // didn't place it
// }
}

Expand Down Expand Up @@ -868,7 +880,7 @@ for (let i = 0; i < bufferdata.inner.length / 2; ++i) {
});

// we can destroy the sprite now, it's texture will remain on the rope?
// sprite.destroy({ children: true });
// sprite.destroy();
}


Expand Down
23 changes: 12 additions & 11 deletions modules/pixi/PixiRenderer.js
Original file line number Diff line number Diff line change
Expand Up @@ -105,24 +105,25 @@ export class PixiRenderer extends PIXI.EventEmitter {
resolution: window.devicePixelRatio,
sharedLoader: true,
sharedTicker: true,
textureGCActive: true
textureGCActive: true,
useBackBuffer: true
})
.then(() => {
// todo - we should stop doing this.. Access to pixi app should be via an instance of PixiRenderer
// so we can have multiple Pixi renderers - this will make the minimap less hacky & enable restriction editor
this.context.pixi = this.pixi;

// Prepare a basic bitmap font that we can use for things like debug messages
// BitmapFont.install('debug', {
// fill: 0xffffff,
// fontSize: 14,
// stroke: 0x333333,
// strokeThickness: 2
// },{
// chars: BitmapFont.ASCII,
// padding: 0,
// resolution: 2
// });
PIXI.BitmapFont.install({
name: 'rapid-debug',
style: {
fill: { color: 0xffffff },
fontSize: 14,
stroke: { color: 0x333333 }
},
chars: PIXI.BitmapFontManager.ASCII,
resolution: 2
});

// Register Pixi with the pixi-inspector extension if it is installed
// https://github.com/bfanger/pixi-inspector
Expand Down
2 changes: 1 addition & 1 deletion modules/pixi/PixiScene.js
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ export class PixiScene extends EventEmitter {
new PixiLayerKartaPhotos(this, 'kartaview'),
new PixiLayerStreetsidePhotos(this, 'streetside'),

new PixiLayerLabels(this, 'labels'),
// new PixiLayerLabels(this, 'labels'),
new PixiLayerEditBlocks(this, 'edit-blocks'),
new PixiLayerMapUI(this, 'map-ui')
].forEach(layer => this.layers.set(layer.id, layer));
Expand Down
6 changes: 3 additions & 3 deletions modules/pixi/PixiTextures.js
Original file line number Diff line number Diff line change
Expand Up @@ -211,7 +211,7 @@ export class PixiTextures {

if (tdata.refcount === 0) {
atlas.free(tdata.texture);
tdata.texture.destroy(false); // false = don't destroy base texture
tdata.texture.destroy(false); // false = don't destroy textureSource
tdata.texture = null;
this._textureData.delete(key);
}
Expand All @@ -227,7 +227,7 @@ export class PixiTextures {
* This is much more performant than drawing the graphcs.
*
* We also pack these graphics into a "texture atlas" so that they all live in the same
* BaseTexture. This texture gets sent to the GPU once then reused, so WebGL isn't constantly
* TextureSource. This texture gets sent to the GPU once then reused, so WebGL isn't constantly
* swapping between textures as it draws things.
*
* @param textureID Texture identifier (e.g. 'boldPin')
Expand Down Expand Up @@ -311,7 +311,7 @@ return PIXI.Texture.WHITE;

const resolution = 2;

//Now, make a canvas and render the svg into it at higher resolution.
//Now, make a canvas and render the svg into it at higher resolution.
const svgCanvas = renderer.extract.canvas({resolution: resolution, target: svgGraphics});
let ctx = svgCanvas.getContext('2d');
const imageData = ctx.getImageData(0,0,svgCanvas.width, svgCanvas.height);
Expand Down

0 comments on commit 665391e

Please sign in to comment.