document body style minHeight 600 let canvas document createElement canvas document body appendChild canvas canvas width canvas height 500 canvas id canvas let div document createElement div document body appendChild div div innerHTML Frequency input id freq type range min 0 1 max 8 0 step 0 1 value 2 br Fluid Speed input id fluidspeed type range min 1 max 100 step 1 value 20 br No Particles input id numparticles type range min 1 max 2000 step 1 value 500 br Speed input id speed type range min 0 1 max 3 0 step 0 1 br Thickness input id thickness type range min 1 max 10 0 step 1 value 3 br Random Noise input id randomnoise type range min 0 0 max 2 0 step 0 1 value 0 br Draw Field input id showfield type checkbox button id clear Clear button br Helper function for fract fractional part function myfract x return x Math floor x Helper function indot product function dot v1 v2 return v1 x v2 x v1 y v2 y Random function function random uv return myfract Math sin dot uv x 12 9898 y 78 233 43758 5453 Smooth random function function randomsmooth st let freq document getElementById freq value Integer grid coordinates let i x Math floor st x freq y Math floor st y freq Fractional coordinates within the grid cell let f x myfract st x freq y myfract st y freq Sample four corners of the cell using the random function let a random i let b random x i x 1 0 y i y let c random x i x y i y 1 0 let d random x i x 1 0 y i y 1 0 Smooth the interpolation factor f for smoother transition between values f x f x f x 3 0 2 0 f x f y f y f y 3 0 2 0 f y Bilinear interpolation between corners let x1 a 1 0 f x b f x let x2 c 1 0 f x d f x let y1 x1 1 0 f y x2 f y return y1 const simplex3 a b c Sample noise values using randomsmooth let vx randomsmooth x a c 3 2390230 y b c 1 3923 let vy randomsmooth x a c 2 19339023 y b c 0 19009323 let t Math sin c return vx vy vx t function valid val if val undefined throw invalid value if isNaN val throw NaN value if val 9999999 throw number warning range if val 9999999 throw number warning range Constructor for vec2 function vec2 x y this x x this y y valid this x valid this y return this vec2 prototype float32 function let r new Float32Array 2 r 0 this x r 1 this y return r vec2 operations vec2 add function v0 v1 return new vec2 v0 x v1 x v0 y v1 y vec2 sub function v0 v1 return new vec2 v0 x v1 x v0 y v1 y vec2 scale function v0 s return new vec2 v0 x s v0 y s vec2 dot function v0 v1 return v0 x v1 x v0 y v1 y vec2 dist function v0 return Math sqrt v0 x v0 x v0 y v0 y vec2 norm function v0 let ln Math sqrt v0 x v0 x v0 y v0 y valid ln return vec2 scale v0 1 0 ln vec2 lerp function a b t let ti 1 t return new vec2 ti a x t b x ti a y t b y vec2 fromAngle function angle return new vec2 Math cos angle Math sin angle class Particle constructor x y this pos new vec2 x y this vel new vec2 Math random 2 1 Math random 2 1 this acc new vec2 0 0 this size 2 move acc if acc this acc vec2 add this acc acc let speed document getElementById speed value this vel vec2 add this vel this acc this pos vec2 add this pos vec2 scale this vel 1 0 if vec2 dist this vel 1 0 this vel vec2 scale vec2 norm this vel speed this acc new vec2 0 0 draw let ss this size ss document getElementById thickness value ctx fillRect this pos x this pos y ss ss wrap if this pos x w this pos x 0 else if this pos x 0 this size this pos x w 2 if this pos y h this pos y 0 else if this pos y 0 this size this pos y h 2 let ctx let field let w h let size let columns let rows let noiseZ let particles let hue function setup size 10 hue 0 noiseZ 0 canvas document querySelector canvas ctx canvas getContext 2d reset window addEventListener resize reset function initParticles particles let numberOfParticles w h 3000 let numberOfParticles 2000 document getElementById numparticles value for let i 0 i numberOfParticles i let particle new Particle Math random w Math random h particles push particle console log init particles function initField console log init field field new Array columns for let x 0 x columns x field x new Array columns for let y 0 y rows y field x y let v new vec2 0 0 field x y v function calculateField console log calc field for let x 0 x columns x for let y 0 y rows y let angle simplex3 x 20 y 20 noiseZ Math PI 2 let len simplex3 x 40 40000 y 40 40000 noiseZ 0 5 field x y vec2 norm field x y field x y angle angle field x y vec2 fromAngle angle field x y len len field x y angle angle function reset w canvas width window innerWidth h canvas height window innerHeight ctx strokeStyle white columns Math round w size 1 rows Math round h size 1 initParticles initField console log reset finished drawBackground function draw now requestAnimationFrame draw calculateField noiseZ 0 001 noiseZ document getElementById fluidspeed value 10000 0 if document getElementById showfield checked drawBackground drawFlowField drawParticles document getElementById clear onclick drawBackground function drawBackground ctx fillStyle black ctx fillRect 0 0 w h function drawParticles hue 0 5 ctx fillStyle hsla hue 50 50 0 1 particles forEach p k let numparticles document getElementById numparticles value if k numparticles return p draw let pos vec2 scale p pos 1 0 size let v x 1 y 1 if pos x 0 pos x columns pos y 0 pos y rows v field Math floor pos x Math floor pos y const randomnoise document getElementById randomnoise value v x randomsmooth x k 0 0238932 y k 1 239023 randomnoise v y randomsmooth x k 0 12323 y k 0 3892083 randomnoise p move v p wrap function drawFlowField for let x 0 x columns x for let y 0 y rows y ctx beginPath let x1 x size let y1 y size ctx moveTo x1 y1 ctx lineTo x1 field x y x size y1 field x y y size ctx stroke setup draw performance now
let speed document getElementById speed value this vel vec2 add this vel this acc this pos vec2 add this pos vec2 scale this vel 1 0 if vec2 dist this vel 1 0 this vel vec2 scale vec2 norm this vel speed this acc new vec2 0 0 draw let ss this size ss document getElementById thickness value ctx fillRect this pos x this pos y ss ss wrap if this pos x w this pos x 0 else if this pos x 0 this size this pos x w 2 if this pos y h this pos y 0 else if this pos y 0 this size this pos y h 2 let ctx let field let w h let size let columns let rows let noiseZ let particles let hue function setup size 10 hue 0 noiseZ 0 canvas document querySelector canvas ctx canvas getContext 2d reset window addEventListener resize reset function initParticles particles let numberOfParticles w h 3000 let numberOfParticles 2000 document getElementById numparticles value for let i 0 i numberOfParticles i let particle new Particle Math random w Math random h particles push particle console log init particles function initField console log init field field new Array columns for let x 0 x columns x field x new Array columns for let y 0 y rows y field x y let v new vec2 0 0 field x y v function calculateField console log calc field for let x 0 x columns x for let y 0 y rows y let angle simplex3 x 20 y 20 noiseZ Math PI 2 let len simplex3 x 40 40000 y 40 40000 noiseZ 0 5 field x y vec2 norm field x y field x y angle angle field x y vec2 fromAngle angle field x y len len field x y angle angle function reset w canvas width window innerWidth h canvas height window innerHeight ctx strokeStyle white columns Math round w size 1 rows Math round h size 1 initParticles initField console log reset finished drawBackground function draw now requestAnimationFrame draw calculateField noiseZ 0 001 noiseZ document getElementById fluidspeed value 10000 0 if document getElementById showfield checked drawBackground drawFlowField drawParticles document getElementById clear onclick drawBackground function drawBackground ctx fillStyle black ctx fillRect 0 0 w h function drawParticles hue 0 5 ctx fillStyle hsla hue 50 50 0 1 particles forEach p k let numparticles document getElementById numparticles value if k numparticles return p draw let pos vec2 scale p pos 1 0 size let v x 1 y 1 if pos x 0 pos x columns pos y 0 pos y rows v field Math floor pos x Math floor pos y const randomnoise document getElementById randomnoise value v x randomsmooth x k 0 0238932 y k 1 239023 randomnoise v y randomsmooth x k 0 12323 y k 0 3892083 randomnoise p move v p wrap function drawFlowField for let x 0 x columns x for let y 0 y rows y ctx beginPath let x1 x size let y1 y size ctx moveTo x1 y1 ctx lineTo x1 field x y x size y1 field x y y size ctx stroke setup draw performance now