ARTICLE DETAIL

资讯详情

深耕编程入门与网站建设的一线实战洞察。

three.js TSL 中的 ArrayNode:数组节点的创建、属性与着色器生成机制

three.js TSL 中的 ArrayNode:数组节点的创建、属性与着色器生成机制 three.js TSL 中的 ArrayNode数组节点的创建、属性与着色器生成机制【免费下载链接】three.jsJavaScript 3D Library.项目地址: https://gitcode.com/GitHub_Trending/th/three.jsArrayNode 是 three.js 节点着色语言TSL中用于表示节点集合的核心数据类型通过array()函数即可在着色器逻辑中声明带类型与初值的数组并用.element()按下标取值。本文基于 docs/pages/ArrayNode.html.md 与 src/nodes/core/ArrayNode.js 的实现源码完整覆盖 ArrayNode 的构造参数、属性、方法并向下追溯其 shader 字符串生成链路与元素访问节点帮助你在自定义材质、存储缓冲等场景中正确使用数组节点。继承链与定位文档给出的继承关系为EventDispatcher → Node → TempNode → ArrayNode从源码结构看ArrayNode直接继承自TempNode见 src/nodes/core/ArrayNode.js 的class ArrayNode extends TempNode。这意味着数组节点被声明为临时节点当它参与更大的节点表达式时TSL 编译器会为其分配临时变量并内联初始化而不是要求你手动声明 GLSL 变量。ArrayNode表示一组节点的集合通常通过 TSL 的array()函数创建。该函数与ArrayNode类一同从 src/nodes/core/ArrayNode.js 导出并经 src/nodes/tsl/TSLBase.js 统一汇入 TSL 命名空间export * from ../core/ArrayNode.js; // array(), .toArray()。用 array() 创建数组节点array()是一个接受可变参数的 TSL 函数src/nodes/core/ArrayNode.js源码中支持两种调用形式形式一直接传入元素列表自动推断类型与长度const colors array( [ vec3( 1, 0, 0 ), vec3( 0, 1, 0 ), vec3( 0, 0, 1 ) ] ); const redColor colors.element( 0 );源码逻辑src/nodes/core/ArrayNode.js当参数只有一个时会先对每个元素执行nodeObject( value )把普通值包装成节点然后以nodeType null、count values.length构造ArrayNode。类型由第一个元素的节点类型在编译期推断因此文档示例中colors自动成为vec3[ 3 ]类型的数组节点。形式二显式指定类型与数量const points array( vec3, 8 );源码逻辑src/nodes/core/ArrayNode.js参数为两个时第一个是元素类型字符串如vec3第二个是数组长度此时values缺省为null。便捷链式方法 .toArray( count )同一文件末尾还注册了链式方法src/nodes/core/ArrayNode.jsaddMethodChaining( toArray, ( node, count ) array( Array( count ).fill( node ) ) );这使得任意节点可以一行展开为同值数组例如vec3( 1, 0, 0 ).toArray( 4 )等价于array( [ vec3(1,0,0), vec3(1,0,0), vec3(1,0,0), vec3(1,0,0) ] )。构造函数new ArrayNode( nodeType : string, count : number, values : Array. )构造一个新的数组节点各参数说明与文档一致并结合源码补充默认值细节src/nodes/core/ArrayNode.js参数类型说明默认值nodeTypestring数组元素的数据类型如vec3、floatnull此时类型从values[ 0 ]推断countnumber数组大小元素个数必填valuesArrayNode数组的默认值节点列表null构造函数内将count与values存为实例属性并置this.isArrayNode true作为类型测试标志。属性.count : number数组大小。getArrayCount()直接返回它见下文方法节是编译器决定 GLSL 数组维度的唯一依据。.isArrayNode : boolean (readonly)恒为true的类型测试标志文档与源码src/nodes/core/ArrayNode.js均注明可用于instanceof之外的快速类型判断例如在自定义节点中判断上游依赖是否为数组节点。.values : Array.数组的默认值节点列表可能为null。在 shader 生成阶段values中存在的元素会按类型逐个 build 为初值缺失的位置则由类型默认常量填充详见下文generate()分析。方法与着色器字符串生成文档列出的五个方法均对应 src/nodes/core/ArrayNode.js 中的实际实现.generate( builder : NodeBuilder ) : string构建输出节点并返回数组的着色器字符串覆盖TempNode#generate。源码实现src/nodes/core/ArrayNode.jsgenerate( builder ) { const type this.getNodeType( builder ); return builder.generateArray( type, this.count, this.values ); }它委托给NodeBuilder.generateArray该方法在 src/nodes/core/NodeBuilder.js 中先由generateArrayDeclaration( type, count )生成type[ count ]形式的声明片段src/nodes/core/NodeBuilder.js再逐个拼接初值——若values[ i ]存在则value.build( this, type )生成带类型的初值表达式否则回退为this.generateConst( type )生成的类型默认常量。因此array( vec3, 3 )与array( [ vec3(1,0,0), vec3(0,1,0), vec3(0,0,1) ] )最终都会产出vec3 3这类初始化器字符串。.generateNodeType( builder : NodeBuilder ) : string返回节点类型覆盖TempNode#generateNodeType。源码src/nodes/core/ArrayNode.js显示了一个关键行为当nodeType null即通过元素列表构造时返回this.values[ 0 ].getNodeType( builder )即元素类型在首次生成时才被确定否则直接返回构造时显式传入的类型字符串。.getArrayCount( builder : NodeBuilder ) : number返回节点数组的元素个数覆盖TempNode#getArrayCount。实现即return this.count;src/nodes/core/ArrayNode.js是 TSL 类型系统询问这是一个多大的数组的入口例如NodeBuilder在生成vec3[ N ]声明src/nodes/core/NodeBuilder.js时会用到这类信息。.getElementType( builder : NodeBuilder ) : string返回元素类型覆盖TempNode#getElementType。实现为return this.getNodeType( builder );src/nodes/core/ArrayNode.js即数组节点自身的节点类型就是元素类型。.getMemberType( builder : NodeBuilder, name : string ) : string返回成员变量的类型覆盖TempNode#getMemberType。源码src/nodes/core/ArrayNode.js同样体现类型延迟推断nodeType null时转发给this.values[ 0 ].getMemberType( builder, name )否则回退到父类super.getMemberType。元素访问.element() 与 ArrayElementNode文档示例中的colors.element( 0 )由 TSL 的element代理函数实现它在 src/nodes/tsl/TSLCore.js 中定义为export const element /*__PURE__*/ nodeProxy( ArrayElementNode ).setParameterLength( 2 );对应的 src/nodes/utils/ArrayElementNode.js 是数组元素访问的基础类它持有数组类节点 下标节点两个成员并在generate()中生成标准 GLSL 下标语法src/nodes/utils/ArrayElementNode.jsgenerate( builder ) { const indexType this.indexNode.getNodeType( builder ); const nodeSnippet this.node.build( builder ); const indexSnippet this.indexNode.build( builder, ! builder.isVector( indexType ) builder.isInteger( indexType ) ? indexType : uint ); return ${ nodeSnippet }[ ${ indexSnippet } ]; }可以看到两点值得注意的实现细节元素节点的节点类型并不硬编码而是通过this.node.getElementType( builder )从上游数组节点推断src/nodes/utils/ArrayElementNode.js这正是前面ArrayNode#getElementType存在的意义——两者构成一条类型推断链ArrayElementNode → ArrayNode#getElementType → nodeType 或 values[0]下标构建时若非向量且是整数类型则保留原类型否则统一以uint构建保证 GLSL/WGSL 索引合法性。因此文档示例const redColor colors.element( 0 )编译产物形如colors[ 0 ]其中colors是vec3 3 , vec3( 0.0, 1.0, 0.0 ), vec3( 0.0, 0.0, 1.0 ) )。小结与相关文件ArrayNode 在 TSL 中承担了类型化数组常量/初始化器的角色array()负责构造支持显式类型与元素推断两种形态TempNode继承保证其在表达式中的临时变量语义generate()委托NodeBuilder.generateArray完成 shader 字符串拼装.element()则经由ArrayElementNode完成下标访问与类型回溯。继续深入可参考src/nodes/core/ArrayNode.js —ArrayNode类与array()、.toArray()实现src/nodes/core/NodeBuilder.js —generateArrayDeclaration/generateArray的字符串生成逻辑src/nodes/utils/ArrayElementNode.js — 元素访问节点与下标类型处理src/nodes/tsl/TSLCore.js —elementTSL 函数定义src/nodes/tsl/TSLBase.js — TSL 命名空间对array()的导出。需注意的适用前提本文所述行为基于当前仓库源码TSL 位于src/nodes/随 WebGPU 渲染管线一起演进nodeType为null时取values[0]推断类型的实现意味着元素列表不能为空数组否则会触发values[ 0 ]访问错误。【免费下载链接】three.jsJavaScript 3D Library.项目地址: https://gitcode.com/GitHub_Trending/th/three.js创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表