Skip to content

Commit

Permalink
fade out
Browse files Browse the repository at this point in the history
  • Loading branch information
dkaraush committed Sep 20, 2023
1 parent 3fdf8fb commit efa9c18
Show file tree
Hide file tree
Showing 2 changed files with 104 additions and 51 deletions.
130 changes: 81 additions & 49 deletions main.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@ const resize = () => {
window.onresize = resize
resize()

function easeOutQuint(x) {
return 1 - Math.pow(1 - x, 5);
}

let reset = true
const GUI = {
particlesCount: 5000,
Expand All @@ -32,7 +36,10 @@ const GUI = {
longevity: 1.4,
noiseMovement: 4,
timeScale: .65,
color: 0xffffff
color: 0xffffff,

fadeOut: false,
fadeOutXY: [0, 0]
}

const gl = canvas.getContext('webgl2')
Expand Down Expand Up @@ -61,6 +68,9 @@ let maxVelocityHandle
let noiseMovementHandle
let colorHandle

let fadeOutHandle
let fadeOutXYHandle

const genBuffer = () => {
if (buffer) {
gl.deleteBuffer(buffer[0])
Expand Down Expand Up @@ -117,6 +127,9 @@ const init = async () => {
noiseMovementHandle = gl.getUniformLocation(program, 'noiseMovement')
colorHandle = gl.getUniformLocation(program, 'color')

fadeOutHandle = gl.getUniformLocation(program, 'fadeOut')
fadeOutXYHandle = gl.getUniformLocation(program, 'fadeOutXY')

gl.clearColor(0, 0, 0, 0)
gl.viewport(0, 0, W, H)
gl.enable(gl.BLEND)
Expand All @@ -125,6 +138,7 @@ const init = async () => {

let running = true
let time = 0
let fadeOutTime = 0
let lastDrawTime = window.performance.now()
const loop = () => {
if (!running) {
Expand All @@ -137,6 +151,11 @@ const loop = () => {
lastDrawTime = now

time += dt
if (GUI.fadeOut) {
const fadeOutDuration = 400 // ms
fadeOutTime += (dt * 1000 / fadeOutDuration)
}
const fadeOutT = easeOutQuint(Math.min(fadeOutTime, 1))

if (bufferParticlesCount < GUI.particlesCount) {
genBuffer()
Expand All @@ -146,53 +165,57 @@ const loop = () => {
gl.viewport(0, 0, W, H)
gl.clear(gl.COLOR_BUFFER_BIT)

gl.useProgram(program)
gl.uniform1f(resetHandle, reset ? 1 : 0)
if (reset) {
time = 0
reset = false;
}
gl.uniform1f(timeHandle, time)
gl.uniform1f(deltaTimeHandle, dt)
gl.uniform2f(sizeHandle, W, H)
gl.uniform1f(seedHandle, GUI.seed)
gl.uniform1f(radiusHandle, GUI.radius)
gl.uniform1f(noiseScaleHandle, GUI.noiseScale)
gl.uniform1f(noiseSpeedHandle, GUI.noiseSpeed)
gl.uniform1f(dampingMultHandle, GUI.dampingMult)
gl.uniform1f(velocityMultHandle, GUI.velocityMult)
gl.uniform1f(forceMultHandle, GUI.forceMult)
gl.uniform1f(longevityHandle, GUI.longevity)
gl.uniform1f(maxVelocityHandle, GUI.maxVelocity)
gl.uniform1f(noiseMovementHandle, GUI.noiseMovement)
gl.uniform3f(colorHandle,
((GUI.color >> 16) & 0xff) / 0xff,
((GUI.color >> 8) & 0xff) / 0xff,
(GUI.color & 0xff) / 0xff,
)
gl.bindBuffer(gl.ARRAY_BUFFER, buffer[bufferIndex])
gl.vertexAttribPointer(0, 2, gl.FLOAT, false, 24, 0)
gl.enableVertexAttribArray(0)
gl.vertexAttribPointer(1, 2, gl.FLOAT, false, 24, 8)
gl.enableVertexAttribArray(1)
gl.vertexAttribPointer(2, 1, gl.FLOAT, false, 24, 16)
gl.enableVertexAttribArray(2)
gl.vertexAttribPointer(3, 1, gl.FLOAT, false, 24, 20)
gl.enableVertexAttribArray(3)
gl.bindBufferBase(gl.TRANSFORM_FEEDBACK_BUFFER, 0, buffer[1 - bufferIndex])
gl.vertexAttribPointer(0, 2, gl.FLOAT, false, 24, 0)
gl.enableVertexAttribArray(0)
gl.vertexAttribPointer(1, 2, gl.FLOAT, false, 24, 8)
gl.enableVertexAttribArray(1)
gl.vertexAttribPointer(2, 1, gl.FLOAT, false, 24, 16)
gl.enableVertexAttribArray(2)
gl.vertexAttribPointer(3, 1, gl.FLOAT, false, 24, 20)
gl.enableVertexAttribArray(3)
gl.beginTransformFeedback(gl.POINTS)
gl.drawArrays(gl.POINTS, 0, GUI.particlesCount)
gl.endTransformFeedback()
gl.bindBuffer(gl.ARRAY_BUFFER, null)
gl.bindBufferBase(gl.TRANSFORM_FEEDBACK_BUFFER, 0, null)
if (fadeOutT < 1) {
gl.useProgram(program)
gl.uniform1f(resetHandle, reset ? 1 : 0)
if (reset) {
time = 0
reset = false;
}
gl.uniform1f(timeHandle, time)
gl.uniform1f(deltaTimeHandle, dt)
gl.uniform2f(sizeHandle, W, H)
gl.uniform1f(seedHandle, GUI.seed)
gl.uniform1f(radiusHandle, GUI.radius)
gl.uniform1f(noiseScaleHandle, GUI.noiseScale)
gl.uniform1f(noiseSpeedHandle, GUI.noiseSpeed)
gl.uniform1f(dampingMultHandle, GUI.dampingMult)
gl.uniform1f(velocityMultHandle, GUI.velocityMult)
gl.uniform1f(forceMultHandle, GUI.forceMult)
gl.uniform1f(longevityHandle, GUI.longevity)
gl.uniform1f(maxVelocityHandle, GUI.maxVelocity)
gl.uniform1f(noiseMovementHandle, GUI.noiseMovement)
gl.uniform3f(colorHandle,
((GUI.color >> 16) & 0xff) / 0xff,
((GUI.color >> 8) & 0xff) / 0xff,
(GUI.color & 0xff) / 0xff
)
gl.uniform1f(fadeOutHandle, fadeOutT)
gl.uniform2f(fadeOutXYHandle, GUI.fadeOutXY[0], GUI.fadeOutXY[1])
gl.bindBuffer(gl.ARRAY_BUFFER, buffer[bufferIndex])
gl.vertexAttribPointer(0, 2, gl.FLOAT, false, 24, 0)
gl.enableVertexAttribArray(0)
gl.vertexAttribPointer(1, 2, gl.FLOAT, false, 24, 8)
gl.enableVertexAttribArray(1)
gl.vertexAttribPointer(2, 1, gl.FLOAT, false, 24, 16)
gl.enableVertexAttribArray(2)
gl.vertexAttribPointer(3, 1, gl.FLOAT, false, 24, 20)
gl.enableVertexAttribArray(3)
gl.bindBufferBase(gl.TRANSFORM_FEEDBACK_BUFFER, 0, buffer[1 - bufferIndex])
gl.vertexAttribPointer(0, 2, gl.FLOAT, false, 24, 0)
gl.enableVertexAttribArray(0)
gl.vertexAttribPointer(1, 2, gl.FLOAT, false, 24, 8)
gl.enableVertexAttribArray(1)
gl.vertexAttribPointer(2, 1, gl.FLOAT, false, 24, 16)
gl.enableVertexAttribArray(2)
gl.vertexAttribPointer(3, 1, gl.FLOAT, false, 24, 20)
gl.enableVertexAttribArray(3)
gl.beginTransformFeedback(gl.POINTS)
gl.drawArrays(gl.POINTS, 0, GUI.particlesCount)
gl.endTransformFeedback()
gl.bindBuffer(gl.ARRAY_BUFFER, null)
gl.bindBufferBase(gl.TRANSFORM_FEEDBACK_BUFFER, 0, null)
} // else, everything is faded out, nothing to render

bufferIndex = 1 - bufferIndex
stats.end();
Expand Down Expand Up @@ -244,4 +267,13 @@ gui.add(GUI, 'dampingMult', 0.9, 0.9999)
gui.add(GUI, 'seed', 0, 100)
gui.add(GUI, 'reset')
gui.add(GUI, 'destroy')
gui.addColor(GUI, 'color')
gui.add(GUI, 'fadeOut')
gui.addColor(GUI, 'color')

canvas.onclick = e => {
GUI.fadeOut = true
GUI.fadeOutXY = [
e.offsetX * window.devicePixelRatio,
H - e.offsetY * window.devicePixelRatio
]
}
25 changes: 23 additions & 2 deletions vertex.glsl
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,9 @@ uniform float velocityMult;
uniform float longevity;
uniform float maxVelocity;

uniform float fadeOut;
uniform vec2 fadeOutXY;

float rand(vec2 n) {
return fract(sin(dot(n,vec2(12.9898,4.1414-seed*.42)))*43758.5453);
}
Expand Down Expand Up @@ -122,7 +125,25 @@ void main() {
}

position += velocity * velocityMult * deltaTime;
position = fract(position / size) * size;

float fadeOutAlpha = 1.;
if (fadeOut > 0.) {
vec2 vector = position - fadeOutXY;
float dist = length(vector);
vec2 dir = normalize(vector);
float dst = max(0., 1. - max(0., dist / max(size.x, size.y) - 1.));
position += dir * deltaTime * 2000. * dst;
fadeOutAlpha = 1. - pow(fadeOut, 16.);
}
if ((position.x < 0. || position.y < 0. || position.x > size.x || position.y > size.y) && fadeOut < .1) {
particleTime = 0.0;
position = size * vec2(
rand(vec2(42., -3.) * vec2(cos(float(gl_VertexID) - seed), gl_VertexID)),
rand(vec2(-3., 42.) * vec2(time * time, sin(float(gl_VertexID) + seed)))
);
particleDuration = .5 + 2. * rand(vec2(gl_VertexID) + position);
velocity = vec2(0.);
}

outPosition = position;
outVelocity = velocity;
Expand All @@ -131,7 +152,7 @@ void main() {

gl_PointSize = r;
gl_Position = vec4((position / size * 2.0 - vec2(1.0)), 0.0, 1.0);
alpha = sin(particleTime * 3.14) * (.6 + .4 * rand(vec2(gl_VertexID)));
alpha = sin(particleTime * 3.14) * fadeOutAlpha * (.6 + .4 * rand(vec2(gl_VertexID)));
}

// @dkaraush

0 comments on commit efa9c18

Please sign in to comment.