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 木材材质

**机制:**片元着色器会在不同拉伸程度和尺度下读取同一个经过 MIP 过滤的小型周期性噪声场,因此环纹位置、晚材、孔隙、纤维、射线和刀痕都来自同一片蜿蜒的纹理,并共同影响颜色、粗糙度和浮雕效果,各自按照对应的屏幕占用范围逐渐淡出。

适用范围。本技能仅涉及木材表面。要处理整场景光照、射线和木材渲染评分,请使用 3d-wood-lighting-scorecard。对于基于图像的 PBR 贴图集(下载的贴图、纹素预算、KTX2 交付),请使用 3d-high-resolution-textures;需要照片或扫描的木材种类时,也应使用它。要处理轮廓、倒角和 LOD 几何体,请使用 3d-high-poly-models;本技能只需要圆钝的棱边(见下文)。布料、金属和纸张各有对应的同类技能。

先运行 demo.html(Kibori 工作台、四种木材、四种表面处理、宏观视图,以及可切换为失效效果的开关)。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. 烘焙一个场。 将周期梯度噪声渲染到一个 1024² 的 RepeatWrapping、LinearMipmapLinear、NoColorSpace 渲染目标中(周期为 64,三个八度:.r 为基础值,.g 为 fbm 0.60/0.27/0.13,.b 为偏移副本)。读取时使用 texture(p/64),只需一次采样。所有木材共用它;木板间的差异通过种子偏移实现,而不是使用不同纹理。
  3. 木纹轴。 uAxis 的 0/1/2 分别选择木轴;along 是该坐标,cross2 是另外两个坐标。endgrain = pow(|n·axis|, 6) 会让导管从条纹翻转为开放细胞,并使端面颜色变暗。
  4. 年轮。 用两个缓变场让髓心漂移,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,端面处乘以 0.25
木射线(across*13, along*115),smoothstep(0.64,0.78)色调向浅色偏移 +0.26,粗糙度 -0.075
裂纹curl.b smoothstep(0.70,0.82) 乘以 uChecks色调向 dark*0.68 偏移,高度 -0.20
节疤哈希单元尺寸为 1.85 x 4.6,占比 29%,影响在单元边缘处消失核心色调 +0.44,使纤维偏折
工具痕迹(along*17, across*0.4)高度 +0.045 乘以 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 才合适。

常见问题及解决方案

  • 第二块木板上出现重复的纹理图块。 使用 repeat 的画布图块会在每块木板上绘制相同的年轮,并在掠射光下显出接缝。采样物体空间中的位置,为每种材质设置不同种子,并通过纹理场偏移几何体。
  • 平坦的粗糙度看起来像塑料。 粗糙度必须随木纹变化:导管更粗糙(+0.19),晚材略粗糙(+0.13),木射线更光滑(-0.075)。固定为 0.3 会产生均匀明亮的光泽,年轮上也不会出现变化。
  • 只有颜色,没有凹凸。 只在反照率中绘制的年轮,在掠射光下会显得平坦。将相同的 late、pores 和 fibres 输入高度并添加凹凸;同时限制梯度,否则年轮边缘过硬会导致法线翻转。
  • 木纹没有顺着形体延伸。 从构件的实际轴线获取 along,不要从 UV 获取。在带倒角的方盒上使用 UV,会使圆角处的导管拉伸,并让木板变成条纹测试图。使用物体空间采样时,木纹会直穿角部,端面也会自动将导管切换为细胞。
  • 细节在远处和掠射面上闪烁或爬动。 每个高频层都必须根据自身的屏幕覆盖范围淡出:x *= 1 - smoothstep(a, b, fwidth-of-its-coordinate)。对纹理场生成 mipmap;当 fwidth(growth) 超过 0.16..0.72 时,将 late 和 early 混合到各自的平均值。否则,年轮在 3 m 处会在木板表面产生摩尔纹。
  • 大尺度纹理看起来模糊、团块状,或凹凸上出现淡淡的方格网格。 当 grain 1.0 时,1024² 纹理场被放大到每单位约 2,500 到 4,000 px 以上。双线性纹素边缘会渗入凹凸导数,形成网格;导管细胞会变软,年轮边缘也会在边界处呈点状。提高 uGrainScale 以缩小纤维尺寸,或将烘焙分辨率提高到 2048,以用于重点表面;切勿通过缩放网格来解决。
  • 色彩空间错误。 纹理场是数据,应使用 NoColorSpace,而非 sRGB。色调映射只在最后应用一次(工作坊会在手写的最终渲染阶段执行;演示使用 ACESFilmicToneMapping)。
  • 油饰面材质却使用了原始饰面着色。 只在 extra 片段上不同的材质会共用一个程序缓存键(onBeforeCompile.toString()),因此第二种材质会悄悄复用第一种材质的程序。为每种饰面设置不同的 customProgramCacheKey;Urushi 包装器已这样处理。
  • 环境光没有呈现粗糙度变化。 仅设置 scene.environment 时,envMapIntensity 会被忽略(r163+);请使用 scene.environmentIntensity。木材需要在 PMREM 中加入明亮的窗户卡片,才能显示粗糙度贴图;灰色穹顶会将其隐藏。
  • 切面看起来和顶面一样。 将切面乘以 1 - endgrain*(0.045+pores*0.10),并将其粗糙度提高 +0.14:端纹会吸收饰面并保持哑光,这是最快判断材料为实木块的线索。
  • 锐利的木板看起来像浮着。 没有倒棱且没有接触阴影的方盒看起来像是贴上去的。让每个部件准确放在支撑物上(y = h/2),烘焙一次阴影贴图(shadowMap.autoUpdate=false),并检查特写视图中是否存在间隙。

性能预算

  • 烘焙一次,使用带 mipmap 的 1024² RGBA8(约占用 5.6 MB GPU 显存),供所有木材共用。
  • 在这块 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 s。
  • 对于 prefers-reduced-motion,跳过缓慢环绕并让摄像机移动时直接跳转;静止画面就是构图完成的主视觉。控件仍可使用。

本材质的自评分(0 至 10,基于以下标准)

标准:2 分,平铺照片,粗糙度均一。4 分,程序化条纹,仅有反照率。6 分,带年轮、浮雕和变化的粗糙度,近距离观察效果良好。8 分,孔隙、射线和端面木纹在 5 cm 处仍清晰,涂层和磨损效果可信,且无闪烁。10 分,任何距离下都像扫描得到的树种照片。

维度评分原因
近距离的木纹结构7.5年轮宽度、拱形纹理和节疤各不相同;默认静止画面中的 keyaki 仍略显规则
微观细节(3 至 5 cm)6.5孔隙、纤维和工具痕迹都清晰可见;当每单位超过 4,000 px 时,1024² 纹理会变模糊
粗糙度和涂层7.5油、蜡和 urushi 会随年轮和孔隙呈现不同效果;没有各向异性高光
端面木纹和边缘7开放的细胞结构和哑光切面;倒角圆润,但没有真实的边缘磨损
闪烁和掠射角表现8足迹淡出效果干净,掠射角和远距离观察效果也很干净
总分7.3

来源

提取自 Kibori 木彫工坊页面,其中一个 woodMat() 木材着色器用于墙壁、长凳、工具手柄、kumiko 格栅和漆器箱;demo.html 中的生成器原样复制自该文件。木材针对近距离观察摄像机进行了调校,因此以上所有常量均为工坊原有设置。

评论

支持 Markdown