feat: colors
This commit is contained in:
@@ -12,6 +12,12 @@ class AuroraCurtainsPreset extends BasePreset {
|
||||
waveSpeed: 0.35,
|
||||
horizontalSway: 0.45,
|
||||
brightness: 1.0,
|
||||
color1: '01010a',
|
||||
color2: '041332',
|
||||
color3: '0c3857',
|
||||
color4: '1aa07a',
|
||||
color5: '68d284',
|
||||
color6: 'f4f5c6',
|
||||
};
|
||||
}
|
||||
|
||||
@@ -41,12 +47,12 @@ class AuroraCurtainsPreset extends BasePreset {
|
||||
const timeSeconds = this.frameCount * 0.05; // Convert frame count to time
|
||||
|
||||
const paletteStops = [
|
||||
{ stop: 0.0, color: hexToRgb('01010a') },
|
||||
{ stop: 0.2, color: hexToRgb('041332') },
|
||||
{ stop: 0.4, color: hexToRgb('0c3857') },
|
||||
{ stop: 0.65, color: hexToRgb('1aa07a') },
|
||||
{ stop: 0.85, color: hexToRgb('68d284') },
|
||||
{ stop: 1.0, color: hexToRgb('f4f5c6') },
|
||||
{ stop: 0.0, color: hexToRgb(this.getParameter('color1') || '01010a') },
|
||||
{ stop: 0.2, color: hexToRgb(this.getParameter('color2') || '041332') },
|
||||
{ stop: 0.4, color: hexToRgb(this.getParameter('color3') || '0c3857') },
|
||||
{ stop: 0.65, color: hexToRgb(this.getParameter('color4') || '1aa07a') },
|
||||
{ stop: 0.85, color: hexToRgb(this.getParameter('color5') || '68d284') },
|
||||
{ stop: 1.0, color: hexToRgb(this.getParameter('color6') || 'f4f5c6') },
|
||||
];
|
||||
|
||||
for (let row = 0; row < this.height; ++row) {
|
||||
@@ -101,6 +107,12 @@ class AuroraCurtainsPreset extends BasePreset {
|
||||
waveSpeed: { type: 'range', min: 0.1, max: 2.0, step: 0.05, default: 0.35 },
|
||||
horizontalSway: { type: 'range', min: 0.1, max: 1.0, step: 0.05, default: 0.45 },
|
||||
brightness: { type: 'range', min: 0.1, max: 1.0, step: 0.1, default: 1.0 },
|
||||
color1: { type: 'color', default: '01010a' },
|
||||
color2: { type: 'color', default: '041332' },
|
||||
color3: { type: 'color', default: '0c3857' },
|
||||
color4: { type: 'color', default: '1aa07a' },
|
||||
color5: { type: 'color', default: '68d284' },
|
||||
color6: { type: 'color', default: 'f4f5c6' },
|
||||
},
|
||||
width: this.width,
|
||||
height: this.height,
|
||||
|
||||
@@ -8,19 +8,19 @@ class CircuitPulsePreset extends BasePreset {
|
||||
super(width, height);
|
||||
this.paths = [];
|
||||
this.pulses = [];
|
||||
this.paletteStops = [
|
||||
{ stop: 0.0, color: hexToRgb('020209') },
|
||||
{ stop: 0.3, color: hexToRgb('023047') },
|
||||
{ stop: 0.6, color: hexToRgb('115173') },
|
||||
{ stop: 0.8, color: hexToRgb('1ca78f') },
|
||||
{ stop: 1.0, color: hexToRgb('94fdf3') },
|
||||
];
|
||||
this.accentColors = ['14f5ff', 'a7ff4d', 'ffcc3f'];
|
||||
this.defaultParameters = {
|
||||
pathFade: 0.85,
|
||||
pulseLength: 6,
|
||||
pulseSpeed: 5.0,
|
||||
pulseCount: 3,
|
||||
color1: '020209',
|
||||
color2: '023047',
|
||||
color3: '115173',
|
||||
color4: '1ca78f',
|
||||
color5: '94fdf3',
|
||||
accentColor1: '14f5ff',
|
||||
accentColor2: 'a7ff4d',
|
||||
accentColor3: 'ffcc3f',
|
||||
};
|
||||
}
|
||||
|
||||
@@ -65,7 +65,12 @@ class CircuitPulsePreset extends BasePreset {
|
||||
}
|
||||
|
||||
spawnPulse(pathIndex) {
|
||||
const color = this.accentColors[pathIndex % this.accentColors.length];
|
||||
const accentColors = [
|
||||
this.getParameter('accentColor1') || '14f5ff',
|
||||
this.getParameter('accentColor2') || 'a7ff4d',
|
||||
this.getParameter('accentColor3') || 'ffcc3f',
|
||||
];
|
||||
const color = accentColors[pathIndex % accentColors.length];
|
||||
return {
|
||||
pathIndex,
|
||||
position: 0,
|
||||
@@ -95,6 +100,13 @@ class CircuitPulsePreset extends BasePreset {
|
||||
}
|
||||
|
||||
const pulseLength = this.getParameter('pulseLength');
|
||||
const paletteStops = [
|
||||
{ stop: 0.0, color: hexToRgb(this.getParameter('color1') || '020209') },
|
||||
{ stop: 0.3, color: hexToRgb(this.getParameter('color2') || '023047') },
|
||||
{ stop: 0.6, color: hexToRgb(this.getParameter('color3') || '115173') },
|
||||
{ stop: 0.8, color: hexToRgb(this.getParameter('color4') || '1ca78f') },
|
||||
{ stop: 1.0, color: hexToRgb(this.getParameter('color5') || '94fdf3') },
|
||||
];
|
||||
|
||||
for (let offset = 0; offset < pulseLength; ++offset) {
|
||||
const index = Math.floor(pulse.position) - offset;
|
||||
@@ -104,7 +116,7 @@ class CircuitPulsePreset extends BasePreset {
|
||||
|
||||
const { x, y } = path[index];
|
||||
const intensity = Math.max(0, 1 - offset / pulseLength);
|
||||
const baseColor = samplePalette(this.paletteStops, intensity);
|
||||
const baseColor = samplePalette(paletteStops, intensity);
|
||||
this.frame[toIndex(x, y, this.width)] = baseColor;
|
||||
addHexColor(this.frame, toIndex(x, y, this.width), pulse.color, intensity * 1.4);
|
||||
}
|
||||
@@ -142,6 +154,14 @@ class CircuitPulsePreset extends BasePreset {
|
||||
pulseLength: { type: 'range', min: 3, max: 12, step: 1, default: 6 },
|
||||
pulseSpeed: { type: 'range', min: 2.0, max: 8.0, step: 0.5, default: 5.0 },
|
||||
pulseCount: { type: 'range', min: 1, max: 6, step: 1, default: 3 },
|
||||
color1: { type: 'color', default: '020209' },
|
||||
color2: { type: 'color', default: '023047' },
|
||||
color3: { type: 'color', default: '115173' },
|
||||
color4: { type: 'color', default: '1ca78f' },
|
||||
color5: { type: 'color', default: '94fdf3' },
|
||||
accentColor1: { type: 'color', default: '14f5ff' },
|
||||
accentColor2: { type: 'color', default: 'a7ff4d' },
|
||||
accentColor3: { type: 'color', default: 'ffcc3f' },
|
||||
},
|
||||
width: this.width,
|
||||
height: this.height,
|
||||
|
||||
@@ -1,51 +0,0 @@
|
||||
// Fade Green Blue preset for LEDLab
|
||||
|
||||
const BasePreset = require('./base-preset');
|
||||
const { createFrame, frameToPayload } = require('./frame-utils');
|
||||
|
||||
class FadeGreenBluePreset extends BasePreset {
|
||||
constructor(width = 16, height = 16) {
|
||||
super(width, height);
|
||||
this.tick = 0;
|
||||
this.defaultParameters = {
|
||||
speed: 0.5, // cycles per second
|
||||
brightness: 1.0,
|
||||
};
|
||||
}
|
||||
|
||||
renderFrame() {
|
||||
const frame = createFrame(this.width, this.height);
|
||||
const timeSeconds = (this.tick * 0.016); // Assume 60 FPS
|
||||
const phase = timeSeconds * this.getParameter('speed') * Math.PI * 2;
|
||||
const blend = (Math.sin(phase) + 1) * 0.5; // 0..1
|
||||
|
||||
const brightness = this.getParameter('brightness') || 1.0;
|
||||
const green = Math.round(255 * (1 - blend) * brightness);
|
||||
const blue = Math.round(255 * blend * brightness);
|
||||
|
||||
const gHex = green.toString(16).padStart(2, '0');
|
||||
const bHex = blue.toString(16).padStart(2, '0');
|
||||
|
||||
for (let i = 0; i < frame.length; i++) {
|
||||
frame[i] = '00' + gHex + bHex;
|
||||
}
|
||||
|
||||
this.tick++;
|
||||
return frame;
|
||||
}
|
||||
|
||||
getMetadata() {
|
||||
return {
|
||||
name: 'Fade Green Blue',
|
||||
description: 'Smooth fade between green and blue colors',
|
||||
parameters: {
|
||||
speed: { type: 'range', min: 0.1, max: 2.0, step: 0.1, default: 0.5 },
|
||||
brightness: { type: 'range', min: 0.1, max: 1.0, step: 0.1, default: 1.0 },
|
||||
},
|
||||
width: this.width,
|
||||
height: this.height,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = FadeGreenBluePreset;
|
||||
68
presets/fade-preset.js
Normal file
68
presets/fade-preset.js
Normal file
@@ -0,0 +1,68 @@
|
||||
// Fade preset for LEDLab
|
||||
|
||||
const BasePreset = require('./base-preset');
|
||||
const { createFrame, frameToPayload } = require('./frame-utils');
|
||||
|
||||
class FadePreset extends BasePreset {
|
||||
constructor(width = 16, height = 16) {
|
||||
super(width, height);
|
||||
this.tick = 0;
|
||||
this.defaultParameters = {
|
||||
speed: 0.5, // cycles per second
|
||||
brightness: 1.0,
|
||||
color1: '00ff00', // Green
|
||||
color2: '0000ff', // Blue
|
||||
};
|
||||
}
|
||||
|
||||
hexToRgb(hex) {
|
||||
const r = parseInt(hex.slice(0, 2), 16);
|
||||
const g = parseInt(hex.slice(2, 4), 16);
|
||||
const b = parseInt(hex.slice(4, 6), 16);
|
||||
return { r, g, b };
|
||||
}
|
||||
|
||||
renderFrame() {
|
||||
const frame = createFrame(this.width, this.height);
|
||||
const timeSeconds = (this.tick * 0.016); // Assume 60 FPS
|
||||
const phase = timeSeconds * this.getParameter('speed') * Math.PI * 2;
|
||||
const blend = (Math.sin(phase) + 1) * 0.5; // 0..1
|
||||
|
||||
const brightness = this.getParameter('brightness') || 1.0;
|
||||
const color1 = this.hexToRgb(this.getParameter('color1') || '00ff00');
|
||||
const color2 = this.hexToRgb(this.getParameter('color2') || '0000ff');
|
||||
|
||||
const r = Math.round((color1.r * (1 - blend) + color2.r * blend) * brightness);
|
||||
const g = Math.round((color1.g * (1 - blend) + color2.g * blend) * brightness);
|
||||
const b = Math.round((color1.b * (1 - blend) + color2.b * blend) * brightness);
|
||||
|
||||
const rHex = r.toString(16).padStart(2, '0');
|
||||
const gHex = g.toString(16).padStart(2, '0');
|
||||
const bHex = b.toString(16).padStart(2, '0');
|
||||
|
||||
for (let i = 0; i < frame.length; i++) {
|
||||
frame[i] = rHex + gHex + bHex;
|
||||
}
|
||||
|
||||
this.tick++;
|
||||
return frame;
|
||||
}
|
||||
|
||||
getMetadata() {
|
||||
return {
|
||||
name: 'Fade',
|
||||
description: 'Smooth fade between two colors',
|
||||
parameters: {
|
||||
speed: { type: 'range', min: 0.1, max: 2.0, step: 0.1, default: 0.5 },
|
||||
brightness: { type: 'range', min: 0.1, max: 1.0, step: 0.1, default: 1.0 },
|
||||
color1: { type: 'color', default: '00ff00' },
|
||||
color2: { type: 'color', default: '0000ff' },
|
||||
},
|
||||
width: this.width,
|
||||
height: this.height,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = FadePreset;
|
||||
|
||||
@@ -7,20 +7,18 @@ class LavaLampPreset extends BasePreset {
|
||||
constructor(width = 16, height = 16) {
|
||||
super(width, height);
|
||||
this.blobs = [];
|
||||
this.paletteStops = [
|
||||
{ stop: 0.0, color: hexToRgb('050319') },
|
||||
{ stop: 0.28, color: hexToRgb('2a0c4f') },
|
||||
{ stop: 0.55, color: hexToRgb('8f1f73') },
|
||||
{ stop: 0.75, color: hexToRgb('ff4a22') },
|
||||
{ stop: 0.9, color: hexToRgb('ff9333') },
|
||||
{ stop: 1.0, color: hexToRgb('fff7b0') },
|
||||
];
|
||||
this.defaultParameters = {
|
||||
blobCount: 6,
|
||||
blobSpeed: 0.18,
|
||||
minBlobRadius: 0.18,
|
||||
maxBlobRadius: 0.38,
|
||||
intensity: 1.0,
|
||||
color1: '050319',
|
||||
color2: '2a0c4f',
|
||||
color3: '8f1f73',
|
||||
color4: 'ff4a22',
|
||||
color5: 'ff9333',
|
||||
color6: 'fff7b0',
|
||||
};
|
||||
}
|
||||
|
||||
@@ -85,11 +83,19 @@ class LavaLampPreset extends BasePreset {
|
||||
this.updateBlobs(0.016); // Assume 60 FPS
|
||||
|
||||
const frame = createFrame(this.width, this.height);
|
||||
const paletteStops = [
|
||||
{ stop: 0.0, color: hexToRgb(this.getParameter('color1') || '050319') },
|
||||
{ stop: 0.28, color: hexToRgb(this.getParameter('color2') || '2a0c4f') },
|
||||
{ stop: 0.55, color: hexToRgb(this.getParameter('color3') || '8f1f73') },
|
||||
{ stop: 0.75, color: hexToRgb(this.getParameter('color4') || 'ff4a22') },
|
||||
{ stop: 0.9, color: hexToRgb(this.getParameter('color5') || 'ff9333') },
|
||||
{ stop: 1.0, color: hexToRgb(this.getParameter('color6') || 'fff7b0') },
|
||||
];
|
||||
|
||||
for (let row = 0; row < this.height; ++row) {
|
||||
for (let col = 0; col < this.width; ++col) {
|
||||
const energy = this.calculateEnergyAt(col, row);
|
||||
const color = samplePalette(this.paletteStops, energy);
|
||||
const color = samplePalette(paletteStops, energy);
|
||||
frame[toIndex(col, row, this.width)] = color;
|
||||
}
|
||||
}
|
||||
@@ -136,6 +142,12 @@ class LavaLampPreset extends BasePreset {
|
||||
minBlobRadius: { type: 'range', min: 0.1, max: 0.3, step: 0.02, default: 0.18 },
|
||||
maxBlobRadius: { type: 'range', min: 0.2, max: 0.5, step: 0.02, default: 0.38 },
|
||||
intensity: { type: 'range', min: 0.5, max: 2.0, step: 0.1, default: 1.0 },
|
||||
color1: { type: 'color', default: '050319' },
|
||||
color2: { type: 'color', default: '2a0c4f' },
|
||||
color3: { type: 'color', default: '8f1f73' },
|
||||
color4: { type: 'color', default: 'ff4a22' },
|
||||
color5: { type: 'color', default: 'ff9333' },
|
||||
color6: { type: 'color', default: 'fff7b0' },
|
||||
},
|
||||
width: this.width,
|
||||
height: this.height,
|
||||
|
||||
@@ -7,17 +7,15 @@ class MeteorRainPreset extends BasePreset {
|
||||
constructor(width = 16, height = 16) {
|
||||
super(width, height);
|
||||
this.meteors = [];
|
||||
this.paletteStops = [
|
||||
{ stop: 0.0, color: hexToRgb('0a0126') },
|
||||
{ stop: 0.3, color: hexToRgb('123d8b') },
|
||||
{ stop: 0.7, color: hexToRgb('21c7d9') },
|
||||
{ stop: 1.0, color: hexToRgb('f7ffff') },
|
||||
];
|
||||
this.defaultParameters = {
|
||||
meteorCount: 12,
|
||||
minSpeed: 4,
|
||||
maxSpeed: 10,
|
||||
trailDecay: 0.76,
|
||||
color1: '0a0126',
|
||||
color2: '123d8b',
|
||||
color3: '21c7d9',
|
||||
color4: 'f7ffff',
|
||||
};
|
||||
}
|
||||
|
||||
@@ -45,7 +43,7 @@ class MeteorRainPreset extends BasePreset {
|
||||
};
|
||||
}
|
||||
|
||||
drawMeteor(meteor) {
|
||||
drawMeteor(meteor, paletteStops) {
|
||||
const col = Math.round(meteor.x);
|
||||
const row = Math.round(meteor.y);
|
||||
if (col < 0 || col >= this.width || row < 0 || row >= this.height) {
|
||||
@@ -53,15 +51,15 @@ class MeteorRainPreset extends BasePreset {
|
||||
}
|
||||
|
||||
const energy = clamp(1.2 - Math.random() * 0.2, 0, 1);
|
||||
this.frame[toIndex(col, row, this.width)] = samplePalette(this.paletteStops, energy);
|
||||
this.frame[toIndex(col, row, this.width)] = samplePalette(paletteStops, energy);
|
||||
}
|
||||
|
||||
updateMeteors(deltaSeconds) {
|
||||
updateMeteors(deltaSeconds, paletteStops) {
|
||||
this.meteors.forEach((meteor, index) => {
|
||||
meteor.x += meteor.vx * deltaSeconds;
|
||||
meteor.y += meteor.vy * deltaSeconds;
|
||||
|
||||
this.drawMeteor(meteor);
|
||||
this.drawMeteor(meteor, paletteStops);
|
||||
|
||||
if (meteor.x > this.width + 1 || meteor.y > this.height + 1) {
|
||||
this.meteors[index] = this.spawnMeteor(this.width, this.height);
|
||||
@@ -74,6 +72,13 @@ class MeteorRainPreset extends BasePreset {
|
||||
const trailDecay = this.getParameter('trailDecay') || 0.76;
|
||||
const meteorCount = this.getParameter('meteorCount') || 12;
|
||||
|
||||
const paletteStops = [
|
||||
{ stop: 0.0, color: hexToRgb(this.getParameter('color1') || '0a0126') },
|
||||
{ stop: 0.3, color: hexToRgb(this.getParameter('color2') || '123d8b') },
|
||||
{ stop: 0.7, color: hexToRgb(this.getParameter('color3') || '21c7d9') },
|
||||
{ stop: 1.0, color: hexToRgb(this.getParameter('color4') || 'f7ffff') },
|
||||
];
|
||||
|
||||
fadeFrame(this.frame, trailDecay);
|
||||
|
||||
// Update meteor count if it changed
|
||||
@@ -84,7 +89,7 @@ class MeteorRainPreset extends BasePreset {
|
||||
this.meteors.pop();
|
||||
}
|
||||
|
||||
this.updateMeteors(0.016); // Assume 60 FPS
|
||||
this.updateMeteors(0.016, paletteStops); // Assume 60 FPS
|
||||
|
||||
return this.frame;
|
||||
}
|
||||
@@ -98,6 +103,10 @@ class MeteorRainPreset extends BasePreset {
|
||||
minSpeed: { type: 'range', min: 2, max: 8, step: 1, default: 4 },
|
||||
maxSpeed: { type: 'range', min: 6, max: 15, step: 1, default: 10 },
|
||||
trailDecay: { type: 'range', min: 0.6, max: 0.9, step: 0.02, default: 0.76 },
|
||||
color1: { type: 'color', default: '0a0126' },
|
||||
color2: { type: 'color', default: '123d8b' },
|
||||
color3: { type: 'color', default: '21c7d9' },
|
||||
color4: { type: 'color', default: 'f7ffff' },
|
||||
},
|
||||
width: this.width,
|
||||
height: this.height,
|
||||
|
||||
@@ -7,19 +7,17 @@ class NebulaDriftPreset extends BasePreset {
|
||||
constructor(width = 16, height = 16) {
|
||||
super(width, height);
|
||||
this.timeSeconds = 0;
|
||||
this.paletteStops = [
|
||||
{ stop: 0.0, color: hexToRgb('100406') },
|
||||
{ stop: 0.25, color: hexToRgb('2e0f1f') },
|
||||
{ stop: 0.5, color: hexToRgb('6a1731') },
|
||||
{ stop: 0.7, color: hexToRgb('b63b32') },
|
||||
{ stop: 0.85, color: hexToRgb('f48b2a') },
|
||||
{ stop: 1.0, color: hexToRgb('ffe9b0') },
|
||||
];
|
||||
this.defaultParameters = {
|
||||
primarySpeed: 0.15,
|
||||
secondarySpeed: 0.32,
|
||||
waveScale: 0.75,
|
||||
brightness: 1.0,
|
||||
color1: '100406',
|
||||
color2: '2e0f1f',
|
||||
color3: '6a1731',
|
||||
color4: 'b63b32',
|
||||
color5: 'f48b2a',
|
||||
color6: 'ffe9b0',
|
||||
};
|
||||
}
|
||||
|
||||
@@ -33,6 +31,15 @@ class NebulaDriftPreset extends BasePreset {
|
||||
const frame = createFrame(this.width, this.height);
|
||||
const brightness = this.getParameter('brightness') || 1.0;
|
||||
|
||||
const paletteStops = [
|
||||
{ stop: 0.0, color: hexToRgb(this.getParameter('color1') || '100406') },
|
||||
{ stop: 0.25, color: hexToRgb(this.getParameter('color2') || '2e0f1f') },
|
||||
{ stop: 0.5, color: hexToRgb(this.getParameter('color3') || '6a1731') },
|
||||
{ stop: 0.7, color: hexToRgb(this.getParameter('color4') || 'b63b32') },
|
||||
{ stop: 0.85, color: hexToRgb(this.getParameter('color5') || 'f48b2a') },
|
||||
{ stop: 1.0, color: hexToRgb(this.getParameter('color6') || 'ffe9b0') },
|
||||
];
|
||||
|
||||
for (let row = 0; row < this.height; ++row) {
|
||||
const v = row / Math.max(1, this.height - 1);
|
||||
for (let col = 0; col < this.width; ++col) {
|
||||
@@ -45,7 +52,7 @@ class NebulaDriftPreset extends BasePreset {
|
||||
const envelope = Math.sin((u * v) * Math.PI * 2 + this.timeSeconds * 0.1) * 0.25 + 0.75;
|
||||
const value = clamp((combined * 0.5 + 0.5) * envelope, 0, 1);
|
||||
|
||||
let color = samplePalette(this.paletteStops, value);
|
||||
let color = samplePalette(paletteStops, value);
|
||||
|
||||
// Apply brightness
|
||||
if (brightness < 1.0) {
|
||||
@@ -71,6 +78,12 @@ class NebulaDriftPreset extends BasePreset {
|
||||
secondarySpeed: { type: 'range', min: 0.2, max: 0.5, step: 0.02, default: 0.32 },
|
||||
waveScale: { type: 'range', min: 0.5, max: 1.0, step: 0.05, default: 0.75 },
|
||||
brightness: { type: 'range', min: 0.3, max: 1.0, step: 0.1, default: 1.0 },
|
||||
color1: { type: 'color', default: '100406' },
|
||||
color2: { type: 'color', default: '2e0f1f' },
|
||||
color3: { type: 'color', default: '6a1731' },
|
||||
color4: { type: 'color', default: 'b63b32' },
|
||||
color5: { type: 'color', default: 'f48b2a' },
|
||||
color6: { type: 'color', default: 'ffe9b0' },
|
||||
},
|
||||
width: this.width,
|
||||
height: this.height,
|
||||
|
||||
@@ -7,19 +7,17 @@ class OceanGlimmerPreset extends BasePreset {
|
||||
constructor(width = 16, height = 16) {
|
||||
super(width, height);
|
||||
this.timeSeconds = 0;
|
||||
this.paletteStops = [
|
||||
{ stop: 0.0, color: hexToRgb('031521') },
|
||||
{ stop: 0.35, color: hexToRgb('024f6d') },
|
||||
{ stop: 0.65, color: hexToRgb('13a4a1') },
|
||||
{ stop: 0.85, color: hexToRgb('67dcd0') },
|
||||
{ stop: 1.0, color: hexToRgb('fcdba4') },
|
||||
];
|
||||
this.defaultParameters = {
|
||||
shimmer: 0.08,
|
||||
waveSpeed1: 1.2,
|
||||
waveSpeed2: 0.9,
|
||||
waveSpeed3: 0.5,
|
||||
brightness: 1.0,
|
||||
color1: '031521',
|
||||
color2: '024f6d',
|
||||
color3: '13a4a1',
|
||||
color4: '67dcd0',
|
||||
color5: 'fcdba4',
|
||||
};
|
||||
}
|
||||
|
||||
@@ -30,6 +28,14 @@ class OceanGlimmerPreset extends BasePreset {
|
||||
const shimmer = this.getParameter('shimmer') || 0.08;
|
||||
const brightness = this.getParameter('brightness') || 1.0;
|
||||
|
||||
const paletteStops = [
|
||||
{ stop: 0.0, color: hexToRgb(this.getParameter('color1') || '031521') },
|
||||
{ stop: 0.35, color: hexToRgb(this.getParameter('color2') || '024f6d') },
|
||||
{ stop: 0.65, color: hexToRgb(this.getParameter('color3') || '13a4a1') },
|
||||
{ stop: 0.85, color: hexToRgb(this.getParameter('color4') || '67dcd0') },
|
||||
{ stop: 1.0, color: hexToRgb(this.getParameter('color5') || 'fcdba4') },
|
||||
];
|
||||
|
||||
for (let row = 0; row < this.height; ++row) {
|
||||
const v = row / Math.max(1, this.height - 1);
|
||||
for (let col = 0; col < this.width; ++col) {
|
||||
@@ -42,7 +48,7 @@ class OceanGlimmerPreset extends BasePreset {
|
||||
const noise = (Math.random() - 0.5) * shimmer;
|
||||
const value = clamp(base + noise, 0, 1);
|
||||
|
||||
let color = samplePalette(this.paletteStops, value);
|
||||
let color = samplePalette(paletteStops, value);
|
||||
|
||||
// Apply brightness
|
||||
if (brightness < 1.0) {
|
||||
@@ -69,6 +75,11 @@ class OceanGlimmerPreset extends BasePreset {
|
||||
waveSpeed2: { type: 'range', min: 0.5, max: 2.0, step: 0.1, default: 0.9 },
|
||||
waveSpeed3: { type: 'range', min: 0.2, max: 1.0, step: 0.1, default: 0.5 },
|
||||
brightness: { type: 'range', min: 0.3, max: 1.0, step: 0.1, default: 1.0 },
|
||||
color1: { type: 'color', default: '031521' },
|
||||
color2: { type: 'color', default: '024f6d' },
|
||||
color3: { type: 'color', default: '13a4a1' },
|
||||
color4: { type: 'color', default: '67dcd0' },
|
||||
color5: { type: 'color', default: 'fcdba4' },
|
||||
},
|
||||
width: this.width,
|
||||
height: this.height,
|
||||
|
||||
@@ -4,7 +4,7 @@ const RainbowPreset = require('./rainbow-preset');
|
||||
const AuroraCurtainsPreset = require('./aurora-curtains-preset');
|
||||
const BouncingBallPreset = require('./bouncing-ball-preset');
|
||||
const CircuitPulsePreset = require('./circuit-pulse-preset');
|
||||
const FadeGreenBluePreset = require('./fade-green-blue-preset');
|
||||
const FadePreset = require('./fade-preset');
|
||||
const LavaLampPreset = require('./lava-lamp-preset');
|
||||
const MeteorRainPreset = require('./meteor-rain-preset');
|
||||
const NebulaDriftPreset = require('./nebula-drift-preset');
|
||||
@@ -24,7 +24,7 @@ class PresetRegistry {
|
||||
this.register('aurora-curtains', AuroraCurtainsPreset);
|
||||
this.register('bouncing-ball', BouncingBallPreset);
|
||||
this.register('circuit-pulse', CircuitPulsePreset);
|
||||
this.register('fade-green-blue', FadeGreenBluePreset);
|
||||
this.register('fade', FadePreset);
|
||||
this.register('lava-lamp', LavaLampPreset);
|
||||
this.register('meteor-rain', MeteorRainPreset);
|
||||
this.register('nebula-drift', NebulaDriftPreset);
|
||||
|
||||
@@ -8,19 +8,17 @@ class SpiralBloomPreset extends BasePreset {
|
||||
super(width, height);
|
||||
this.rotation = 0;
|
||||
this.hueShift = 0;
|
||||
this.paletteStops = [
|
||||
{ stop: 0.0, color: hexToRgb('051923') },
|
||||
{ stop: 0.2, color: hexToRgb('0c4057') },
|
||||
{ stop: 0.45, color: hexToRgb('1d7a70') },
|
||||
{ stop: 0.7, color: hexToRgb('39b15f') },
|
||||
{ stop: 0.88, color: hexToRgb('9dd54c') },
|
||||
{ stop: 1.0, color: hexToRgb('f7f5bc') },
|
||||
];
|
||||
this.defaultParameters = {
|
||||
rotationSpeed: 0.7,
|
||||
hueSpeed: 0.2,
|
||||
spiralArms: 5,
|
||||
brightness: 1.0,
|
||||
color1: '051923',
|
||||
color2: '0c4057',
|
||||
color3: '1d7a70',
|
||||
color4: '39b15f',
|
||||
color5: '9dd54c',
|
||||
color6: 'f7f5bc',
|
||||
};
|
||||
}
|
||||
|
||||
@@ -32,6 +30,15 @@ class SpiralBloomPreset extends BasePreset {
|
||||
const brightness = this.getParameter('brightness') || 1.0;
|
||||
const spiralArms = this.getParameter('spiralArms') || 5;
|
||||
|
||||
const paletteStops = [
|
||||
{ stop: 0.0, color: hexToRgb(this.getParameter('color1') || '051923') },
|
||||
{ stop: 0.2, color: hexToRgb(this.getParameter('color2') || '0c4057') },
|
||||
{ stop: 0.45, color: hexToRgb(this.getParameter('color3') || '1d7a70') },
|
||||
{ stop: 0.7, color: hexToRgb(this.getParameter('color4') || '39b15f') },
|
||||
{ stop: 0.88, color: hexToRgb(this.getParameter('color5') || '9dd54c') },
|
||||
{ stop: 1.0, color: hexToRgb(this.getParameter('color6') || 'f7f5bc') },
|
||||
];
|
||||
|
||||
const cx = (this.width - 1) / 2;
|
||||
const cy = (this.height - 1) / 2;
|
||||
const radiusNorm = Math.hypot(cx, cy) || 1;
|
||||
@@ -45,7 +52,7 @@ class SpiralBloomPreset extends BasePreset {
|
||||
const arm = 0.5 + 0.5 * Math.sin(spiralArms * (angle + this.rotation) + this.hueShift * Math.PI * 2);
|
||||
const value = Math.min(1, radius * 0.8 + arm * 0.4);
|
||||
|
||||
let color = samplePalette(this.paletteStops, value);
|
||||
let color = samplePalette(paletteStops, value);
|
||||
|
||||
// Apply brightness
|
||||
if (brightness < 1.0) {
|
||||
@@ -71,6 +78,12 @@ class SpiralBloomPreset extends BasePreset {
|
||||
hueSpeed: { type: 'range', min: 0.1, max: 0.5, step: 0.05, default: 0.2 },
|
||||
spiralArms: { type: 'range', min: 3, max: 8, step: 1, default: 5 },
|
||||
brightness: { type: 'range', min: 0.3, max: 1.0, step: 0.1, default: 1.0 },
|
||||
color1: { type: 'color', default: '051923' },
|
||||
color2: { type: 'color', default: '0c4057' },
|
||||
color3: { type: 'color', default: '1d7a70' },
|
||||
color4: { type: 'color', default: '39b15f' },
|
||||
color5: { type: 'color', default: '9dd54c' },
|
||||
color6: { type: 'color', default: 'f7f5bc' },
|
||||
},
|
||||
width: this.width,
|
||||
height: this.height,
|
||||
|
||||
@@ -7,20 +7,19 @@ class VoxelFirefliesPreset extends BasePreset {
|
||||
constructor(width = 16, height = 16) {
|
||||
super(width, height);
|
||||
this.fireflies = [];
|
||||
this.paletteStops = [
|
||||
{ stop: 0.0, color: hexToRgb('02030a') },
|
||||
{ stop: 0.2, color: hexToRgb('031c2d') },
|
||||
{ stop: 0.4, color: hexToRgb('053d4a') },
|
||||
{ stop: 0.6, color: hexToRgb('107b68') },
|
||||
{ stop: 0.8, color: hexToRgb('14c491') },
|
||||
{ stop: 1.0, color: hexToRgb('f2ffd2') },
|
||||
];
|
||||
this.defaultParameters = {
|
||||
fireflyCount: 18,
|
||||
hoverSpeed: 0.6,
|
||||
glowSpeed: 1.8,
|
||||
trailDecay: 0.8,
|
||||
brightness: 1.0,
|
||||
color1: '02030a',
|
||||
color2: '031c2d',
|
||||
color3: '053d4a',
|
||||
color4: '107b68',
|
||||
color5: '14c491',
|
||||
color6: 'f2ffd2',
|
||||
accentColor: 'ffd966',
|
||||
};
|
||||
}
|
||||
|
||||
@@ -69,10 +68,11 @@ class VoxelFirefliesPreset extends BasePreset {
|
||||
firefly.glowPhase += deltaSeconds * (this.getParameter('glowSpeed') || 1.8) * (0.7 + Math.random() * 0.6);
|
||||
}
|
||||
|
||||
drawFirefly(firefly) {
|
||||
drawFirefly(firefly, paletteStops) {
|
||||
const baseGlow = (Math.sin(firefly.glowPhase) + 1) * 0.5;
|
||||
const col = Math.round(firefly.x);
|
||||
const row = Math.round(firefly.y);
|
||||
const accentColor = this.getParameter('accentColor') || 'ffd966';
|
||||
|
||||
for (let dy = -1; dy <= 1; ++dy) {
|
||||
for (let dx = -1; dx <= 1; ++dx) {
|
||||
@@ -89,9 +89,9 @@ class VoxelFirefliesPreset extends BasePreset {
|
||||
continue;
|
||||
}
|
||||
|
||||
this.frame[toIndex(sampleX, sampleY, this.width)] = samplePalette(this.paletteStops, intensity);
|
||||
this.frame[toIndex(sampleX, sampleY, this.width)] = samplePalette(paletteStops, intensity);
|
||||
if (distance === 0) {
|
||||
addHexColor(this.frame, toIndex(sampleX, sampleY, this.width), 'ffd966', intensity * 1.6);
|
||||
addHexColor(this.frame, toIndex(sampleX, sampleY, this.width), accentColor, intensity * 1.6);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -103,6 +103,15 @@ class VoxelFirefliesPreset extends BasePreset {
|
||||
const fireflyCount = this.getParameter('fireflyCount') || 18;
|
||||
const brightness = this.getParameter('brightness') || 1.0;
|
||||
|
||||
const paletteStops = [
|
||||
{ stop: 0.0, color: hexToRgb(this.getParameter('color1') || '02030a') },
|
||||
{ stop: 0.2, color: hexToRgb(this.getParameter('color2') || '031c2d') },
|
||||
{ stop: 0.4, color: hexToRgb(this.getParameter('color3') || '053d4a') },
|
||||
{ stop: 0.6, color: hexToRgb(this.getParameter('color4') || '107b68') },
|
||||
{ stop: 0.8, color: hexToRgb(this.getParameter('color5') || '14c491') },
|
||||
{ stop: 1.0, color: hexToRgb(this.getParameter('color6') || 'f2ffd2') },
|
||||
];
|
||||
|
||||
fadeFrame(this.frame, trailDecay);
|
||||
|
||||
// Update firefly count if it changed
|
||||
@@ -115,7 +124,7 @@ class VoxelFirefliesPreset extends BasePreset {
|
||||
|
||||
this.fireflies.forEach((firefly) => {
|
||||
this.updateFirefly(firefly, 0.016); // Assume 60 FPS
|
||||
this.drawFirefly(firefly);
|
||||
this.drawFirefly(firefly, paletteStops);
|
||||
});
|
||||
|
||||
return this.frame;
|
||||
@@ -131,6 +140,13 @@ class VoxelFirefliesPreset extends BasePreset {
|
||||
glowSpeed: { type: 'range', min: 1.0, max: 3.0, step: 0.2, default: 1.8 },
|
||||
trailDecay: { type: 'range', min: 0.7, max: 0.95, step: 0.05, default: 0.8 },
|
||||
brightness: { type: 'range', min: 0.5, max: 1.5, step: 0.1, default: 1.0 },
|
||||
color1: { type: 'color', default: '02030a' },
|
||||
color2: { type: 'color', default: '031c2d' },
|
||||
color3: { type: 'color', default: '053d4a' },
|
||||
color4: { type: 'color', default: '107b68' },
|
||||
color5: { type: 'color', default: '14c491' },
|
||||
color6: { type: 'color', default: 'f2ffd2' },
|
||||
accentColor: { type: 'color', default: 'ffd966' },
|
||||
},
|
||||
width: this.width,
|
||||
height: this.height,
|
||||
|
||||
@@ -7,14 +7,6 @@ class WormholeTunnelPreset extends BasePreset {
|
||||
constructor(width = 16, height = 16) {
|
||||
super(width, height);
|
||||
this.timeSeconds = 0;
|
||||
this.paletteStops = [
|
||||
{ stop: 0.0, color: hexToRgb('010005') },
|
||||
{ stop: 0.2, color: hexToRgb('07204f') },
|
||||
{ stop: 0.45, color: hexToRgb('124aa0') },
|
||||
{ stop: 0.7, color: hexToRgb('36a5ff') },
|
||||
{ stop: 0.87, color: hexToRgb('99e6ff') },
|
||||
{ stop: 1.0, color: hexToRgb('f1fbff') },
|
||||
];
|
||||
this.defaultParameters = {
|
||||
ringDensity: 8,
|
||||
ringSpeed: 1.4,
|
||||
@@ -23,6 +15,12 @@ class WormholeTunnelPreset extends BasePreset {
|
||||
twistSpeed: 0.9,
|
||||
coreExponent: 1.6,
|
||||
brightness: 1.0,
|
||||
color1: '010005',
|
||||
color2: '07204f',
|
||||
color3: '124aa0',
|
||||
color4: '36a5ff',
|
||||
color5: '99e6ff',
|
||||
color6: 'f1fbff',
|
||||
};
|
||||
}
|
||||
|
||||
@@ -32,6 +30,15 @@ class WormholeTunnelPreset extends BasePreset {
|
||||
const frame = createFrame(this.width, this.height);
|
||||
const brightness = this.getParameter('brightness') || 1.0;
|
||||
|
||||
const paletteStops = [
|
||||
{ stop: 0.0, color: hexToRgb(this.getParameter('color1') || '010005') },
|
||||
{ stop: 0.2, color: hexToRgb(this.getParameter('color2') || '07204f') },
|
||||
{ stop: 0.45, color: hexToRgb(this.getParameter('color3') || '124aa0') },
|
||||
{ stop: 0.7, color: hexToRgb(this.getParameter('color4') || '36a5ff') },
|
||||
{ stop: 0.87, color: hexToRgb(this.getParameter('color5') || '99e6ff') },
|
||||
{ stop: 1.0, color: hexToRgb(this.getParameter('color6') || 'f1fbff') },
|
||||
];
|
||||
|
||||
const cx = (this.width - 1) / 2;
|
||||
const cy = (this.height - 1) / 2;
|
||||
const radiusNorm = Math.hypot(cx, cy) || 1;
|
||||
@@ -51,7 +58,7 @@ class WormholeTunnelPreset extends BasePreset {
|
||||
|
||||
const value = clamp(ring * 0.6 + depth * 0.3 + twist * 0.1, 0, 1);
|
||||
|
||||
let color = samplePalette(this.paletteStops, value);
|
||||
let color = samplePalette(paletteStops, value);
|
||||
|
||||
// Apply brightness
|
||||
if (brightness < 1.0) {
|
||||
@@ -80,6 +87,12 @@ class WormholeTunnelPreset extends BasePreset {
|
||||
twistSpeed: { type: 'range', min: 0.3, max: 1.5, step: 0.1, default: 0.9 },
|
||||
coreExponent: { type: 'range', min: 1.0, max: 2.5, step: 0.1, default: 1.6 },
|
||||
brightness: { type: 'range', min: 0.3, max: 1.0, step: 0.1, default: 1.0 },
|
||||
color1: { type: 'color', default: '010005' },
|
||||
color2: { type: 'color', default: '07204f' },
|
||||
color3: { type: 'color', default: '124aa0' },
|
||||
color4: { type: 'color', default: '36a5ff' },
|
||||
color5: { type: 'color', default: '99e6ff' },
|
||||
color6: { type: 'color', default: 'f1fbff' },
|
||||
},
|
||||
width: this.width,
|
||||
height: this.height,
|
||||
|
||||
Reference in New Issue
Block a user