Skip to content

Instantly share code, notes, and snippets.

@ciccarone
Created February 16, 2018 19:15
Show Gist options
  • Save ciccarone/2a06b09aecbab7ecf564cf168b60dc2c to your computer and use it in GitHub Desktop.
Save ciccarone/2a06b09aecbab7ecf564cf168b60dc2c to your computer and use it in GitHub Desktop.
WebGL Particles
<canvas id="canvas"></div>
<script id="vertex-shader" type="x-shader/x-vertex">
attribute vec2 a_position;
void main(void) {
gl_Position = vec4(a_position, 0, 1);
}
</script>
<script id="fragment-shader" type="x-shader/x-fragment">
#ifdef GL_ES
precision mediump float;
#endif
uniform vec2 u_resolution;
uniform float u_millis;
const int PARTICLES = 18;
const float ENERGY = 0.2;
const float BLOBINESS = 1.6;
const float BRIGHTNESS = 1.1;
const float OFFSET = 30000.0;
float rand(vec2 co) {
return fract(sin(dot(co.xy, vec2(12.9898, 78.233))) * 43758.5453);
}
void main(void) {
vec2 pixel = (gl_FragCoord.xy / u_resolution.x);
float t = (u_millis + OFFSET ) * 0.001 * ENERGY;
float a = 0.0;
float b = 0.0;
float c = 0.0;
vec2 particle;
vec2 center = vec2(0.5, 0.5 * (u_resolution.y / u_resolution.x));
float na, nb, nc, nd, d;
float size = float(PARTICLES);
float step = 1.0 / size;
float n = step;
for (int i = 0; i < PARTICLES; i++) {
vec2 np = vec2(n, 0.0);
na = rand(np * 1.1);
nb = rand(np * 2.8);
nc = rand(np * 0.7);
nd = rand(np * 3.2);
particle = center;
particle.x += sin(t*na) * cos(t*nb) * 0.6;
particle.y += cos(t*nc) * sin(t*nd) * 0.4;
d = pow(1.2 * na / length(particle - pixel), BLOBINESS);
if (float(i) < size * 0.3333) {
a += d;
} else if (float(i) < size * 0.6666) {
b += d;
} else {
c += d;
}
n += step;
}
vec3 col = vec3(a*c, b*c, a*b) * 0.0001 * BRIGHTNESS;
gl_FragColor = vec4(col, 1.0);
}
</script>
'use strict';
// Create program
const canvas = document.getElementById("canvas");
const gl = canvas.getContext('webgl');
const program = webglUtils.createProgramFromScripts(gl, ['vertex-shader', 'fragment-shader']);
// Create and initialize buffer
const geometryBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, geometryBuffer);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([
-1.0, -1.0,
1.0, -1.0,
-1.0, 1.0,
1.0, 1.0
]), gl.STATIC_DRAW);
// Set up attributes and uniforms
const attributes = {
position: gl.getAttribLocation(program, 'a_position')
};
const uniforms = {
resolution: gl.getUniformLocation(program, 'u_resolution'),
millis: gl.getUniformLocation(program, 'u_millis')
};
// Set WebGL program here (we have only one)
gl.useProgram(program);
// Setup canvas
window.onresize = resize;
resize();
// Start rendering
requestAnimationFrame(draw);
// Resize canvas and viewport
function resize () {
webglUtils.resizeCanvasToDisplaySize(gl.canvas);
gl.viewport(0, 0, gl.canvas.width, gl.canvas.height);
}
// Draw frame
function draw (now) {
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
gl.bindBuffer(gl.ARRAY_BUFFER, geometryBuffer);
gl.enableVertexAttribArray(attributes.position);
gl.vertexAttribPointer(attributes.position, 2, gl.FLOAT, false, 0, 0);
gl.uniform2f(uniforms.resolution, window.innerWidth, window.innerHeight);
gl.uniform1f(uniforms.millis, now);
gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);
requestAnimationFrame(draw);
}
<script src="https://webglfundamentals.org/webgl/resources/webgl-utils.js"></script>
html, body {
background: #111;
overflow: hidden;
margin: 0;
}
canvas {
width: 100vw;
height: 100vh;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment