资讯动态

three.js Transpiler 完全指南:将 GLSL 着色器一键转换为 TSL 节点代码

发布时间:2026/9/9 23:25:38 来源:尧图企业网站定制
three.js Transpiler 完全指南将 GLSL 着色器一键转换为 TSL 节点代码【免费下载链接】three.jsJavaScript 3D Library.项目地址: https://gitcode.com/GitHub_Trending/th/three.jsTranspiler 是 three.js 提供的一个代码转译器工具能够在不同着色器语言之间进行转换目前官方支持的场景是将 GLSL 着色器代码转换为 TSLThree Shading Language节点式着色语言其核心目标是帮助开发者在迁移自研材质时把旧版 shader 平滑过渡到新的节点化材质系统Node Material System。阅读本文后你将掌握 Transpiler 的构造方式、三大内部组件decoder / linker / encoder的职责划分并能直接使用它配合GLSLDecoder、TSLEncoder、ShaderToyDecoder等配套模块把一段自定义 GLSL 源码实时转译为可在MeshBasicNodeMaterial等新材质中运行的 TSL 代码。Transpiler 是什么Transpiler是一个语言到语言的着色器代码转换器。从当前仓库的实现看examples/jsm/transpiler/Transpiler.js其类注释对它的定位做了清晰描述A class that transpiles shader code from one language into another.目前它只能用于把 GLSL 转成 TSLTranspiler can only be used to convert GLSL into TSL right now。这一限制并非架构上的先天约束而是当前官方验证并支持的组合路径。仓库中同时提供了WGSLEncoder等编码器交互式示例 webgpu_tsl_transpiler.html 中甚至在编码器下拉框里同时允许选择 TSL 与 WGSL 两种输出但文档明确标注的成熟用法是 GLSL → TSL。它的典型应用场景是材质迁移。当你的项目拥有大量基于RawShaderMaterial/ShaderMaterial编写的自定义着色器而你想迁移到 WebGPU 与 TSL 的节点化材质系统时可以借助 Transpiler 完成机械性的语法转换省去逐行手写 TSL 节点代码的工作量。安装与导入Transpiler 属于**插件addon**而非核心库的一部分不会被打包进three主模块必须显式导入。import Transpiler from three/addons/transpiler/Transpiler.js;在仓库中其源码位于 examples/jsm/transpiler/Transpiler.js与它同目录的配套模块还包括模块文件职责GLSLDecoderexamples/jsm/transpiler/GLSLDecoder.jsGLSL 解码器负责词法/语法解析ShaderToyDecoderexamples/jsm/transpiler/ShaderToyDecoder.js面向 ShaderToy 的 GLSL 解码器TSLEncoderexamples/jsm/transpiler/TSLEncoder.js把 AST 输出为 TSL 代码WGSLEncoderexamples/jsm/transpiler/WGSLEncoder.js把 AST 输出为 WGSL 代码Linkerexamples/jsm/transpiler/Linker.js链接器解析变量与函数引用ASTexamples/jsm/transpiler/AST.js语言无关的 AST 节点定义TranspilerUtilsexamples/jsm/transpiler/TranspilerUtils.js内置类型判断等公共工具按 three.js 的 addon 惯例three/addons/前缀在构建后的环境中指向examples/jsm/目录在仓库示例里对应的 import map 写法为three/addons/: ./jsm/见 webgpu_tsl_transpiler.html。构造函数组合一个转译器new Transpiler( decoder : GLSLDecoder, encoder : TSLEncoder )Transpiler的构造函数接收两个关键协作对象并在内部自动创建一个Linker注意linker 不需要、也不能由外部传入它由构造函数自动实例化见源码第 44 行this.linker new Linker()。参数类型说明decoderGLSLDecoder解码器负责解析 GLSL 源码encoderTSLEncoder编码器负责把中间结果输出为 TSL一个最小可用组合如下import Transpiler from three/addons/transpiler/Transpiler.js; import GLSLDecoder from three/addons/transpiler/GLSLDecoder.js; import TSLEncoder from three/addons/transpiler/TSLEncoder.js; const decoder new GLSLDecoder(); const encoder new TSLEncoder(); const transpiler new Transpiler( decoder, encoder );如果是从 ShaderToy 迁移片元着色器则把GLSLDecoder换成ShaderToyDecoder详见下文迁移 ShaderToy 着色器一节。三个公开属性decoder、encoder 与 linkerTranspiler 把整条转换链路拆成三个职责单一的可替换组件并全部以实例属性形式暴露方便调试与替换。.decoder : GLSLDecoderGLSL 解码器。这一阶段负责把 GLSL 文本读懂它对源码做分词tokenize与语法解析最终产出一棵与具体语言无关的 AST抽象语法树供后续进一步处理。在 GLSLDecoder.js 内部可以印证这一点——它定义了一套完整的操作符表一元操作符 - ~ ! --、算术操作符、优先级分层precedenceOperators、右结合性列表等以及对数字、字符串、注释、标识符的正则识别规则解析得到的节点类型如FunctionDeclaration、VariableDeclaration、For、Switch、Ternary、Accessor等全部来自 AST.js。这套 AST 是语言无关的因此同一个 AST 理论上可以被不同语言的编码器消费。.encoder : TSLEncoderTSL 编码器。它接收 AST 并输出 TSL 代码字符串是读 AST → 生成文本的最终出口。在 TSLEncoder.js 中可以看到编码阶段的语义映射逻辑操作符映射表opLib把 - * / % ! || ^ | 以及各类复合赋值操作符映射为add / sub / mul / div / remainder / lessThan / equal / and / bitAnd / shiftLeft / addAssign等 TSL 语义函数一元操作符映射表unaryLib- → negate、! → not、~ → bitNot、 → increment、-- → decrement纹理查找函数清单textureLookupFunctions覆盖texture / texture2D / texture3D / textureCube / textureLod / texelFetch / textureGrad等GLSL 内建函数名转换表glslToTSL例如inversesqrt → inverseSqrt内置采样器类型清单sampler2D、samplerCube、sampler3D及其 isampler/usampler 变体等。这解释了为什么生成结果可以直接喂给节点化材质编码器输出的是符合three/tsl语义的表达式链。.linker : Linker链接器由构造函数自动创建。它处理 AST 并解析变量与函数引用确保所有依赖都被正确链接——类似于编译器中符号解析阶段。在 Transpiler 的parse()流程中linker 在 decoder 之后、encoder 之前介入处理。核心方法parse().parse( source : string ) : string解析给定的 GLSL 源码并返回 TSL 语法字符串。项说明参数source待转换的 GLSL 源码字符串返回值转换得到的 TSL 代码字符串结合 Transpiler.js 的实现parse()内部严格按三阶段流水线执行parse( source ) { const ast this.decoder.parse( source ); // 1. GLSL → AST // 2. 处理 AST解析变量与函数引用、做优化 this.linker.process( ast ); return this.encoder.emit( ast ); // 3. AST → TSL }这条decoder.parse → linker.process → encoder.emit的调用链就是整个转译器的核心工作流。理解这一点后你可以自由替换链路中的任意环节换不同的 decoder如ShaderToyDecoder或换不同的 encoder如WGSLEncoder拼接出你自己的语言转换管线。实战一把一段 GLSL 噪声函数转成 TSL下面给出一个完整、可运行的示例演示如何把仓库 webgpu_tsl_transpiler.html 中内置的 Perlin 噪声 GLSL 源码转换为 TSL。import Transpiler from three/addons/transpiler/Transpiler.js; import GLSLDecoder from three/addons/transpiler/GLSLDecoder.js; import TSLEncoder from three/addons/transpiler/TSLEncoder.js; const glsl const float PI 3.141592653589793; float rand(vec2 c){ return fract(sin(dot(c.xy ,vec2(12.9898,78.233))) * 43758.5453); } float noise(vec2 p, float freq ){ float unit 1./freq; vec2 ij floor(p/unit); vec2 xy mod(p,unit)/unit; xy .5*(1.-cos(PI*xy)); float a rand((ijvec2(0.,0.))); float b rand((ijvec2(1.,0.))); float c rand((ijvec2(0.,1.))); float d rand((ijvec2(1.,1.))); float x1 mix(a, b, xy.x); float x2 mix(c, d, xy.x); return mix(x1, x2, xy.y); } ; const decoder new GLSLDecoder(); const encoder new TSLEncoder(); const transpiler new Transpiler( decoder, encoder ); const tsl transpiler.parse( glsl ); // 得到 TSL 代码字符串 console.log( tsl );注意到这段 GLSL 中出现了常量定义const float PI、自定义函数rand、noise、内建函数调用fract、sin、dot、mix、floor、mod、cos以及向量构造vec2(...)。解码器需要把这些全部解析为 AST随后编码器再翻译成 TSL 的链式节点表达。从源码看上述 GLSL 运算符与内建函数均位于 GLSLDecoder.js 与 TSLEncoder.js 已支持的操作符与查找函数清单内属于典型的可转换代码。实战二实时转译交互界面官方示例仓库自带的 webgpu_tsl_transpiler.html 是一个实时转译编辑器界面左侧为 Monaco 编辑器右侧为只读输出面板。它把上述流程封装成了可交互的演示左侧下拉框选择解码语言当前仅GLSL右侧下拉框选择编码语言TSL或WGSL每次修改左侧 GLSL 源码经约 1 秒防抖后自动触发build()内部流程与手写代码完全一致见该文件第 200-235 行const decoder new GLSLDecoder(); const transpiler new Transpiler( decoder, encoder ); const tsl transpiler.parse( glsl ); showCode( tsl );其中encoder依据选择动态实例化let encoder; if ( options.encoder TSL ) { encoder new TSLEncoder(); } else if ( options.encoder WGSL ) { encoder new WGSLEncoder(); }任何解析或转换异常都会被try/catch捕获并显示为Error: ...方便定位不支持的语法。实战三把 ShaderToy 片元着色器接入节点化材质Transpiler的另一个典型用法是迁移 ShaderToy 风格着色器。ShaderToy 片元着色器以mainImage( out vec4 fragColor, in vec2 fragCoord )为入口并依赖iResolution、iTime等内建输入。仓库为此提供了专用的ShaderToyDecoder配套示例是 webgpu_shadertoy.html。在 ShaderToy 场景中组合变为import Transpiler from three/addons/transpiler/Transpiler.js; import ShaderToyDecoder from three/addons/transpiler/ShaderToyDecoder.js; import TSLEncoder from three/addons/transpiler/TSLEncoder.js; const decoder new ShaderToyDecoder(); const encoder new TSLEncoder(); const jsCode new Transpiler( decoder, encoder ).parse( glsl );官方示例 webgpu_shadertoy.html 定义了一个ShaderToyNode extends THREE.Node的节点类把转译结果封装成一个可直接被 TSL 图消费的节点transpile( glsl, iife false ) { const decoder new ShaderToyDecoder(); const encoder new TSLEncoder(); encoder.iife iife; // 是否包裹为立即执行函数 const jsCode new Transpiler( decoder, encoder ).parse( glsl ); return jsCode; } parse( glsl ) { const jsCode this.transpile( glsl, true ); const { mainImage } eval( jsCode )( TSL ); // 导出 mainImage 函数 this.mainImage mainImage; }这里用到了TSLEncoder的一个重要可配置属性.iife。从 TSLEncoder.js 源码可见其默认值为false当iife true时编码器输出的 TSL 代码会被包裹成 IIFE立即执行函数便于通过eval/ 动态import直接取回导出的mainImage等符号。示例中还提供了异步方案parseAsync()——把转译出的 JS 字符串经data:text/javascriptURL 动态导入执行。生成自定义节点后即可作为 TSL 表达式接入新材质系统。示例最终将其挂在平面网格的MeshBasicNodeMaterial上与时间节点混合做场景切换const material new THREE.MeshBasicNodeMaterial(); material.colorNode TSL.oscSine( TSL.time.mul( .3 ) ).mix( shaderToy1Node, shaderToy2Node );其中THREE.MeshBasicNodeMaterial与TSL空间分别来自three/webgpu与three/tsl见示例 import 部分。这条链路完整展示了 Transpiler 在旧着色器资产 → 新节点系统迁移中的实际价值着色器代码不用重写只需转换后包一层节点即可复用。迁移时值得注意的语法边界Transpiler 的定位是机械性语法迁移并非所有 GLSL 写法都能无差别转换。根据文档描述与源码结构可以总结出如下适用边界编写源着色器时尽量规避支持的语法以解码器的分词/解析规则为上限运算符、字面量、注释、函数/结构体/分支循环的解析规则都硬编码在解码器中超出清单的语法如某些编译器扩展指令会产生解析错误可在交互示例中得到Error反馈函数与变量命名遵循 TSL 语义映射例如 GLSL 的inversesqrt会被重命名为inverseSqrtglslToTSL表运算符会被展开为add、mix对应的节点调用入口函数的差异普通 GLSL 顶点/片元着色器与 ShaderToy 的mainImage入口形态不同需选用对应的 decoderGLSLDecoder或ShaderToyDecoder转换产物需配合节点材质使用转译输出的 TSL 字符串本质是供MeshBasicNodeMaterial、MeshPhysicalNodeMaterial等节点化材质或自定义THREE.Node使用的表达式代码而非传统ShaderMaterial的着色器文本。小结与延伸阅读综上所述Transpiler以解码decoder→ 链接linker→ 编码encoder三段式流水线完成 GLSL → TSL 的转换代码规模小、组件可替换、接口极简仅一个parse()方法。无论你是想批量迁移旧 GLSL 材质还是想把 ShaderToy 作品搬进 WebGPU 渲染管线都可以把它作为自动化转换的基础设施。进一步深入时可参考以下仓库内资料转译器核心实现examples/jsm/transpiler/Transpiler.js语言无关 AST 节点定义examples/jsm/transpiler/AST.js可交互的实时转译示例examples/webgpu_tsl_transpiler.htmlShaderToy 转译节点示例examples/webgpu_shadertoy.htmlGLSL 解码器源码examples/jsm/transpiler/GLSLDecoder.jsTSL 编码器源码含opLib/unaryLib/.iifeexamples/jsm/transpiler/TSLEncoder.jsShaderToy 专用解码器examples/jsm/transpiler/ShaderToyDecoder.js【免费下载链接】three.jsJavaScript 3D Library.项目地址: https://gitcode.com/GitHub_Trending/th/three.js创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价