Skip to content

调试

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

技术实现

  1. 类型系统集成:NodeMaterial 直接导入并使用 TSL 的基础类型,如 floatvec3vec4bool 等,这些是构建节点材质的基础构建块。 1
  2. 材质属性访问:MaterialNode 类负责创建 TSL 对象来访问材质属性,它使用 TSL 的类型系统来确保类型安全。 2
  3. 预定义 TSL 对象:MaterialNode 使用 nodeImmutable 函数创建了大量预定义的 TSL 对象,如 materialColormaterialOpacitymaterialNormal 等,这些对象可以直接在 NodeMaterial 中使用。 3

TSL 的作用

TSL 是一个完整的着色器语言抽象层,提供了数百个函数和类型,涵盖了从基础数学运算到复杂材质属性的所有功能。 4

使用模式

在 NodeMaterial 中,开发者可以:

  • 使用 TSL 提供的材质访问器来获取当前材质的属性
  • 通过节点组合来构建复杂的材质效果
  • 利用 TSL 的类型安全特性避免着色器编译错误

TSL 提供了着色器编程的"语言"和"词汇",而 NodeMaterial 则是使用这套语言来构建材质的"框架"

  1. 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的属性过渡指南,如positionpositionGeometry等。

30. 附加资源

  • 提供了Three.js Shading Language的附加资源链接,如使用SketchUp模型等。
本站总访问量 次 本站访客数 人次

1111111111111111111