
ํํ์ ๋ฐ์ดํฐํ(Form as Data)๋ ๋์์ธ ์์๋ฅผ ํฝ์ ์ด๋ ์ง์ ์ ์ธ ์ ์ขํ๋ก ์ ์ํ๋ ๋์ , ์ํ ํจ์, ์๊ณ ๋ฆฌ์ฆ(์ ์ฐจ), ๋๋ ์ธ๋ถ ๋ฐ์ดํฐ(๋ ธ์ด์ฆ, ์ผ์ ๊ฐ)๋ฅผ ์ฌ์ฉํ์ฌ ์ถ์์ ์ผ๋ก ์ ์ํ๊ณ ์ ์ดํ๋ ๋ฐฉ์์ ๋๋ค.
์ด ์์ ๋ ๋ค์๊ณผ ๊ฐ์ ๋ฐฉ์์ผ๋ก "ํํ๋ฅผ ๋ฐ์ดํฐํ"ํฉ๋๋ค.
์ํ์ ์ ์: ๋ํ์ ๋ชจ๋ ์ ์ ๊ทน์ขํ๊ณ (Polar Coordinates, ๋ฐ์ง๋ฆ r๊ณผ ๊ฐ๋ angle)๋ผ๋ ๋ฐ์ดํฐ๋ก ์ ์ํฉ๋๋ค.
์ ์ฐจ์ ์ ์ด: ํผ๋ฆฐ ๋ ธ์ด์ฆ(Perlin Noise)๋ผ๋ ์ธ๋ถ ๋ฐ์ดํฐ๋ฅผ ์ฌ์ฉํ์ฌ ์ด ๋ฐ์ง๋ฆ r ๊ฐ์ ์ ์ฐจ์ ์ผ๋ก ๋ณํ์ํต๋๋ค.
์๊ฐ์ฑ ๊ฒฐํฉ: draw() ๋ฃจํ๋ฅผ ํตํด ๋ ธ์ด์ฆ ํ๋๋ฅผ ์ด๋์์ผ, ํํ๊ฐ ๋ฐ์ดํฐ์ ๋ณํ์ ๋ฐ๋ผ ์ด์์๋ ๊ฒ์ฒ๋ผ ์์ง์ด๋๋ก ๊ตฌํํฉ๋๋ค.

// ====== ์ ์ญ ๋ณ์ ์ค์ ======
let W = 700;
let H = 700;
let radius = 200; // ๊ธฐ๋ณธ ๋ฐ์ง๋ฆ (ํํ์ ํฌ๊ธฐ ๋ฐ์ดํฐ)
let numPoints = 100; // ํด๋ฆฌ๊ณค์ ๊ตฌ์ฑํ ์ ์ ๊ฐ์ (๋ฐ์ดํฐ ํด์๋)
let noiseScale = 0.01; // ๋
ธ์ด์ฆ์ ์ค์ผ์ผ (ํํ์ ๊ฑฐ์น ๊ธฐ ์ ์ด ๋ฐ์ดํฐ)
let timeOffset = 0; // ์๊ฐ ํ๋ฆ์ ๋ฐ๋ฅธ ๋
ธ์ด์ฆ์ Z์ถ ์คํ์
function setup() {
// ์บ๋ฒ์ค ์์ฑ ๋ฐ ๊ธฐ๋ณธ ์ค์
createCanvas(W, H);
background(10);
// ์ธ๊ณฝ์ ๊ณผ ์ฑ์ฐ๊ธฐ ์์ ์ค์
stroke(255, 100, 150); // ํํฌ๋น ์ธ๊ณฝ์
strokeWeight(2);
fill(255, 100, 150, 50); // ๋ฐํฌ๋ช
ํ๊ฒ ์ฑ์ฐ๊ธฐ
}
function draw() {
// 1. ๋ฐฐ๊ฒฝ์ ๋ฐํฌ๋ช
ํ๊ฒ ๋ฎ์ด ์์ ํจ๊ณผ๋ฅผ ๋ง๋ญ๋๋ค.
background(10, 20);
// 2. ์บ๋ฒ์ค ์ค์์ผ๋ก ์ขํ๊ณ๋ฅผ ์ด๋ํฉ๋๋ค.
translate(width / 2, height / 2);
// 3. ์ ์ฐจ์ ํํ ์์ฑ ํจ์ ํธ์ถ
drawProceduralShape();
// 4. ์๊ฐ ๊ฒฝ๊ณผ์ ๋ฐ๋ผ ๋
ธ์ด์ฆ ํ๋(Z์ถ)๋ฅผ ์ด๋์์ผ ํํ๋ฅผ ์ฐ์์ ์ผ๋ก ๋ณํ์ํต๋๋ค.
timeOffset += 0.005;
}
/**
* ์ํ์ ๋ฐ์ดํฐ(๊ทน์ขํ)์ ์ธ๋ถ ๋ฐ์ดํฐ(๋
ธ์ด์ฆ)๋ฅผ ์ด์ฉํด ํํ๋ฅผ ๊ทธ๋ฆฝ๋๋ค.
*/
function drawProceduralShape() {
beginShape();
// ํด๋ฆฌ๊ณค์ ๋ชจ๋ ์ ์ ์ํํฉ๋๋ค.
for (let i = 0; i < numPoints; i++) {
// 1. ๊ฐ๋ ๋ฐ์ดํฐ ์์ฑ: 0๋ถํฐ 360๋(TWO_PI)๊น์ง ๊ท ๋ฑ ๋ถํ
let angle = map(i, 0, numPoints, 0, TWO_PI);
// 2. ๋
ธ์ด์ฆ ์
๋ ฅ ์ขํ ๋ฐ์ดํฐ ์์ฑ (๊ทน์ขํ ๊ธฐ๋ฐ)
// ๋
ธ์ด์ฆ ๊ณต๊ฐ์ ์ํ์ผ๋ก ํ์ํ๋ฉด์, timeOffset(Z์ถ)์ ๋ํด ์์ง์์ ๋ง๋ญ๋๋ค.
let xoff = cos(angle) * noiseScale + timeOffset;
let yoff = sin(angle) * noiseScale + timeOffset;
// 3. ๋
ธ์ด์ฆ ๊ฐ ๋ฐ์ดํฐ ํ๋: ๋
ธ์ด์ฆ ๊ฐ(0~1)์ด ๊ณง ๋ฐ์ง๋ฆ ๋ณํ์ ๋ฐ์ดํฐ์
๋๋ค.
let noiseValue = noise(xoff, yoff);
// 4. ๋ฐ์ง๋ฆ(r) ๋ฐ์ดํฐ ๋ณํ ๋ฐ ์ ์ (์ ์ฐจ์ ๋ชจ๋ธ๋ง)
// ๋
ธ์ด์ฆ ๊ฐ์ -30์์ +50 ํฝ์
๋ฒ์๋ก ๋งคํํ์ฌ ๊ธฐ๋ณธ ๋ฐ์ง๋ฆ(200)์ ๋ํฉ๋๋ค.
let r = radius + map(noiseValue, 0, 1, -30, 50);
// 5. ๊ทน์ขํ(r, angle)๋ฅผ ํ๋ฉด ์ขํ์ธ ์ง๊ต์ขํ(x, y)๋ก ๋ณํ
let x = r * cos(angle);
let y = r * sin(angle);
// 6. ์ ๋ฐ์ดํฐ๋ก ํํ ์ ์
vertex(x, y);
}
endShape(CLOSE); // ํด๋ฆฌ๊ณค์ ์์์ ๊ณผ ๋์ ์ ์ฐ๊ฒฐํ์ฌ ํํ๋ฅผ ๋ซ์ต๋๋ค.
}
๐ก ์ฝ๋ ์์ธ ์ค๋ช
: ์ํ์ ยท๋ฐ์ดํฐ ๊ธฐ๋ฐ ์ ์ด
1. ๐ ๊ทน์ขํ๊ณ๋ฅผ ํตํ ํํ ์ ์ (Generative Geometry)
์ด ์ฝ๋๋ ๋ํ์ ์์น๋ฅผ ๊ทน์ขํ๊ณ (, )๋ผ๋ ๋ฐ์ดํฐ๋ก ์ ์ํฉ๋๋ค. ์ด๋ ์ง๊ต์ขํ()๋ณด๋ค ์ํ ํํ๋ฅผ ์์ฑํ๊ณ ๋ณํํ๋ ๋ฐ ํจ์ฌ ํจ์จ์ ์
๋๋ค.
let angle = map(i, 0, numPoints, 0, TWO_PI);r๊ณผ angle์ด๋ผ๋ ๋ ๊ฐ์ง ๋ฐ์ดํฐ๋ฅผ ๋ค์ ๊ณต์์ ๋ฐ๋ผ ํ๋ฉด์ ์ง๊ต์ขํ๋ก ๋ณํํ์ฌ ์ ์ ์ต์ข
์์น๋ฅผ ๊ฒฐ์ ํฉ๋๋ค.noiseScale ๋ณ์๋ ๋
ธ์ด์ฆ ์
๋ ฅ ์ขํ์ ๊ฐ๊ฒฉ์ ์ ์ดํ์ฌ, ๋ํ์ ๊ฑฐ์น ๊ธฐ๋ ์์ํจ๊ณผ ๊ฐ์ ์ง๊ฐ์ ์ ์ํ๋ ๋ฐ์ดํฐ๋ก ์ฌ์ฉ๋ฉ๋๋ค.noiseValue (0.0 ~ 1.0)๋ฅผ ํ๋ํ ํ, map() ํจ์๋ฅผ ์ฌ์ฉํ์ฌ ์ด ๊ฐ์ ์ํ๋ ๋ฐ์ง๋ฆ ๋ณ๋ ํญ์ผ๋ก ๋ณํํฉ๋๋ค.radius์ ๋ํ์ฌ ๊ฐ ์ ์ ์ต์ข
r ๊ฐ์ ์ ์ํฉ๋๋ค. ์ด๋ก์จ ์ ๊ธฐ์ ์ด๊ณ ์์ธก ๋ถ๊ฐ๋ฅํ ์๊ณก์ด ๋ฐ์ํฉ๋๋ค.timeOffset):draw() ํจ์๊ฐ ๋ฐ๋ณต๋ ๋๋ง๋ค timeOffset ๊ฐ์ด ๋ฏธ์ธํ๊ฒ ์ฆ๊ฐํฉ๋๋ค. ์ด ๊ฐ์ ๋
ธ์ด์ฆ ํจ์์ ์ธ ๋ฒ์งธ ์ธ์(Z์ถ)์ ๋ํด์ง๋๋ค.
let points = [];
let amplitude = 100; // ํ๋ ๋์ด
let detail = 300; // ํฌ์ธํธ ๊ฐ์
function setup() {
createCanvas(800, 400);
noFill();
stroke(255);
// ๐ ๋ฐ์ดํฐ ์์ฑ ๋จ๊ณ
for (let i = 0; i < detail; i++) {
let x = map(i, 0, detail, 0, width);
let y = height / 2 + sin(i * 0.05) * amplitude;
points.push({ x, y });
}
}
function draw() {
background(20);
// ๐ ๋ฐ์ดํฐ โ ํํ ์๊ฐํ
beginShape();
for (let p of points) {
vertex(p.x, p.y);
}
endShape();
}
๊ทธ๋ฆฌ๋๋ฅผ ๋ฐ์ดํฐ ๋ฐฐ์ด๋ก ๊ตฌ์ฑํ๊ณ , ๊ฐ ์
์ ๊ฐ์ ๊ธฐ๋ฐ์ผ๋ก ๊ธฐํํ์ ํํ๋ฅผ ์์ฑ.

// ์์ B: ๋ฐ์ดํฐ ๊ทธ๋ฆฌ๋ โ ๊ธฐํ ๊ตฌ์กฐ ์์ฑ
let cols = 20;
let rows = 20;
let grid = [];
function setup() {
createCanvas(600, 600);
noStroke();
// ๐ ๋ฐ์ดํฐ ์์ฑ ๋จ๊ณ
for (let i = 0; i < cols; i++) {
grid[i] = [];
for (let j = 0; j < rows; j++) {
grid[i][j] = noise(i * 0.2, j * 0.2); // 0 ~ 1 ๊ฐ
}
}
}
function draw() {
background(10);
// ๐ ๋ฐ์ดํฐ โ ํํ ์๊ฐํ
let cellW = width / cols;
let cellH = height / rows;
for (let i = 0; i < cols; i++) {
for (let j = 0; j < rows; j++) {
let val = grid[i][j];
// ๋ฐ์ดํฐ์ ๋ฐ๋ฅธ ์/ํฌ๊ธฐ ๋ณํ
let size = cellW * val;
fill(val * 255, 150, 255);
ellipse(
i * cellW + cellW / 2,
j * cellH + cellH / 2,
size,
size
);
}
}
}

// ์์ C: ํ๋ผ๋ฏธํฐ ๊ธฐ๋ฐ ์ ์ฐจ์ ๋ค๊ฐํ
let sides = 7; // ๋ณ ๊ฐ์ (๋ฐ์ดํฐ)
let radius = 200; // ๋ฐ์ง๋ฆ
let rotationSpeed = 0.01;
function setup() {
createCanvas(600, 600);
angleMode(RADIANS);
}
function draw() {
background(30);
translate(width / 2, height / 2);
rotate(frameCount * rotationSpeed);
stroke(255);
noFill();
strokeWeight(2);
beginShape();
for (let i = 0; i < sides; i++) {
let angle = TWO_PI * (i / sides);
let x = cos(angle) * radius;
let y = sin(angle) * radius;
vertex(x, y);
}
endShape(CLOSE);
}