Update to use new SDF2D version
This commit is contained in:
parent
f0a9c1df68
commit
9062ae04a3
14 changed files with 160 additions and 209 deletions
|
|
@ -45,7 +45,7 @@
|
||||||
"resolve-url-loader": "^3.1.1",
|
"resolve-url-loader": "^3.1.1",
|
||||||
"sass": "^1.26.3",
|
"sass": "^1.26.3",
|
||||||
"sass-loader": "^9.0.3",
|
"sass-loader": "^9.0.3",
|
||||||
"sdf-2d": "^0.5.0",
|
"sdf-2d": "^0.6.0",
|
||||||
"source-map-loader": "^1.1.0",
|
"source-map-loader": "^1.1.0",
|
||||||
"svg-url-loader": "^6.0.0",
|
"svg-url-loader": "^6.0.0",
|
||||||
"terser-webpack-plugin": "^2.3.8",
|
"terser-webpack-plugin": "^2.3.8",
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
export const prettyPrint = (o: any): string =>
|
export const prettyPrint = (o: any): string =>
|
||||||
JSON.stringify(o, (_, v) => (v.toFixed ? Number(v.toFixed(3)) : v), ' ')
|
JSON.stringify(o, (_, v) => (v?.toFixed ? Number(v.toFixed(3)) : v), ' ')
|
||||||
.replace(/("|,|{|^\n)/g, '')
|
.replace(/("|,|{|^\n)/g, '')
|
||||||
.replace(/(\W*}\n?)+/g, '\n\n');
|
.replace(/(\W*}\n?)+/g, '\n\n');
|
||||||
|
|
|
||||||
|
|
@ -25,7 +25,7 @@
|
||||||
|
|
||||||
<a id="info" href="https://github.com/schmelczerandras/sdf-2d" target="_BLANK">
|
<a id="info" href="https://github.com/schmelczerandras/sdf-2d" target="_BLANK">
|
||||||
<p>SDF-2D</p>
|
<p>SDF-2D</p>
|
||||||
<img src="static/logo-white.svg" alt="logo" />
|
<img width="64" height="64" src="static/logo-white.svg" alt="logo" />
|
||||||
</a>
|
</a>
|
||||||
<code id="overlay"></code>
|
<code id="overlay"></code>
|
||||||
<button id="toggle-text">Loading…</button>
|
<button id="toggle-text">Loading…</button>
|
||||||
|
|
|
||||||
41
src/index.ts
41
src/index.ts
|
|
@ -7,22 +7,18 @@ import '../static/logo-white.svg';
|
||||||
import '../static/no-change/404.html';
|
import '../static/no-change/404.html';
|
||||||
import '../static/no-change/robots.txt';
|
import '../static/no-change/robots.txt';
|
||||||
import '../static/og-image.png';
|
import '../static/og-image.png';
|
||||||
import { DeltaTimeCalculator } from './helper/delta-time-calculator';
|
|
||||||
import { removeUnnecessaryOutlines } from './helper/remove-unnecessary-outlines';
|
import { removeUnnecessaryOutlines } from './helper/remove-unnecessary-outlines';
|
||||||
import { BlobScene } from './scenes/blob/blob-scene';
|
import { BlobScene } from './scenes/blob/blob-scene';
|
||||||
import { MetaballScene } from './scenes/metaball/metaball-scene';
|
import { MetaballScene } from './scenes/metaball/metaball-scene';
|
||||||
import { RainScene } from './scenes/rain/rain-scene';
|
import { RainScene } from './scenes/rain/rain-scene';
|
||||||
import { Scene } from './scenes/scene';
|
|
||||||
import { TunnelScene } from './scenes/tunnel-scene';
|
import { TunnelScene } from './scenes/tunnel-scene';
|
||||||
import './styles/index.scss';
|
import './styles/index.scss';
|
||||||
|
|
||||||
const scenes = [TunnelScene, MetaballScene, RainScene, BlobScene];
|
const scenes = [TunnelScene, MetaballScene, RainScene, BlobScene];
|
||||||
const sceneIntervalInSeconds = 8;
|
|
||||||
|
|
||||||
glMatrix.setMatrixArrayType(Array);
|
glMatrix.setMatrixArrayType(Array);
|
||||||
removeUnnecessaryOutlines();
|
removeUnnecessaryOutlines();
|
||||||
|
|
||||||
const deltaTimeCalculator = new DeltaTimeCalculator();
|
|
||||||
const canvas = document.querySelector('canvas') as HTMLCanvasElement;
|
const canvas = document.querySelector('canvas') as HTMLCanvasElement;
|
||||||
const errorText = document.querySelector('#error-text') as HTMLParamElement;
|
const errorText = document.querySelector('#error-text') as HTMLParamElement;
|
||||||
const errorsContainer = document.querySelector('#errors-container') as HTMLDivElement;
|
const errorsContainer = document.querySelector('#errors-container') as HTMLDivElement;
|
||||||
|
|
@ -43,44 +39,13 @@ const handleTextToggle = () => {
|
||||||
toggleButton.addEventListener('click', handleTextToggle);
|
toggleButton.addEventListener('click', handleTextToggle);
|
||||||
handleTextToggle();
|
handleTextToggle();
|
||||||
|
|
||||||
const handleScene = async (
|
|
||||||
currentScene: Scene,
|
|
||||||
NextSceneConstructor: new () => Scene
|
|
||||||
): Promise<Scene> => {
|
|
||||||
let triggerIsOver: () => void;
|
|
||||||
const isOver = new Promise((resolve) => (triggerIsOver = resolve));
|
|
||||||
let timeSinceStart = 0;
|
|
||||||
|
|
||||||
const handleFrame = (currentTime: DOMHighResTimeStamp) => {
|
|
||||||
const deltaTime = deltaTimeCalculator.getNextDeltaTime(currentTime);
|
|
||||||
|
|
||||||
currentScene.drawNextFrame(currentTime, deltaTime);
|
|
||||||
|
|
||||||
if ((timeSinceStart += deltaTime) > sceneIntervalInSeconds * 1000) {
|
|
||||||
triggerIsOver();
|
|
||||||
} else {
|
|
||||||
requestAnimationFrame(handleFrame);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
requestAnimationFrame(handleFrame);
|
|
||||||
|
|
||||||
await isOver;
|
|
||||||
currentScene.destroy();
|
|
||||||
|
|
||||||
const nextScene = new NextSceneConstructor();
|
|
||||||
await nextScene.initialize(canvas, overlay);
|
|
||||||
|
|
||||||
return nextScene;
|
|
||||||
};
|
|
||||||
|
|
||||||
const main = async () => {
|
const main = async () => {
|
||||||
try {
|
try {
|
||||||
let i = 0;
|
let i = 0;
|
||||||
let currentScene: Scene = new scenes[i++]();
|
|
||||||
await currentScene.initialize(canvas, overlay);
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
currentScene = await handleScene(currentScene, scenes[i++ % scenes.length]);
|
const currentScene = new scenes[i++ % scenes.length]();
|
||||||
|
|
||||||
|
await currentScene.run(canvas, overlay);
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error(e);
|
console.error(e);
|
||||||
|
|
|
||||||
|
|
@ -1,65 +1,66 @@
|
||||||
import { vec2 } from 'gl-matrix';
|
import { vec2 } from 'gl-matrix';
|
||||||
import { CircleFactory, CircleLight, compile, Renderer, rgb, rgb255 } from 'sdf-2d';
|
import { CircleFactory, CircleLight, Renderer, rgb, rgb255, runAnimation } from 'sdf-2d';
|
||||||
import { prettyPrint } from '../../helper/pretty-print';
|
import { prettyPrint } from '../../helper/pretty-print';
|
||||||
|
import { settings } from '../../settings';
|
||||||
import { Scene } from '../scene';
|
import { Scene } from '../scene';
|
||||||
import { Blob } from './blob';
|
import { Blob } from './blob';
|
||||||
|
|
||||||
const Circle = CircleFactory(rgb255(119, 143, 120));
|
const Circle = CircleFactory(rgb255(119, 143, 120));
|
||||||
|
|
||||||
export class BlobScene implements Scene {
|
export class BlobScene implements Scene {
|
||||||
private renderer: Renderer;
|
|
||||||
private canvas: HTMLCanvasElement;
|
private canvas: HTMLCanvasElement;
|
||||||
private overlay: HTMLDivElement;
|
private overlay: HTMLDivElement;
|
||||||
|
|
||||||
public async initialize(
|
public async run(canvas: HTMLCanvasElement, overlay: HTMLDivElement): Promise<void> {
|
||||||
canvas: HTMLCanvasElement,
|
|
||||||
overlay: HTMLDivElement
|
|
||||||
): Promise<void> {
|
|
||||||
this.canvas = canvas;
|
this.canvas = canvas;
|
||||||
this.overlay = overlay;
|
this.overlay = overlay;
|
||||||
this.renderer = await compile(canvas, [
|
|
||||||
Circle.descriptor,
|
|
||||||
{
|
|
||||||
...CircleLight.descriptor,
|
|
||||||
shaderCombinationSteps: [0, 1, 2],
|
|
||||||
},
|
|
||||||
Blob.descriptor,
|
|
||||||
]);
|
|
||||||
|
|
||||||
this.renderer.setRuntimeSettings({
|
|
||||||
ambientLight: rgb255(89, 25, 115),
|
|
||||||
colorPalette: [
|
|
||||||
rgb255(0, 0, 0),
|
|
||||||
rgb255(119, 143, 120),
|
|
||||||
rgb255(119, 143, 120),
|
|
||||||
rgb255(224, 96, 126),
|
|
||||||
],
|
|
||||||
});
|
|
||||||
|
|
||||||
const { width, height } = this.canvas.getBoundingClientRect();
|
const { width, height } = this.canvas.getBoundingClientRect();
|
||||||
const length = vec2.length([width, height]);
|
const length = vec2.length([width, height]);
|
||||||
|
|
||||||
this.blob = new Blob([width / 2, -length / 4 + length / 2]);
|
this.blob = new Blob([width / 2, -length / 4 + length / 2]);
|
||||||
|
|
||||||
|
await runAnimation(
|
||||||
|
canvas,
|
||||||
|
[
|
||||||
|
Circle.descriptor,
|
||||||
|
{
|
||||||
|
...CircleLight.descriptor,
|
||||||
|
shaderCombinationSteps: [0, 1, 2],
|
||||||
|
},
|
||||||
|
Blob.descriptor,
|
||||||
|
],
|
||||||
|
this.drawNextFrame.bind(this),
|
||||||
|
{},
|
||||||
|
{
|
||||||
|
ambientLight: rgb255(89, 25, 115),
|
||||||
|
enableHighDpiRendering: true,
|
||||||
|
colorPalette: [
|
||||||
|
rgb255(0, 0, 0),
|
||||||
|
rgb255(119, 143, 120),
|
||||||
|
rgb255(119, 143, 120),
|
||||||
|
rgb255(224, 96, 126),
|
||||||
|
],
|
||||||
|
}
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
private blob: Blob;
|
private blob: Blob;
|
||||||
|
|
||||||
private deltaSinceStart = 0;
|
private drawNextFrame(
|
||||||
public drawNextFrame(
|
renderer: Renderer,
|
||||||
currentTime: DOMHighResTimeStamp,
|
currentTime: DOMHighResTimeStamp,
|
||||||
deltaTime: DOMHighResTimeStamp
|
deltaTime: DOMHighResTimeStamp
|
||||||
): void {
|
): boolean {
|
||||||
const { width, height } = this.canvas.getBoundingClientRect();
|
const { width, height } = this.canvas.getBoundingClientRect();
|
||||||
this.deltaSinceStart += deltaTime;
|
renderer.setViewArea([0, height], [width, height]);
|
||||||
this.renderer.setViewArea([0, height], [width, height]);
|
|
||||||
|
|
||||||
this.renderer.autoscaleQuality(deltaTime);
|
this.overlay.innerText = prettyPrint(renderer.insights);
|
||||||
this.overlay.innerText = prettyPrint(this.renderer.insights);
|
|
||||||
|
|
||||||
const length = vec2.length([width, height]);
|
const length = vec2.length([width, height]);
|
||||||
|
|
||||||
const q = (this.deltaSinceStart % 8000) / 4300;
|
const q = (currentTime % 8000) / 4300;
|
||||||
this.blob.animate(this.deltaSinceStart);
|
this.blob.animate(currentTime);
|
||||||
[
|
[
|
||||||
new Circle([width / 2, -length / 4], length / 2),
|
new Circle([width / 2, -length / 4], length / 2),
|
||||||
this.blob,
|
this.blob,
|
||||||
|
|
@ -79,12 +80,8 @@ export class BlobScene implements Scene {
|
||||||
rgb(0, 0.8, 1),
|
rgb(0, 0.8, 1),
|
||||||
1
|
1
|
||||||
),
|
),
|
||||||
].forEach((d) => this.renderer.addDrawable(d));
|
].forEach((d) => renderer.addDrawable(d));
|
||||||
|
|
||||||
this.renderer.renderDrawables();
|
return currentTime < settings.sceneTimeInMilliseconds;
|
||||||
}
|
|
||||||
|
|
||||||
public destroy(): void {
|
|
||||||
this.renderer.destroy();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,45 +1,20 @@
|
||||||
import { vec2 } from 'gl-matrix';
|
import { vec2 } from 'gl-matrix';
|
||||||
import { compile, Flashlight, Renderer, rgb, rgb255 } from 'sdf-2d';
|
import { Flashlight, Renderer, rgb, rgb255, runAnimation } from 'sdf-2d';
|
||||||
import { prettyPrint } from '../../helper/pretty-print';
|
import { prettyPrint } from '../../helper/pretty-print';
|
||||||
import { Random } from '../../helper/random';
|
import { Random } from '../../helper/random';
|
||||||
|
import { settings } from '../../settings';
|
||||||
import { Scene } from '../scene';
|
import { Scene } from '../scene';
|
||||||
import { Metaball, MetaCircle } from './metaball';
|
import { Metaball, MetaCircle } from './metaball';
|
||||||
|
|
||||||
export class MetaballScene implements Scene {
|
export class MetaballScene implements Scene {
|
||||||
private circles: Array<Metaball> = [];
|
private circles: Array<Metaball> = [];
|
||||||
|
|
||||||
private renderer: Renderer;
|
|
||||||
private canvas: HTMLCanvasElement;
|
private canvas: HTMLCanvasElement;
|
||||||
private overlay: HTMLDivElement;
|
private overlay: HTMLDivElement;
|
||||||
|
|
||||||
public async initialize(
|
public async run(canvas: HTMLCanvasElement, overlay: HTMLDivElement): Promise<void> {
|
||||||
canvas: HTMLCanvasElement,
|
|
||||||
overlay: HTMLDivElement
|
|
||||||
): Promise<void> {
|
|
||||||
this.canvas = canvas;
|
this.canvas = canvas;
|
||||||
this.overlay = overlay;
|
this.overlay = overlay;
|
||||||
this.renderer = await compile(canvas, [
|
|
||||||
{
|
|
||||||
...Flashlight.descriptor,
|
|
||||||
shaderCombinationSteps: [0, 2],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
...MetaCircle.descriptor,
|
|
||||||
shaderCombinationSteps: [0, 1, 2, 4, 8, 12, 16],
|
|
||||||
},
|
|
||||||
]);
|
|
||||||
|
|
||||||
this.renderer.setRuntimeSettings({
|
|
||||||
ambientLight: rgb(0.1, 0.1, 0.3),
|
|
||||||
colorPalette: [
|
|
||||||
rgb(1, 1, 1),
|
|
||||||
rgb(1, 1, 1),
|
|
||||||
rgb(1, 1, 1),
|
|
||||||
rgb(1, 1, 1),
|
|
||||||
rgb(1, 1, 0),
|
|
||||||
rgb255(186, 59, 70),
|
|
||||||
],
|
|
||||||
});
|
|
||||||
|
|
||||||
for (let i = 0; i < 16; i++) {
|
for (let i = 0; i < 16; i++) {
|
||||||
this.circles.push(
|
this.circles.push(
|
||||||
|
|
@ -55,26 +30,46 @@ export class MetaballScene implements Scene {
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
await runAnimation(
|
||||||
|
canvas,
|
||||||
|
[
|
||||||
|
{
|
||||||
|
...Flashlight.descriptor,
|
||||||
|
shaderCombinationSteps: [0, 2],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
...MetaCircle.descriptor,
|
||||||
|
shaderCombinationSteps: [0, 1, 2, 4, 8, 12, 16],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
this.drawNextFrame.bind(this),
|
||||||
|
{},
|
||||||
|
{
|
||||||
|
ambientLight: rgb(0.1, 0.1, 0.3),
|
||||||
|
enableHighDpiRendering: true,
|
||||||
|
}
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public drawNextFrame(
|
private drawNextFrame(
|
||||||
|
renderer: Renderer,
|
||||||
currentTime: DOMHighResTimeStamp,
|
currentTime: DOMHighResTimeStamp,
|
||||||
deltaTime: DOMHighResTimeStamp
|
deltaTime: DOMHighResTimeStamp
|
||||||
): void {
|
): boolean {
|
||||||
const { width, height } = this.canvas.getBoundingClientRect();
|
const { width, height } = this.canvas.getBoundingClientRect();
|
||||||
const viewAreaWidth = width / Math.max(width, height);
|
const viewAreaWidth = width / Math.max(width, height);
|
||||||
const viewAreaHeight = height / Math.max(width, height);
|
const viewAreaHeight = height / Math.max(width, height);
|
||||||
this.renderer.setViewArea(
|
renderer.setViewArea(
|
||||||
vec2.fromValues(0, viewAreaHeight),
|
vec2.fromValues(0, viewAreaHeight),
|
||||||
vec2.fromValues(viewAreaWidth, viewAreaHeight)
|
vec2.fromValues(viewAreaWidth, viewAreaHeight)
|
||||||
);
|
);
|
||||||
this.renderer.autoscaleQuality(deltaTime);
|
|
||||||
|
|
||||||
this.overlay.innerText = prettyPrint(this.renderer.insights);
|
this.overlay.innerText = prettyPrint(renderer.insights);
|
||||||
|
|
||||||
this.circles.forEach((c) => {
|
this.circles.forEach((c) => {
|
||||||
c.animate(currentTime / 2000, viewAreaWidth, viewAreaHeight);
|
c.animate(currentTime / 2000, viewAreaWidth, viewAreaHeight);
|
||||||
this.renderer.addDrawable(c.shape);
|
renderer.addDrawable(c.shape);
|
||||||
});
|
});
|
||||||
|
|
||||||
const light1 = new Flashlight(
|
const light1 = new Flashlight(
|
||||||
|
|
@ -90,13 +85,9 @@ export class MetaballScene implements Scene {
|
||||||
vec2.fromValues(-1, 1)
|
vec2.fromValues(-1, 1)
|
||||||
);
|
);
|
||||||
|
|
||||||
this.renderer.addDrawable(light1);
|
renderer.addDrawable(light1);
|
||||||
this.renderer.addDrawable(light2);
|
renderer.addDrawable(light2);
|
||||||
|
|
||||||
this.renderer.renderDrawables();
|
return currentTime < settings.sceneTimeInMilliseconds;
|
||||||
}
|
|
||||||
|
|
||||||
public destroy(): void {
|
|
||||||
this.renderer.destroy();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
import { vec2 } from 'gl-matrix';
|
import { vec2 } from 'gl-matrix';
|
||||||
import { MetaCircleFactory } from 'sdf-2d';
|
import { MetaCircleFactory, rgb255 } from 'sdf-2d';
|
||||||
import { Random } from '../../helper/random';
|
import { Random } from '../../helper/random';
|
||||||
|
|
||||||
export const MetaCircle = MetaCircleFactory(5);
|
export const MetaCircle = MetaCircleFactory(rgb255(186, 59, 70));
|
||||||
|
|
||||||
export class Metaball {
|
export class Metaball {
|
||||||
public shape = new MetaCircle(vec2.create(), Random.getRandomInRange(0.025, 0.075));
|
public shape = new MetaCircle(vec2.create(), Random.getRandomInRange(0.025, 0.075));
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
import { vec2 } from 'gl-matrix';
|
import { vec2 } from 'gl-matrix';
|
||||||
import { DropletFactory } from 'sdf-2d';
|
import { DropletFactory, rgb } from 'sdf-2d';
|
||||||
import { Random } from '../../helper/random';
|
import { Random } from '../../helper/random';
|
||||||
|
|
||||||
export const Droplet = DropletFactory(1);
|
export const Droplet = DropletFactory(rgb(0.3, 1, 1));
|
||||||
export class DropletWrapper {
|
export class DropletWrapper {
|
||||||
public readonly drawable: InstanceType<typeof Droplet>;
|
public readonly drawable: InstanceType<typeof Droplet>;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
import { vec2 } from 'gl-matrix';
|
import { vec2 } from 'gl-matrix';
|
||||||
import { CircleLight, compile, Renderer, rgb, rgb255 } from 'sdf-2d';
|
import { CircleLight, Renderer, rgb, rgb255, runAnimation } from 'sdf-2d';
|
||||||
import { prettyPrint } from '../../helper/pretty-print';
|
import { prettyPrint } from '../../helper/pretty-print';
|
||||||
|
import { settings } from '../../settings';
|
||||||
import { Scene } from '../scene';
|
import { Scene } from '../scene';
|
||||||
import { Droplet, DropletWrapper } from './droplet';
|
import { Droplet, DropletWrapper } from './droplet';
|
||||||
|
|
||||||
|
|
@ -9,47 +10,47 @@ export class RainScene implements Scene {
|
||||||
private light1: CircleLight = new CircleLight(vec2.create(), rgb255(184, 41, 255), 2);
|
private light1: CircleLight = new CircleLight(vec2.create(), rgb255(184, 41, 255), 2);
|
||||||
private light2: CircleLight = new CircleLight(vec2.create(), rgb255(255, 31, 109), 2);
|
private light2: CircleLight = new CircleLight(vec2.create(), rgb255(255, 31, 109), 2);
|
||||||
|
|
||||||
private renderer: Renderer;
|
|
||||||
private canvas: HTMLCanvasElement;
|
private canvas: HTMLCanvasElement;
|
||||||
private overlay: HTMLDivElement;
|
private overlay: HTMLDivElement;
|
||||||
|
|
||||||
public async initialize(
|
public async run(canvas: HTMLCanvasElement, overlay: HTMLDivElement): Promise<void> {
|
||||||
canvas: HTMLCanvasElement,
|
|
||||||
overlay: HTMLDivElement
|
|
||||||
): Promise<void> {
|
|
||||||
this.canvas = canvas;
|
this.canvas = canvas;
|
||||||
this.overlay = overlay;
|
this.overlay = overlay;
|
||||||
this.renderer = await compile(canvas, [
|
|
||||||
{
|
|
||||||
...Droplet.descriptor,
|
|
||||||
shaderCombinationSteps: [0, 1, 2, 4, 8, 12, 16, 24],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
...CircleLight.descriptor,
|
|
||||||
shaderCombinationSteps: [0, 2],
|
|
||||||
},
|
|
||||||
]);
|
|
||||||
|
|
||||||
this.renderer.setRuntimeSettings({
|
|
||||||
ambientLight: rgb(0.2, 0.2, 0.2),
|
|
||||||
colorPalette: [rgb(1, 1, 1), rgb(0.3, 1, 1), rgb(1, 1, 0), rgb(0.3, 1, 1)],
|
|
||||||
});
|
|
||||||
|
|
||||||
for (let i = 0; i < (canvas.getBoundingClientRect().width / 800) * 20; i++) {
|
for (let i = 0; i < (canvas.getBoundingClientRect().width / 800) * 20; i++) {
|
||||||
this.droplets.push(new DropletWrapper());
|
this.droplets.push(new DropletWrapper());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
await runAnimation(
|
||||||
|
canvas,
|
||||||
|
[
|
||||||
|
{
|
||||||
|
...Droplet.descriptor,
|
||||||
|
shaderCombinationSteps: [0, 1, 2, 4, 8, 12, 16, 24],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
...CircleLight.descriptor,
|
||||||
|
shaderCombinationSteps: [0, 2],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
this.drawNextFrame.bind(this),
|
||||||
|
{},
|
||||||
|
{
|
||||||
|
ambientLight: rgb(0.2, 0.2, 0.2),
|
||||||
|
enableHighDpiRendering: true,
|
||||||
|
}
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public drawNextFrame(
|
private drawNextFrame(
|
||||||
|
renderer: Renderer,
|
||||||
currentTime: DOMHighResTimeStamp,
|
currentTime: DOMHighResTimeStamp,
|
||||||
deltaTime: DOMHighResTimeStamp
|
deltaTime: DOMHighResTimeStamp
|
||||||
): void {
|
): boolean {
|
||||||
const { width, height } = this.canvas.getBoundingClientRect();
|
const { width, height } = this.canvas.getBoundingClientRect();
|
||||||
this.renderer.setViewArea(vec2.fromValues(0, height), vec2.fromValues(width, height));
|
renderer.setViewArea(vec2.fromValues(0, height), vec2.fromValues(width, height));
|
||||||
this.renderer.autoscaleQuality(deltaTime);
|
this.overlay.innerText = prettyPrint(renderer.insights);
|
||||||
this.overlay.innerText = prettyPrint(this.renderer.insights);
|
|
||||||
|
|
||||||
const viewAreaSize = this.renderer.viewAreaSize;
|
const viewAreaSize = renderer.viewAreaSize;
|
||||||
|
|
||||||
vec2.set(this.light1.center, 0, viewAreaSize.y / 2);
|
vec2.set(this.light1.center, 0, viewAreaSize.y / 2);
|
||||||
vec2.set(this.light2.center, viewAreaSize.x, viewAreaSize.y / 2);
|
vec2.set(this.light2.center, viewAreaSize.x, viewAreaSize.y / 2);
|
||||||
|
|
@ -57,13 +58,9 @@ export class RainScene implements Scene {
|
||||||
this.droplets.forEach((d) => d.animate(currentTime, viewAreaSize));
|
this.droplets.forEach((d) => d.animate(currentTime, viewAreaSize));
|
||||||
|
|
||||||
[...this.droplets.map((d) => d.drawable), this.light1, this.light2].forEach((d) =>
|
[...this.droplets.map((d) => d.drawable), this.light1, this.light2].forEach((d) =>
|
||||||
this.renderer.addDrawable(d)
|
renderer.addDrawable(d)
|
||||||
);
|
);
|
||||||
|
|
||||||
this.renderer.renderDrawables();
|
return currentTime < settings.sceneTimeInMilliseconds;
|
||||||
}
|
|
||||||
|
|
||||||
public destroy(): void {
|
|
||||||
this.renderer.destroy();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,3 @@
|
||||||
export interface Scene {
|
export interface Scene {
|
||||||
initialize(canvas: HTMLCanvasElement, overlay: HTMLDivElement): Promise<void>;
|
run(canvas: HTMLCanvasElement, overlay: HTMLDivElement): Promise<void>;
|
||||||
drawNextFrame(currentTime: DOMHighResTimeStamp, deltaTime: DOMHighResTimeStamp): void;
|
|
||||||
destroy(): void;
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,24 +1,24 @@
|
||||||
import { vec2, vec3 } from 'gl-matrix';
|
import { vec2, vec3 } from 'gl-matrix';
|
||||||
import {
|
import {
|
||||||
CircleLight,
|
CircleLight,
|
||||||
compile,
|
|
||||||
FilteringOptions,
|
FilteringOptions,
|
||||||
InvertedTunnelFactory,
|
InvertedTunnelFactory,
|
||||||
Renderer,
|
Renderer,
|
||||||
renderNoise,
|
renderNoise,
|
||||||
rgb,
|
rgb,
|
||||||
|
runAnimation,
|
||||||
WrapOptions,
|
WrapOptions,
|
||||||
} from 'sdf-2d';
|
} from 'sdf-2d';
|
||||||
import { clamp } from '../helper/clamp';
|
import { clamp } from '../helper/clamp';
|
||||||
import { last } from '../helper/last';
|
import { last } from '../helper/last';
|
||||||
import { prettyPrint } from '../helper/pretty-print';
|
import { prettyPrint } from '../helper/pretty-print';
|
||||||
import { Random } from '../helper/random';
|
import { Random } from '../helper/random';
|
||||||
|
import { settings } from '../settings';
|
||||||
import { Scene } from './scene';
|
import { Scene } from './scene';
|
||||||
|
|
||||||
const InvertedTunnel = InvertedTunnelFactory(3);
|
const InvertedTunnel = InvertedTunnelFactory(3);
|
||||||
|
|
||||||
export class TunnelScene implements Scene {
|
export class TunnelScene implements Scene {
|
||||||
private renderer: Renderer;
|
|
||||||
private canvas: HTMLCanvasElement;
|
private canvas: HTMLCanvasElement;
|
||||||
private overlay: HTMLDivElement;
|
private overlay: HTMLDivElement;
|
||||||
|
|
||||||
|
|
@ -68,73 +68,69 @@ export class TunnelScene implements Scene {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public async initialize(
|
public async run(canvas: HTMLCanvasElement, overlay: HTMLDivElement): Promise<void> {
|
||||||
canvas: HTMLCanvasElement,
|
|
||||||
overlay: HTMLDivElement
|
|
||||||
): Promise<void> {
|
|
||||||
const noiseTexture = await renderNoise([1024, 1], 15, 1);
|
const noiseTexture = await renderNoise([1024, 1], 15, 1);
|
||||||
|
|
||||||
this.canvas = canvas;
|
this.canvas = canvas;
|
||||||
this.overlay = overlay;
|
this.overlay = overlay;
|
||||||
this.renderer = await compile(canvas, [
|
|
||||||
{
|
|
||||||
...InvertedTunnel.descriptor,
|
|
||||||
shaderCombinationSteps: [0, 1, 2, 4, 8, 12],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
...CircleLight.descriptor,
|
|
||||||
shaderCombinationSteps: [0, 1, 2, 3, 4, 5, 6, 7],
|
|
||||||
},
|
|
||||||
]);
|
|
||||||
|
|
||||||
this.renderer.setRuntimeSettings({
|
|
||||||
isWorldInverted: true,
|
|
||||||
ambientLight: rgb(0.35, 0.1, 0.45),
|
|
||||||
colorPalette: [rgb(0.4, 0.5, 0.6), rgb(0, 0, 0), rgb(0, 0, 0), rgb(0, 0, 0)],
|
|
||||||
textures: {
|
|
||||||
noiseTexture: {
|
|
||||||
source: noiseTexture,
|
|
||||||
overrides: {
|
|
||||||
maxFilter: FilteringOptions.LINEAR,
|
|
||||||
wrapS: WrapOptions.MIRRORED_REPEAT,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
for (let i = 0; i < 200; i++) {
|
for (let i = 0; i < 200; i++) {
|
||||||
this.generateTunnel();
|
this.generateTunnel();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
await runAnimation(
|
||||||
|
canvas,
|
||||||
|
[
|
||||||
|
{
|
||||||
|
...InvertedTunnel.descriptor,
|
||||||
|
shaderCombinationSteps: [0, 1, 2, 4, 8, 12],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
...CircleLight.descriptor,
|
||||||
|
shaderCombinationSteps: [0, 1, 2, 3, 4, 5, 6, 7],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
this.drawNextFrame.bind(this),
|
||||||
|
{ lightPenetrationRatio: 0.5 },
|
||||||
|
{
|
||||||
|
isWorldInverted: true,
|
||||||
|
enableHighDpiRendering: true,
|
||||||
|
ambientLight: rgb(0.35, 0.1, 0.45),
|
||||||
|
colorPalette: [rgb(0.4, 0.5, 0.6), rgb(0, 0, 0), rgb(0, 0, 0), rgb(0, 0, 0)],
|
||||||
|
textures: {
|
||||||
|
noiseTexture: {
|
||||||
|
source: noiseTexture,
|
||||||
|
overrides: {
|
||||||
|
maxFilter: FilteringOptions.LINEAR,
|
||||||
|
wrapS: WrapOptions.MIRRORED_REPEAT,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
private deltaSinceStart = 0;
|
private deltaSinceStart = 0;
|
||||||
public drawNextFrame(
|
private drawNextFrame(
|
||||||
|
renderer: Renderer,
|
||||||
currentTime: DOMHighResTimeStamp,
|
currentTime: DOMHighResTimeStamp,
|
||||||
deltaTime: DOMHighResTimeStamp
|
deltaTime: DOMHighResTimeStamp
|
||||||
): void {
|
): boolean {
|
||||||
const { width, height } = this.canvas.getBoundingClientRect();
|
const { width, height } = this.canvas.getBoundingClientRect();
|
||||||
this.deltaSinceStart += deltaTime;
|
this.deltaSinceStart += deltaTime;
|
||||||
const startX = this.deltaSinceStart / 3;
|
const startX = this.deltaSinceStart / 3;
|
||||||
const endX = startX + width;
|
const endX = startX + width;
|
||||||
this.renderer.setViewArea(
|
renderer.setViewArea(vec2.fromValues(startX, height), vec2.fromValues(width, height));
|
||||||
vec2.fromValues(startX, height),
|
|
||||||
vec2.fromValues(width, height)
|
|
||||||
);
|
|
||||||
|
|
||||||
this.renderer.autoscaleQuality(deltaTime);
|
this.overlay.innerText = prettyPrint(renderer.insights);
|
||||||
this.overlay.innerText = prettyPrint(this.renderer.insights);
|
|
||||||
|
|
||||||
[
|
[
|
||||||
...this.tunnels.filter(
|
...this.tunnels.filter(
|
||||||
(t) => startX < t.to.x + t.toRadius && t.from.x - t.fromRadius <= endX
|
(t) => startX < t.to.x + t.toRadius && t.from.x - t.fromRadius <= endX
|
||||||
),
|
),
|
||||||
...this.lights,
|
...this.lights,
|
||||||
].forEach((d) => this.renderer.addDrawable(d));
|
].forEach((d) => renderer.addDrawable(d));
|
||||||
|
|
||||||
this.renderer.renderDrawables();
|
return currentTime < settings.sceneTimeInMilliseconds;
|
||||||
}
|
|
||||||
|
|
||||||
public destroy(): void {
|
|
||||||
this.renderer.destroy();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
3
src/settings.ts
Normal file
3
src/settings.ts
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
export const settings = {
|
||||||
|
sceneTimeInMilliseconds: 7000,
|
||||||
|
};
|
||||||
|
|
@ -66,12 +66,15 @@ body {
|
||||||
|
|
||||||
#overlay {
|
#overlay {
|
||||||
right: 0;
|
right: 0;
|
||||||
font-size: 0.75rem;
|
white-space: pre-wrap;
|
||||||
white-space: pre;
|
overflow-wrap: break-word;
|
||||||
font-family: 'Lucida Console', Monaco, monospace;
|
font-family: 'Lucida Console', Monaco, monospace;
|
||||||
|
|
||||||
|
font-size: 0.75rem;
|
||||||
|
max-width: 400px;
|
||||||
@media (max-width: $breakpoint) {
|
@media (max-width: $breakpoint) {
|
||||||
font-size: 0.6rem;
|
font-size: 0.6rem;
|
||||||
|
max-width: 200px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
@mixin card {
|
@mixin card {
|
||||||
backdrop-filter: blur(16px);
|
backdrop-filter: blur(16px);
|
||||||
|
background-color: rgba(0, 0, 0, 0.15);
|
||||||
border: 2px solid white;
|
border: 2px solid white;
|
||||||
border-radius: 12px;
|
border-radius: 12px;
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue