const ColorPalette = Object.freeze({
attribute vec3 aPosition;
attribute vec2 aTexCoord;
uniform mat4 uProjectionMatrix;
uniform mat4 uModelViewMatrix;
vec3 uPosition = aPosition;
vec4 positionVec4 = vec4(uPosition, 1.0);
gl_Position = uProjectionMatrix * uModelViewMatrix * positionVec4;//positionVec4;
uniform sampler2D fillGraphics;
uniform sampler2D wireGraphics;
uniform sampler2D maskGraphics;
#define R_LUMINANCE 0.298912
#define G_LUMINANCE 0.586611
#define B_LUMINANCE 0.114478
const vec3 monochromeScale = vec3(R_LUMINANCE, G_LUMINANCE, B_LUMINANCE);
const vec3 sepiaCoef = vec3(0.9, 0.7, 0.4);
vec4 offsetLookup(sampler2D tex, vec2 uv, float xOffset, float yOffset){
vec2 inverseTexSize = vec2(1.0 / resolution.x, 1.0 / resolution.y);
return texture2D(tex, uv + vec2(xOffset * inverseTexSize.x, yOffset * inverseTexSize.y));
return fract(sin(234.14 * v) * 347.12);
float seg(vec2 uv, vec2 s){
return floor(s.x * uv.x) + s.x * floor(s.y * uv.y);
vec3 latticeTex(vec2 uv){
float checker = mod(floor(uv.x), 2.0);
// float checker = mod(floor(uv.x) + floor(uv.y), 2.0);
// vec2 uv = vec2(vTexCoord.x, 1.0 - vTexCoord.y);
// vec4 fillGraphicsTex = texture2D(fillGraphics, uv);
// vec4 wireGraphicsTex = texture2D(wireGraphics, uv);
// vec3 checker = latticeTex(uv * 20.0);
// float circle = step((sin(length(uv - vec2(0.5)) * 20.0 - time * 2.0) + 1.0) * 0.5, 0.5);
// color += mix(fillGraphicsTex.rgb, fillGraphicsTex.rgb, circle);
// vec4 tex = texture2D(fillGraphics, uv);
// vec4 tex = texture2D(fillGraphics, uv);
// float gray = dot(tex.rgb, monochromeScale);
// vec4 tex = texture2D(fillGraphics, uv);
// color = vec3(1.0) - tex.rgb;
// vec4 tex = texture2D(fillGraphics, uv);
// float v = dot(tex.rgb, monochromeScale);
// color = sepiaCoef * v;
// vec4 tex = texture2D(fillGraphics, uv);
// float v = dot(tex.rgb, monochromeScale);
// color = vec3(step(0.53333, v));
// vec2 fPos = fract(uv * 5.0);
// vec4 tex = texture2D(fillGraphics, fPos);
// vec2 uv2 = vec2(uv.x + sin(time * 0.7 + uv.y * 15.0) * 0.022, uv.y + cos(time * 0.72 + uv.x * 105.0) * 0.022);
// vec2 uv3 = mix(uv, uv2, sin(time*0.4)*0.5+0.5);
// vec4 tex = texture2D(fillGraphics, uv3);
// float t = step(uv.x, (sin(time*0.2) + 1.0) * 0.5);
// vec4 fillGraphicsTex = texture2D(fillGraphics, uv);
// vec4 wireGraphicsTex = texture2D(wireGraphics, uv);
// color = mix(fillGraphicsTex.rgb, wireGraphicsTex.rgb, t);
vec4 fillGraphicsTex = texture2D(fillGraphics, uv);
vec4 wireGraphicsTex = texture2D(wireGraphics, uv);
vec4 maskGraphicsTex = texture2D(maskGraphics, uv);
color = mix(wireGraphicsTex.rgb, fillGraphicsTex.rgb, maskGraphicsTex.rgb);
// vec4 texColor = offsetLookup(wireGraphics, uv, -8.0, 0.0) * 0.5;
// texColor += offsetLookup(wireGraphics, uv, -6.0, 0.0) * 0.09;
// texColor += offsetLookup(wireGraphics, uv, -4.0, 0.0) * 0.12;
// texColor += offsetLookup(wireGraphics, uv, -2.0, 0.0) * 0.15;
// texColor += offsetLookup(wireGraphics, uv, 0.0, 0.0) * 0.16;
// texColor += offsetLookup(wireGraphics, uv, 2.0, 0.0) * 0.15;
// texColor += offsetLookup(wireGraphics, uv, 4.0, 0.0) * 0.12;
// texColor += offsetLookup(wireGraphics, uv, 6.0, 0.0) * 0.09;
// texColor += offsetLookup(wireGraphics, uv, 8.0, 0.0) * 0.05;
gl_FragColor = vec4(color, 1.0);
createCanvas(800, 800, WEBGL);
fillGraphics = createGraphics(width, height, WEBGL);
wireGraphics = createGraphics(width, height, WEBGL);
maskGraphics = createGraphics(width, height);
scenes = new Scenes(fillGraphics, wireGraphics);
useShader = createShader(vs, fs);
fillGraphics.background(255);
wireGraphics.background(0);
maskGraphics.background(0);
for(let i = 0; i < balls.length; i++){
balls[i].display(maskGraphics);
useShader.setUniform("resolution", [fillGraphics.width, fillGraphics.height]);
useShader.setUniform("time", frameCount*0.04);
useShader.setUniform("fillGraphics", fillGraphics);
useShader.setUniform("wireGraphics", wireGraphics);
useShader.setUniform("maskGraphics", maskGraphics);
rect(0, 0, width, height);
this.pos = createVector(random(width), random(height));
this.vel = p5.Vector.random2D().mult(random(3, 6));
this.radius = random(140, 200);
this.update = function(){
this.boundary = function(){
if(this.pos.x > width - this.radius * 0.5){
this.pos.x = width - this.radius * 0.5;
if(this.pos.x < this.radius * 0.5){
this.pos.x = this.radius * 0.5;
if(this.pos.y > height - this.radius * 0.5){
this.pos.y = height - this.radius * 0.5;
if(this.pos.y < this.radius * 0.5){
this.pos.y = this.radius * 0.5;
this.display = function(gr){
gr.ellipse(this.pos.x, this.pos.y, this.radius, this.radius);
function Scenes(fillGraphics, wireGraphics){
this.fillGraphics = fillGraphics;
this.wireGraphics = wireGraphics;
this.fillScene = new Scene(fillGraphics, false, color(ColorPalette.colorN));
this.wireScene = new Scene(wireGraphics, true, color(ColorPalette.colorS));
this.updateLoop = function(){
let p = createVector(random(-width, width), random(height, height * 2), random(-width, width));
let v = createVector(0.0, -random(2.0, 6.0), 0.0);
let len = random(20, 60);
let aVec = createVector(random(TWO_PI), random(TWO_PI), random(TWO_PI));
let aVel = createVector(random(aVelMin, aVelMax) * (random(1) > 0.5 ? -1 : 1), random(aVelMin, aVelMax) * (random(1) > 0.5 ? -1 : 1), random(aVelMin, aVelMax) * (random(1) > 0.5 ? -1 : 1));
this.fillScene.addBp(p, v, len, aVec, aVel);
this.wireScene.addBp(p, v, len, aVec, aVel);
this.fillScene.updateLoop();
this.wireScene.updateLoop();
this.getFillGraphics = function(){
return this.fillGraphics;
this.getWireGraphics = function(){
return this.wireGraphics;
function Scene(graphics, isWire, col){
this.graphics = graphics;
this.bps = new BoxParticleSystem(this.graphics, this.isWire, this.col);
this.updateLoop = function(){
this.graphics.translate(0, 0, 0);
this.graphics.rotateY(frameCount * 0.02);
this.graphics.stroke(this.col);
this.graphics.noStroke();
this.graphics.ambientLight(120);
const v = createVector(-2, 1, -1);
this.graphics.directionalLight(this.col, v);
this.graphics.ambientMaterial(this.col);
this.graphics.specularMaterial(100, 255);
this.graphics.sphere(100);
this.addBp = function(pos, vel, len, angleVec, angleVel){
this.bps.addParticle(pos, vel, len, angleVec, angleVel)
this.getGraphics = function(){
function BoxParticleSystem(graphics, isWire, col){
this.graphics = graphics;
this.updateLoop = function(){
for(let i = this.boxes.length-1; i >= 0; i--){
if(this.boxes[i].isDeadParticle()){
this.addParticle = function(pos, vel, len, angleVec, angleVel){
this.boxes.push(new BoxParticle(this.graphics, this.isWire, this.col, pos, vel, len, angleVec, angleVel));
function BoxParticle(graphics, isWire, col, pos, vel, len, angleVec, angleVel){
this.graphics = graphics;
this.angleVec = angleVec;
this.angleVel = angleVel;
this.update = function(){
this.angleVec.add(this.angleVel);
this.display = function(){
this.graphics.translate(this.pos.x, this.pos.y, this.pos.z);
this.graphics.rotateX(this.angleVec.x);
this.graphics.rotateY(this.angleVec.y);
this.graphics.rotateZ(this.angleVec.z);
this.graphics.stroke(this.col);
this.graphics.ambientLight(120);
const v = createVector(-2, 1, -1);
this.graphics.directionalLight(this.col, v);
this.graphics.ambientMaterial(this.col);
this.graphics.specularMaterial(100, 255);
this.graphics.box(this.len);
this.isDeadParticle = function(){
return this.pos.y < -height * 1.2;