调试 
js
创建NodeBuilder:
	NodeBuilder (NodeBuilder.js:90)
	WGSLNodeBuilder (WGSLNodeBuilder.js:180)
	createNodeBuilder (WebGPUBackend.js:1972)
	`getForRender (Nodes.js:196)` // 创建和构建的分水岭
	getNodeBuilderState (RenderObject.js:379)
	getMonitor (RenderObject.js:390)
	needsRefresh (Nodes.js:797)
	_renderObjectDirect (Renderer.js:2977)
	renderObject (Renderer.js:2925)
	_renderObjects (Renderer.js:2833)
	_renderScene (Renderer.js:1486)
	render (Renderer.js:1197)
	animate (webgpu_reflection_blurred2.html:301)
	update (Animation.js:73)
	requestAnimationFrame
	update (Animation.js:65)
	start (Animation.js:77)
	(匿名) (Renderer.js:803)
	await in (匿名)
	init (Renderer.js:753)
	setAnimationLoop (Renderer.js:1606)
	init (webgpu_reflection_blurred2.html:256)
	(匿名) (webgpu_reflection_blurred2.html:77)
构建NodeBuilder.build:
	`https://cdn.jsdelivr.net/npm/three/src/nodes/core/NodeBuilder.js`
	build() {
		const { object, material, renderer } = this;
		if ( material !== null ) {
			nodeMaterial.build
		} else {
			this.addFlow( 'compute', object );
		}
	  	// setup() -> 阶段 1: 创建可能的 [新] 节点和/或返回一个输出引用节点
		// analyze()   -> 阶段 2: 分析节点以进行可能的优化和验证
		// generate()  -> 阶段 3: 生成着色器
		for ( const buildStage of defaultBuildStages ) {
			this.setBuildStage( buildStage );
			if ( this.context.vertex && this.context.vertex.isNode ) {
				this.flowNodeFromShaderStage( 'vertex', this.context.vertex );
			}
			for ( const shaderStage of shaderStages ) {
				this.setShaderStage( shaderStage );
				const flowNodes = this.flowNodes[ shaderStage ];
				for ( const node of flowNodes ) {
					if ( buildStage === 'generate' ) {
						this.flowNode( node );
					} else {
						node.build( this );
							// 可能会执行(从下到上):
							flowStagesNode
							flowShaderNode (NodeBuilder.js:2215)
							buildFunctionCode (WGSLNodeBuilder.js:1022)
							buildFunctionNode (NodeBuilder.js:2167)
							call (TSLCore.js:387)
							setupOutput (TSLCore.js:450)
							getOutputNode (TSLCore.js:461)
							build (TSLCore.js:476)
							build (VarNode.js:158)
							build (Node.js:711)
							build (TempNode.js:82)
							build (VarNode.js:158)
							build (Node.js:711)
							build (TempNode.js:82)
							build (Node.js:711)
							build (TempNode.js:82)
							build (VarNode.js:158)
							build (StackNode.js:328)
					}
				}
			}
		}
		this.setBuildStage( null );
		this.setShaderStage( null );
		// stage 4: build code for a specific output
		this.buildCode();
			_getWGSLFragmentCode (WGSLNodeBuilder.js:2037)
			buildCode (WGSLNodeBuilder.js:1861)
			`build (NodeBuilder.js:2794)`对应此处的 `this.buildCode();`
			getForRender (Nodes.js:211)
	
		this.buildUpdateNodes();
		return this;
	}drawCircle 函数如何转换为最终的 GLSL 字符串 
js
## 转换流程分析
### 1. Fn 函数包装
`drawCircle` 通过 `Fn` 函数创建,这会将 JavaScript 函数包装成 `ShaderNodeInternal` 对象 [1](#7-0) 。
### 2. 函数调用处理
当 `drawCircle` 被调用时,会创建 `ShaderCallNodeInternal` 实例,处理参数转换和节点调用 [1](#7-0) 。
### 3. 代码生成过程
在 `GLSLNodeBuilder.buildFunctionCode()` 中生成 GLSL 函数代码 [2](#7-1) 
### 4. 节点转换细节
每个 TSL 表达式都会转换为对应的 GLSL 代码:
- `length(pos)` → `length(pos)` (数学函数直接映射) [3](#7-2) 
- `dist1.assign()` → `dist1 = ...` (赋值操作)
- `color.rgb.mul()` → `color * ...` (向量乘法) [4](#7-3) 
- `max(sub(0.8, abs(dist2)), 0.0)` → `max(0.8 - abs(dist2), 0.0)`
### 5. 最终集成到片段着色器
生成的函数会被添加到片段着色器的代码段中,通过 `_getGLSLFragmentCode()` 方法组装 [5](#7-4)Node Material 和 TSL 有着密切的关系:Search | DeepWiki 
核心关系 
NodeMaterial 是基于 TSL 构建的材质系统。NodeMaterial 作为所有基于节点的材质的基类,广泛使用了 TSL (Three.js Shading Language) 提供的类型和功能。 1
技术实现 
- 类型系统集成:NodeMaterial 直接导入并使用 TSL 的基础类型,如 float、vec3、vec4、bool等,这些是构建节点材质的基础构建块。 1
- 材质属性访问:MaterialNode 类负责创建 TSL 对象来访问材质属性,它使用 TSL 的类型系统来确保类型安全。 2
- 预定义 TSL 对象:MaterialNode 使用 nodeImmutable函数创建了大量预定义的 TSL 对象,如materialColor、materialOpacity、materialNormal等,这些对象可以直接在 NodeMaterial 中使用。 3
TSL 的作用 
TSL 是一个完整的着色器语言抽象层,提供了数百个函数和类型,涵盖了从基础数学运算到复杂材质属性的所有功能。 4
使用模式 
在 NodeMaterial 中,开发者可以:
- 使用 TSL 提供的材质访问器来获取当前材质的属性
- 通过节点组合来构建复杂的材质效果
- 利用 TSL 的类型安全特性避免着色器编译错误
TSL 提供了着色器编程的"语言"和"词汇",而 NodeMaterial 则是使用这套语言来构建材质的"框架"
- TSL的优势: - TSL的节点本质上是函数,可以被使用、组合和链接以生成最终着色器。
- TSL自动处理适应不同API的适配,无论是WebGL的GLSL还是WebGPU的WGSL。
 
Three.js Shading Language (TSL) 笔记 
1. 引言与目的 
- Why TSL?- TSL旨在简化着色器的创建过程,使开发者即使没有从头开始编写GLSL代码的经验,也能创建所需的图形效果。
- TSL的目标是创建一个易于使用的着色器创建环境,同时保持渲染器的通用性,并通过模块化和树摇算法优化性能。
 
2. 示例 
- 细节贴图(Detail Map)- 通过UV缩放和基础纹理的乘法,为游戏内物体表面增加微小细节,如裂缝或凸起。
 
3. TSL的新旧对比 
- Old Method- 使用.onBeforeCompile()方法手动修改GLSL着色器代码,随着代码修改的增加,复杂性迅速上升。
 
- 使用
- New Method- TSL通过节点系统简化了代码编写,无需关心组件创建的顺序,节点系统会自动声明和包含一次。
 
4. 架构 
- 构建过程- 基于三个支柱:设置(setup)、分析(analyze)和生成(generate)。
- 节点可以有多个输入但总是单个输出,通过分析节点来生成代码片段。
 
5. 常量与显式转换 
- 支持创建常量和显式类型转换,如float(),int(),bool()等。
6. 统一变量(Uniform) 
- 用于更新颜色、光照或变换等变量值,无需重新创建着色器程序。
7. 操作符 
- 提供了基本的数学操作符,如加(add)、减(sub)、乘(mul)、除(div)等。
8. 函数 
- 支持使用传统的JS函数或tslFn()接口,后者提供了一个可控环境,允许使用堆栈进行条件赋值。
9. 条件语句 
- TSL中的条件语句使用If,elseif,else构建,支持在tslFn()中使用。
10. 三元运算符 
- 与if-else不同,三元运算符返回一个值,并且可以在tslFn()外部使用。
11. 数学函数 
- 提供了一系列数学函数,如abs(),acos(),all(),any()等。
12. 方法链 
- 方法链仅包括操作符、转换器、数学和一些核心函数。
13. 纹理(Texture) 
- 提供了从纹理中检索像素值的函数,如texture(),cubeTexture()等。
14. 属性(Attributes) 
- 用于获取几何属性,如uv(),vertexColor(),positionGeometry()等。
15. 位置(Position) 
- 描述了与位置相关的属性和变量,如positionLocal,positionWorld等。
16. 法线(Normal) 
- 描述了与法线相关的属性和变量,如normalLocal,normalView等。
17. 切线与副法线(Tangent & Bitangent) 
- 提供了切线和副法线的属性和变量,如tangentLocal,bitangentLocal等。
18. 相机(Camera) 
- 提供了相机相关的属性和变量,如cameraPosition,cameraViewMatrix等。
19. 模型(Model) 
- 描述了模型相关的属性和变量,如modelPosition,modelWorldMatrix等。
20. 视口(Viewport) 
- 提供了视口相关的属性和函数,如viewportTopLeft,viewportResolution等。
21. 混合模式(Blend Mode) 
- 提供了不同的混合模式函数,如burn(),dodge(),overlay()等。
22. 反射(Reflect) 
- 提供了计算反射方向的函数,如reflectView(),reflectVector()等。
23. UV工具(UV Utils) 
- 提供了UV相关的工具函数,如matcapUV(),rotateUV()等。
24. 插值(Interpolation) 
- 提供了值的插值函数,如remap(),remapClamp()等。
25. 随机数(Random) 
- 提供了生成随机数的函数,如hash(),range()等。
26. 振荡器(Oscillator) 
- 提供了生成不同波形振荡的函数,如oscSine(),oscSquare()等。
27. 打包(Packing) 
- 提供了方向向量与颜色之间的转换函数,如directionToColor(),colorToDirection()等。
28. 函数 
- 描述了如何使用.toVar()和.varying()函数来优化计算和创建变量。
29. 从GLSL属性过渡到TSL 
- 提供了从GLSL到TSL的属性过渡指南,如position到positionGeometry等。
30. 附加资源 
- 提供了Three.js Shading Language的附加资源链接,如使用SketchUp模型等。