Community影像github.com

Three.js 程式生成材質貼圖

在 Three.js 中即時生成照片級、可無縫重複的程式化材質貼圖,無需任何圖片檔案。

Three.js 程式生成材質貼圖 是什麼?

這是一個專為 Three.js 設計的程式化材質生成庫,能即時產生高品質、可重複的貼圖,完全不需要外部圖檔。它支援多種平台(Claude Code、Cursor、Codex 等),核心優勢在於以物理單位(公釐)設計高度場,並將粗糙度與顏色分開處理,讓材質在光照下更具真實感。此技能提供多種現成材質,包括牆面、木地板、織物、使用痕跡(如灰塵、指紋、刮痕)及印刷品(書封、假文字)等。所有貼圖均透過 RNG(seed) 可重現,確保光照烘焙與回歸測試的一致性。其 API 直接回傳 Three.js 相容的貼圖物件,並具備接縫檢查與平均反照率計算功能,方便整合至光照烘焙流程。

相容平台✓Claude Code~Codex CLI~Cursor
npx skills add https://github.com/ammosu/claude-threejs-photoreal/tree/HEAD/skills/threejs-procedural-textures

Installed? Explore more 影像 skills: steipete/songsee, affaan-m/frontend-design, mattpocock/improve-codebase-architecture · View all 6 →

在你喜歡的 AI 中提問

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

說明文件

程式生成材質貼圖

來源:room-at-dawn(MIT),出自 src/core/tex.js、rng.js、src/scene/materials.js,以及 parts/ 底下各零件的材質函式。 原專案的臥室裡一張圖檔都沒有,所有貼圖都在載入時用程式生成。

核心想法:

  1. **用物理單位設計。**高度以公釐計,貼圖一格代表幾公尺都寫清楚,UV 也用公尺。這樣 repeat = 1 / tile公尺,換解析度也不會改變外觀。
  2. **大部分的「真實感」在粗糙度,不在顏色。**指紋、擦拭痕、積灰在顏色上幾乎看不出來,要等高光掃過才會顯現。
  3. **一律可以重複、可以重現。**雜訊都有週期,亂數一律走 RNG(seed),同一個 seed 每次產生的結果都一樣(光照烘焙、截圖回歸都靠這一點)。

檔案

路徑內容
scripts/tex.js基礎:RNG、pnoise/pfbm(每軸可以有不同週期)、worley、vn(查表的快速雜訊)、field、normalBytes(公釐單位)、dataTex/canvasTex/packTex/colorTex、avgColor、once(快取)、rep(共用圖片、只改 repeat)、seamScore、texData
scripts/surfaces.jswallNormal+wallPatch(木屑壁紙加上 3.2 m 尺度的灰泥與漆色變化)、lacquerNormal、smudgeRough、dustRough、floorMaps、woodMaps、oakVeneer
scripts/textiles.jsweaveNormal、waffleNormal、terryNormal、ribNormal、knitNormal、feltNormal、ropeNormal、fabricMaterial(sheen 加逆光透光)
scripts/wear.jswornMaps(一整面用過的表面:顏色與粗糙度兩張)、speckleTexture、scuffTexture,以及基本筆刷 softBlob、strand、fingerprint、noiseTile、overlay
scripts/print.jsword/phrase(用音節拼出的假字)、PAL、packer、fitText、paperGrain、makeBook+bookAtlas+bookGeometry、pagesTexture、topoPoster、photoPrints
example/房間一角,每個表面都用程式庫裡的一種材質。?cam=(room、desk、glint、fabric、floor、wall、books);?flat=1 換成純色對照
example/preview.jpg範例截圖
references/recipes.md每種材質的做法、尺寸、參數,以及怎麼自己加新的
references/verify-engines.md驗證方式、遇過的問題、效能,以及搬到 Godot/Unreal

跑範例

cd <skill 資料夾> && python3 -m http.server 5422 --bind 127.0.0.1
# 開 http://127.0.0.1:5422/example/   (window.__tex 有每張貼圖的生成時間、接縫分數、平均反照率)

(<skill 資料夾> 是載入這個 skill 時顯示的 Base directory;裝成 plugin 時位於 ~/.claude/plugins/cache/ 底下)

用法

import { rep } from './scripts/tex.js';
import { floorMaps, wallNormal, wallPatch, lacquerNormal } from './scripts/surfaces.js';
import { knitNormal, fabricMaterial } from './scripts/textiles.js';
import { wornMaps } from './scripts/wear.js';

const fl = floorMaps();                                   // UV 用公尺;repeat 已經設好
floor.material = new THREE.MeshStandardMaterial({ map: fl.map, normalMap: fl.normalMap, roughnessMap: fl.roughnessMap, roughness: 1 });
wall.material = wallPatch(new THREE.MeshStandardMaterial({ color: 0xebebe6, roughness: 0.93, normalMap: wallNormal() }));
door.material = new THREE.MeshStandardMaterial({ color: 0xdddddd, roughness: 0.6, normalMap: rep(lacquerNormal(), 9), normalScale: new THREE.Vector2(0.18, 0.18) });
sweater.material = fabricMaterial(0x6f7f6a, { normal: knitNormal(), tileM: 0.1 });
const w = wornMaps({ sizeM: [1.2, 0.6], hands: [[0.55, 0.5]], rings: [[0.9, 0.4, 0.032, 0.6]], prints: 6 });
deskTop.material = new THREE.MeshStandardMaterial({ map: w.map, roughnessMap: w.roughnessMap, roughness: 1 });
  • 有 roughnessMap 的材質,roughness 要設成 1。three.js 會把兩者相乘。
  • packTex 和 wornMaps 的粗糙度放在 G 通道,灰階 canvas 也可以直接用。
  • 每個材質都會回傳 avg(線性的平均顏色),給 threejs-baked-gi 當反彈光的反照率。

一定要遵守

  1. **不能用 Math.random()。**每張貼圖都要有固定的 seed。
  2. 雜訊的週期必須是整數,而且和貼圖的格數對齊(例如 pfbm(u*6, v*6, oct, seed, 6))。不對齊就會有接縫。要用 seamScore 檢查。
  3. **高度以公釐計,用 normalBytes(H, w, h, 每格公釐數)。**換解析度時凹凸的強度不會跟著改變;有些材質本來就不是方形格子(地板 1.1 × 1.9 mm),兩個軸要分開給。
  4. 粗糙度要和顏色一起畫。wornMaps 每一筆都同時畫進兩張 canvas,而且用同一個 new RNG(i),兩張的形狀才會對齊。
  5. 深色的表面,碎屑和亮點要減量(範例的深色桌面從 9000 降到 2500),不然看起來會像花崗岩。
  6. Canvas 畫的文字和圖案一律自己編(word()、幾何圖形),不要放真實的書名、品牌或商標。
  7. 最大的貼圖(2048²)建立需要 0.1–0.35 秒,同一張用 once 快取,再用 rep() 共用。不要每個物件各產生一次。

實測(RTX 4090、Chrome headless,範例整體 1.1 秒)

貼圖尺寸時間接縫分數 (x/y)
floorMaps2048² × 3 張0.32 s顏色 0.96/1.10、法線 1.00/1.02、粗糙度 0.89/1.05
woodMaps1024² × 30.20–0.23 s顏色 0.93/1.12、法線 1.30/1.06
wornMaps(1.2 × 0.6 m,3400 px/m)4080×2040+一半大小的粗糙度0.13 s不重複
oakVeneer1024² × 30.10 s0.98–1.06
wallNormal1024²0.04 s1.00/1.07
lacquerNormal、smudgeRough512²0.02–0.04 s0.98–1.04
織物 7 種128²–512²1–19 ms0.94–1.10(棉繩的 y 是 2.03,是刻意的溝,見 verify-engines.md)
bookAtlas(12 本)2048×15360.05–0.08 s—

接縫分數約等於 1 表示看不出接縫,大於 2 就要檢查。計算時分子分母各加 1 個色階,避免順紋木頭這類幾乎沒有起伏的方向,因為小於 1 個色階的雜訊而算出很大的比值。

Individual skills in this repo

This repo contains 3 individual skills — each has its own dedicated page.

threejs-photoreal-interior

用 three.js 從零做一個照片級的室內場景,完全用程式生成、不需要模型檔、貼圖或 HDRI 的總綱與起手式。內容包括:整體流程(尺寸與座標 → 外殼與窗 → 主角物件 → 材質 → 小物 → 烘焙光照 → 後製 → 驗證 → 電影輸出)、各步驟該用哪個 skill、跨 skill 整合的規則(決定性、細分、材質要經過 GI 補丁且保留原本的 shader 補丁、反照率、太陽直射與烘焙分工、陰影漏光)、一個指令就能建立可執行的新專案(房間、窗、木地板、牆面、桌椅、掛在椅背的毛巾、書架、杯子、水壺、現場烘焙、後製),以及驗收清單和實測數字。當使用者說「做一個寫實的房間/室內」「three.js 照片級場景」「程式生成整個場景」「不用模型做室內」「room-at-dawn 那種」「從哪裡開始做寫實 3D 場景」「開一個新的寫實場景專案」「把這些 skill 串起來」「寫實室內場景流程」時使用;做其中單一環節時,直接用對應的子 skill。

threejs-procedural-cloth

用程式「設計」出照片級的靜態布料(不做物理模擬):沒鋪好的棉被、毯子、桌巾、垂下床緣或桌緣的布、翻起一角的被子、布上放東西,以及掛在桿子上的窗簾(吊環夾出的折、往下鬆開與散開、綁起下擺、車線與雙層縫邊、亞麻平織)。方法是平面高度場(團塊+有方向的長折+削峰+逐條畫上的皺褶)→ 包到支撐物上 → 高的折往一側倒 → 翻角 → 依 3D 曲面攤平 UV → 細皺紋 normal map+凹處變暗,含可重用程式庫、分階段範例、驗證數據,以及搬到 Godot/Unreal 的做法。當使用者說「程式生成布料」「棉被/床單/毯子/桌巾建模」「布料皺褶」「布垂下床邊」「被子翻一角」「布料不要用模擬」「cloth without simulation」「procedural cloth」「布上的花紋被拉長」「布料看起來像塑膠/像山」「窗簾建模」「程式生成窗簾」「窗簾皺褶」「curtain」「布簾」時使用。

threejs-sky-backdrop

在 three.js 用程式做天空與窗外遠景,不需要 HDRI 或圖檔。天空的同一份參數同時用在三個地方:烘焙光照用的解析式天空、看得到的天空球(雲層、高空薄雲、地平線霧帶、太陽),以及不烘焙時用的太陽光、半球光與環境貼圖。內含四種預設(清晨、白天、陰天、黃昏)和一個量測工具,確認看到的天空和照亮場景的天空亮度一致。遠景部分包括:只建從室內窗戶看得到的東西(窗洞可見性與 LOD)、隨距離變淡的大氣霧化、遠處逐漸變粗的草地網格、碎石小路、樹籬、鄰居房子(陶瓦屋頂、窗戶、煙囪、天窗)、封住地平線的遠方樹牆,並可以搭配 threejs-procedural-vegetation 種樹。當使用者說「天空」「sky shader」「雲」「程式生成天空」「不用 HDRI」「窗外景色」「遠景」「背景房子」「地平線」「大氣透視」「霧化」「窗外的樹」「天空和光照對不上」「清晨/黃昏/陰天的天空」「只建看得到的東西」時使用。

相關技能