Modernise website by migrating to vite
This commit is contained in:
parent
5f0f500725
commit
f350b1ff37
34 changed files with 3185 additions and 21045 deletions
|
|
@ -1,4 +1,2 @@
|
|||
// @ts-ignore: injected by webpack
|
||||
export const isProduction: boolean = __IS_PRODUCTION__;
|
||||
// @ts-ignore: injected by webpack
|
||||
export const lastEdit = new Date(__CURRENT_DATE__);
|
||||
export const isProduction: boolean = import.meta.env.PROD;
|
||||
export const lastEdit = new Date(__BUILD_DATE__);
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
import { vec2 } from 'gl-matrix';
|
||||
|
||||
import { AgentGenerationPipeline } from '../pipelines/agents/agent-generation/agent-generation-pipeline';
|
||||
import { AgentPipeline } from '../pipelines/agents/agent-pipeline';
|
||||
import { BrushPipeline } from '../pipelines/brush/brush-pipeline';
|
||||
|
|
@ -13,8 +15,6 @@ import { sleep } from '../utils/sleep';
|
|||
import { GamePresentation } from './game-presentation';
|
||||
import { GameRules } from './game-rules';
|
||||
|
||||
import { vec2 } from 'gl-matrix';
|
||||
|
||||
export default class GameLoop {
|
||||
private readonly trailMapA: ResizableTexture;
|
||||
private readonly trailMapB: ResizableTexture;
|
||||
|
|
@ -170,7 +170,7 @@ export default class GameLoop {
|
|||
);
|
||||
document.documentElement.style.setProperty(
|
||||
'--accent-color',
|
||||
`rgb(${accentColor.map((v: number) => v * 255).join(',')})`
|
||||
`rgb(${accentColor[0] * 255},${accentColor[1] * 255},${accentColor[2] * 255})`
|
||||
);
|
||||
|
||||
const deltaTime = this.deltaTimeCalculator.calculateDeltaTimeInSeconds(time);
|
||||
|
|
|
|||
|
|
@ -1,10 +1,10 @@
|
|||
import { vec3 } from 'gl-matrix';
|
||||
|
||||
import { settings } from '../settings';
|
||||
import { hsl } from '../utils/hsl';
|
||||
import { last } from '../utils/last';
|
||||
import { Random } from '../utils/random';
|
||||
|
||||
import { vec3 } from 'gl-matrix';
|
||||
|
||||
const hues = [settings.startColorHue];
|
||||
|
||||
for (let i = 0; i < 100; i++) {
|
||||
|
|
|
|||
|
|
@ -1,11 +1,11 @@
|
|||
import { vec2 } from 'gl-matrix';
|
||||
|
||||
import { GenerationCounts } from '../pipelines/agents/agent-generation/generation-counts';
|
||||
import { settings } from '../settings';
|
||||
import { clamp, clamp01 } from '../utils/clamp';
|
||||
import { mix } from '../utils/mix';
|
||||
import { Random } from '../utils/random';
|
||||
|
||||
import { vec2 } from 'gl-matrix';
|
||||
|
||||
export interface SpawnAction {
|
||||
generation: number;
|
||||
position: vec2;
|
||||
|
|
@ -76,8 +76,8 @@ export class GameRules {
|
|||
this.lastSpawnAction = {
|
||||
generation: this.nextGenerationId,
|
||||
position: vec2.fromValues(
|
||||
Random.randomBetween(0, canvasSize.x),
|
||||
Random.randomBetween(0, canvasSize.y)
|
||||
Random.randomBetween(0, canvasSize[0]),
|
||||
Random.randomBetween(0, canvasSize[1])
|
||||
),
|
||||
radius: this.currentSpawnRadius,
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,72 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
|
||||
<meta property="og:title" content="Just a bunch of blobs" />
|
||||
<meta property="og:description" content="Discover my projects." />
|
||||
<meta property="og:url" content="https://schmelczer.dev" />
|
||||
|
||||
<meta property="og:image:width" content="1920" />
|
||||
<meta property="og:image:height" content="1920" />
|
||||
<meta property="og:image" content="https://schmelczer.dev/og-image.jpg" />
|
||||
|
||||
<link rel="apple-touch-icon" sizes="180x180" href="/apple-touch-icon.png" />
|
||||
<link rel="icon" href="favicon.ico" type="image/x-icon" />
|
||||
<link rel="icon" type="image/png" sizes="32x32" href="/favicon-32x32.png" />
|
||||
<link rel="icon" type="image/png" sizes="16x16" href="/favicon-16x16.png" />
|
||||
<meta
|
||||
name="description"
|
||||
content="I'm Andras Schmelczer, and this is my portfolio. Discover some of my projects. I'm passionate about solving challenging problems and designing large-scale systems, especially in the context of machine learning."
|
||||
/>
|
||||
<meta
|
||||
name="viewport"
|
||||
content="width=device-width,initial-scale=1,viewport-fit=cover"
|
||||
/>
|
||||
<meta name="theme-color" content="#b7455e" />
|
||||
|
||||
<title>Just a bunch of blobs</title>
|
||||
|
||||
<link inline inline-asset="index.css" inline-asset-delete />
|
||||
</head>
|
||||
<body>
|
||||
<main class="canvas-container">
|
||||
<canvas></canvas>
|
||||
|
||||
<section class="errors-container">
|
||||
<noscript>JavaScript is required for this website.</noscript>
|
||||
</section>
|
||||
|
||||
<!-- <div class="counters"><pre></pre></div> -->
|
||||
</main>
|
||||
|
||||
<aside>
|
||||
<nav class="buttons">
|
||||
<button class="info"></button>
|
||||
<button class="maximize-full-screen"></button>
|
||||
<button class="minimize-full-screen"></button>
|
||||
<button class="settings"></button>
|
||||
<button class="restart"></button>
|
||||
</nav>
|
||||
|
||||
<main class="pages hidden info-page">
|
||||
<section>
|
||||
<h1>Just a bunch of blobs</h1>
|
||||
<p>
|
||||
Lorem ipsum dolor sit amet consectetur adipisicing elit. Eaque itaque
|
||||
perspiciatis nesciunt, molestiae officiis dignissimos porro! Provident totam
|
||||
sit enim, dolores dicta possimus ex assumenda earum, ea tempore, aut quidem?
|
||||
</p>
|
||||
</section>
|
||||
</main>
|
||||
|
||||
<main class="pages hidden settings-page">
|
||||
<section>
|
||||
<div class="settings-content"></div>
|
||||
<button id="apply-defaults" class="large-button">Apply defaults</button>
|
||||
</section>
|
||||
</main>
|
||||
</aside>
|
||||
<script inline inline-asset="index.js" inline-asset-delete></script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -16,7 +16,9 @@ html > body {
|
|||
height: 100%;
|
||||
width: 100%;
|
||||
|
||||
cursor: url('../assets/icons/brush.svg') 0 24, auto;
|
||||
cursor:
|
||||
url('../assets/icons/brush.svg') 0 24,
|
||||
auto;
|
||||
}
|
||||
|
||||
> .errors-container {
|
||||
|
|
@ -107,7 +109,8 @@ html > body {
|
|||
@include on-large-screen {
|
||||
width: 0;
|
||||
border-radius: 0 var(--border-radius) var(--border-radius) 0;
|
||||
transition: background-color var(--transition-time),
|
||||
transition:
|
||||
background-color var(--transition-time),
|
||||
width var(--transition-time);
|
||||
left: calc(-1 * var(--small-margin));
|
||||
height: 140%;
|
||||
|
|
@ -118,7 +121,8 @@ html > body {
|
|||
@include on-small-screen {
|
||||
height: 0;
|
||||
border-radius: 0 0 var(--border-radius) var(--border-radius);
|
||||
transition: background-color var(--transition-time),
|
||||
transition:
|
||||
background-color var(--transition-time),
|
||||
height var(--transition-time);
|
||||
top: calc(-1 * var(--small-margin));
|
||||
width: 140%;
|
||||
|
|
@ -130,7 +134,8 @@ html > body {
|
|||
&::after {
|
||||
background-color: var(--accent-color);
|
||||
|
||||
transition: transform var(--transition-time),
|
||||
transition:
|
||||
transform var(--transition-time),
|
||||
background-color var(--transition-time);
|
||||
|
||||
-webkit-mask-repeat: no-repeat;
|
||||
|
|
@ -201,7 +206,9 @@ html > body {
|
|||
|
||||
&,
|
||||
> * {
|
||||
transition: width var(--transition-time-long), height var(--transition-time-long);
|
||||
transition:
|
||||
width var(--transition-time-long),
|
||||
height var(--transition-time-long);
|
||||
|
||||
@include on-large-screen {
|
||||
width: max(500px, 10vw);
|
||||
|
|
|
|||
23
src/index.ts
23
src/index.ts
|
|
@ -1,36 +1,19 @@
|
|||
import '../assets/icons/info.svg';
|
||||
import { isProduction, lastEdit } from './constants';
|
||||
import GameLoop from './game-loop/game-loop';
|
||||
import { GameRules } from './game-loop/game-rules';
|
||||
|
||||
import './index.scss';
|
||||
|
||||
import { CollapsiblePanelAnimator } from './page/collapsible-panel-animator';
|
||||
import { FullScreenHandler } from './page/full-screen-handler';
|
||||
import { MenuHider } from './page/menu-hider';
|
||||
import { setUpSettingsPage } from './page/set-up-settings-page';
|
||||
import { SettingsSlider } from './page/settings-slider';
|
||||
import { resetSettings } from './settings';
|
||||
import { applyArrayPlugins } from './utils/array';
|
||||
import { DeltaTimeCalculator } from './utils/delta-time-calculator';
|
||||
import { ErrorHandler, Severity } from './utils/error-handler';
|
||||
import { initializeGpu } from './utils/graphics/initialize-gpu';
|
||||
|
||||
declare global {
|
||||
interface Array<T> {
|
||||
x: T;
|
||||
y: T;
|
||||
}
|
||||
|
||||
interface ReadonlyArray<T> {
|
||||
x: T;
|
||||
y: T;
|
||||
}
|
||||
|
||||
interface Float32Array {
|
||||
x: number;
|
||||
y: number;
|
||||
}
|
||||
}
|
||||
|
||||
const elements = {
|
||||
aside: document.querySelector('aside') as HTMLDivElement,
|
||||
infoButton: document.querySelector('button.info') as HTMLButtonElement,
|
||||
|
|
@ -57,8 +40,6 @@ const main = async () => {
|
|||
let shouldStop = false;
|
||||
let game: GameLoop | null = null;
|
||||
|
||||
applyArrayPlugins();
|
||||
|
||||
ErrorHandler.addOnErrorListener((error, _metadata) => {
|
||||
elements.errorContainer.innerHTML += `
|
||||
<pre class="${error.severity}">${error.message}</div>
|
||||
|
|
|
|||
|
|
@ -16,14 +16,16 @@ export class FullScreenHandler {
|
|||
// on full screen request, only apply it to the target
|
||||
if (e.key === 'F11') {
|
||||
e.preventDefault();
|
||||
FullScreenHandler.isInFullScreenMode()
|
||||
? document.exitFullscreen()
|
||||
: target.requestFullscreen();
|
||||
if (FullScreenHandler.isInFullScreenMode()) {
|
||||
document.exitFullscreen();
|
||||
} else {
|
||||
target.requestFullscreen();
|
||||
}
|
||||
}
|
||||
});
|
||||
addEventListener('fullscreenchange', this.updateButtons.bind(this));
|
||||
maximizeButton.addEventListener('click', target.requestFullscreen.bind(target));
|
||||
minimizeButton.addEventListener('click', document.exitFullscreen.bind(document));
|
||||
maximizeButton.addEventListener('click', () => target.requestFullscreen());
|
||||
minimizeButton.addEventListener('click', () => document.exitFullscreen());
|
||||
}
|
||||
|
||||
public static isInFullScreenMode(): boolean {
|
||||
|
|
|
|||
|
|
@ -2,9 +2,9 @@ import { getWorkgroupCounts } from '../../../utils/graphics/get-workgroup-counts
|
|||
import { smartCompile } from '../../../utils/graphics/smart-compile';
|
||||
import { CommonState } from '../../common-state/common-state';
|
||||
import { AGENT_SIZE_IN_BYTES } from './agent';
|
||||
import countingShader from './agent-counting.wgsl';
|
||||
import firstGenerationShader from './agent-first-generation.wgsl';
|
||||
import agentSchema from './agent-schema.wgsl';
|
||||
import countingShader from './agent-counting.wgsl?raw';
|
||||
import firstGenerationShader from './agent-first-generation.wgsl?raw';
|
||||
import agentSchema from './agent-schema.wgsl?raw';
|
||||
import { GenerationCounts } from './generation-counts';
|
||||
|
||||
export class AgentGenerationPipeline {
|
||||
|
|
|
|||
|
|
@ -1,11 +1,11 @@
|
|||
import { vec2 } from 'gl-matrix';
|
||||
|
||||
import { getWorkgroupCounts } from '../../utils/graphics/get-workgroup-counts';
|
||||
import { smartCompile } from '../../utils/graphics/smart-compile';
|
||||
import { CommonState } from '../common-state/common-state';
|
||||
import agentSchme from './agent-generation/agent-schema.wgsl';
|
||||
import agentSchme from './agent-generation/agent-schema.wgsl?raw';
|
||||
import { AgentSettings } from './agent-settings';
|
||||
import shader from './agent.wgsl';
|
||||
|
||||
import { vec2 } from 'gl-matrix';
|
||||
import shader from './agent.wgsl?raw';
|
||||
|
||||
export class AgentPipeline {
|
||||
private static readonly WORKGROUP_SIZE = 64;
|
||||
|
|
|
|||
|
|
@ -1,11 +1,11 @@
|
|||
import { vec2 } from 'gl-matrix';
|
||||
|
||||
import { clamp } from '../../utils/clamp';
|
||||
import { smartCompile } from '../../utils/graphics/smart-compile';
|
||||
import { last } from '../../utils/last';
|
||||
import { CommonState } from '../common-state/common-state';
|
||||
import { BrushSettings } from './brush-settings';
|
||||
import shader from './brush.wgsl';
|
||||
|
||||
import { vec2 } from 'gl-matrix';
|
||||
import shader from './brush.wgsl?raw';
|
||||
|
||||
export class BrushPipeline {
|
||||
private static readonly UNIFORM_COUNT = 2;
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import { generateNoise } from '../../utils/graphics/noise';
|
||||
|
||||
import { vec2 } from 'gl-matrix';
|
||||
|
||||
import { generateNoise } from '../../utils/graphics/noise';
|
||||
|
||||
export class CommonState {
|
||||
private static readonly UNIFORM_COUNT = 4;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
import { smartCompile } from '../../utils/graphics/smart-compile';
|
||||
import shader from './copy.wgsl';
|
||||
|
||||
import { vec2 } from 'gl-matrix';
|
||||
|
||||
import { smartCompile } from '../../utils/graphics/smart-compile';
|
||||
import shader from './copy.wgsl?raw';
|
||||
|
||||
export class CopyPipeline {
|
||||
private static readonly UNIFORM_COUNT = 2;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import { setUpFullScreenQuad } from '../../utils/graphics/full-screen-quad';
|
||||
import { smartCompile } from '../../utils/graphics/smart-compile';
|
||||
import { CommonState } from '../common-state/common-state';
|
||||
import shader from './diffuse.wgsl';
|
||||
import shader from './diffuse.wgsl?raw';
|
||||
import { DiffusionSettings } from './diffusion-settings';
|
||||
|
||||
export class DiffusionPipeline {
|
||||
|
|
|
|||
|
|
@ -1,10 +1,10 @@
|
|||
import { vec3 } from 'gl-matrix';
|
||||
|
||||
import { setUpFullScreenQuad } from '../../utils/graphics/full-screen-quad';
|
||||
import { smartCompile } from '../../utils/graphics/smart-compile';
|
||||
import { CommonState } from '../common-state/common-state';
|
||||
import { RenderSettings } from './render-settings';
|
||||
import shader from './render.wgsl';
|
||||
|
||||
import { vec3 } from 'gl-matrix';
|
||||
import shader from './render.wgsl?raw';
|
||||
|
||||
export class RenderPipeline {
|
||||
private static readonly UNIFORM_COUNT = 13;
|
||||
|
|
|
|||
|
|
@ -4,7 +4,8 @@
|
|||
font-style: normal;
|
||||
font-weight: 400;
|
||||
font-display: swap;
|
||||
src: local(''),
|
||||
src:
|
||||
local(''),
|
||||
url('../../assets/fonts/comfortaa-v40-latin-regular.woff2') format('woff2'),
|
||||
/* Chrome 26+, Opera 23+, Firefox 39+ */
|
||||
url('../../assets/fonts/comfortaa-v40-latin-regular.woff') format('woff'); /* Chrome 6+, Firefox 3.6+, IE 9+, Safari 5.1+ */
|
||||
|
|
@ -16,7 +17,8 @@
|
|||
font-style: normal;
|
||||
font-weight: 400;
|
||||
font-display: swap;
|
||||
src: local(''),
|
||||
src:
|
||||
local(''),
|
||||
url('../../assets/fonts/open-sans-v34-latin-regular.woff2') format('woff2'),
|
||||
/* Chrome 26+, Opera 23+, Firefox 39+ */
|
||||
url('../../assets/fonts/open-sans-v34-latin-regular.woff') format('woff'); /* Chrome 6+, Firefox 3.6+, IE 9+, Safari 5.1+ */
|
||||
|
|
|
|||
|
|
@ -65,7 +65,9 @@ $breakpoint-width: 600px !default;
|
|||
}
|
||||
|
||||
@mixin title-font() {
|
||||
font: 400 3rem 'Comfortaa', sans-serif;
|
||||
font:
|
||||
400 3rem 'Comfortaa',
|
||||
sans-serif;
|
||||
color: var(--normal-text-color);
|
||||
line-height: 1;
|
||||
|
||||
|
|
@ -76,20 +78,26 @@ $breakpoint-width: 600px !default;
|
|||
}
|
||||
|
||||
@mixin sub-title-font() {
|
||||
font: 400 1.75rem 'Comfortaa', sans-serif;
|
||||
font:
|
||||
400 1.75rem 'Comfortaa',
|
||||
sans-serif;
|
||||
color: var(--normal-text-color);
|
||||
hyphens: auto;
|
||||
}
|
||||
|
||||
@mixin main-font() {
|
||||
font: 400 1.1rem 'Open Sans', sans-serif;
|
||||
font:
|
||||
400 1.1rem 'Open Sans',
|
||||
sans-serif;
|
||||
color: var(--normal-text-color);
|
||||
line-height: 1.8;
|
||||
hyphens: auto;
|
||||
}
|
||||
|
||||
@mixin special-text-font() {
|
||||
font: 400 1rem 'Open Sans', sans-serif;
|
||||
font:
|
||||
400 1rem 'Open Sans',
|
||||
sans-serif;
|
||||
color: var(--special-text-color);
|
||||
hyphens: auto;
|
||||
font-style: italic;
|
||||
|
|
|
|||
|
|
@ -1,19 +0,0 @@
|
|||
const setIndexAlias = (name: string, index: number, type: any) => {
|
||||
if (!Object.prototype.hasOwnProperty.call(type.prototype, name)) {
|
||||
Object.defineProperty(type.prototype, name, {
|
||||
get() {
|
||||
return this[index];
|
||||
},
|
||||
set(value) {
|
||||
this[index] = value;
|
||||
},
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
export const applyArrayPlugins = () => {
|
||||
setIndexAlias('x', 0, Array);
|
||||
setIndexAlias('y', 1, Array);
|
||||
setIndexAlias('x', 0, Float32Array);
|
||||
setIndexAlias('y', 1, Float32Array);
|
||||
};
|
||||
|
|
@ -1,14 +1,17 @@
|
|||
import { CopyPipeline } from '../../pipelines/copy/copy-pipeline';
|
||||
|
||||
import { vec2 } from 'gl-matrix';
|
||||
|
||||
import { CopyPipeline } from '../../pipelines/copy/copy-pipeline';
|
||||
|
||||
export class ResizableTexture {
|
||||
private texture: GPUTexture;
|
||||
private textureView: GPUTextureView;
|
||||
private readonly copyPipeline: CopyPipeline;
|
||||
private size: vec2 | null = null;
|
||||
|
||||
public constructor(private readonly device: GPUDevice, size: vec2) {
|
||||
public constructor(
|
||||
private readonly device: GPUDevice,
|
||||
size: vec2
|
||||
) {
|
||||
this.copyPipeline = new CopyPipeline(this.device);
|
||||
this.resize(size);
|
||||
}
|
||||
|
|
@ -21,8 +24,8 @@ export class ResizableTexture {
|
|||
const newTexture = this.device.createTexture({
|
||||
format: 'rgba16float',
|
||||
size: {
|
||||
width: size.x,
|
||||
height: size.y,
|
||||
width: size[0],
|
||||
height: size[1],
|
||||
},
|
||||
usage:
|
||||
GPUTextureUsage.STORAGE_BINDING |
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import { rgb } from './rgb';
|
||||
|
||||
import { vec3 } from 'gl-matrix';
|
||||
|
||||
import { rgb } from './rgb';
|
||||
|
||||
export const hsl = (hue: number, saturation: number, lightness: number): vec3 => {
|
||||
hue /= 360;
|
||||
saturation /= 100;
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ export const persist = <T extends Record<string, number>>(wrapee: T): T => {
|
|||
const keys = Object.keys(wrapee);
|
||||
keys.sort();
|
||||
|
||||
const keysToShortKeys = Object.fromEntries(keys.map((key, i) => [key, key]));
|
||||
const keysToShortKeys = Object.fromEntries(keys.map((key) => [key, key]));
|
||||
|
||||
const params = new URLSearchParams(window.location.search);
|
||||
const newParams = new URLSearchParams();
|
||||
|
|
|
|||
Loading…
Reference in a new issue