前言
我一直覺得,程式生成藝術(Generative Art)最迷人的地方在於「可控的隨機」— 你定義規則,讓演算法在規則裡自由發揮,每次執行都可能產出令人驚喜的結果。但生成藝術有個小遺憾:作品通常活在螢幕裡。
直到我把 p5.js 生成的圖案匯出成 SVG,然後送進雷切機 — 那一刻,數位的幾何圖案變成了真實可觸摸的木質作品。這種從「程式碼到實體」的跨越,是我做 maker 專案最感動的體驗之一。
這篇文章會帶你走過完整的流程:用 p5.js 寫生成式圖案、匯出 SVG 檔案、送進雷切軟體、最後在材料上切割出來。
p5.js 與 SVG 模式
什麼是 p5.js
p5.js 是一個 JavaScript 創意編程函式庫,語法簡潔,非常適合做視覺化和生成藝術。如果你之前用過 Processing,p5.js 就是它的 JavaScript 版本。
預設情況下,p5.js 在 HTML Canvas 上畫圖,輸出是點陣圖。但我們需要向量圖才能用於雷切。
使用 p5.js-svg 外掛
有一個社群開發的外掛 p5.js-svg,可以讓 p5.js 直接在 SVG 元素上繪圖,所有的線條都會保持為向量路徑。
環境設置
最簡單的方式是建一個 HTML 檔案:
<!DOCTYPE html>
<html>
<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.9.0/p5.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/p5.js-svg@1.5.1/dist/p5.svg.js"></script>
</head>
<body>
<script src="sketch.js"></script>
</body>
</html>
在 sketch.js 裡建立 SVG canvas:
function setup() {
createCanvas(200, 200, SVG); // 第三個參數指定 SVG 模式
noLoop(); // 靜態圖案只需畫一次
}
function draw() {
background(255);
noFill();
stroke(0);
strokeWeight(0.5);
// 在這裡畫你的圖案
circle(100, 100, 80);
}
匯出 SVG
畫完之後,用以下方式把 SVG 存下來:
function keyPressed() {
if (key === 's') {
saveSVG('my-pattern.svg');
}
}
或者直接用瀏覽器開發者工具,從 DOM 裡複製 SVG 元素的 HTML 存成 .svg 檔案。
生成幾何圖案範例
範例 1:同心圓漸變
最簡單的生成圖案,但雷切出來意外地好看。
function setup() {
createCanvas(150, 150, SVG); // 150mm x 150mm
noLoop();
}
function draw() {
noFill();
stroke(0);
strokeWeight(0.3);
let cx = 75;
let cy = 75;
for (let r = 5; r < 70; r += 2) {
circle(cx, cy, r * 2);
}
}
這會生成一組密集的同心圓。雷切在木板上後,因為線條間距很小,光線透過時會有類似莫列紋的視覺效果。
範例 2:旋轉正多邊形
function setup() {
createCanvas(150, 150, SVG);
noLoop();
}
function draw() {
noFill();
stroke(0);
strokeWeight(0.3);
translate(75, 75);
for (let i = 0; i < 36; i++) {
rotate(PI / 36);
polygon(0, 0, 50, 6); // 正六邊形
}
}
// 自訂正多邊形函式
function polygon(x, y, radius, npoints) {
let angle = TWO_PI / npoints;
beginShape();
for (let a = 0; a < TWO_PI; a += angle) {
let sx = x + cos(a) * radius;
let sy = y + sin(a) * radius;
vertex(sx, sy);
}
endShape(CLOSE);
}
36 個旋轉的正六邊形疊在一起,會形成一個複雜的幾何花紋。手動畫這個要花很久,程式幾秒就搞定。
範例 3:Perlin Noise 流場
這是我最喜歡的生成式圖案之一 — 有機、流動、每次都不一樣。
function setup() {
createCanvas(200, 200, SVG);
noLoop();
}
function draw() {
noFill();
stroke(0);
strokeWeight(0.3);
let step = 5;
let lineLength = 100;
let noiseScale = 0.01;
for (let x = 10; x < 190; x += step) {
for (let y = 10; y < 190; y += step) {
let angle = noise(x noiseScale, y noiseScale) TWO_PI 2;
beginShape();
let px = x;
let py = y;
for (let i = 0; i < lineLength; i++) {
vertex(px, py);
let a = noise(px noiseScale, py noiseScale) TWO_PI 2;
px += cos(a) * 1;
py += sin(a) * 1;
// 超出邊界就停
if (px < 0 || px > 200 || py < 0 || py > 200) break;
}
endShape();
}
}
}
這個圖案雷切在深色木板上非常有質感,每條流線都是一道雕刻痕跡。
範例 4:遞迴分割
function setup() {
createCanvas(150, 150, SVG);
noLoop();
}
function draw() {
noFill();
stroke(0);
strokeWeight(0.3);
subdivide(10, 10, 130, 130, 5);
}
function subdivide(x, y, w, h, depth) {
if (depth <= 0 || w < 5 || h < 5) {
rect(x, y, w, h);
return;
}
if (random() < 0.5) {
// 水平分割
let split = random(0.3, 0.7);
let h1 = h * split;
subdivide(x, y, w, h1, depth - 1);
subdivide(x, y + h1, w, h - h1, depth - 1);
} else {
// 垂直分割
let split = random(0.3, 0.7);
let w1 = w * split;
subdivide(x, y, w1, h, depth - 1);
subdivide(x + w1, y, w - w1, h, depth - 1);
}
}
這會產生類似 Mondrian 風格的不規則格子。每次執行結果都不同,如果看到喜歡的就趕快存 SVG。
從 SVG 到雷切軟體
整理 SVG 檔案
p5.js 生成的 SVG 通常需要一些整理:
- 檢查尺寸:用 Inkscape 或 Illustrator 開啟 SVG,確認實際尺寸。p5.js 的座標是像素,需要確認 SVG 的 viewBox 和單位是否正確
- 移除多餘元素:p5.js 可能會加上背景矩形或其他不需要的元素
- 合併路徑:如果有太多零碎的小路徑,可以合併以減少機器的起停次數
- 加上外框切割線:如果需要把整個作品切下來,在最外層加一個切割用的外框
在 Inkscape 裡整理
1. 開啟 SVG
- 全選(Ctrl+A)
- 檢查物件大小(W 和 H 欄位,確認單位是 mm)
- 如果尺寸不對,用「縮放」功能調整
- 設定線條顏色(雕刻線和切割線分開)
- 另存為標準 SVG 或 DXF
匯入 LightBurn
LightBurn 可以直接開啟 SVG 檔案:
File > Import,選擇你的 SVG- 確認尺寸是否正確
- 將不同用途的線條分配到不同圖層
- 設定每個圖層的參數(速度、功率、模式)
- 預覽切割路徑
- 送出到機器
設計時的注意事項
線條密度
生成式圖案很容易產生非常密集的線條。太密的線條在雷切時有幾個問題:
- 時間過長:每條線都要走一趟,線條越多時間越久
- 過度燃燒:相鄰的雕刻線會累積熱量,可能燒穿材料
- 視覺效果差:太密的線條在實體上看起來會糊成一片
我的經驗是:線條間距不要小於 1mm(如果是木板雕刻的話)。在程式裡可以用 step 變數控制密度。
路徑複雜度
SVG 裡的節點數量會影響雷切軟體的處理速度和機器的運動平順度。
- 盡量用簡單的幾何元素(線段、圓弧)而不是大量的短線段
- 如果用了 Perlin Noise 之類的算法,可以在 Inkscape 裡用
路徑 > 簡化(Ctrl+L)減少節點
尺寸思考
在螢幕上看起來精緻的細節,切在實體上可能太小了。一般來說:
- 最小的可辨識線條間距:約 0.5mm
- 最小的可讀文字高度:約 3-4mm
- 最小的可切割孔洞直徑:約 1mm(取決於材料厚度)
建議在設計時就以 1:1 的比例預覽,甚至印出來看看大小感覺。
完整工作流程總結
讓我用一個具體的例子串起整個流程:
步驟 1:寫程式
用 p5.js 生成一個 100mm x 100mm 的幾何圖案。
步驟 2:匯出 SVG
按 S 鍵存檔,得到 my-pattern.svg。
步驟 3:整理向量稿
用 Inkscape 開啟,確認尺寸是 100mm x 100mm。加上一個 100mm x 100mm 的外框矩形作為切割線,顏色設為紅色。內部圖案維持黑色(雕刻線)。
步驟 4:匯入雷切軟體
在 LightBurn 裡匯入,設定參數:
- 黑色圖層:Line 模式,Speed 40mm/s,Power 20%(線雕刻)
- 紅色圖層:Line 模式,Speed 15mm/s,Power 60%(切割)
步驟 5:測試
先用廢料跑一小塊測試,確認雕刻深度和切割效果。
步驟 6:正式切割
確認參數 OK 後,放上正式材料,執行切割。
步驟 7:後處理
取下作品,用砂紙輕磨邊緣,如果需要可以上一層護木油。
延伸想法
一旦你掌握了這個流程,可以嘗試的方向非常多:
- 參數化圖案:在程式裡加上 slider,即時調整圖案參數,找到最喜歡的版本再匯出
- 資料驅動圖案:把外部資料(天氣、音樂、股票)轉換成視覺圖案,雷切出來就是一個「資料實體化」的作品
- 多層組合:生成多個互補的圖案,分別切在不同顏色的材料上,堆疊組合
- 搭配 LED:生成的圖案切在壓克力上,底部加 LED 就是一盞獨一無二的燈
小結
p5.js 是連接「程式」和「實體作品」最順暢的橋樑之一。你不需要是程式高手,基本的迴圈、函式、數學就能生成令人驚豔的圖案。而雷切機則是把這些數位圖案「物質化」的最佳工具。
這個工作流程的核心精神是:讓電腦做它擅長的事(重複、精確、大量運算),讓人做人擅長的事(審美、選擇、組合)。你定義規則和美學方向,程式負責探索可能性,最後由你挑選最好的版本送去切割。
下一篇我們會介紹另一個強大的參數化設計工具 — OpenSCAD,它更適合做三維的、有功能性的零件設計。