前言
我常常被問到:「我想學創意編程(Creative Coding),應該用什麼工具?」這個問題沒有標準答案,因為這個領域的工具鏈在過去二十多年裡不斷演化,每一代工具都有它獨特的定位和優勢。
從 2001 年 Processing 在 MIT Media Lab 誕生,到 2014 年 p5.js 讓瀏覽器成為創作畫布,再到 GLSL shader 直接在 GPU 上作畫——這是一段從「降低程式門檻」到「追求極致效能與表現力」的演化史。
這篇文章會帶你走一遍這段歷程,比較各工具的特點,幫你找到最適合自己的創作工具。
Processing:創意編程的開山鼻祖
誕生背景
2001 年,Casey Reas 和 Ben Fry 在 MIT Media Lab 的 Aesthetics + Computation Group(由 John Maeda 領導)創造了 Processing。他們的初衷很明確:讓藝術家和設計師也能用程式來創作。
在當時,如果你想用程式碼畫東西,你得和 OpenGL 的 C/C++ API 搏鬥,或者用 Java 的 AWT/Swing——這對非程式背景的人來說簡直是噩夢。Processing 做了一件很了不起的事:它把「在螢幕上畫東西」這件事簡化到了極致。
核心設計理念
Processing 的程式結構建立在兩個函數上:
void setup() {
size(800, 600);
background(0);
}
void draw() {
// 每幀被呼叫一次
ellipse(mouseX, mouseY, 50, 50);
}
setup() 跑一次做初始化,draw() 每秒跑 60 次做繪圖。就這麼簡單。不需要理解 main function、事件迴圈、視窗管理——所有的複雜性都被藏在底層。
Processing 的影響
Processing 的影響遠超出工具本身:
- 教育:全世界數百所大學把 Processing 用於程式設計入門課程。它證明了「用視覺回饋來學程式」是有效的。
- 藝術:催生了「生成式藝術」(Generative Art)的蓬勃發展。無數藝術家用 Processing 創作展覽作品。
- 社群:Processing Foundation 是一個非營利組織,致力於讓程式設計更具包容性。OpenProcessing 等平台讓全球的創作者可以分享作品。
- 衍生工具:Processing 的理念啟發了一大批後續工具。
Processing 的局限
到了 2010 年代,Processing(基於 Java)的局限逐漸顯現:
- 需要安裝 JRE:分享作品不方便,接收者也得安裝 Java
- 桌面限定:在行動裝置和網頁上無法直接運行
- Java 語法:對完全的初學者來說,型別宣告、分號、大括號還是有門檻
- 效能上限:雖然可以呼叫 OpenGL,但架構上不如原生 C++
p5.js:Processing 的 Web 轉生
誕生
2014 年,Lauren Lee McCarthy 創造了 p5.js——Processing 理念的 JavaScript 實現。這不是把 Processing 翻譯成 JavaScript 那麼簡單,而是一次深思熟慮的重新設計。
p5.js 的口號很棒:“p5.js is for everyone.” 它特別強調包容性——不只是技術上的低門檻,還包括文件的多語言化、對身心障礙者的可及性支援等。
p5.js vs Processing
// p5.js — 和 Processing 幾乎一模一樣的結構
function setup() {
createCanvas(800, 600);
background(0);
}
function draw() {
ellipse(mouseX, mouseY, 50, 50);
}
主要差異:
- 語言:JavaScript(動態型別、不需要分號、函數是一等公民)
- 平台:在瀏覽器中運行,任何裝置都能看
- 分享:一個 URL 就能分享作品(p5.js Web Editor)
- 生態系:可以輕鬆整合 HTML/CSS、Web API(攝影機、麥克風、MIDI…)
- DOM 互動:可以加入 HTML 元素(滑桿、按鈕、輸入框)
p5.js 的獨特優勢
Web Editor
p5.js 有一個非常好用的線上編輯器(editor.p5js.org),打開瀏覽器就能開始創作,不需要安裝任何東西。這對教學來說是殺手級的特性。
豐富的附加庫
// p5.sound — 音訊
let fft = new p5.FFT();
let spectrum = fft.analyze();
// p5.dom — HTML 元素互動(已內建)
let slider = createSlider(0, 255, 127);
// ml5.js — 機器學習
let classifier = ml5.imageClassifier('MobileNet');
// matter.js — 物理模擬
// tone.js — 合成器
// ... 數十個社群庫
實例模式
// 在同一頁面放多個 p5 canvas
const sketch1 = (p) => {
p.setup = () => {
p.createCanvas(300, 300);
};
p.draw = () => {
p.background(51);
p.ellipse(p.mouseX, p.mouseY, 50, 50);
};
};
const sketch2 = (p) => {
p.setup = () => {
p.createCanvas(300, 300);
};
p.draw = () => {
p.background(200, 50, 50);
p.rect(p.mouseX, p.mouseY, 50, 50);
};
};
new p5(sketch1, 'container1');
new p5(sketch2, 'container2');
p5.js 的局限
- 效能:JavaScript 在 CPU 密集運算上不如 Java/C++,更遠不如 GPU
- 像素操作慢:
loadPixels()+ 逐像素計算在高解析度下很吃力 - 沒有多執行緒:Web Worker 可以幫忙,但整合不夠方便
- 2D 為主:雖然有 WEBGL 模式,但 3D 能力比專業 3D 框架弱
GLSL Shader:直接和 GPU 對話
為什麼需要 Shader?
當你在 p5.js 中對每個像素做計算(比如碎形、Voronoi、反應擴散),你會發現效能瓶頸來得很快。一個 800×800 的畫布有 64 萬個像素,每個像素要做幾十次浮點運算,全部交給 CPU 的一個核心——太慢了。
GPU 就是為了這種「大量獨立的平行計算」而生的。一個中階 GPU 有幾千個核心,可以同時計算所有像素。Shader(著色器)就是你寫給 GPU 執行的程式。
GLSL 基礎
GLSL(OpenGL Shading Language)是最通用的 shader 語言。在 WebGL 中使用的是 GLSL ES。
一個最基本的 fragment shader:
precision mediump float;
uniform vec2 u_resolution; // 畫布大小
uniform float u_time; // 時間
void main() {
// 正規化座標到 [0, 1]
vec2 uv = gl_FragCoord.xy / u_resolution;
// 一個簡單的漸層
vec3 color = vec3(uv.x, uv.y, abs(sin(u_time)));
gl_FragColor = vec4(color, 1.0);
}
每個像素都會獨立執行一次 main() 函數。你不能存取「隔壁像素」的計算結果(除非透過紋理),你也不能在像素之間共享狀態。這種限制反而成了一種創作的獨特思維方式。
在 p5.js 中使用 Shader
let myShader;
function preload() {
myShader = loadShader('shader.vert', 'shader.frag');
}
function setup() {
createCanvas(800, 800, WEBGL);
noStroke();
}
function draw() {
shader(myShader);
myShader.setUniform('u_resolution', [width, height]);
myShader.setUniform('u_time', millis() / 1000.0);
myShader.setUniform('u_mouse', [mouseX / width, mouseY / height]);
// 畫一個覆蓋全畫面的矩形,讓 shader 在上面運行
rect(0, 0, width, height);
}
Shadertoy:Shader 的遊樂場
Shadertoy(shadertoy.com)是全世界最大的 shader 分享平台,由 Inigo Quilez 和 Pol Jeremias 創建。在上面你可以看到令人難以置信的作品——完全用數學公式即時渲染的 3D 場景、流體模擬、光線追蹤。
Shadertoy 的 shader 格式稍有不同,但核心相同:
void mainImage(out vec4 fragColor, in vec2 fragCoord) {
vec2 uv = fragCoord / iResolution.xy;
vec3 col = 0.5 + 0.5 * cos(iTime + uv.xyx + vec3(0, 2, 4));
fragColor = vec4(col, 1.0);
}
GLSL 的學習曲線
GLSL 的思維方式和一般程式設計很不一樣:
- 沒有迴圈跑像素:你不是「一個一個畫像素」,而是「定義每個像素的顏色」
- 沒有狀態:每個像素的計算是獨立的,不能讀取其他像素的結果
- 數學密集:很多效果需要靠向量數學、距離函數、噪聲函數等技巧
- 除錯困難:沒有
console.log,只能靠「把值映射成顏色」來觀察
但一旦你適應了這種思維,GLSL 會打開一個全新的創作世界。
其他重要工具
TouchDesigner
TouchDesigner 是 Derivative 公司開發的視覺化程式設計環境,專攻即時視覺(real-time visuals)。它使用節點式(node-based)的介面,你透過連接不同功能的節點來建構視覺管線。
適合場景:
- 現場演出的 VJ 視覺
- 互動裝置藝術(結合感測器、Kinect、MIDI 控制器)
- 投影映射(Projection Mapping)
- 即時生成式視覺
特色:
- 內建 GPU 加速的粒子系統、流體模擬
- 可以直接寫 GLSL 和 Python
- 支援多螢幕輸出、Spout/Syphon/NDI
- 社群版(非商業用)免費
不足:
- 只有 Windows 和 macOS
- 學習曲線陡峭
- 商業授權昂貴
- 不方便做網頁分享
cables.gl
cables.gl 是一個基於瀏覽器的視覺化程式設計工具,由 undev 團隊開發。它和 TouchDesigner 一樣使用節點式介面,但完全在 WebGL 上運行。
適合場景:
- 互動式網頁視覺
- WebGL 學習(可以看到底層的 GL 操作)
- 快速原型設計
特色:
- 完全在瀏覽器中運行,不需安裝
- 可以匯出獨立的 WebGL 應用
- 可以寫自訂 GLSL 節點
- 社群分享方便
three.js 與 WebGL 框架
如果你想做更複雜的 3D 互動內容,three.js 是 WebGL 生態系統中最流行的框架:
// three.js 基本結構
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(75, w/h, 0.1, 1000);
const renderer = new THREE.WebGLRenderer();
const geometry = new THREE.BoxGeometry(1, 1, 1);
const material = new THREE.ShaderMaterial({
vertexShader: vertexCode,
fragmentShader: fragmentCode,
uniforms: {
u_time: { value: 0.0 }
}
});
const mesh = new THREE.Mesh(geometry, material);
scene.add(mesh);
function animate() {
requestAnimationFrame(animate);
material.uniforms.u_time.value = performance.now() / 1000;
renderer.render(scene, camera);
}
animate();
three.js 是 p5.js WEBGL 模式和原始 WebGL 之間的甜蜜點——比 p5.js 靈活得多,但比原始 WebGL 友善得多。
其他值得一提的工具
- openFrameworks:C++ 的創意編程框架,效能最強,適合硬體互動和大型裝置
- Cinder:另一個 C++ 框架,API 更現代
- nannou:Rust 的創意編程框架,型別安全 + 高效能
- Hydra:即時 shader 編碼,專為 VJ 和 live coding 設計
- Sonic Pi:音樂的創意編程工具(Ruby-based)
- Unity/Unreal:遊戲引擎,越來越多藝術家用它做互動裝置
選擇地圖:我該用什麼?
| 需求 | 推薦工具 |
|——|———|
| 剛開始學程式 | p5.js |
| 教小朋友/工作坊 | p5.js Web Editor |
| 做網頁互動作品 | p5.js / three.js |
| 追求像素級的視覺效果 | GLSL (Shadertoy) |
| 做即時演出 VJ | TouchDesigner / Hydra |
| 做大型互動裝置 | openFrameworks / TouchDesigner |
| 做數學教學影片 | Manim |
| 做 3D 互動網站 | three.js / cables.gl |
| 做生成式 NFT 藝術 | p5.js / GLSL |
| 學習圖形學原理 | GLSL + 手寫 WebGL |
我的個人建議
如果你是初學者,從 p5.js 開始。它的學習曲線最平緩,社群最活躍,文件最完善。等你在 p5.js 中遇到效能瓶頸(通常是想做像素級的效果時),自然就會開始學 GLSL。
如果你已經有程式基礎,直接從 The Book of Shaders 開始學 GLSL 也很好。它會徹底改變你思考圖形的方式。
如果你想做互動裝置或現場演出,TouchDesigner 是行業標準。它的節點式工作流程非常適合快速迭代和即時調整。
最後,不要被工具困住。創意編程的核心不是工具,而是 「用計算思維來表達美」 的能力。這種能力是可以跨工具遷移的。一旦你理解了正弦波、噪聲、距離場、矩陣變換這些基本概念,無論用什麼工具都能快速上手。
小結
從 Processing 到 p5.js 到 GLSL,創意編程工具的演化不是「新工具取代舊工具」的線性過程,而是一棵不斷分枝的大樹。每一個工具都在特定的生態位上繁盛:Processing 在教育和社群中根基深厚,p5.js 讓網頁成為最開放的創作平台,GLSL 讓 GPU 的平行算力為藝術家所用,TouchDesigner 統治了即時演出的世界。
我相信這棵樹還會繼續生長。WebGPU 正在取代 WebGL,AI 輔助生成正在改變創作流程,AR/VR 正在拓展「畫布」的定義。但不管工具怎麼變,那個最初的衝動——「我想用程式碼畫出美麗的東西」——永遠不會改變。
延伸閱讀
- 《Processing: A Programming Handbook for Visual Designers and Artists》— Casey Reas & Ben Fry
- The Coding Train (YouTube) — Daniel Shiffman 的 p5.js 教學頻道
- The Book of Shaders — Patricio Gonzalez Vivo(thebookofshaders.com)
- Inigo Quilez 的部落格(iquilezles.org)— shader 技術的百科全書
- Creative Applications Network (creativeapplications.net) — 互動藝術作品報導
- 嘗試在三種不同的工具中做同一個作品(例如粒子系統),比較體驗的差異