前言

我一直覺得,程式生成藝術(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 通常需要一些整理:

  1. 檢查尺寸:用 Inkscape 或 Illustrator 開啟 SVG,確認實際尺寸。p5.js 的座標是像素,需要確認 SVG 的 viewBox 和單位是否正確
  2. 移除多餘元素:p5.js 可能會加上背景矩形或其他不需要的元素
  3. 合併路徑:如果有太多零碎的小路徑,可以合併以減少機器的起停次數
  4. 加上外框切割線:如果需要把整個作品切下來,在最外層加一個切割用的外框

在 Inkscape 裡整理

1. 開啟 SVG
  1. 全選(Ctrl+A)
  2. 檢查物件大小(W 和 H 欄位,確認單位是 mm)
  3. 如果尺寸不對,用「縮放」功能調整
  4. 設定線條顏色(雕刻線和切割線分開)
  5. 另存為標準 SVG 或 DXF

匯入 LightBurn

LightBurn 可以直接開啟 SVG 檔案:

  1. File > Import,選擇你的 SVG
  2. 確認尺寸是否正確
  3. 將不同用途的線條分配到不同圖層
  4. 設定每個圖層的參數(速度、功率、模式)
  5. 預覽切割路徑
  6. 送出到機器

設計時的注意事項

線條密度

生成式圖案很容易產生非常密集的線條。太密的線條在雷切時有幾個問題:

  • 時間過長:每條線都要走一趟,線條越多時間越久
  • 過度燃燒:相鄰的雕刻線會累積熱量,可能燒穿材料
  • 視覺效果差:太密的線條在實體上看起來會糊成一片

我的經驗是:線條間距不要小於 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,它更適合做三維的、有功能性的零件設計。