mcpField
3
3d-wood-material

3d-wood-material

github.com/mengtoクリエイティブ・メディア7.1k353 回インストール3 日前に更新
リポジトリ

3d-wood-material について

Three.js シーン向けのプロシージャルな木材マテリアルを作るスキルです。共有ノイズ場から木目、導管、繊維、放射組織、色、粗さ、凹凸を生成し、樹種やオイル、ワックス、漆の仕上げをパラメーターで調整できます。

主な機能

  1. 01木目と年輪のプロシージャル生成
  2. 02導管、繊維、放射組織の表現
  3. 03木目に連動する粗さと凹凸
  4. 04樹種と仕上げのパラメーター化
  5. 05画面上の細かさに応じたディテール低減

活用シーン

  1. 01木製モデルのプロシージャルな表面作成
  2. 02木口と異なる木目方向の表現
  3. 03オイル、ワックス、漆仕上げの適用

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/mengto/skills --skill 3d-wood-material

インストール後、Claude Code で/3d-wood-materialを入力して読み込まれたか確認します。

同梱ファイル

SKILL.md と一緒にインストールされる参考資料やスクリプト。

demo.html
PROMPT.md
agents/
openai.yaml

詳細

3D 木材マテリアル

仕組み: 小さな周期ノイズフィールドをミップフィルタリングし、フラグメントシェーダー内で伸縮率とスケールを変えて複数回サンプリングします。これにより、年輪の位置、晩材、導管、繊維、放射組織、加工痕がすべて同じ揺らぐ木目から生成され、色、粗さ、凹凸に連動して反映されます。それぞれの要素は、画面上で占める範囲に応じて個別にフェードアウトします。

適用範囲。本スキルが扱うのは、木材の表面そのものです。シーン全体の照明、木目を際立たせるライティング、採点用の木材レンダリングには、3d-wood-lighting-scorecard を使用してください。画像ベースの PBR セット(ダウンロードしたマップ、テクセル予算、KTX2 での配布)には、3d-high-resolution-textures を使用してください。写真またはスキャンに基づく樹種が必要な場合は、こちらを選んでください。シルエット、ベベル、LOD ジオメトリには、3d-high-poly-models を使用してください。このスキルで必要なのは、以下で説明する丸みを付けた稜線だけです。布、金属、紙には、それぞれ専用の関連スキルがあります。

まず demo.html を実行してください(木彫りの作業台、4 種類の樹種、4 種類の仕上げ、マクロ表示、失敗例に切り替えるスイッチを用意しています)。PROMPT.md で同じデモを再現できます。

レシピ

  1. 置き換えずにパッチを適用します。 MeshPhysicalMaterial({color:0xffffff, roughness:max(0.43,r), ior:1.43, specularIntensity:0.72}) を作成し、onBeforeCompile で編集します。#include <map_fragment> では diffuseColor に木材の色を乗算し、#include <roughnessmap_fragment> では roughnessFactor=clamp(roughness*W.rough,0.35,1) を設定し、#include <normal_fragment_maps> では木材の高さ W.h によるスクリーンスペースのバンプで法線を置き換えます。ライティング、シャドウ、IBL、トーンマッピングは標準のままにします。頂点ステージではオブジェクト空間の位置 vOP とオブジェクト法線だけを渡します。
  2. フィールドを1つだけベイクします。 周期的なグラデーションノイズを描画する、1024² の RepeatWrapping、LinearMipmapLinear、NoColorSpace のレンダーターゲットを用意します(周期64、3オクターブ:.r はベース、.g は fbm 0.60/0.27/0.13、.b はずらしたコピー)。texture(p/64) として読み取るため、サンプリングは1回で済みます。すべての木材でこれを共有し、板ごとの差はテクスチャではなくシードのオフセットで付けます。
  3. 木目の軸。 uAxis の0/1/2で丸太の軸を選びます。along はその座標、cross2 は残りの2座標です。endgrain = pow(|n·axis|, 6) により、導管を筋から開いた細胞へと切り替え、木口面の色をくすませます。
  4. 年輪。 2つの緩やかなフィールドで髄をずらし、radius=|(cross2+(-drift, offAxis+0.48))*(1,0.56)|、growth=radius*ringFreq に fbm の揺らぎ(年輪±1.25本分)を加え、ring=floor(growth)、phase=fract とします。各年輪の幅は annual ノイズから取り、lateWidth=0.065+annual*0.21 とします。晩材は急峻な smoothstep(0.94-w, 0.97-w, phase) で描き、1-smoothstep(0.965,1,phase) でカットオフします。小さな offAxis は扇形の木目、大きな offAxis は柾目の直線を生みます。
  5. ディテールの各レイヤーは、それぞれのフットプリント(growth の fwidth、導管・繊維・虎斑の座標の length(dFdx,dFdy))に応じてフェードさせます。
レイヤー座標強度
導管(道管)(fiberX*96, along*7.5)、木口では cross2*88 の細胞、smoothstep(0.59,0.75)色調 +0.25、粗さ +0.19、高さ -0.42
繊維(fiberX*230, along*2.4)色調 -0.16、高さ +0.09、木口では x0.25
虎斑(across*13, along*115)、smoothstep(0.64,0.78)淡色方向に色調 +0.26、粗さ -0.075
ひびcurl.b smoothstep(0.70,0.82) x uChecksdark*0.68 に向けた色調、高さ -0.20
節ハッシュセル 1.85 x 4.6、占有率29%、影響はセルの縁で消失芯の色調 +0.44、繊維を偏向
加工痕(along*17, across*0.4)高さ +0.045 x uTool
  1. 色調:tone=0.075+late*0.40+early*0.070+pores*0.25-fibres*0.16+(broad.g-0.5)*0.23+knotCore*0.44、色は mix(pale,dark,clamp(tone,0.035,0.83)) とし、その後 *(0.93+annual*0.095+…) を適用します。粗さは 0.91+late*0.13+pores*0.19+(broad.b-0.5)*0.20-rays*0.075+endgrain*0.14 です。
  2. 法線マップではなくバンプを使います。 bumpNormal は微分ベースの Mikkelsen バンプを使用し、勾配を 0.38*|det| にクランプするため、急峻な段差でも法線が反転しません。uBump=bump*0.020 とします。
  3. 仕上げはテクスチャではなくパラメーターです。 無塗装:clearcoat 0。オイル:pow(rgb,1.16) と rough*0.88、clearcoat 0.10 / 0.55。ワックス:clearcoat 0.22 / 0.38。漆:輝度カーブ pow(l,0.5)、木口を暗くする *(1-eg*0.55)、暖色の色味、摩耗した稜線は淡色へ擦り戻し、clearcoat 0.42 / 0.40。
  4. 稜線を丸めます。 すべての板に chamferBox を適用し、半径は min(w,h,d)*0.055(各辺の最大0.24)、分割数は3~5とし、丸めた角から法線を設定します。箱の鋭いエッジにはハイライトがなく、切り抜いたように見えます。
  5. 板ごとに異なるシードを割り当てます。 樹種や仕上げを変更してもシードが安定するようにします(ビルド中は woodMaterialSerial を保存して復元し、シードには n*7.113 を使います)。ジオメトリをフィールド内でオフセットします(woodBox(..., ox,oy,oz))。これにより、マージ済みのマテリアルや共有マテリアルでも板ごとの差が生まれます。

種類ごとの定数(ワークショップより)

種類明色 / 暗色粗さ木目ringFreqoffAxis備考
keyaki#8a5f38 / #3d24120.621.520 to 340.75放射組織 0.35、バンプ 0.10
sugi#c8a579 / #9b774d0.581.88 to 302.8晩材の輪郭は鮮明、ツール 0.30
hinoki#d8c096 / #8a6b400.44 to 0.502.26 to 421.6木目が細かく、コントラストは低い
kuri#6f4d2c / #2c1a0b0.553.05 to 221.4放射組織 0.5、干割れ 0.10
焼杉#1a1511 / #0e0b080.970.890.55放射組織 0、干割れ 0.30

ringFreq はモデルの単位あたりの値です。そのため、シーン間で数値をそのままコピーするのではなく、実際の年輪間隔(モデリングしているスケールで約 2〜5 mm)に合わせて設定してください。ワークショップの 7〜8 はデモのスケールでは太い縞模様に見え、20〜42 に上げる必要がありました。

よくある失敗と対処法

  • 2枚目の板にタイルの繰り返しが見える。 repeat を使ったキャンバスタイルでは、すべての板に同じ年輪が描画され、斜光で継ぎ目が見えます。オブジェクト空間の位置をサンプリングし、マテリアルごとにシードを設定し、フィールドを通じてジオメトリにオフセットを加えてください。
  • 粗さが一定だとプラスチックのように見える。 粗さは木目に合わせて変化させる必要があります。道管は粗め(+0.19)、晩材はやや粗め(+0.13)、放射組織は光沢を強めます(-0.075)。一律に 0.3 を指定すると、年輪に沿った変化のない、均一で明るい光沢になります。
  • 色だけで凹凸がない。 アルベドに年輪を描くだけでは、斜光で平坦に見えます。同じ late、pores、fibres を高さに反映してバンプを加え、勾配をクランプしてください。そうしないと、年輪の鋭い境界で法線が反転します。
  • 木目が形状に沿わない。 along は UV ではなく、部材の実際の軸から取得してください。面取りした箱で UV を使うと、丸みのある縁で道管が引き伸ばされ、板が縞模様のテストパターンのようになります。オブジェクト空間でサンプリングすれば、木目は角をまっすぐに通り、木口では道管が自動的に細胞に切り替わります。
  • 遠距離や斜めの面でディテールがちらついたり、這うように動いたりする。 高周波の各レイヤーは、それぞれの画面上のフットプリントに応じてフェードさせる必要があります。x *= 1 - smoothstep(a, b, fwidth-of-its-coordinate) とします。フィールドにミップマップを適用し、fwidth(growth) が 0.16..0.72 を超えたら late と early を平均値にブレンドしてください。これを行わないと、3 m 離れた位置で年輪が板の壁面にモアレ状に現れます。
  • マクロ表示がぼやけたり、塊状になったり、凹凸にかすかな正方形の格子が見えたりする。 grain 1.0 のとき、1024² フィールドを 1 単位あたり約 2,500〜4,000 px を超えて拡大しています。バイリニア補間のテクセル境界がバンプの微分に格子状のノイズとして現れ、道管セルがぼやけ、年輪の境界が点状になります。より細かい繊維サイズになるよう uGrainScale を上げるか、目立つ面ではベイク解像度を 2048 に上げてください。メッシュをリスケールしてはいけません。
  • 色空間の指定ミス。 フィールドはデータなので、sRGB ではなく NoColorSpace を指定します。トーンマッピングは最後に一度だけ適用します(ワークショップでは手書きの最終パスで適用し、デモでは ACESFilmicToneMapping を使用しています)。
  • オイル仕上げが無塗装面として照らされる。 extra スニペットだけが異なるマテリアルは、1つのプログラムキャッシュキー(onBeforeCompile.toString())を共有します。そのため、2つ目のマテリアルでは1つ目のプログラムが何も通知されずに再利用されます。仕上げごとに異なる customProgramCacheKey を設定してください。Urushi ラッパーではこれを行っています。
  • 環境光で粗さの変化が見えない。 scene.environment だけが設定されている場合、envMapIntensity は無視されます(r163 以降)。scene.environmentIntensity を使用してください。木の粗さマップを見せるには、PMREM に明るい窓のカードが必要です。灰色のドームでは見えません。
  • 切断面が上面と同じように見える。 切断面に 1 - endgrain*(0.045+pores*0.10) を乗算し、粗さを +0.14 上げてください。木口は仕上げ材をよく吸い込み、つや消しの状態を保つため、これが無垢材だと見分ける最も手早い手掛かりになります。
  • 角の鋭い板が浮いて見える。 面取りも接地影もない箱は、貼り付けたように見えます。各部材を支持面にぴったり接するように置き(y = h/2)、シャドウマップを一度だけベイクして(shadowMap.autoUpdate=false)、クローズアップで隙間がないか確認してください。

パフォーマンス予算

  • ミップマップ付きの 1024² RGBA8 テクスチャを一度だけベイクし、すべての木材で共有します(GPU メモリ使用量は約 5.6 MB)。
  • この Apple GPU でヘッドレス Chrome を使って測定した結果、MSAA を有効にした状態で、面取りしたボックス、ベンチ、壁の合計 13 ドローコール、約 2,000 トライアングルでは、1440×900 でフレームあたり 1.0〜1.5 ms、2880×1800 で 3.4〜4.5 ms でした。一方、単純なタイル状の MeshStandardMaterial は、それぞれ 0.65 ms と 4.2 ms でした。このシーンではプロシージャルシェーダーのコストは 1x で約 0.4 ms で、2x ではフィルコストに埋もれます。負荷を左右するのはフィルレート(DPR、MSAA)であり、ノイズではありません。
  • DPR は 2 に制限します。板材が静止している場合は、シャドウを一度だけベイクします。document.hidden の間は一時停止し、クロックをリセットします。dt は 1/30 秒に制限します。
  • prefers-reduced-motion が有効な場合は、ゆっくりしたオービットを省略して、カメラ移動を瞬時に切り替えます。静止画は構成済みのヒーロービューです。コントロールは引き続き操作できます。

このマテリアルの自己評価(0〜10、基準付き)

基準:2 はラフネスが一定のタイル状写真。4 はアルベドのみのプロシージャルな縞模様。6 は年輪とレリーフがあり、腕を伸ばした距離では問題ありません。8 は細孔、放射組織、木口が 5 cm の距離でも見え、塗装と摩耗が本物らしく、ちらつきません。10 はどの距離でも樹種を判別できるスキャン写真です。

項目評価理由
腕を伸ばした距離での木目構造7.5年輪の幅、弧状の木目、節があります。デフォルト設定ではケヤキの木目がやや定規で引いたように見えます
マクロ(3〜5 cm)6.5細孔、繊維、工具跡を確認できます。1024² のテクスチャは、1 単位あたり 4,000 px を超えるとぼやけます
ラフネスと仕上げ7.5オイル、ワックス、漆が年輪や細孔に応じて変化します。異方性ハイライトはありません
木口とエッジ7開いた細胞とつや消しの切断面があります。稜線は丸めていますが、実際のエッジ摩耗はありません
ちらつきと斜めからの見え方8フットプリントのフェードにより、斜めから見た場合も遠距離でもきれいに表示されます
総合7.3

出典

木彫工房のページから抜粋しました。そこでは、1 つの woodMat() 木材シェーダーで壁、ベンチ、工具の柄、組子格子、漆塗りの箪笥を装飾しています。demo.html のジェネレーターは、そのファイルから変更せずにコピーしたものです。木材は近距離での鑑賞用カメラに合わせて調整されているため、上記の定数はすべて工房独自のものです。

コメント