diff --git a/assets/fonts/comfortaa-v40-latin-regular.woff b/assets/fonts/comfortaa-v40-latin-regular.woff new file mode 100644 index 0000000..c54393b Binary files /dev/null and b/assets/fonts/comfortaa-v40-latin-regular.woff differ diff --git a/assets/fonts/comfortaa-v40-latin-regular.woff2 b/assets/fonts/comfortaa-v40-latin-regular.woff2 new file mode 100644 index 0000000..bc4da8b Binary files /dev/null and b/assets/fonts/comfortaa-v40-latin-regular.woff2 differ diff --git a/assets/fonts/open-sans-v34-latin-regular.woff b/assets/fonts/open-sans-v34-latin-regular.woff new file mode 100644 index 0000000..b083626 Binary files /dev/null and b/assets/fonts/open-sans-v34-latin-regular.woff differ diff --git a/assets/fonts/open-sans-v34-latin-regular.woff2 b/assets/fonts/open-sans-v34-latin-regular.woff2 new file mode 100644 index 0000000..15339ea Binary files /dev/null and b/assets/fonts/open-sans-v34-latin-regular.woff2 differ diff --git a/assets/icons/info.svg b/assets/icons/info.svg new file mode 100644 index 0000000..a047bf5 --- /dev/null +++ b/assets/icons/info.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/static/maximize.svg b/assets/icons/maximize.svg similarity index 55% rename from static/maximize.svg rename to assets/icons/maximize.svg index 7118488..9c8558e 100644 --- a/static/maximize.svg +++ b/assets/icons/maximize.svg @@ -1,4 +1,4 @@ - + diff --git a/static/minimize.svg b/assets/icons/minimize.svg similarity index 55% rename from static/minimize.svg rename to assets/icons/minimize.svg index 93a212a..05d54a8 100644 --- a/static/minimize.svg +++ b/assets/icons/minimize.svg @@ -1,4 +1,4 @@ - + diff --git a/assets/icons/restart.svg b/assets/icons/restart.svg new file mode 100644 index 0000000..f87e22b --- /dev/null +++ b/assets/icons/restart.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/assets/no-change/404.html b/assets/no-change/404.html new file mode 100644 index 0000000..7c62e5c --- /dev/null +++ b/assets/no-change/404.html @@ -0,0 +1,43 @@ + + + + + + Not found + + + + + + + Page not found. + Go back + + + diff --git a/static/no-change/robots.txt b/assets/no-change/robots.txt similarity index 100% rename from static/no-change/robots.txt rename to assets/no-change/robots.txt diff --git a/src/game-loop/game-loop.ts b/src/game-loop/game-loop.ts index 0221917..833c632 100644 --- a/src/game-loop/game-loop.ts +++ b/src/game-loop/game-loop.ts @@ -6,36 +6,45 @@ import { RenderPipeline } from '../pipelines/render/render-pipeline'; import { settings } from '../settings'; import { DeltaTimeCalculator } from '../utils/delta-time-calculator'; import { Random } from '../utils/random'; -import { sleep } from '../utils/sleep'; import { vec2 } from 'gl-matrix'; export default class GameLoop { - private context: GPUCanvasContext; - private device: GPUDevice; + private readonly deltaTimeCalculator = new DeltaTimeCalculator(); - private agentPipeline: AgentPipeline; - private renderPipeline: RenderPipeline; - private brushPipeline: BrushPipeline; - private diffusionPipeline: DiffusionPipeline; + private readonly agentPipeline: AgentPipeline; + private readonly renderPipeline: RenderPipeline; + private readonly brushPipeline: BrushPipeline; + private readonly diffusionPipeline: DiffusionPipeline; private trailMapA?: GPUTexture; private trailMapB?: GPUTexture; + private hasFinished = false; + private readonly hasFinishedPromise: Promise = new Promise( + (resolve) => (this.resolveHasFinished = resolve) + ); + private resolveHasFinished: () => void; + private isSwipeActive = false; - private readonly deltaTimeCalculator = new DeltaTimeCalculator(); - public constructor(private canvas: HTMLCanvasElement) {} - - async start() { - await this.initializeDevice(); + public constructor( + private readonly canvas: HTMLCanvasElement, + private readonly device: GPUDevice + ) { + const context = this.canvas.getContext('webgpu') as any; + context.configure({ + device: this.device, + format: navigator.gpu.getPreferredCanvasFormat(), + alphaMode: 'premultiplied', + }); this.resize(); this.agentPipeline = new AgentPipeline(this.device, this.spawnAgents()); this.brushPipeline = new BrushPipeline(this.device); this.diffusionPipeline = new DiffusionPipeline(this.device); - this.renderPipeline = new RenderPipeline(this.context, this.device); + this.renderPipeline = new RenderPipeline(context, this.device); window.addEventListener('resize', this.resize.bind(this)); window.addEventListener('mousemove', this.onSwipe.bind(this)); @@ -44,8 +53,11 @@ export default class GameLoop { this.isSwipeActive = false; this.brushPipeline.clearSwipes(); }); + } + public async start(): Promise { requestAnimationFrame(this.render.bind(this)); + return this.hasFinishedPromise; } private onSwipe(event: MouseEvent) { @@ -112,24 +124,11 @@ export default class GameLoop { }); } - private async initializeDevice(): Promise { - const gpu = navigator.gpu; - if (!gpu) { - throw new Error('WebGPU is not supported'); + private render(time: DOMHighResTimeStamp) { + if (this.hasFinished) { + return; } - const adapter = await gpu.requestAdapter(); - this.device = await adapter.requestDevice(); // could request more resources - - this.context = this.canvas.getContext('webgpu') as any; - this.context.configure({ - device: this.device, - format: gpu.getPreferredCanvasFormat(), - alphaMode: 'premultiplied', - }); - } - - private async render(time: DOMHighResTimeStamp) { const deltaTime = this.deltaTimeCalculator.calculateDeltaTimeInSeconds(time); const params = { @@ -161,4 +160,18 @@ export default class GameLoop { // await sleep(200); requestAnimationFrame(this.render.bind(this)); } + + public destroy() { + this.hasFinished = true; + + this.agentPipeline?.destroy(); + this.brushPipeline?.destroy(); + this.diffusionPipeline?.destroy(); + this.renderPipeline?.destroy(); + + this.trailMapA?.destroy(); + this.trailMapB?.destroy(); + + this.resolveHasFinished(); + } } diff --git a/src/index.html b/src/index.html index ed9b4a4..45c0470 100644 --- a/src/index.html +++ b/src/index.html @@ -30,9 +30,37 @@ - JavaScript is required for this website. - - + + + + + + JavaScript is required for this website. + + + + + + +
+ JavaScript is required for this website. +