Improve demos

This commit is contained in:
Andras Schmelczer 2026-06-11 08:26:26 +01:00
parent 414149293a
commit 491d5817c2
6 changed files with 319 additions and 22 deletions

View file

@ -5,17 +5,26 @@ import { settings } from '../../settings';
import { Scene } from '../scene';
import { Droplet, DropletWrapper } from './droplet';
const WIND_SLANT = 0.2;
export class RainScene implements Scene {
private droplets: Array<DropletWrapper> = [];
private light1: CircleLight = new CircleLight(vec2.create(), rgb255(184, 41, 255), 1.5);
private light2: CircleLight = new CircleLight(vec2.create(), rgb255(255, 31, 109), 1.5);
private lights = [
new CircleLight(vec2.create(), rgb255(184, 41, 255), 1.5),
new CircleLight(vec2.create(), rgb255(255, 31, 109), 1.5),
new CircleLight(vec2.create(), rgb255(64, 110, 255), 1.5),
];
private overlay: HTMLDivElement;
public insights?: any;
public async run(canvas: HTMLCanvasElement, overlay: HTMLDivElement): Promise<void> {
this.overlay = overlay;
for (let i = 0; i < (canvas.getBoundingClientRect().width / 800) * 20; i++) {
for (
let i = 0;
i < Math.max(100, (canvas.getBoundingClientRect().width / 800) * 100);
i++
) {
this.droplets.push(new DropletWrapper());
}
@ -24,18 +33,24 @@ export class RainScene implements Scene {
[
{
...Droplet.descriptor,
shaderCombinationSteps: [0, 1, 2, 4, 8, 12, 16, 24],
// Tiles that contain more droplets than the largest step have no
// compiled shader to fall back on and flicker; together with the
// raised tileMultiplier, 48 keeps the worst-case tile comfortably
// covered.
shaderCombinationSteps: [0, 2, 4, 8, 16, 32, 48],
},
{
...CircleLight.descriptor,
shaderCombinationSteps: [0, 2],
shaderCombinationSteps: [0, 3],
},
],
this.drawNextFrame.bind(this),
{
backgroundColor: rgb(0.5, 0.5, 0.5),
ambientLight: rgb(0.2, 0.2, 0.2),
ambientLight: rgb(0.2, 0.2, 0.23),
enableHighDpiRendering: true,
// More, smaller tiles keep the droplet count per tile low.
tileMultiplier: 12,
}
);
}
@ -55,12 +70,19 @@ export class RainScene implements Scene {
const viewAreaSize = renderer.viewAreaSize;
vec2.set(this.light1.center, 0, viewAreaSize.y / 2);
vec2.set(this.light2.center, viewAreaSize.x, viewAreaSize.y / 2);
// each light sweeps within its own third of the screen
this.lights.forEach((light, i) => {
vec2.set(
light.center,
viewAreaSize.x *
((i + 0.5) / 3 + (1 / 6) * Math.sin(currentTime / 900 + (i * Math.PI * 2) / 3)),
0
);
});
this.droplets.forEach((d) => d.animate(currentTime, viewAreaSize));
this.droplets.forEach((d) => d.animate(currentTime, viewAreaSize, WIND_SLANT));
[...this.droplets.map((d) => d.drawable), this.light1, this.light2].forEach((d) =>
[...this.droplets.map((d) => d.drawable), ...this.lights].forEach((d) =>
renderer.addDrawable(d)
);