Glimmer
by krollster+domestika @krollster_1746535593
- 69
- 1
- 0



const canvasSketch = require('canvas-sketch');
const random = require('canvas-sketch-util/random');
const math = require('canvas-sketch-util/math');
const Tweakpane = require('tweakpane');
let settings = {
dimensions: [ 1920, 1080 ],
animate: true,
};
const params = {
animate: true,
frame: 0,
fps: 15,
timeScale: 1,
bgColour: 'rgba(0,0,0,1)',
nX: settings.dimensions[0],
nY: settings.dimensions[1],
nZAmp: 10,
nFreq: 0.001,
rColour: 'rgba(245,149,0,0)',
rWidthMin: 1,
rWidthMax: 4,
rHeightMin: settings.dimensions[1]/10,
rHeightMax: settings.dimensions[1],
rLIOffset: -50,
rLIIOffset: -150,
rLIIIOffset: -250,
rLIVOffset: -350,
rLVOffset: -350,
rLVIOffset: -450,
rLIRender: true,
rLIIRender: true,
rLIIIRender: true,
rLIVRender: true,
rLVRender: true,
rLVIRender: false,
rUpdateThreshold: 0.95,
rLayerDensity: 1.0,
}
settings.fps = params.fps;
settings.timeScale = params.timeScale;
const sketch = ({ context, width, height }) => {
// code by Hugh Haworth
// https://css-tricks.com/using-javascript-to-adjust-saturation-and-brightness-of-rgb-colors/
const getLowestMiddleHighest = function (rgbIntArray) {
let highest = {val:-1,index:-1};
let lowest = {val:Infinity,index:-1};
rgbIntArray.map((val,index)=>{
if(val>highest.val){
highest = {val:val,index:index};
}
if(val<lowest.val){
lowest = {val:val,index:index};
}
});
if(lowest.index===highest.index){
lowest.index=highest.index+1;
}
let middle = {index: (3 - highest.index - lowest.index)};
middle.val = rgbIntArray[middle.index];
return [lowest,middle,highest];
}
// based on code by Hugh Haworth
// https://css-tricks.com/using-javascript-to-adjust-saturation-and-brightness-of-rgb-colors/
const lightenByFraction = function(rgba, fraction) {
const rgbaIntArray = rgba.replace(/ /g, '').slice(5, -1).split(',').map(e => parseInt(e));
// Grab the values in order of magnitude
// This uses the getLowestMiddleHighest function from the saturate section
const [lowest,middle,highest]=getLowestMiddleHighest(rgbaIntArray.slice(0,3));
if(lowest.val===255){
return rgba;
}
const returnArray = [];
// First work out increase on lower value
returnArray[lowest.index]= Math.round(lowest.val+(Math.min(255-lowest.val,fraction)));
// Then apply to the middle and higher values
const increaseFraction = (returnArray[lowest.index]-lowest.val)/ (255-lowest.val);
returnArray[middle.index]= middle.val +(255-middle.val)*increaseFraction ;
returnArray[highest.index]= highest.val +(255-highest.val)*increaseFraction ;
// Convert the array back into an rgba string
return (`rgba(${returnArray.join()},${rgbaIntArray[3]})`);
}
// based on code by Hugh Haworth
// https://css-tricks.com/using-javascript-to-adjust-saturation-and-brightness-of-rgb-colors/
const darkenByFraction = function(rgba, fraction) {
// Our rgb to int array function again
const rgbaIntArray = rgba.replace(/ /g, '').slice(5, -1).split(',').map(e => parseInt(e));
//grab the values in order of magnitude
//this uses the function from the saturate function
const [lowest,middle,highest]=getLowestMiddleHighest(rgbaIntArray.slice(0,3));
if (highest.val===0){
return rgba;
}
const returnArray = [];
returnArray[highest.index] = highest.val-(Math.min(highest.val,fraction));
const decreaseFraction = (highest.val-returnArray[highest.index])/ (highest.val);
returnArray[middle.index] = middle.val -middle.val*decreaseFraction;
returnArray[lowest.index] = lowest.val -lowest.val*decreaseFraction;
// Convert the array back into an rgba string
return (`rgba(${returnArray.join()},${rgbaIntArray[3]}) `);
}
const rays = [];
for (let i = 0; i < width; i++) {
const x = i;
const y = 0;
if (params.rLayerDensity >= Math.random()) {
if (params.rLIRender) { rays.push(new Ray(x, params.rLIOffset, darkenByFraction(params.rColour, random.range(127.6, 191.25)))); }
if (params.rLIIRender) { rays.push(new Ray(x, params.rLIIOffset, darkenByFraction(params.rColour, random.range(63.76, 127.5)))); }
if (params.rLIIIRender) { rays.push(new Ray(x, params.rLIIIOffset, lightenByFraction(params.rColour, random.range(0, 63.75)))); }
if (params.rLIVRender) { rays.push(new Ray(x, params.rLIVOffset, lightenByFraction(params.rColour, random.range(63.76, 127.5)))); }
if (params.rLVRender) { rays.push(new Ray(x, params.rLVOffset, lightenByFraction(params.rColour, random.range(127.6, 191.25)))); }
if (params.rLVIRender) { rays.push(new Ray(x, params.rLVIOffset, lightenByFraction(params.rColour, random.range(191.26, 255)))); }
}
}
return ({ context, width, height, frame }) => {
context.clearRect(0, 0, settings.dimensions[0], settings.dimensions[1]);
context.fillStyle = params.bgColour;
context.fillRect(0, 0, width, height);
const f = (params.animate)? frame : params.frame;
rays.forEach(ray => {
ray.update(f);
ray.draw(context);
});
};
};
const createPane = () => {
const pane = new Tweakpane.Pane();
const refreshCanvas = function (ev){
if (ev.last) {
let element = document.getElementsByTagName("canvas");
for (let index = element.length - 1; index >= 0; index--) {
element[index].parentNode.removeChild(element[index]);
}
canvasSketch(sketch, settings);
}
}
let folder;
folder = pane.addFolder({ title: 'Global', expanded: false });
folder.addInput(params, 'animate');
folder.addInput(params, 'frame', { min: 0, step: 1, max: 999 });
folder.addInput(params, 'fps', { min: 1, step: 1, max: 120 });
folder.addInput(params, 'timeScale', { label: 'time scale', min: 0, max: 1 });
folder.addInput(params, 'bgColour', { label: 'bg colour'});
folder = pane.addFolder({ title: 'Noise', expanded: false });
folder.addInput(params, 'nX', { label: 'x', min: 0, step: 1, max: settings.dimensions[0] });
folder.addInput(params, 'nY', { label: 'y', min: 0, step: 1, max: settings.dimensions[1] });
folder.addInput(params, 'nZAmp', { label: 'z amp', min: 0, max: 999 });
folder.addInput(params, 'nFreq', { label: 'frequency', min: 0.0, max: 1.00 });
folder = pane.addFolder({ title: 'Rays', expanded: false });
folder.addInput(params, 'rColour', { label: 'colour'}).on('change', refreshCanvas);
folder.addInput(params, 'rWidthMin', { label: 'w min', min: 1, step: 1, max: 100 }).on('change', refreshCanvas);
folder.addInput(params, 'rWidthMax', { label: 'w max', min: 1, step: 1, max: 100 }).on('change', refreshCanvas);
folder.addInput(params, 'rHeightMin', { label: 'h min', min: 1, max: settings.dimensions[1] }).on('change', refreshCanvas);
folder.addInput(params, 'rHeightMax', { label: 'h max', min: 1, max: settings.dimensions[1] }).on('change', refreshCanvas);
folder = pane.addFolder({ title: 'Layers', expanded: false });
folder.addInput(params, 'rLIOffset', { label: 'l1 y', min: -settings.dimensions[1], step: 25, max: settings.dimensions[1] }).on('change', refreshCanvas);
folder.addInput(params, 'rLIIOffset', { label: 'l2 y', min: -settings.dimensions[1], step: 25, max: settings.dimensions[1] }).on('change', refreshCanvas);
folder.addInput(params, 'rLIIIOffset', { label: 'l3 y', min: -settings.dimensions[1], step: 25, max: settings.dimensions[1] }).on('change', refreshCanvas);
folder.addInput(params, 'rLIVOffset', { label: 'l4 y', min: -settings.dimensions[1], step: 25, max: settings.dimensions[1] }).on('change', refreshCanvas);
folder.addInput(params, 'rLVOffset', { label: 'l5 y',min: -settings.dimensions[1], step: 25, max: settings.dimensions[1] }).on('change', refreshCanvas);
folder.addInput(params, 'rLVIOffset', { label: 'l6 y',min: -settings.dimensions[1], step: 25, max: settings.dimensions[1] }).on('change', refreshCanvas);
folder.addInput(params, 'rLIRender', { label: 'render l1' }).on('change', refreshCanvas);
folder.addInput(params, 'rLIIRender', { label: 'render l2' }).on('change', refreshCanvas);
folder.addInput(params, 'rLIIIRender', { label: 'render l3' }).on('change', refreshCanvas);
folder.addInput(params, 'rLIVRender', { label: 'render l4' }).on('change', refreshCanvas);
folder.addInput(params, 'rLVRender', { label: 'render l5' }).on('change', refreshCanvas);
folder.addInput(params, 'rLVIRender', { label: 'render l6' }).on('change', refreshCanvas);
folder.addInput(params, 'rLayerDensity', { label: 'ray density', min: 0, max: 1.0 }).on('change', refreshCanvas);
folder.addInput(params, 'rUpdateThreshold', { label: 'update threshold', min: 0, max: 0.99 });
}
createPane();
canvasSketch(sketch, settings);
class Vector {
constructor(x, y) {
this.x = x;
this.y = y;
}
}
class Ray {
constructor(x, y, colour) {
this.pos = new Vector(x, y);
this.w = parseInt(random.range(params.rWidthMin, params.rWidthMax));
this.h = parseInt(random.range(params.rHeightMin, params.rHeightMax));
this.colour = colour;
}
draw(context) {
context.save();
context.translate(this.pos.x, this.pos.y);
context.beginPath();
context.fillStyle = this.colour;
context.fillRect( this.pos.x, this.pos.y, this.w, this.h );
context.fill();
context.restore();
}
update(frame) {
if (params.rUpdateThreshold < Math.random()) {
const [red, green, blue, alpha] = this.colour.replace(/ /g, '').slice(5, -1).split(',').map(e => parseInt(e));
const n = random.noise3D(params.nX, params.nY, frame * params.nZAmp, params.nFreq);
this.colour = `rgba(${red},${green},${blue},${math.mapRange(n, -1, 1, 0, 1)})`;
}
}
}
0 comments
Log in or join for Free to comment