
p5.js๋ฅผ ํฌํจํ ๋๋ถ๋ถ์ ๊ทธ๋ํฝ ํ๋ ์์ํฌ์์ ์ฌ์ฉํ๋ ์์ ๋ณด๊ฐ(Color Interpolation), ํนํ Lerp (Linear Interpolation)์ ๋ํ ์ค๋ช ์ ๋๋ค.
Lerp๋ ๊ฐ์ฅ ์ผ๋ฐ์ ์ธ ํํ์ ๋ณด๊ฐ์ผ๋ก, ๋ ๊ฐ A์ B ์ฌ์ด๋ฅผ ์ง์ ์ ์ผ๋ก ์ฐ๊ฒฐํ๋ ์ค๊ฐ๊ฐ V๋ฅผ ์ฐพ๋ ์ํ์ ๋ฐฉ๋ฒ์ ๋๋ค.
Lerp ํจ์๋ ๋ค์๊ณผ ๊ฐ์ด ์ ์๋ฉ๋๋ค:
0.0์์ 1.0 ์ฌ์ด์ ๊ฐ๊ฐ์ ๋ฐ๋ฅธ ๊ฒฐ๊ณผ:
| t ๊ฐ | ๊ฒฐ๊ณผ V | ์๋ฏธ |
|---|---|---|
| 0.0 | A | ์์ ๊ฐ๊ณผ ๋์ผ |
| 0.25 | A + (B-A)ร0.25 | ์์์ ์์ 25% ์ง์ |
| 0.5 | (A+B)/2 | ์ ํํ ์ค๊ฐ |
| 0.75 | A + (B-A)ร0.75 | ๋์ ์์ 25% ์ |
| 1.0 | B | ๋ ๊ฐ๊ณผ ๋์ผ |
A์ B์ ๋น์จ์ด t์ ๋ฐ๋ผ ๋ฌ๋ผ์ง๋ ์๋ฆฌ๋ ์ด๋ ๊ฒ ์ดํดํ๋ฉด ๋ฉ๋๋ค.
t=0์ผ ๋: 100% A, 0% Bt=0.3์ผ ๋: 70% A, 30% Bt=0.5์ผ ๋: 50% A, 50% Bt=1์ผ ๋: 0% A, 100% B์ค์ ์ฝ๋์์ ์ซ์๋ง ๊ฐ์ง๊ณ Lerp๋ฅผ ์ดํดํด๋ด ์๋ค. ์์์ด 10์ด๊ณ ๋์ด 100์ธ ๋ฒ์๋ฅผ ๋ณด๊ฐํ๋ ์์์ ๋๋ค.
// ์ซ์ Lerp ์์
function setup() {
let start = 10;
let end = 100;
// t=0.0 โ 10
console.log(lerp(start, end, 0.0)); // 10
// t=0.5 โ 55 (์ค๊ฐ๊ฐ)
console.log(lerp(start, end, 0.5)); // 55
// t=1.0 โ 100
console.log(lerp(start, end, 1.0)); // 100
}
p5.js์์๋ lerpColor() ํจ์๋ฅผ ์ฌ์ฉํ์ฌ ์์์ ๋ณด๊ฐํฉ๋๋ค. ์ด ํจ์๋ ๋ด๋ถ์ ์ผ๋ก ์์์ ๊ฐ ์ฑ๋(R, G, B, A ๋ฑ)์ ๋ํด ๊ฐ๋ณ์ ์ผ๋ก ์ ํ ๋ณด๊ฐ์ ์ํํฉ๋๋ค.
lerpColor() ํจ์ ๊ตฌ๋ฌธlerpColor(c1, c2, amt)
ํ๋ผ๋ฏธํฐ:
c1: ์์ ์์ (p5.Color ๊ฐ์ฒด)c2: ๋ ์์ (p5.Color ๊ฐ์ฒด)amt: ๋ณด๊ฐ ๊ณ์ t (0.0์์ 1.0 ์ฌ์ด์ float ๊ฐ)๋ฐํ๊ฐ:
์์ ๋ณด๊ฐ์ ์ ํ๋ ์์ ๋ชจ๋(RGB, HSB ๋ฑ)์ ๊ฐ ์ฑ๋์ ๋ํด ๋ ๋ฆฝ์ ์ผ๋ก Lerp ๊ณต์์ ์ ์ฉํฉ๋๋ค.
RGB ๋ชจ๋์์ ์์ Cโ = (Rโ, Gโ, Bโ)๊ณผ Cโ = (Rโ, Gโ, Bโ)๋ฅผ t๋งํผ ๋ณด๊ฐํ๋ฉด:
R_lerp = Rโ + (Rโ - Rโ) ร t
G_lerp = Gโ + (Gโ - Gโ) ร t
B_lerp = Bโ + (Bโ - Bโ) ร t
๋นจ๊ฐ(255, 0, 0)๊ณผ ํ๋(0, 0, 255)์ t=0.5๋ก ๋ณด๊ฐํ๋ ๊ณผ์ ์ ๊ณ์ฐํด๋ณด๋ฉด,
์ด๋ ๊ฒ ๊ณ์ฐ๋๋ ๊ฒ์ ๋ณผ ์ ์์ต๋๋ค.
let colorA, colorB;
function setup() {
createCanvas(400, 200);
// ์์ ๊ฐ์ฒด ์์ฑ
colorMode(RGB);
colorA = color(255, 0, 0); // ๋นจ๊ฐ์
colorB = color(0, 0, 255); // ํ๋์
noStroke();
}
function draw() {
// ๋ง์ฐ์ค X ์ขํ๋ฅผ 0.0~1.0 ์ฌ์ด์ t ๊ฐ์ผ๋ก ๋งคํ
let t = map(mouseX, 0, width, 0.0, 1.0, true);
// true๋ ๊ฐ์ 0.0~1.0 ์ฌ์ด๋ก ํด๋จํ(์ ํ)
// ๋ ์์์ t๋งํผ ๋ณด๊ฐ
let interpolatedColor = lerpColor(colorA, colorB, t);
// ๋ณด๊ฐ๋ ์์์ผ๋ก ๋ฐฐ๊ฒฝ ์ฑ์ฐ๊ธฐ
background(interpolatedColor);
// ์ ๋ณด ํ์
fill(255);
textAlign(CENTER, CENTER);
textSize(16);
text("๋ง์ฐ์ค๋ฅผ ์ข์ฐ๋ก ์์ง์ฌ ๋ณด์ธ์", width / 2, height / 2 - 20);
text("t = " + t.toFixed(2), width / 2, height / 2 + 10);
}
let colorA, colorB;
let t = 0;
function setup() {
createCanvas(400, 200);
colorA = color(255, 100, 0); // ์ฃผํฉ์
colorB = color(100, 0, 255); // ๋ณด๋ผ์
noStroke();
}
function draw() {
// sin ํจ์๋ฅผ ์ฌ์ฉํด t๋ฅผ 0~1 ์ฌ์ด์์ ์๋ณต
t = (sin(frameCount * 0.02) + 1) / 2;
let c = lerpColor(colorA, colorB, t);
background(c);
fill(255);
textAlign(CENTER, CENTER);
text("t = " + t.toFixed(2), width / 2, height / 2);
}
Lerp๋ ์ ํ์ ์ด์ง๋ง, ์ธ๊ฐ์ ๋์ ์์์ ์ ํ์ ์ผ๋ก ์ธ์งํ์ง ์์ต๋๋ค. ์ด๋ค ์์ ๋ชจ๋์์ ๋ณด๊ฐํ๋๋์ ๋ฐ๋ผ ์ค๊ฐ์์ด ๋งค์ฐ ๋ค๋ฅด๊ฒ ๋ํ๋ฉ๋๋ค.
RGB ๊ณต๊ฐ์์ Lerp๋ 3์ฐจ์ ํ๋ธ ๋ด๋ถ๋ฅผ ๊ฐ์ฅ ์ง์ ์ผ๋ก ์ด๋ํฉ๋๋ค.
์ฅ์ :
๋จ์ :
function setup() {
createCanvas(600, 200);
colorMode(RGB);
let red = color(255, 0, 0);
let green = color(0, 255, 0);
// RGB ๋ณด๊ฐ - ์น์นํ ์ค๊ฐ์
for (let i = 0; i < width; i++) {
let t = i / width;
let c = lerpColor(red, green, t);
stroke(c);
line(i, 0, i, height);
}
fill(255);
noStroke();
textAlign(CENTER);
text("RGB ๋ณด๊ฐ: ์ค๊ฐ์ ํ์๋น์ด ๋๋ ์", width/2, height/2);
}
HSB ๋๋ HSL ๊ณต๊ฐ์์ ๋ณด๊ฐ์ ์ํํ๋ฉด ์์กฐ(Hue)๋ ์์ํ์ ๋ฐ๋ผ ์ด๋ํ๊ณ , ์ฑ๋(Saturation)์ ๋ฐ๊ธฐ(Brightness)๋ ๋ ๋ฆฝ์ ์ผ๋ก ๋ณํด์.
์ฅ์ :
์ฃผ์์ฌํญ:
function setup() {
createCanvas(600, 200);
colorMode(HSB, 360, 100, 100);
let red = color(0, 100, 100); // Hue 0
let green = color(120, 100, 100); // Hue 120
// HSB ๋ณด๊ฐ - ์ ๋ช
ํ ์ค๊ฐ์
for (let i = 0; i < width; i++) {
let t = i / width;
let c = lerpColor(red, green, t);
stroke(c);
line(i, 0, i, height);
}
fill(255);
noStroke();
textAlign(CENTER);
text("HSB ๋ณด๊ฐ: ์๋๊ฐ ์๋ ์์ ์ ํ", width/2, height/2);
}
function setup() {
createCanvas(600, 200);
colorMode(HSB, 360, 100, 100);
// ์ฌ๋ฌ ์์ ์ ์
let colors = [
color(0, 100, 100), // ๋นจ๊ฐ
color(60, 100, 100), // ๋
ธ๋
color(120, 100, 100), // ์ด๋ก
color(240, 100, 100), // ํ๋
color(300, 100, 100) // ์ํ
];
noStroke();
let segmentWidth = width / (colors.length - 1);
for (let i = 0; i < width; i++) {
// ํ์ฌ ์์น๊ฐ ์ด๋ ๊ตฌ๊ฐ์ ์ํ๋์ง ๊ณ์ฐ
let segment = floor(i / segmentWidth);
let t = (i % segmentWidth) / segmentWidth;
// ๋ง์ง๋ง ๊ตฌ๊ฐ ์ฒ๋ฆฌ
if (segment >= colors.length - 1) {
segment = colors.length - 2;
t = 1;
}
let c = lerpColor(colors[segment], colors[segment + 1], t);
stroke(c);
line(i, 0, i, height);
}
}
function setup() {
createCanvas(400, 400);
colorMode(HSB, 360, 100, 100);
let centerColor = color(200, 80, 100); // ์ค์ฌ: ํ๋์
let edgeColor = color(0, 100, 50); // ๊ฐ์ฅ์๋ฆฌ: ์ด๋์ด ๋นจ๊ฐ
noStroke();
let maxDist = dist(0, 0, width/2, height/2);
for (let y = 0; y < height; y++) {
for (let x = 0; x < width; x++) {
// ์ค์ฌ์ผ๋ก๋ถํฐ์ ๊ฑฐ๋ฆฌ ๊ณ์ฐ
let d = dist(x, y, width/2, height/2);
let t = d / maxDist;
t = constrain(t, 0, 1); // 0~1๋ก ์ ํ
let c = lerpColor(centerColor, edgeColor, t);
stroke(c);
point(x, y);
}
}
}
function setup() {
createCanvas(600, 400);
noStroke();
}
function draw() {
colorMode(HSB, 360, 100, 100);
// ์๊ฐ์ ์๋ฎฌ๋ ์ด์
(0~1, ํ๋ฃจ๋ฅผ ํํ)
let timeOfDay = (frameCount * 0.005) % 1;
let dawn = color(30, 70, 60); // ์๋ฒฝ: ์ฃผํฉ๋น
let day = color(200, 60, 90); // ๋ฎ: ๋ฐ์ ํ๋์
let dusk = color(15, 80, 50); // ์ ๋
: ๋ถ์๋น
let night = color(240, 70, 20); // ๋ฐค: ์ด๋์ด ํ๋
let skyColor;
if (timeOfDay < 0.25) {
// ์๋ฒฝ โ ๋ฎ
let t = timeOfDay * 4;
skyColor = lerpColor(dawn, day, t);
} else if (timeOfDay < 0.5) {
// ๋ฎ โ ์ ๋
let t = (timeOfDay - 0.25) * 4;
skyColor = lerpColor(day, dusk, t);
} else if (timeOfDay < 0.75) {
// ์ ๋
โ ๋ฐค
let t = (timeOfDay - 0.5) * 4;
skyColor = lerpColor(dusk, night, t);
} else {
// ๋ฐค โ ์๋ฒฝ
let t = (timeOfDay - 0.75) * 4;
skyColor = lerpColor(night, dawn, t);
}
background(skyColor);
// ์ ๋ณด ํ์
colorMode(RGB);
fill(255);
textSize(50);
textAlign(CENTER);
text("์๊ฐ: " + (timeOfDay * 24).toFixed(1) + "์", width/2, height/2);
}
let baseColor;
let numColors = 5;
function setup() {
createCanvas(600, 400);
colorMode(HSB, 360, 100, 100);
baseColor = color(random(360), 80, 90);
noStroke();
}
function draw() {
background(220);
// ๋ณด์ ๊ณ์ฐ
let hue = hue(baseColor);
let complementaryColor = color((hue + 180) % 360, 80, 90);
// ์์ ํ๋ ํธ ๊ทธ๋ฆฌ๊ธฐ
let boxWidth = width / numColors;
for (let i = 0; i < numColors; i++) {
let t = i / (numColors - 1);
let c = lerpColor(baseColor, complementaryColor, t);
fill(c);
rect(i * boxWidth, 0, boxWidth, height * 0.7);
// ์์ ์ ๋ณด ํ์
fill(0);
textAlign(CENTER);
textSize(12);
text("t=" + t.toFixed(2), i * boxWidth + boxWidth/2, height * 0.75);
text("H=" + hue(c).toFixed(0), i * boxWidth + boxWidth/2, height * 0.8);
}
// ์๋ด ํ
์คํธ
fill(0);
textSize(16);
textAlign(CENTER);
text("ํด๋ฆญํ์ฌ ์๋ก์ด ์์ ํ๋ ํธ ์์ฑ", width/2, height * 0.95);
}
function mousePressed() {
baseColor = color(random(360), 80, 90);
}
์ ํ ๋ณด๊ฐ ๋์ easing ํจ์๋ฅผ ์ ์ฉํ๋ฉด ๋์ฑ ์์ฐ์ค๋ฌ์ด ์์ ๋ณํ๋ฅผ ๋ง๋ค ์ ์์ต๋๋ค.
function setup() {
createCanvas(600, 200);
colorMode(HSB, 360, 100, 100);
noStroke();
}
function draw() {
let c1 = color(0, 100, 100);
let c2 = color(240, 100, 100);
for (let i = 0; i < width; i++) {
let t = i / width;
// easeInOut ์ ์ฉ
let easedT = t < 0.5
? 2 * t * t
: 1 - pow(-2 * t + 2, 2) / 2;
let c = lerpColor(c1, c2, easedT);
stroke(c);
line(i, 0, i, height);
}
}
function setup() {
createCanvas(400, 400);
colorMode(HSB, 360, 100, 100);
let h1 = 0, s1 = 100, b1 = 100;
let h2 = 240, s2 = 50, b2 = 80;
for (let y = 0; y < height; y++) {
for (let x = 0; x < width; x++) {
let tX = x / width;
let tY = y / height;
// X์ถ: Hue ๋ณํ, Y์ถ: Saturation ๋ณํ
let h = lerp(h1, h2, tX);
let s = lerp(s1, s2, tY);
let b = b1; // ๋ฐ๊ธฐ๋ ๊ณ ์
stroke(h, s, b);
point(x, y);
}
}
}
๋ฐ๋ณต๋ฌธ์์ ๋งค๋ฒ lerpColor()๋ฅผ ํธ์ถํ๋ ๋์ , ๊ฐ๋ฅํ๋ฉด ๋ฏธ๋ฆฌ ๊ณ์ฐ๋ ์์ ๋ฐฐ์ด์ ์ฌ์ฉํ์ธ์.
// ๋นํจ์จ์
function draw() {
for (let i = 0; i < 1000; i++) {
let c = lerpColor(colorA, colorB, random());
// ...
}
}
// ํจ์จ์
let colorPalette = [];
function setup() {
for (let i = 0; i < 100; i++) {
colorPalette[i] = lerpColor(colorA, colorB, i / 100);
}
}
function draw() {
for (let i = 0; i < 1000; i++) {
let c = colorPalette[floor(random(100))];
// ...
}
}
createGraphics() ์ฌ์ฉ๋ณต์กํ ๊ทธ๋ผ๋์ธํธ๋ ํ ๋ฒ๋ง ๊ทธ๋ฆฐ ํ ์ด๋ฏธ์ง๋ก ์ฌ์ฌ์ฉํ๋ ๊ฒ์ด ์ข์ต๋๋ค.
let gradient;
function setup() {
createCanvas(400, 400);
// ๊ทธ๋ผ๋์ธํธ๋ฅผ ํ ๋ฒ๋ง ์์ฑ
gradient = createGraphics(width, height);
gradient.colorMode(HSB, 360, 100, 100);
for (let i = 0; i < width; i++) {
let t = i / width;
let c = lerpColor(color(0, 100, 100), color(240, 100, 100), t);
gradient.stroke(c);
gradient.line(i, 0, i, height);
}
}
function draw() {
// ๋ฏธ๋ฆฌ ๋ง๋ ๊ทธ๋ผ๋์ธํธ ์ฌ์ฉ
image(gradient, 0, 0);
// ๋ค๋ฅธ ๊ทธ๋ฆฌ๊ธฐ ์์
...
}
RGB ๋ณด๊ฐ์ ์ฌ์ฉํ๋ ๊ฒฝ์ฐ:
HSB/HSL ๋ณด๊ฐ์ ์ฌ์ฉํ๋ ๊ฒฝ์ฐ:
- Lerp๋ ์ ํ ๋ณด๊ฐ:
V = A + (B - A) ร tlerpColor()๋ ๊ฐ ์ฑ๋์ ๋ ๋ฆฝ์ ์ผ๋ก ๋ณด๊ฐ: RGB์ ๊ฒฝ์ฐ R, G, B ๊ฐ๊ฐ Lerp ์ ์ฉ- ์์ ๋ชจ๋๊ฐ ๊ฒฐ๊ณผ์ ํฐ ์ํฅ: RGB๋ ์ง์ ๊ฒฝ๋ก, HSB๋ ์์ํ ๊ฒฝ๋ก
- ์์ฐ์ค๋ฌ์ด ์์ ์ ํ์๋ HSB ์ถ์ฒ: ์ค๊ฐ์์ ์ฑ๋์ ์๋๊ฐ ์ ์ง
- ์ฑ๋ฅ ๊ณ ๋ ค: ๋ฐ๋ณต ๊ณ์ฐ๋ณด๋ค๋ ๋ฏธ๋ฆฌ ๊ณ์ฐ๋ ํ๋ ํธ ํ์ฉ