refactor: Simplify texture loading and disposal in draw-relief-icons renderer

This commit is contained in:
Azgaar 2026-03-12 19:36:25 +01:00
parent ae6d105bf1
commit dc6ff785ba
2 changed files with 19 additions and 31 deletions

View file

@ -4,7 +4,7 @@ import { byId } from "../utils";
export interface WebGLLayerConfig {
id: string;
setup: (group: Group) => void; // called once after WebGL2 confirmed; add meshes to group
render: (group: Group) => void; // called each frame before renderer.render(); update uniforms/geometry
render?: (group: Group) => void; // called each frame before renderer.render(); update uniforms/geometry
dispose: (group: Group) => void; // called on unregister(); dispose all GPU objects in group
}
interface RegisteredLayer {
@ -48,7 +48,7 @@ export class WebGL2LayerClass {
return true;
}
register(config: WebGLLayerConfig): void {
register(config: WebGLLayerConfig) {
if (!this.scene) {
// init() has not been called yet — queue for processing in init()
this.pendingConfigs.push(config);
@ -63,7 +63,7 @@ export class WebGL2LayerClass {
this.layers.set(config.id, { config, group });
}
unregister(id: string): void {
unregister(id: string) {
const layer = this.layers.get(id);
if (!layer || !this.scene) return;
const scene = this.scene;
@ -74,7 +74,7 @@ export class WebGL2LayerClass {
if (this.canvas && !anyVisible) this.canvas.style.display = "none";
}
setVisible(id: string, visible: boolean): void {
setVisible(id: string, visible: boolean) {
const layer = this.layers.get(id);
if (!layer) return;
layer.group.visible = visible;
@ -83,14 +83,14 @@ export class WebGL2LayerClass {
if (visible) this.requestRender();
}
clearLayer(id: string): void {
clearLayer(id: string) {
const layer = this.layers.get(id);
if (!layer) return;
layer.group.clear();
this.requestRender();
}
requestRender(): void {
requestRender() {
if (this.rafId !== null) return;
this.rafId = requestAnimationFrame(() => {
this.rafId = null;
@ -98,7 +98,7 @@ export class WebGL2LayerClass {
});
}
syncTransform(): void {
private syncTransform() {
if (!this.camera) return;
const x = -viewX / scale;
const y = -viewY / scale;
@ -112,11 +112,12 @@ export class WebGL2LayerClass {
this.camera.updateProjectionMatrix();
}
private render(): void {
private render() {
if (!this.renderer || !this.scene || !this.camera) return;
this.syncTransform();
for (const layer of this.layers.values()) {
if (layer.group.visible) layer.config.render(layer.group);
if (layer.group.visible && layer.config.render)
layer.config.render(layer.group);
}
this.renderer.render(this.scene, this.camera);
}

View file

@ -25,10 +25,7 @@ WebGLLayer.register({
id: "terrain",
setup(group: Group): void {
terrainGroup = group;
preloadTextures();
},
render(_group: Group): void {
// no-op: relief geometry is static between drawRelief() calls
for (const set of Object.keys(RELIEF_SYMBOLS)) loadTexture(set);
},
dispose(group: Group): void {
group.traverse((obj) => {
@ -38,14 +35,11 @@ WebGLLayer.register({
(obj.material as MeshBasicMaterial).dispose();
}
});
disposeTextureCache();
for (const tex of textureCache.values()) tex?.dispose();
textureCache.clear();
},
});
function preloadTextures(): void {
for (const set of Object.keys(RELIEF_SYMBOLS)) loadTexture(set);
}
function loadTexture(set: string): Promise<Texture | null> {
if (textureCache.has(set))
return Promise.resolve(textureCache.get(set) ?? null);
@ -147,11 +141,6 @@ function buildSetMesh(
return new Mesh(geo, mat);
}
function disposeTextureCache(): void {
for (const tex of textureCache.values()) tex?.dispose();
textureCache.clear();
}
function buildReliefScene(icons: ReliefIcon[]): void {
if (!terrainGroup) return;
terrainGroup.traverse((obj) => {
@ -208,14 +197,12 @@ window.drawRelief = (
drawSvg(icons, parentEl);
} else {
const set = parentEl.getAttribute("set") || "simple";
loadTexture(set).then(() => {
if (icons !== lastBuiltIcons || set !== lastBuiltSet) {
buildReliefScene(icons);
lastBuiltIcons = icons;
lastBuiltSet = set;
}
WebGLLayer.requestRender();
});
if (icons !== lastBuiltIcons || set !== lastBuiltSet) {
buildReliefScene(icons);
lastBuiltIcons = icons;
lastBuiltSet = set;
}
WebGLLayer.requestRender();
}
};