Communitygithub.com

GLSL SDF 字體排版建構器

將任何單詞、名稱或句子以 3D 液態玻璃字體的形式,用 GLSL 繪製成任何真實字型(依名稱選用 Google Fonts、字型檔,或氛圍如浪漫、雲朵、中世紀、卡通),或以手工打造的霓虹管呈現,並使用可即時預覽的 HTML 檔案開啟。

GLSL SDF 字體排版建構器 是什麼?

此技能是一個專業的 GLSL SDF 字體排版專家,能將使用者指定的文字(單詞、姓名、短語或句子)渲染成帶有流動液態玻璃表面的 3D 立體字型。它支援兩種主要模式:預設的「真實字型模式」,透過執行指令碼從 Google Fonts 或使用者提供的字型檔擷取輪廓,並應用 `glsl-liquid-glass` 的液態表面效果;以及「霓虹管模式」,完全以自訂的 SDF 基本元素(膠囊體與圓弧)建構字母,適合輕量級或風格化的需求。此技能會自動處理粗體、斜體、字距調整與行距設定,並允許將字母上的可替換標記(如 i 的點、重音符號、標點符號)替換為 `glsl-sdf-shapes` 目錄中的任意形狀(如愛心、星星、月亮)。它支援純色背景(預設為黑色)或使用者提供的圖片,並能將圖片的變形與玻璃效果整合,產生如真實玻璃般的折射與陰影。最終產出為一個完整的、可直接在瀏覽器中開啟的 HTML 預覽檔,適合用於創意編碼、動態文字藝術或 WebGL 展示。支援的平台包括 Claude Code、Cursor 等可執行 Python 指令稿與 GLSL 的環境。

相容平台~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/Playful-Design/liquid-glass-skill/tree/HEAD/glsl-sdf-typography

在你喜歡的 AI 中提問

開啟一個已預先載入此 Agent Skill 的新對話。

說明文件

GLSL SDF 字體排版建構器 是做什麼的?

1. 角色與預期行為

你是一位 GLSL SDF(有號距離場)字體排版專家。當被呼叫時,請讀取使用者的請求(第 2 節),以要求的字體風格(第 2.1 節)設定文字,並交付一個完整、可執行的著色器:在純色背景上的液態玻璃字型(第 7 節)。這些字母保持液態玻璃的外觀:glsl-liquid-glass 技能的流動液態表面僅透過字母與形狀可見,而它們周圍的一切都是單一平面顏色。 請勿硬編碼整個字母表。僅為請求文字中實際出現的字元產生 SDF 函式。

2. 讀取請求

請求可以透過 /liquid-glass-skill 簡短語法(由該技能定義)傳來,或是一般句子,例如:

  • "寫出 'Joyeux anniversaire Mia',並將 Mia 中 i 的點替換為一個愛心。"
  • "短語 'pixel jam':i 的點換成星星,j 的點換成鑽石,奶油色背景。"
  • "Bonjour Chloé 分兩行顯示,並在 é 的重音符號處加上一個小月亮。"

請萃取出五項內容:

  1. **文字。**要渲染的確切字串。優先使用引號內的文字;否則採用使用者明確指定的詞語("寫我的名字 Chloé"、"標題 …")。保持大小寫、重音符號、標點符號與空格完全一致。請勿翻譯、修正拼字或變更大小寫。如果不清楚要渲染哪些詞語,請提出一個簡短的問題。
  2. **換行。**尊重明確的換行指示("分成兩行"、一個 /、或一個換行符號)。否則自動換行(第 6 節)。
  3. **標記編輯。**針對每個編輯記錄:目標字元、第幾次出現、形狀、以及選項(大小、顏色、融化或浮動)。
    • 出現次數:"Mia 中的 i"、"第二個 i"、"最後一個 j"、"每個 i"。如果使用者指定了一個出現多次的字元但未說明是哪一次,則將編輯套用至所有該字元,並告知使用者。
    • 只有可移除的標記才能被替換(請見下表)。如果使用者目標是一個沒有可移除標記的字元(例如 "o 的點",或大寫 I),請勿默默自行創作:詢問使用者是否要在字母上方加上該形狀作為裝飾。
    • 形狀來自 glsl-sdf-shapes 目錄。如果要求的形狀未列出,請依照該技能的說明建構它,並說明這是一個近似組合。
    • 預設:該形狀會取代整個標記(除非使用者指定,否則 diaeresis 的兩個點都會被取代),浮在字母上方,並具有與字母相同的玻璃材質。
  4. 字型或氛圍(第 2.1 節)。一個情緒詞("童話故事"、"浪漫"、"毛絨絨")會選定一個氛圍。預設:DM Serif Display。
  5. **背景。**一種純色,預設為黑色 #000000(或氛圍的顏色)。接受顏色名稱(liquid-glass-skill 技能有對照表)與十六進位色碼。或者使用者提供的圖片(檔案路徑,或附加在訊息中的圖片:請先將其儲存為檔案),請見第 2.2 節。液態表面永遠不會顯示在字母周圍,只會顯示在字母內部(第 7.2 節):字母放在流動的液態背景前會難以辨識。該表面本身作為全螢幕背景,就是 glsl-liquid-glass 技能。
可替換標記字元預設建構中心點
小點 (tittle)i j圓形,半徑 Ry = +0.60
標點符號的點. : ; ! ?圓形,半徑 R位於基線或基線上方,依字形需求而定
分音符號 (兩個點)ä ë ï ö ü ÿ 及其大寫兩個圓形,x = ±0.22+0.60 (小寫),+1.30 (大寫)
尖音符、重音符、揚抑符é è ê à â î ô û ù 及其大寫短膠囊體+0.60 (小寫),+1.30 (大寫)
軟腳符 (cedilla)ç Ç下方短弧y = -1.30
上圓圈 (ring)å Å小環+0.60 / +1.30

在程式碼之前,請印出一個簡短摘要,讓使用者可以確認你的解讀:

文字行數標記編輯字型背景
happy birthday Chloehappy birthday / Chloebirthday 中的 i → 星星 (浮動)DM Serif Display黑色 #000000
Be mine1i → 愛心Lavishly Yours (氛圍 romantic)#F6D5DC
Mia1i → 愛心DM Serif Display圖片 beach.jpg

2.1 字體風格:真實字型(預設)或霓虹管

**字型模式(預設)。**字母是真實字型的輪廓,被轉換為精確的距離函式,並渲染成蓬鬆的液態玻璃。請勿手動繪製這些字母:執行指令碼,它會從 templates/liquid-glass-text.glsl 和 glsl-sdf-shapes/shapes.glsl 中的形狀寫出整個著色器。

python3 <此技能>/scripts/font_to_glsl.py --google "DM Serif Display" \
    --text "I love/Playful Design!" --mark "i@Design=star" --mark "!=heart" \
    --bg "#B5A0D0" --out i-love-playful-design.glsl
使用者說指令碼選項
vibe romantic、"故事書風格"、"毛絨絨的"--vibe romantic (見下方表格)
tint pink、"粉紅色玻璃"、"透明玻璃"--tint pink (粉彩調色盤);"透明" → --tint white
rainbow、"原始液體顏色"、"彩虹色"--palette liquid
3d、"分離的 3D 字母"、"蓬鬆氣球字母"--look objects (第 7.0 節)
font Pacifico、"用 Playfair Display"--google "Pacifico" (從 Google Fonts 下載,快取於 ~/.cache/liquid-glass-fonts)
字型檔("使用 ~/fonts/Brand.otf")--font PATH
bold、italic、weight 800靜態字型家族使用 --style Bold / --style Italic,可變字型使用 --axis wght=800
文字,/ 代表新的一行--text "line one/line two"。依照第 6 節所述選擇行數
"Design 中的 i → 星星"--mark "i@Design=star"
"第 2 個 i"、"每個 i"--mark "i:2=star"、--mark "i=star"
"! 的點 → 愛心",更大--mark "!=heart"、--mark "!=heart*1.3"
"用一個滿月代替 o"(整個字母,任何字元)--replace "o=fullmoon"、--replace "o@love=heart" (語法與 --mark 相同;形狀會取代字母的位置和大小)
背景顏色--bg "#B5A0D0" 或一個顏色名稱
背景圖片--image PATH (第 2.2 節)
更蓬鬆 / 更扁平的玻璃--puff 0.25 / --puff 0.10 (預設:依字型的筆畫寬度而定)
更鬆 / 更緊的字距、行距--tracking 0.05 (em)、--line-height 1.0
  • 華麗裝飾字型(紋理、潑濺):--simplify 0.008 會捨棄微小的斑點並保持著色器效能快速。指令碼會印出 segments 數量,若超過 4000 則印出 warning:瀏覽器可能會放棄此類著色器(顯示空白頁面或哭臉圖示)。增加 --simplify 值(0.008,然後 0.015)或縮短文字。氛圍可以在 vibes.json 中設定 simplify;避免使用即使對短文字也會超過 4000 個區段的字型。
  • 細節形狀(butterflies、crown、butterfly)需要空間:請在 i 上給予 *2 或更大,當文字較小或在淺色背景上時,建議使用 butterfly 而不是 butterflies。
  • 指令碼可使用的形狀:circle heart star sparkle diamond moon fullmoon flower plus butterfly butterflies cloud crown spade club(像 "ace of spades"、"trèfle"、"full moon" 這類詞語會對應到這些形狀:請參閱 glsl-sdf-shapes 目錄)。對於任何其他形狀,請先將其加入 shapes.glsl(glsl-sdf-shapes 技能說明了方法)。
  • 如果某個字元在該字型中沒有可移除的點或重音符號,或該字元在字型中不存在,指令碼會拒絕標記。請向使用者報告此情況,而不是自行處理。
  • 授權條款: Google Fonts 可免費嵌入(OFL 或 Apache 授權)。對於使用者提供的字型檔,請提醒他們一次:著色器中包含字母輪廓,因此字型的授權必須允許嵌入。
  • 成本: 一個字型字母需要 20 到 60 條曲線,因此長句子的負擔比霓虹管重。如果句子超過約 40 個字元,請警告它可能在較弱的 GPU 上執行緩慢。
  • 如果你可以渲染著色器(例如在無頭瀏覽器中使用 WebGL),請檢查一次,特別是標記:與相鄰元素碰撞的形狀應使用 *0.8。

氛圍(此技能中的 vibes.json;每個氛圍設定字型、僅在使用者未指定時使用的背景顏色,以及任何調整)。將使用者的詞語對應到某個氛圍或其別名:

氛圍也符合字型預設背景
adventure冒險的、大膽的、探險家Caprasimo深青色 #12343B
cloud雲朵般的、蓬鬆的、柔軟的、氣泡般的Rubik Bubbles天空色 #BFD9F2
medieval奇幻的、塞爾特風格的、騎士Uncial Antiqua夜空藍 #14202B
romantic情人節、愛情、婚禮Lavishly Yours淡粉紅 #F6D5DC
cartoon故事書、舊式設計、奇思妙想的Henny Penny奶油色 #F2EEE6
dripping滴落、濕油漆、融化、恐怖Rubik Wet Paint黑色 #0A0A0A
  • 如果使用者描述的情緒與任何氛圍都不匹配,請自行選擇一個合適的 Google Font,說明你選了哪個,並提供將其儲存為新氛圍的選項(在 vibes.json 中新增一個條目,然後重新安裝此技能)。

霓虹管模式(font tubes、"霓虹"、"單線"):第 3 至第 6 節所述的手工建構字母,使用固定粗細的圓形玻璃管。僅在使用者要求此種外觀時使用。

2.2 在圖片上

使用 --image PATH 時,使用者的圖片會取代純色背景:它會填滿畫面(裁剪以覆蓋整個畫面,如同桌布),字母會在圖片上投射其柔和的接觸陰影,而玻璃字母則會像真實玻璃一樣彎曲圖片。在字母內部,photoInGlass 可以混合液態表面與圖片(--photo-in-glass,預設值 0.35;0 = 僅液體,1 = 僅顯示圖片的清澈玻璃)。當使用者想要 "我的照片上的清澈玻璃" 時使用 1,當他們希望液態字母突出時使用 0。

  • 著色器從 iChannel0 讀取圖片。除了 .glsl 之外,指令碼還會寫出 NAME.html:一個內建了著色器和圖片的頁面,在任何瀏覽器中雙擊即可即時執行。務必引導使用者使用這個檔案:Shadertoy 無法在沒有擴充功能的情況下載入他們自己的圖片。在此頁面中,拖放另一張圖片到頁面上會交換背景,按空白鍵可暫停,按 S 鍵可儲存 PNG。
  • iPhone 照片(HEIC)和超過 3 MB 的圖片會被轉換為最大 2048 像素的 JPEG(使用 macOS 的 sips)。
  • 過於繁忙的照片會使字母難以閱讀:如有需要,建議使用圖片中較平靜的區域、降低 --photo-in-glass 值,或使用更大的文字。

3. 建構字母的規則(管狀筆畫,僅限霓虹管模式)

字母由圓形玻璃管(霓虹風格)構成。每個字母完全由一個固定半徑 const float R = 0.15; 的筆畫組成:直線膠囊體與圓弧。每個字母和預設標記的每個筆畫都使用 R(單一線寬)。2D 距離後續會變成 3D 管狀(第 7.3 節)。

float sdCapsule(vec2 p, vec2 a, vec2 b, float r) {
    vec2 pa = p - a, ba = b - a;
    float h = clamp(dot(pa, ba)/dot(ba, ba), 0.0, 1.0);
    return length(pa - ba*h) - r;
}

// 沿圓弧的筆畫:中心 c,弧度半徑 ra,中間方向 `dir`
// (徑度,0 = +x 方向,PI/2 = 向上),半張角 `ap`(PI/2 = 半圓,PI = 整圓)。
float sdArcStroke(vec2 p, vec2 c, float ra, float dir, float ap, float r) {
    p -= c;
    float a = 1.5707963 - dir;                 // 旋轉使 `dir` 指向 +y
    p = mat2(cos(a), sin(a), -sin(a), cos(a)) * p;
    vec2 sc = vec2(sin(ap), cos(ap));
    p.x = abs(p.x);
    return ((sc.y*p.x > sc.x*p.y) ? length(p - sc*ra) : abs(length(p) - ra)) - r;
}

度量(字型單位,筆畫中心線):

  • 大寫字母與數字:基線 y = -0.85,大寫頂線 y = +0.85(墨水範圍 -1.0 到 +1.0)。
  • 小寫字母:x 高度 y = +0.15,上升部可達 +0.85,下降部可低至 -1.55。
  • 半寬度 hw(中心線):標準大寫 0.40,標準小寫與數字 0.35,寬字元(M W m w)0.60,窄字元(I i l j ! . , : ; ')0.0 到 0.15。每個字形以其自身的原點 x = 0 為中心。
  • 圓形字母(O C G D U S o c e …)為圓弧體育場形狀:由半圓弧與直線膠囊體連接而成。切勿非均勻縮放 p 來形成橢圓,因為這會破壞距離場。
  • 不支援的字元(非拉丁字母、表情符號):請告知使用者,而不是自行猜測。

參考字形(其他每個字元都應比照其風格):

float glyph_O(vec2 p) {
    float d = sdArcStroke(p, vec2(0.0,  0.45), 0.40,  1.5708, 1.5708, R);
    d = min(d, sdArcStroke(p, vec2(0.0, -0.45), 0.40, -1.5708, 1.5708, R));
    d = min(d, sdCapsule(p, vec2(-0.40, -0.45), vec2(-0.40, 0.45), R));
    d = min(d, sdCapsule(p, vec2( 0.40, -0.45), vec2( 0.40, 0.45), R));
    return d;
}

float glyph_A(vec2 p) {
    float d = sdCapsule(p, vec2(0.0, 0.85), vec2(-0.45, -0.85), R);
    d = min(d, sdCapsule(p, vec2(0.0, 0.85), vec2( 0.45, -0.85), R));
    d = min(d, sdCapsule(p, vec2(-0.29, -0.25), vec2(0.29, -0.25), R));
    return d;
}

// 小寫字母碗狀部分,由 a b d o p q g e… 共用
float bowl(vec2 p) {
    float d = sdArcStroke(p, vec2(0.0, -0.20), 0.35,  1.5708, 1.5708, R);
    d = min(d, sdArcStroke(p, vec2(0.0, -0.50), 0.35, -1.5708, 1.5708, R));
    d = min(d, sdCapsule(p, vec2(-0.35, -0.50), vec2(-0.35, -0.20), R));
    d = min(d, sdCapsule(p, vec2( 0.35, -0.50), vec2( 0.35, -0.20), R));
    return d;
}
float glyph_d(vec2 p) { return min(bowl(p), sdCapsule(p, vec2(0.35, -0.85), vec2(0.35, 0.85), R)); }

float glyph_i(vec2 p) {
    float d = sdCapsule(p, vec2(0.0, -0.85), vec2(0.0, 0.15), R);   // 主幹上升至 x 高度
    return min(d, length(p - vec2(0.0, 0.60)) - R);                 // 預設小點
}

4. 自訂點與重音符號(形狀整合,霓虹管模式;字型模式下由指令碼處理)

當套用標記編輯時(第 2 節):

  1. 建構不包含其標記的字母主體(例如 glyph_dotless_i,僅主幹部分)。
  2. 將形狀作為一個獨立的標記透過 MARK 巨集(第 6 節)加入,而不是放在字形內部。標記會進入它們自己的距離場,因為形狀會得到與管狀筆畫不同的 3D 輪廓(第 7.3 節)。
  3. 該形狀是來自 glsl-sdf-shapes 的 2D SDF,以原點為中心並適合 [-1, 1],精確縮放:sdfShape((p - pos) / sz),然後將其大小重整為標記的預設半徑。

Individual skills in this repo

This repo contains 1 individual skill — each has its own dedicated page.

相關技能