ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

three.js Node 材质解析:MeshBasicNodeMaterial 无光照材质与着色器节点构建原理

three.js Node 材质解析:MeshBasicNodeMaterial 无光照材质与着色器节点构建原理 three.js Node 材质解析MeshBasicNodeMaterial 无光照材质与着色器节点构建原理【免费下载链接】three.jsJavaScript 3D Library.项目地址: https://gitcode.com/GitHub_Trending/th/three.jsMeshBasicNodeMaterial 是 three.js 新一代 Node 材质体系中 MeshBasicMaterial 的节点化实现它把“不受光照影响的纯色/贴图材质”以 TSLThree Shading Language节点图的形式接入渲染管线最终在 WebGL/WebGPU 后端编译成对应的着色器。本文以 MeshBasicNodeMaterial.html 官方文档 为骨架结合其 源码实现 与若干配套节点源码讲解它的继承关系、构造方式、特殊属性以及五个被重写的着色器构建钩子方法——读完即可理解“无光照材质在节点化管线中如何被表述、如何接入烘焙光照与环境贴图”并能在自己的 WebGPU 项目中直接使用。一、类在继承体系中的位置MeshBasicNodeMaterial 的完整继承链为EventDispatcher → Material → NodeMaterial → MeshBasicNodeMaterial文档开头的*Inheritance: EventDispatcher → Material → NodeMaterial →*说明它是 NodeMaterial 基类 的直接子类。它位于节点材质家族中与 MeshLambertNodeMaterial、MeshStandardNodeMaterial 等并列全部从 NodeMaterials.js 统一导出export { default as MeshBasicNodeMaterial } from ./MeshBasicNodeMaterial.js; // ... 以及其他十几种 Node 材质而 Three.WebGPU.Nodes.js 又通过export * from ./materials/nodes/NodeMaterials.js将整组材质暴露出去因此在实际项目里可以直接从three/webgpu导入import { MeshBasicNodeMaterial } from three/webgpu;从类的static get type()可看到其类型标识为字符串MeshBasicNodeMaterial源码 MeshBasicNodeMaterial.js用于材质序列化/克隆时的类型还原。二、构造器与参数语义文档定义new MeshBasicNodeMaterial( parameters : Object )—— 传入一个包含材质属性的配置对象构造一个新的网格基础节点材质。构造实现源码 MeshBasicNodeMaterial.js做了三件事super(); this.isMeshBasicNodeMaterial true; this.lights true; this.setDefaultValues( _defaultValues ); // 用 pristine 的 MeshBasicMaterial 实例补全默认值 this.setValues( parameters ); // 应用用户传入参数其中_defaultValues是一个模块级缓存的new MeshBasicMaterial()实例源码 MeshBasicMaterial.jssetDefaultValues()会把这套“经典材质默认值”批量搬进节点材质。这意味着MeshBasicMaterial 的全部外观属性都天然可用主要包括参数类型/默认值说明colorColor默认0xffffff漫反射材质本体颜色mapTexture默认null颜色贴图与color相乘建议SRGBColorSpacelightMap/lightMapIntensityTexture/1.0烘焙光照贴图需第二套 UV通常 float 格式/LinearSRGBColorSpaceaoMap/aoMapIntensityTexture/1.0环境光遮蔽贴图取红通道非颜色数据specularMapTexture默认null高光贴图本材质中用于控制环境贴图强度alphaMapTexture默认null灰度透明贴图envMap/envMapRotationTexture/Euler(0,0,0)环境贴图及其旋转combineMultiplyOperation默认/MixOperation/AddOperation表面色与环境贴图的混合方式reflectivitynumber默认1环境贴图影响强度与specularMap相乘refractionRationumber默认0.98折射率比值折射类 envMap 使用wireframeboolean默认false是否以线框渲染fogboolean默认true是否受雾影响因此使用方式与经典材质几乎一致const material new MeshBasicNodeMaterial( { color: 0x049ef4, map: colorTexture, wireframe: false } );三、两个关键属性.isMeshBasicNodeMaterial : boolean只读类型测试标志默认true。由于 ES6 的instanceof跨副本/多版本场景可能失效three.js 统一采用这种鸭子类型判断。例如 examples/jsm/inspector/extensions/tsl-graph/TSLGraphEditor.js 中用它判断材质种类并返回material/basic分类if ( material.isMeshBasicNodeMaterial ) return material/basic;.lights : boolean默认true文档强调基础材质按定义是不受光照的unlit但这里仍置为true因为节点化实现要用一套照明模型去计算片元着色器的出射光。它与普通属性布尔开关不同——它直接决定 NodeMaterial 基类setupLighting()内部是否走“照明上下文”分支当lights true且渲染器启用了 lighting 时会调用setupMaterialLightings()收集环境、光照贴图、AO 节点并经过lightingContext与材质自己的照明模型共同计算出射光。该属性覆写自NodeMaterial#lights默认 false。四、五个被覆写的构建钩子方法NodeMaterial 的着色器不是手写 GLSL而是通过setup*系列方法在构建期动态组装 TSL 节点。MeshBasicNodeMaterial 精准覆写了以下五个方法正好对应它“unlit 但有环境/烘焙光参与”的特殊身份1.setupNormal() : Nodevec3返回法线节点。因为基础材质不受法线贴图与凹凸贴图影响它直接返回默认的normalViewGeometry视图空间几何法线。源码 MeshBasicNodeMaterial.js 额外用negateOnBackSide()包裹并注释引用了 issue #28839背面剔除几何的法线修正setupNormal() { return negateOnBackSide( normalViewGeometry ); // see #28839 }对比基类默认实现this.normalNode ? vec3( this.normalNode ) : materialNormalNodeMaterial.js可见基础材质“跳过法线贴图采样”这一语义是刻意为之。2.setupEnvironment( builder : NodeBuilder ) : BasicEnvironmentNode.vec3实现默认的环境映射。它先调用super.setupEnvironment( builder )基类逻辑会检查用户是否显式传入envNode否则回退到envMap引用见 NodeMaterial.js再把结果包进BasicEnvironmentNodesetupEnvironment( builder ) { const envNode super.setupEnvironment( builder ); return envNode ? new BasicEnvironmentNode( envNode ) : null; }BasicEnvironmentNode 是非 PBR 材质如 MeshBasicNodeMaterial、MeshPhongNodeMaterial专用的 IBL 环境节点cubeMapNode()把立方体/等距柱状环境贴图转成采样节点并写入builder.context.environment供照明模型的finish()阶段消费。若没有 envMap则返回null环境节点是可选的。3.setupLightMap( builder : NodeBuilder ) : BasicLightMapNode.vec3光照贴图烘焙的间接光照必须以特殊缩放因子参与计算因此要覆写。实现与基类差异一目了然// MeshBasicNodeMaterial子类 setupLightMap( builder ) { let node null; if ( builder.material.lightMap ) { node new BasicLightMapNode( materialLightMap ); } return node; }基类版本返回的是IrradianceNodeNodeMaterial.js而这里换成 BasicLightMapNode。两者的核心差异在 BasicLightMapNode 的setup()中它会乘以1 / Math.PIRECIPROCAL_PI后再写入builder.context.irradianceLightMap这是因为基础材质用 Lambert 式的漫反射辐射度语义评估烘焙贴图。4.setupLightingModel() : BasicLightingModel返回本材质的照明模型。覆写自基类的抽象接口方法NodeMaterial.jssetupLightingModel() { return new BasicLightingModel(); }BasicLightingModel 对应“无光照材质”的照明模型核心逻辑分为两段indirect()源码 L32-L58只累积烘焙间接光——存在irradianceLightMap即上面的光照贴图则累加它否则以vec4(1,1,1,0)兜底随后用环境光遮蔽 AO 与diffuseColor.rgb调制。finish()源码 L65-L96执行环境映射。按material.combine取值分派三种算法——MultiplyOperation用materialSpecularStrength * materialReflectivity作为强度做乘法混合、MixOperation做线性插值混合、AddOperation做加法叠加未知取值时输出warn()警告。这也解释了setupNormal()/setupEnvironment()为何都要配套改造基础材质的 IBL 路径与常规 PBR 材质的辐照度/镜面反射两条链路完全不同。5.setupOutgoingLight() : Node.vec3这是文档中“最绕”的一点因为lights被置为true基类默认的setupOutgoingLight()会返回vec3(0)NodeMaterial.jslights true分支意味着“由照明模型计算出射光”但基础材质不应该因照明而变暗所以此处直接返回漫反射颜色本身setupOutgoingLight() { return diffuseColor.rgb; }即无论如何走照明上下文出射光都等于材质的漫反射色color × map照明模型环境、光照贴图、AO只在此基础上做乘法/加法调制而不是产生新的光源方向性贡献。五、构建期调用链小结把 NodeMaterial 的setupLighting()主流程NodeMaterial.js与上述覆写对照可得到 MeshBasicNodeMaterial 的着色器构建骨架setupLighting() ├─ setupOutgoingLight() → diffuseColor.rgb 覆写 ├─ setupMaterialLightings() │ ├─ setupEnvironment() → BasicEnvironmentNode 覆写包装基类 envNode │ └─ setupLightMap() → BasicLightMapNode 覆写烘焙光照×1/π │ └─ (AO) ambientOcclusion ├─ setupLightingModel() → BasicLightingModel 覆写 └─ lightingContext( lightsNode, BasicLightingModel, ... ) └─ BasicLightingModel.indirect() 累积调制烘焙光 AO └─ BasicLightingModel.finish() 按 combine 混合环境贴图 setupNormal() → negateOnBackSide( normalViewGeometry ) 覆写由于 mesh 的基础几何与材质属性UV、map等由 NodeMaterial 基类统一定义MeshBasicNodeMaterial 只需在“法线 / 环境 / 光照贴图 / 照明模型 / 出射光”五个接缝上做最小化覆写就能复用整条节点化渲染管线——这正是该实现小而清晰的原因。六、实际项目中的应用证据MeshBasicNodeMaterial 在仓库中被广泛用于需要“经典基础材质语义 Node/WebGPU 管线”的场景可作参考范例辉光镜头光晕对象examples/jsm/objects/LensflareMesh.js以new MeshBasicNodeMaterial( { opacity: 0, transparent: true } )起步再在运行时用 TSL 动态替换颜色/混合逻辑。MaterialX 材质加载器examples/jsm/loaders/materialx/MaterialXDocument.js把 MaterialX 标准表面最终映射到new MeshBasicNodeMaterial()说明它是 WebGPU 后端中无光照表面的目标材质。渲染器调试遮罩examples/jsm/inspector/RendererInspector.js构建overdraw材质时会实例化一个使用AdditiveBlending、特殊颜色空间与toneMapped: false的MeshBasicNodeMaterial。自行快速验证的方式在任意基于three/webgpu的示例WebGPURenderer中把new MeshBasicMaterial(...)替换为new MeshBasicNodeMaterial( { color, map, envMap, combine: THREE.MixOperation } )即可观察它在节点化管线中产出等价且可编程的着色器图。若要在着色器层面进一步定制其颜色可在 TSL 中借助material.color、diffuseColor等节点继续组合相关 TSLLanguage 语法见 docs/TSL.md。综上MeshBasicNodeMaterial 是理解 three.js 节点材质“用照明模型表达无光照材质”这一设计的关键入口——它用五个精准的方法覆写把经典 MeshBasicMaterial 的视觉语义无损迁移到可编程的节点化着色器管线中是 WebGPU 后端材质迁移与 TSL 二次开发的常用底座。【免费下载链接】three.jsJavaScript 3D Library.项目地址: https://gitcode.com/GitHub_Trending/th/three.js创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表