mirror of
https://github.com/Azgaar/Fantasy-Map-Generator.git
synced 2026-03-24 08:07:23 +01:00
refactor: Simplify texture loading and disposal in draw-relief-icons renderer
This commit is contained in:
parent
ae6d105bf1
commit
dc6ff785ba
2 changed files with 19 additions and 31 deletions
|
|
@ -4,7 +4,7 @@ import { byId } from "../utils";
|
||||||
export interface WebGLLayerConfig {
|
export interface WebGLLayerConfig {
|
||||||
id: string;
|
id: string;
|
||||||
setup: (group: Group) => void; // called once after WebGL2 confirmed; add meshes to group
|
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
|
dispose: (group: Group) => void; // called on unregister(); dispose all GPU objects in group
|
||||||
}
|
}
|
||||||
interface RegisteredLayer {
|
interface RegisteredLayer {
|
||||||
|
|
@ -48,7 +48,7 @@ export class WebGL2LayerClass {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
register(config: WebGLLayerConfig): void {
|
register(config: WebGLLayerConfig) {
|
||||||
if (!this.scene) {
|
if (!this.scene) {
|
||||||
// init() has not been called yet — queue for processing in init()
|
// init() has not been called yet — queue for processing in init()
|
||||||
this.pendingConfigs.push(config);
|
this.pendingConfigs.push(config);
|
||||||
|
|
@ -63,7 +63,7 @@ export class WebGL2LayerClass {
|
||||||
this.layers.set(config.id, { config, group });
|
this.layers.set(config.id, { config, group });
|
||||||
}
|
}
|
||||||
|
|
||||||
unregister(id: string): void {
|
unregister(id: string) {
|
||||||
const layer = this.layers.get(id);
|
const layer = this.layers.get(id);
|
||||||
if (!layer || !this.scene) return;
|
if (!layer || !this.scene) return;
|
||||||
const scene = this.scene;
|
const scene = this.scene;
|
||||||
|
|
@ -74,7 +74,7 @@ export class WebGL2LayerClass {
|
||||||
if (this.canvas && !anyVisible) this.canvas.style.display = "none";
|
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);
|
const layer = this.layers.get(id);
|
||||||
if (!layer) return;
|
if (!layer) return;
|
||||||
layer.group.visible = visible;
|
layer.group.visible = visible;
|
||||||
|
|
@ -83,14 +83,14 @@ export class WebGL2LayerClass {
|
||||||
if (visible) this.requestRender();
|
if (visible) this.requestRender();
|
||||||
}
|
}
|
||||||
|
|
||||||
clearLayer(id: string): void {
|
clearLayer(id: string) {
|
||||||
const layer = this.layers.get(id);
|
const layer = this.layers.get(id);
|
||||||
if (!layer) return;
|
if (!layer) return;
|
||||||
layer.group.clear();
|
layer.group.clear();
|
||||||
this.requestRender();
|
this.requestRender();
|
||||||
}
|
}
|
||||||
|
|
||||||
requestRender(): void {
|
requestRender() {
|
||||||
if (this.rafId !== null) return;
|
if (this.rafId !== null) return;
|
||||||
this.rafId = requestAnimationFrame(() => {
|
this.rafId = requestAnimationFrame(() => {
|
||||||
this.rafId = null;
|
this.rafId = null;
|
||||||
|
|
@ -98,7 +98,7 @@ export class WebGL2LayerClass {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
syncTransform(): void {
|
private syncTransform() {
|
||||||
if (!this.camera) return;
|
if (!this.camera) return;
|
||||||
const x = -viewX / scale;
|
const x = -viewX / scale;
|
||||||
const y = -viewY / scale;
|
const y = -viewY / scale;
|
||||||
|
|
@ -112,11 +112,12 @@ export class WebGL2LayerClass {
|
||||||
this.camera.updateProjectionMatrix();
|
this.camera.updateProjectionMatrix();
|
||||||
}
|
}
|
||||||
|
|
||||||
private render(): void {
|
private render() {
|
||||||
if (!this.renderer || !this.scene || !this.camera) return;
|
if (!this.renderer || !this.scene || !this.camera) return;
|
||||||
this.syncTransform();
|
this.syncTransform();
|
||||||
for (const layer of this.layers.values()) {
|
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);
|
this.renderer.render(this.scene, this.camera);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -25,10 +25,7 @@ WebGLLayer.register({
|
||||||
id: "terrain",
|
id: "terrain",
|
||||||
setup(group: Group): void {
|
setup(group: Group): void {
|
||||||
terrainGroup = group;
|
terrainGroup = group;
|
||||||
preloadTextures();
|
for (const set of Object.keys(RELIEF_SYMBOLS)) loadTexture(set);
|
||||||
},
|
|
||||||
render(_group: Group): void {
|
|
||||||
// no-op: relief geometry is static between drawRelief() calls
|
|
||||||
},
|
},
|
||||||
dispose(group: Group): void {
|
dispose(group: Group): void {
|
||||||
group.traverse((obj) => {
|
group.traverse((obj) => {
|
||||||
|
|
@ -38,14 +35,11 @@ WebGLLayer.register({
|
||||||
(obj.material as MeshBasicMaterial).dispose();
|
(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> {
|
function loadTexture(set: string): Promise<Texture | null> {
|
||||||
if (textureCache.has(set))
|
if (textureCache.has(set))
|
||||||
return Promise.resolve(textureCache.get(set) ?? null);
|
return Promise.resolve(textureCache.get(set) ?? null);
|
||||||
|
|
@ -147,11 +141,6 @@ function buildSetMesh(
|
||||||
return new Mesh(geo, mat);
|
return new Mesh(geo, mat);
|
||||||
}
|
}
|
||||||
|
|
||||||
function disposeTextureCache(): void {
|
|
||||||
for (const tex of textureCache.values()) tex?.dispose();
|
|
||||||
textureCache.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
function buildReliefScene(icons: ReliefIcon[]): void {
|
function buildReliefScene(icons: ReliefIcon[]): void {
|
||||||
if (!terrainGroup) return;
|
if (!terrainGroup) return;
|
||||||
terrainGroup.traverse((obj) => {
|
terrainGroup.traverse((obj) => {
|
||||||
|
|
@ -208,14 +197,12 @@ window.drawRelief = (
|
||||||
drawSvg(icons, parentEl);
|
drawSvg(icons, parentEl);
|
||||||
} else {
|
} else {
|
||||||
const set = parentEl.getAttribute("set") || "simple";
|
const set = parentEl.getAttribute("set") || "simple";
|
||||||
loadTexture(set).then(() => {
|
if (icons !== lastBuiltIcons || set !== lastBuiltSet) {
|
||||||
if (icons !== lastBuiltIcons || set !== lastBuiltSet) {
|
buildReliefScene(icons);
|
||||||
buildReliefScene(icons);
|
lastBuiltIcons = icons;
|
||||||
lastBuiltIcons = icons;
|
lastBuiltSet = set;
|
||||||
lastBuiltSet = set;
|
}
|
||||||
}
|
WebGLLayer.requestRender();
|
||||||
WebGLLayer.requestRender();
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue