feat(assets): use single texture atlas instead of loading all images individually

This commit is contained in:
2026-01-08 19:55:43 +01:00
parent c93a8c4437
commit 44b876a5ca
41 changed files with 488 additions and 377 deletions

View File

@@ -1,29 +1,44 @@
import * as THREE from "three";
import { GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader.js";
const imageCache = new Map<string, HTMLImageElement>();
type Rect = [number, number, number, number];
let atlasImage: HTMLImageElement | null = null;
const modelCache = new Map<string, THREE.Group>();
const loaded = ref(0);
const total = ref({{TOTAL}});
const isReady = computed(() => loaded.value === total.value);
const createImage = (path: string) => {
if (imageCache.has(path)) {
return imageCache.get(path)!;
}
if (import.meta.client) {
atlasImage = document.createElement('img');
atlasImage.src = '/nds/atlas.webp';
const img = document.createElement('img');
img.src = path;
imageCache.set(path, img);
if (img.complete) {
if (atlasImage.complete) {
loaded.value += 1;
} else {
img.onload = () => { loaded.value += 1 };
atlasImage.onload = () => {
loaded.value += 1;
};
}
}
const drawAtlasImage = (
ctx: CanvasRenderingContext2D,
[sx, sy, sw, sh]: Rect,
[dx, dy, dw, dh]: Rect,
opts?: Partial<{ colored: boolean }>,
): void => {
if (!atlasImage) return;
if (opts?.colored) {
const app = useAppStore();
sh /= 16;
sy += (app.color.row * 4 + app.color.col) * sh;
dh = sh;
}
return img;
ctx.drawImage(atlasImage, sx, sy, sw, sh, dx, dy, dw, dh);
};
const createModel = (path: string) => {
@@ -54,7 +69,28 @@ const createModel = (path: string) => {
return model;
};
const assets = {{ASSETS}};
export type AtlasImage = {
draw: (
ctx: CanvasRenderingContext2D,
x: number,
y: number,
opts?: Partial<{ colored: boolean }>,
) => void;
rect: { x: number; y: number; width: number; height: number };
};
type ImageTree = {
[key: string]: AtlasImage | ImageTree;
};
type ModelTree = {
[key: string]: THREE.Group | ModelTree;
};
const assets = {
images: {{IMAGES}} as const satisfies ImageTree,
models: {{MODELS}} as const satisfies ModelTree,
};
export const useAssets = () => {
return {