关于 threejs-procedural-materials
这是一项通过共享成因、材质身份和过滤微结构设计 Three.js 程序化 PBR 材质的技能。它指导开发者选择坐标与映射、配置 NodeMaterial 插槽,并管理动态状态、着色稳定性和验证。
主要功能
- 01将 PBR 通道追溯到共享成因
- 02根据缺陷和成本选择纹理映射
- 03将成因接入 NodeMaterial 插槽
- 04过滤法线与镜面反射响应
- 05管理动态状态和资源生命周期
- 06验证材质、阴影与颜色转换
适用场景
- 01构建 PBR 通道一致的程序化表面
- 02针对接缝或纹理重复选择映射
- 03稳定不同距离下的法线和镜面细节
- 04保持动态透明度与阴影一致
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ linegel/ threejs-complete-set-of-skill --skill threejs-procedural-materials安装后在 Claude Code 中输入/threejs-procedural-materials确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
LICENSEagents/openai.yamlexamples/filtered-height-normal.mjsreferences/procedural-pbr-system.md详细介绍
程序化材质
构建因果图,而不是一组通道效果:
stable coordinates -> structural causes -> identity weights
-> causal modifiers -> filtered microstructure
-> NodeMaterial PBR slots -> final-image owner
标准的不透明/发光 PBR 使用 MeshStandardNodeMaterial,只有当表面需要其额外波瓣或传输属性时才使用 MeshPhysicalNodeMaterial。通过赋值节点插槽,而不是替换整个片元输出,保留 Three.js 的光照、环境、阴影和能量处理。
对于多系统场景,$threejs-choose-skills 是可选的协调器。场负责共享标量/向量因果量,几何负责轮廓,水负责表面/传输,最终图像管线负责色调映射和显示转换。使用每个动态或跨系统因果量时,都要声明其单位、坐标/参考系约定、生产者和消费者归属、版本、空间/时间支持范围及滤波方式、有效域、误差界限、更新频率和过时规则。视觉材质状态不会因此成为另一个模拟归属方。
在分配存储、调度由计算着色器写入的因果贴图或编译基于存储的材质分支之前,先初始化并检查渲染器:
await renderer.init();
if (renderer.backend.isWebGPUBackend !== true) {
throw new Error('Native WebGPU is required for procedural material GPU branches.');
}
const { features, limits } = renderer.backend.device;
根据已初始化的特性和限制,选择采样/存储绑定、可写格式和滤波方式。
1. 固定坐标、因果量和身份
根据物理因果量或创作因果量,选择 UV、对象、世界、径向或生成纹理空间。以米或声明的美术单位记录尺度。只有在表示不同因果量时,混合空间才有效,例如在对象空间颗粒上叠加世界高度湿度。
定义归一化材质身份权重,并为每种身份指定响应束:
linear base reflectance
roughness alpha and metal/dielectric endpoint
resolved height/normal spectrum plus removed variance
causal modifiers such as wetness, wear, heat, or coverage
semantic/material ID and diagnostic color
所有通道都使用相同的滤波权重。硬性语义资格与可见混合宽度保持分离。当一个 GGX 波瓣近似亚像素混合时,混合 alpha=roughness^2,再通过 sqrt(alpha) 还原粗糙度。
涉及地形或海床时,在连接海岸距离、湿度、浅水、泡沫或焦散之前,先阅读底质与水的归属。
完成此步骤的标准:每个 PBR 通道都能追溯到同一坐标/尺度约定中的具名因果量和身份权重;任何零权重区域都有硬性语义回退。
2. 根据缺陷和成本选择映射方式
按以下顺序选择:
- 当接缝和纹素密度失真均达标时,使用 UV。
- 当图层具有相同的尺寸、格式、mip、颜色语义和采样器策略时,使用纹理数组。
- 当不满足数组约束且有明确归属的 mip 安全边距时,使用图集。
- 对于主导方向或顶面/侧面拆分,使用单轴/双轴投影。
- 只有在没有成本更低的参数化方式能保留尺度时,才使用三平面映射。
- 只有在观察到的缺陷是重复,而非参数化问题时,才使用随机平铺。
分别统计绑定数和实际执行的采样次数。已安装的 r185 triplanarTexture() 对每个绑定的纹理执行三次投影采样,并使用法线绝对值作为权重;它不会重新定向切线空间法线,也不提供随机平铺。数组/图集可减少绑定数,但不会减少采样次数。
在使用图集、纹理数组、三平面映射或随机平铺之前,请阅读 映射与滤波。
完成此步骤的标准:所选映射解决了观察到的缺陷;每种纹理的颜色/数据语义和 mip 策略都已明确;编译后的绑定/采样次数符合目标管线要求,且新增采样的价值经过了测量。
3. 将共享成因接入 NodeMaterial 插槽
仅管理材质所需的插槽:
colorNode linear identity color and causal shifts
roughnessNode identity alpha plus filtered modifiers
metalnessNode conductor/dielectric identity
normalNode normalMap, texture bump, or shared-height gradient
aoNode local cavity/contact term
opacity/mask/alphaTest cutout or dissolve
emissiveNode actual scene-linear emitted radiance
positionNode visible local displacement
castShadowPositionNode matching caster displacement
castShadow/maskShadow matching cutout or dissolve
在 r185 中,receivedShadowPositionNode 是独立的世界空间接收器覆盖项;除非明确推导并验证了替代方案,否则应将其留空。可见位移和投射阴影位移共用一个局部空间成因。发光输入 HDR 材质结果;泛光和色调映射仍由下游负责。
数据纹理使用 NoColorSpace;编码为 sRGB 的颜色使用 SRGBColorSpace,而线性 sRGB HDR 使用 LinearSRGBColorSpace。其他颜色编码需要使用其声明的转换;创作时指定颜色空间并不意味着就是 sRGB。通过 RenderPipeline.outputColorTransform 或一次 renderOutput(),确保最终输出转换只有一个负责者。
当每个受管理的插槽都有一个成因、可见/阴影遮罩与位移保持一致、颜色/数据编码正确,且没有材质节点重复执行最终输出转换时,此步骤即告完成。
4. 过滤微结构与镜面响应
在扰动法线之前,先过滤高度/法线频带。片元表面梯度须在导数一致的控制流中计算;顶点/计算位移使用解析梯度或存储的梯度。在各级 mip 中保留法线均值及方差,而不是将均值归一化后丢弃其长度。
Three.js r185 已在 getRoughness() 中加入几何法线变化。自定义镜面抗锯齿只添加尚未解析的材质细节方差。添加程序化凹凸、自定义法线过滤或粗糙度方差前,请先阅读导数法线与镜面抗锯齿。
当标量程序化高度同时用于法线细节和镜面抗锯齿时,请阅读过滤高度法线示例。根据完整的变形后 Jacobian 谱范数提供无量纲的 footprintCyclesPerSample、以每个长度单位的周期数表示的物理支撑频率,以及围绕所提供均值的正频带半宽。heightHalfAmplitude 使用与表面相同的长度单位。它将衰减、移除的斜率方差、双面表面的梯度法线处理以及 roughness^2 扩宽整合到一条因果路径中。字面量输入会按 f32 精度检查;动态节点需要通过等效的生产端准入检查。退化的表面坐标系会返回基础法线和 normalValid=false,而不是对零向量归一化。验证条件数下限,并确保完整的导数路径保持一致。
当所有保留的频带都通过投影足迹检查、移除的斜率/法线方差只被计入一次,且无后期处理的近/中/远距离对比能够排除随距离变化的锐化和掠射角闪烁时,此步骤即告完成。
5. 自主管理动态状态和实例级状态
一个材质图服务一个批次。静态实例差异使用属性;只有在实测更新/访问模式更有优势时,才使用存储缓冲支持的实例数据来实现由 GPU 负责的高频变化。溶解、湿润度、变体或生命周期字段会根据同一稳定的对象/世界原因驱动可见遮罩和阴影遮罩。内置阴影重写不会自动复制动态不透明度/alpha 测试节点;请使用参考中介绍的共享布尔遮罩路径。替换材质节点图时,通过设置 material.needsUpdate = true 使 material.version 失效,以便重建缓存的投射体路径。
原因映射遵循程序化字段的直接计算与烘焙判定。静态映射只构建一次;动态映射按其所有者的更新频率更新,并使依赖的 mip 失效。计算任务的提交先于其消费渲染。在 r185 中,computeAsync() 不是 GPU 完成栅栏。
状态代次在被帧引用期间保持不可变。调整大小、材质标识变化、坐标变化、映射编码变化和设备丢失都会使依赖的历史记录、绑定和诊断信息失效。每种材质、纹理、存储资源和生成的变体都必须有明确的释放负责人。
满足以下条件即表示此步骤完成:每个动态原因都由一个负责人推进,每条实例记录都具有稳定的标识和重置行为,而且无需逐对象克隆材质或执行影响帧关键路径的 CPU 回读。
6. 诊断与验证
公开坐标模式/比例、标识权重与回退、每种结构性原因、映射权重/mip/边缘留白、绑定和采样次数、抗锯齿前后的粗糙度、法线均值/方差、可见物与投射体的一致性、原始自发光、未应用后期处理的美术效果,以及最终后期处理结果。
验证近景/中景/远景和运动视图;导体/电介质端点;所选滤波下的图集边缘留白;编译阶段限制;色彩空间标志;稳定的实例/阴影行为;以及在声称性能时的目标整帧耗时/字节数。
满足以下条件即表示此步骤完成:每种 PBR 标识、映射分支、滤波法线分支、动态状态、阴影路径、颜色转换、资源生命周期,以及声称的目标预算,都有直接的诊断证据。
完成
满足以下条件即表示材质系统完成:一个共享的原因/标识图为所有自主管理的 PBR 槽提供数据;映射与滤波决策有证据支持;材质细节在不同覆盖范围和运动下保持稳定;动态状态只有一个负责人和重置路径;原始材质输出、阴影、后期处理和资源生命周期彼此一致。