raindrop-fx
Version:
Rain drop effect with WebGL
121 lines (103 loc) • 3.59 kB
text/typescript
import { Rect, TextureData, vec2 } from "@sardinefish/zogra-renderer";
import { RaindropRenderer, RenderOptions } from "./renderer";
import { RaindropSimulator, SimulatorOptions } from "./simulator";
import { Time } from "./utils";
interface Options extends SimulatorOptions, RenderOptions
{
}
class RaindropFX
{
public options: Options;
public renderer: RaindropRenderer;
public simulator: RaindropSimulator;
private animHandle = 0;
constructor(options: Partial<Options> & {canvas: HTMLCanvasElement})
{
const canvas = options.canvas;
const defaultOptions: Options = {
// Simulator options
spawnInterval: [0.1, 0.1],
spawnSize: [60, 100],
spawnLimit: 2000,
viewport: new Rect(vec2.zero(), vec2(canvas.width, canvas.height)),
canvas: canvas,
width: canvas.width,
height: canvas.height,
background: "",
gravity: 2400,
slipRate: 0,
motionInterval: [0.1, 0.4],
colliderSize: 1,
trailDropDensity: 0.2,
trailDistance: [20, 30],
trailDropSize: [0.3, 0.5],
trailSpread: 0.6,
initialSpread: 0.5,
shrinkRate: 0.01,
velocitySpread: 0.3,
evaporate: 10,
xShifting: [0, 0.1],
// Rendering options
backgroundBlurSteps: 3,
mist: true,
mistColor: [0.01, 0.01, 0.01, 1],
mistBlurStep: 4,
mistTime: 10,
dropletsPerSeconds: 500,
dropletSize: [10, 30],
smoothRaindrop: [0.96, 0.99],
refractBase: 0.4,
refractScale: 0.6,
raindropCompose: "smoother",
raindropLightPos: [-1, 1, 2, 0],
raindropDiffuseLight: [0.2, 0.2, 0.2],
raindropShadowOffset: 0.8,
raindropEraserSize: [0.93, 1.0],
raindropSpecularLight: [0, 0, 0],
raindropSpecularShininess: 256,
raindropLightBump: 1,
};
this.options = { ...defaultOptions, ...options };
this.simulator = new RaindropSimulator(this.options);
this.renderer = new RaindropRenderer(this.options);
}
async start()
{
await this.renderer.loadAssets();
let lastFrameTime = 0;
const update = (delay: number) =>
{
const dt = (delay - lastFrameTime) / 1000;
lastFrameTime = delay;
const time = <Time>{
dt: 0.03,
total: delay / 1000
};
this.update(time);
this.animHandle = requestAnimationFrame(update);
};
this.animHandle = requestAnimationFrame(update);
}
stop()
{
cancelAnimationFrame(this.animHandle);
}
resize(width: number, height: number)
{
this.options.width = width;
this.options.height = height;
this.options.viewport = new Rect(vec2.zero(), vec2(width, height));
this.renderer.resize();
}
async setBackground(background: string | TextureData)
{
this.renderer.options.background = background;
await this.renderer.reloadBackground();
}
private update(time: Time)
{
this.simulator.update(time);
this.renderer.render(this.simulator.raindrops, time);
}
}
export = RaindropFX;