Drawing is not an image.
It is an event.

InkField preserves the memory of every gesture.

目錄

Part I — 作品概述與功能

  1. 作品概述
  2. 筆刷系統 — 7 種模式與彈簧力學
  3. 墨水擴散效果 — feedback.frag 的 6 種模式
  4. 流場變形系統 — flow.frag 的 8 種混合算法
  5. 金屬蝕刻效果 — scanAndMarkDarkPoints
  6. 錄製與回放系統 — 確定性重現
  7. 雙模式設計 — 創作者 vs 收藏者

Part II — 渲染管線與參考

  1. 渲染管線速覽
  2. 完整流程圖
  3. Buffer 總覽表
  4. 教學系列 — 深入閱讀
0

作品概述

InkField 將繪畫從「圖像」轉回「行為」。

在這個系統中,每一次筆觸的路徑、速度與方向都被完整記錄,使繪畫成為一段可被保存與重新演算的時間結構。

這些運動資料被送入筆刷與墨水的生成系統之中。畫面因此不再只是被回放,而是在既有軌跡上持續生成。墨水的暈染、顆粒與飛白會因隨機種子的微小差異而改變,使每一次重現都保持細微的偏移。

作品既是紀錄,也是系統。

它保存了藝術家身體運動的痕跡,同時允許演算法在同一條路徑上不斷生成新的變化。

在影像生成日益自動化的時代,InkField 將注意力重新放回創作中的「意圖」。

那些短暫存在於手與大腦之間的停頓、轉折與節奏,被轉化為可以被觀看與分析的資料。

繪畫因此不再只是靜止的結果,而是一段持續流動的時間。

技術管線

整個繪畫管線由 10 支 GLSL 著色器27 個離屏緩衝區組成:

筆觸輸入 → encode.frag(35 色查表 + HSB 轉換)
→ typeMapEncode.frag(逐像素記錄筆刷類型)
→ feedback.frag(6 種墨水物理模式)
→ flow.frag(8 種噪聲混合算法)
→ composite.frag(讀取 typeMap 判斷筆刷身份)
→ distort.frag(FBM / 共振波 / 細胞紋理 / 白點 / 顆粒)
→ 螢幕輸出

技術規模

項目數值
JavaScript10,871 行(5 個核心模組)
GLSL 著色器2,775 行(10 支自訂著色器)
緩衝區14 個 Framebuffer + 13 個 createGraphics
WebGL Context3 個(從最初的 16 個優化而來)
技術棧p5.js、WebGL、GLSL、p5.easycam
部署可打包為 index.html + script.js + shader.js
1

筆刷系統 — 7 種模式與彈簧力學

物理模型

筆刷移動以彈簧力學模型(spring force + damping)模擬毛筆的慣性與彈性。滑鼠位置作為目標點,筆頭經由加速度插值追蹤,產生自然的延遲與回彈。

模式名稱特性
1毛筆帶噴灑變化的書法筆觸,力道控制墨色深淺
2麥克筆硬邊方塊筆刷,適合大面積塊面表現
3噴漆液態流動效果,墨跡帶有動態延展
4枯筆噪聲驅動的線寬變化,模擬技術筆繪圖
5噴灑點點狀飛濺效果,密度隨筆速變化
6刷筆逐幀動畫的進階書法筆刷(flyBrushOnBuffer)
7毛邊筆刷不帶噴灑的精細筆觸,線條乾淨俐落

其他參數

  • 筆刷大小:7 級預設(0.1 / 0.25 / 0.5 / 1 / 2 / 3 / 5 倍基礎值)
  • 路徑旋轉:無旋轉 / 5-10° 隨機 / 10-25° 隨機
  • 混合模式:Mix(線性混合)/ Multiply(加深)/ Darken(最暗值)
  • 色彩選擇:35 色預設色板(7×5 格局)+ 自訂顏色
2

墨水擴散效果 — feedback.frag 的 6 種模式

Shader feedback.frag — 回饋擴散

每一幀畫面更新時,feedback shader 對 newBufferBlack 進行物理擴散模擬。它讀取「力場地圖」(forceMap)上每個點的方向和大小,將墨水往該方向推移,模擬真實墨水在紙上的自然流動。

模式名稱效果感覺像什麼
Mode 0MIX 基礎混合大範圍擴散 + 模糊墨汁掉進水裡
Mode 1SHARP 銳化顆粒質感 + 光暈炭筆在粗糙紙上
Mode 2FLYING 飛白多尺度噪聲驅動的乾筆效果宣紙上的飛白書法
Mode 3WET 暈染水彩般的滲透與暈開水彩暈染
Mode 4SALT 鹽巴模擬撒鹽產生的結晶紋理高級水彩撒鹽技法
Mode 5HAIR 慢暈帶方向性條紋的緩慢擴散慢慢暈開的水墨

你放開滑鼠後,墨水還會繼續擴散一小段時間(力道漸漸減弱到零),模擬真實墨水的「餘韻」。

3

流場變形系統 — flow.frag 的 8 種混合算法

Shader flow.frag — 流場變形

長按觸發的流場效果以 Perlin/Simplex 噪聲為基底,疊加不同的混合算法,將靜態筆觸轉化為動態的有機形態。每種 blendType 產生截然不同的視覺風格。

Type符號名稱效果
0~基礎波形Perlin/Simplex 噪聲位移
2同心漣漪從中心擴散的圓環波紋
3垂直波動垂直方向的波浪位移
4水平位移水平方向的波浪位移
5龜裂花紋細胞/龜裂紋理圖案
6馬賽克碎片方塊碎裂的鑲嵌效果
7🌀漩渦向中心捲入的螺旋
8細胞紋理有機細胞狀的變形

關鍵功能:「僅最後一筆」模式

開啟 Last Stroke Only 後,流場效果只作用於最新一筆筆觸,不影響已有筆跡。

技術上需要在 GPU 層面同步位移 TypeMap 身份緩衝區,確保筆刷類型資訊不因變形而錯位——流場的 typeMap pass 使用相同的噪聲偏移量,讓身份跟隨顏色一起移動。

4

金屬蝕刻效果 — scanAndMarkDarkPoints

JS metallic.js — 蟲咬蝕刻模擬

模擬傳統版畫中的蟲咬(bug bite)蝕刻技法:系統掃描畫面暗部像素,以加權隨機選取 10 個目標點,在其上生成程序化的有機形狀。

觸發模式

  • GLOBAL:掃描整張畫布
  • EACH:逐筆掃描新筆觸
  • RANDOM:隨機觸發
  • EACHR:逐筆掃描 + 隨機強度
Shape Type名稱形態
CCircle 圓形圓形穿孔
RERectangle 矩形方形切口
LELightning 閃電小型鋸齒裂紋(回放時放大 1.3 倍確保可見)
BEBig Lightning 大閃電大型分支狀裂紋

材質預設

6 種金屬材質:金 Gold / 銀 Silver / 銅 Copper / 玫瑰金 Rose / 黑鐵 Black / 鑽石 Diamond。透過 metallic.frag 著色器模擬材質光澤和顏色。

5

錄製與回放系統 — 確定性重現

JS recording.js — 事件錄製

完整的事件錄製系統將每一個滑鼠位置、時間戳、筆刷參數編碼為 JSON。配合自製的 crandom 種子隨機數包裝器(js/crandom.js),追蹤每一次 random() 呼叫的計數,實現近乎 100% 的回放一致性。

錄製功能

  • 事件導向的 JSON 捕捉(每筆觸 35+ 欄位)
  • 自動壓縮停頓時間(跳過繪畫間的等待)
  • 蟲咬效果的 targetPoints 直接錄入事件資料,消除回放時像素掃描的不確定性
  • 回放路徑保留與錄製相同的距離檢查(minDistance),確保 bite 數量一致

回放功能

  • 完整筆觸重建(保留原始物理參數)
  • 自動循環播放(可設定等待時間)
  • 播放偏移(X/Y 平移)
  • 進度條百分比顯示
  • 支援 JSON 匯入/貼上(Agent JSON Panel)

一致性保障:crandom 系統

crandom(js/crandom.js)包裝 p5.js 的 random(),為每次呼叫計數。回放時透過比對 randomCount 驗證 PRNG 序列是否對齊。

關鍵設計:shapeSeed = floor(target.x × 1000 + target.y × 333 + shapeSeedRand)——形狀由目標位置決定。generateOrganicShape 內部呼叫 randomSeed(seed) 重置 PRNG,確保相同 seed 產生相同形狀。

6

雙模式設計 — 創作者 vs 收藏者

創作者模式(Artist Mode)

完整的三面板 UI:

  • Art System Log(📋):錄製、回放、開關面板(Paper / Grid / Camera / Loop / Distort / fBM / RS / Cellular / WhiteDot / Grain / Path / Fit)
  • Brush Control(🖌️):筆刷模式 1-7、墨水效果 0-5、筆刷大小、路徑旋轉、混合模式、35 色色板
  • Effect Control(✨):蟲咬觸發模式、金屬材質、流場效果按鈕 + 強度滑桿

所有面板可拖曳移動,位置存於 localStorage。點擊任何面板自動提到最上層。

收藏者模式(Collector Mode)

純粹的動態展演裝置——隱藏所有介面,自動載入作品 JSON 並循環播放。

  • 自動載入 /lib/demo.json
  • URL hash 切換作品:#1#2#3 → 載入 /lib/1.json/lib/2.json
  • 畫布尺寸從 JSON 同步
  • 自動循環開啟

URL 參數系統

格式:?_panel1:value_panel2:value_...

?_camera:0_rs:0_paper:0_console:0_grid:1_path:0 // 自訂開關預設
?_artist:1 // 強制開啟創作者模式
#1, #2, #3 // 收藏者模式載入指定作品
7

渲染管線速覽

想像你在美術課畫水彩畫:

第一步 — 你拿鉛筆在一張 白紙 上畫草稿(深淺代表力道大小)。

第二步 — 老師幫你用吹風機吹一吹,讓墨水自然擴散、有水彩的感覺。

第三步 — 草稿完成後,你用 特殊密碼 把草稿翻譯成一個「編碼版本」,存進保險箱。

第四步 — 每次要展示作品,機器從保險箱讀出編碼,解碼 成漂亮的顏色,貼在有紋路的紙上。

第五步 — 最後灑上一點特效(扭曲、顆粒),完成!

以下是每個階段涉及的 Shader 與 Buffer,以及對應的詳細教學:

階段Shader / Buffer做什麼詳細教學
① 黑白草稿 newBufferBlack 筆刷在白紙上留下灰度痕跡,深淺代表力道 顏色的旅程 →
② 墨水擴散 feedback.frag 每幀讀取力場地圖,讓墨水自然流動擴散 墨水效果全圖鑑 →
③ 編碼存檔 encode.frag 將灰度草稿翻譯為顏色編碼,存入 finalBuffer 顏色的旅程 →
③b 身份記錄 typeMapEncode.frag 同步寫入筆刷類型到獨立的 typeMapBuffer 顏色的旅程 →
④ 解碼合成 composite.frag 查身份證 → 選混合模式 → 疊上紙張紋理 混色與力場 →
⑤ 即時預覽 realtime.frag 繪畫進行中的即時顏色預覽 顏色的旅程 →
⑥ 後處理特效 distort.frag FBM 扭曲 / 漣漪 / 細胞紋理 / 白點 / 顆粒 特效工廠 →
8

完整流程圖

從你按下滑鼠到看到畫面,整個流程如下:

你的滑鼠 / 觸控輸入 位置、壓力、速度
1. 筆刷函數畫在 newBufferBlack 黑白草稿,深淺 = 力道
2. feedback.frag 讓墨水流動擴散 每幀重複:讀力場 → 推墨水 → 加質感
3. encode.frag 把草稿編碼成顏色 白筆 → 純灰 R=G=B / 彩筆 → 混合色 / 黑筆 → 去飽和灰
3b. typeMapEncode.frag 寫入身份證 R=筆刷類型 / G=白色最大不透明度 → typeMapBuffer
4. 存進 finalBuffer + typeMapBuffer 顏色和身份分開存,互不干擾
5. composite.frag 查身份證 + 解碼 + 貼上紙張 讀 typeMapBuffer 判斷筆刷:白筆 → Screen / 彩筆 → Multiply / 黑筆 → Darken
6. realtime.frag 疊上正在畫的那一筆 (只在畫畫中運行,讓你即時看到效果)
7. distort.frag 加上特效 → 螢幕 扭曲 / 細胞 / 白點 / 顆粒(可關閉)
9

Buffer 總覽表

程式裡有很多「畫布」(Buffer),每一個負責不同的事。可以想成 美術教室裡的不同桌子,每張桌子放不同的東西:

Buffer 名稱功能比喻
newBufferBlack 正在畫的黑白草稿 你面前的白紙
pingPongBuffer feedback 擴散的暫存區(專用) 吹風機旁邊的臨時托盤
finalBuffer 所有筆觸的「編碼」版本 保險箱(密碼本)
typeMapBuffer 每個像素的筆刷身份(R=類型, G=白色不透明度) 身份證本
oldBuffer 所有筆觸的灰度疊加 備份影印本
screenBuffer 合成 + 即時預覽的工作區 展示桌(可以擦掉重來)
realtimeIntermediateBuffer composite → realtime 的中間拷貝(避免同一 FBO 同時讀寫) 展示桌的影印版
paperTextureBuffer 有紋路的背景紙 畫室裡的好紙
lastStrokeBuffer 最後一筆的快照(flow 效果用) 最後一筆的照片
img(forceMap) 力場地圖,驅動 feedback 擴散方向 風向圖
finalOut 最終輸出(加了特效的) 裱框好的作品
cursorBuffer 游標和路徑預覽(已遷移為 framebuffer) 玻璃板上的標記

技術細節:createFramebuffer

所有需要 shader 處理的 buffer(以及 cursorBuffer)都使用 p5.js 的 createFramebuffer() 建立。 這跟早期的 createGraphics(WEBGL) 不同 —— framebuffer 共享主畫布的 WebGL context, 不會建立額外的 GL context。Safari 對 GL context 數量有嚴格限制,使用 framebuffer 讓效能從 ~10 FPS 恢復到流暢。

原本的 16 個 WebGL context 已減至 3 個(主 canvas + 2 個 UI/debug overlay)。只有 P2D blur buffer 和 setup-time 紋理仍使用 createGraphics

10

教學系列 — 深入閱讀

以上章節是功能摘要與管線速覽。以下是各主題的完整教學文章:

InkField 墨域 — 技術文件
首頁整理:2026-03-10(精簡重複內容,重構為 Hub 導覽架構)