- 图形学
- 前端
- 开发工具
【免费下载链接】webglstudio.js
A full open source 3D graphics editor in the browser, with scene editor, coding pad, graph editor, virtual file system, and many features more.
WebGLStudio.js 内置了基于 LiteGraph 的可视化节点编辑系统(Graph),无需编写代码即可将场景中不同组件的属性"连线"起来,实现属性同步、数值运算与渲染特效控制。本文以官方文档 guides/graphs.md 为核心,结合编辑器源码(editor/js/modules/graph.js、editor/js/widgets/ui/graphWidget.js、editor/js/extra/litescene.js)逐层拆解:如何在场景节点上创建 Graph 组件、区分行为图(GraphComponent)与渲染图(FXGraphComponent)、如何从检查器拖拽属性进画布、如何连线与调整节点,让你快速上手这套"拖线即编程"的工作流。
Graph 是什么:用连线替代代码
在 WebGLStudio.js 中,Graph(图形化节点编辑器)允许开发者通过可视化节点与连线来控制组件行为,或将不同组件的属性互连。相比手写脚本,这种方式更直观、更不易出错,但表达能力也更有限——它适合解决"两个属性保持相等或存在关联关系"这类问题,而非实现复杂逻辑。
一个典型的场景:移动场景中的一个节点时,希望另一个节点的 Y 位置自动跟随。传统做法是写脚本监听变换事件,而用 Graph 只需把"节点 A 的 Y 属性"用一根线接到"节点 B 的 Y 属性"上即可。
从源码结构看,这套能力分为三层:
- LS.Components.GraphComponent(行为图组件):挂载在任意场景节点上,负责驱动普通逻辑图;
- LS.Components.FXGraphComponent(渲染图组件):挂载在节点上,在渲染管线中执行,可输出纹理、颜色、深度等渲染结果;
- LS.GraphCode(图资源):将一张图以资源形式存储,可被多个 GraphComponent 共享(见 editor/js/extra/litescene.js 中的
GraphCode构造函数,其内部持有LiteGraph.LGraph实例,并在_graph._graphcode上与图互相引用)。
图的值可以来自场景中的其他属性,也可以由更复杂的计算产生——随机数、三角函数、数学运算等节点都可用。这正是 LiteGraph 生态所提供的能力。
创建 Graph 组件:行为图与渲染图
要在场景中使用图,首先需要给场景中的任意节点挂载一个 Graph 组件。WebGLStudio.js 提供了两种 Graph 组件类,用途不同:
| 组件类 | 适用场景 | 典型执行内容 |
|---|---|---|
GraphComponent | 行为/逻辑控制 | 属性同步、数学运算、触发动作、更新变换 |
FXGraphComponent | 渲染特效 | 后处理、纹理生成、光照合成、渲染帧输出 |
创建方式有两种:
- 在Graph 标签页(工具栏上方图标为 tabicon-graph.png)点击顶部的New按钮,在弹出的对话框中用Graph Type下拉框选择
GraphComponent或FXGraphComponent,并选择要挂载的目标Node,然后点击Create Graph。对应实现见 graphWidget.js 的onNewGraph:它创建new LS.Components[graph_type]()并root.addComponent(component)到所选节点上。 - 在任意节点上通过 Inspector 添加组件(
GraphComponent/FXGraphComponent),添加后即可在组件面板中编辑。
值得注意的默认行为(源码级细节):
- 新建
GraphComponent时若未提供序列化数据,会自动创建一个scene/node节点作为默认内容(litescene.js); - 新建
FXGraphComponent时默认图内已有一个名为"Rendered Frame"的scene/frame节点,且该节点被标记为ignore_remove与ignore_rename(不可删除、不可改名),它是渲染帧的入口(litescene.js)。
选择图何时执行:on event
GraphComponent有一个核心配置项on event(on_event属性),决定图在什么时机被驱动。源码中定义的可选值如下(litescene.js):
GraphComponent["@on_event"] = { type:"enum", values: ["start","render","beforeRenderScene","afterRenderScene","update","trigger"] };| 值 | 含义 |
|---|---|
start | 场景启动时执行一次(对应onSceneEvent中的start事件,会向图内节点广播onStart并置图状态为运行中) |
render | 渲染主通道前执行(源码将beforeRenderMainPass事件翻译为render) |
beforeRenderScene/afterRenderScene | 场景渲染前后执行 |
update | 每帧更新阶段执行(默认值) |
trigger | 仅当组件收到trigger事件时执行 |
在 Inspector 中,该配置以下拉框呈现:inspector.addCombo("on event", component.on_event, { values: LS.Components.GraphComponent["@on_event"].values ... })(见 graph.js)。此外还有一个redraw(force_redraw)复选框,勾选后每次运行图都会强制请求重绘帧(对应runGraph中if(this.force_redraw) this._root.scene.requestFrame(),litescene.js)。
对于FXGraphComponent,Inspector 还会额外显示Frame Settings(渲染帧上下文配置)、Antialiasing(use_antialiasing)和Use node camera(use_node_camera)等渲染专属选项(graph.js)。渲染图挂载到场景后,会绑定BEFORE_RENDER、ENABLE_FRAME_CONTEXT、SHOW_FRAME_CONTEXT、RENDER_GUI四个渲染生命周期事件,并向资源管理器注册:color_uid、:depth_uid、:extra_uid三类内部资源,供纹理类节点读写(litescene.js)。
打开图编辑器:Edit Graph
创建组件后,在 Inspector 的组件面板中点击Edit Graph按钮即可打开图编辑器视图。对应实现(graph.js):
inspector.addButton(null,"Edit Graph", { callback: function() { GraphModule.openTab(); GraphModule.editInstanceGraph( component, { id: component.uid, title: component._root.uid } ); }});它会切换到Graph 标签页,并在标签页下部的图编辑区中载入该组件的图。编辑器整体布局(graph.js)分为上下两部分:
- 上部是 3D 场景视口(可点击顶部3D按钮切换显隐);
- 下部是图编辑画布(
LGraphCanvas),背景为 litegraph_grid.png 网格。
图编辑器的顶部工具栏(graphWidget.js)提供以下操作:
| 按钮 | 功能 |
|---|---|
| New | 新建一张图(选择类型与挂载节点) |
| Open | 弹出对话框,列出场景中所有GraphComponent与FXGraphComponent供选择打开 |
| Save | 保存当前图(仅对from_file的图有效,会同步到对应 GraphCode 资源) |
| Compile | 编译图:将画布内容序列化写入 GraphCode,并传播到所有引用该资源的组件 |
| Run Step | 手动执行一步图(graph.runStep(1)并刷新场景) |
| Redraw | 切换画布是否持续重绘 |
| Detach | 将当前图弹出为独立浮动窗口 |
快捷键
图编辑器还支持几个实用的键盘快捷键(graph.js):
- Ctrl + S:保存图;
- Ctrl + Enter:编译图(Compile);
- F6:重新加载编辑器。
创建节点:右键菜单与拖拽
图打开后,有多种方式把节点加入画布:
1. 右键菜单创建
在画布空白处右键,会弹出节点创建菜单,节点按类别分组排列,数量众多。选择任意节点后它就会出现在画布中。这一交互由LGraphCanvas的内置右键菜单实现(LiteGraph 核心能力)。
2. 从 Inspector 拖入组件或属性
如果你想把场景中的任意属性带入图内,直接把组件或属性从Inspector 检查器拖到画布即可:
- 拖组件:按住组件名称旁边的组件图标拖拽;
- 拖属性:按住属性名称旁边的圆球图标拖拽。
拖入后画布中会出现对应的 GraphNode。源码中注册了多种可拖入类型(graphWidget.js):
| 拖入类型 | 生成的节点类型 | 说明 |
|---|---|---|
SceneNode(场景节点) | scene/node | 引用场景中的某个节点 |
Component(组件) | scene/transform或scene/component | Transform 组件生成变换节点,其他组件生成组件节点 |
Material(材质) | scene/material | 引用指定材质 |
property(属性) | scene/property | 以 locator(属性定位符)绑定具体属性 |
resource(资源,图片等) | texture/texture | 拖入图片资源会自动创建纹理节点并加载 |
此外,在场景中选中对象后,右键图画布还会出现"Add <类名>"快捷菜单,直接把当前选中对象(节点、组件或变换)添加为图中的节点(graphWidget.js)。
节点插槽:输入、输出与自定义
GraphNode 默认带有输入(inputs)和输出(outputs)插槽。你可以在节点上右键,从Inputs/Outputs菜单中为节点添加新的输入或输出(是否可加取决于节点类型本身)。
以输出为例,源码允许为节点新增自定义事件输出(graphWidget.js):
options.push({content:"New event", className: "event", callback: function( node ){ LiteGUI.prompt("Enter event name", function(v){ if(!v) return; node.addOutput( "on_" + v, LiteGraph.EVENT ); }); }});输入与输出的数据类型会决定哪些节点可以互相连接——WebGLStudio.js 用连线颜色区分类型,其中Component类型连线为紫色(LGraphCanvas.link_type_colors["Component"] = "#D99",graphWidget.js)。
连接与断开:拖线即绑定
连接两个节点的值,只需把源节点的输出插槽拖到目标节点的输入插槽:
- 拖动输出端到输入端 → 建立数据流连接;
- 单击输入端的连接点 → 断开该连接。
连接建立/断开后,编辑器会自动刷新场景以反映新数据流(graphcanvas.onConnectionChange中setTimeout(function(){ LS.GlobalScene.refresh(); }, 100),graphWidget.js)。
当你把鼠标悬停在一条连线上时,若该连线传输的数据是GL.Texture(纹理),还会弹出纹理预览工具提示(onDrawLinkTooltip,graphWidget.js)。
编辑节点属性:双击节点
想要调整任意节点的属性,双击节点即可在检查器(Inspector)中查看和编辑其属性。节点检查面板(graphWidget.js)提供:
- Title / ID:节点标题与唯一 ID;
- Size:节点在画布中的尺寸(Vector2);
- Mode:节点的执行模式(
Always始终执行 /On Event事件驱动 /On Trigger触发执行 /Never永不执行); - properties 面板:根据节点类型自动生成属性控件——若节点定义了
widgets_info则按其声明渲染,否则依据属性类型自动推断控件(数值、布尔、字符串、向量等); - 底部按钮:Collapse(折叠节点)、Remove(删除节点)、Show JSON(查看节点序列化 JSON);
- 描述信息:
graphnode.help或constructor.desc会显示在面板底部,便于理解节点用途。
特殊节点:scene/global(全局变量)
图中若包含scene/global类型的节点,它的Name / Type / Value(及 Min/Max)会直接呈现在所属组件的 Inspector 面板上(graph.js),相当于把图内的全局变量"提升"到组件层级,可像普通属性一样实时调节,甚至支持与动画关键帧联动(pretitle: AnimationModule.getKeyframeCode(...))。调节后若组件的on_event为render或update,会立即执行一步图并刷新场景。
图的存储与共享:inner graph 与 graph file
Graph 组件支持两种存储方式(源码中由from_file标志区分):
- inner graph(内嵌图):
from_file = false,图直接序列化在组件内部,随场景保存;工具栏中的Save按钮对这类图不可用; - graph from file(文件图):
from_file = true,图存储为独立的GraphCode资源(.graph文件),同一份图可被多个组件共享;编辑后需点击Compile或Save,将画布内容写回 GraphCode 并传播到所有引用它的组件(graphcode.propagate(),graphWidget.js)。
在组件 Inspector 中(graph.js)可以通过右键动作在两种模式间切换:
- Convert to Inner Graph:转为内嵌图;
- Convert to Graph From File:转为文件图(需指定图文件名)。
另外,组件上还有两个实用动作(graph.js):
- Set Title:为图设置标题;
- Show Graph JSON:在弹出的 JSON 检查器中查看整张图的序列化结构——这也是排查连线问题的好帮手。
深入原理:图如何驱动场景
从实现层面看,GraphComponent每次执行调用的是this._graph.runStep(1, LS.catch_exceptions)(litescene.js),即 LiteGraph 的LGraph.runStep单步求值:所有Always模式节点按拓扑顺序执行一次,把输出数据沿连线推送到下游输入。而FXGraphComponent则完全绑定渲染管线:在BEFORE_RENDER阶段向所有节点广播onPreRenderExecute预读纹理,在帧上下文启用后执行图,最终把渲染结果注册为:color_uid、:depth_uid、:extra_uid三类可复用资源(litescene.js)。理解这条链路,有助于判断"为什么我的图在某个时机没生效"——通常要回到on event配置与节点的Mode设置上排查。
更多资料
- 图编辑器底层基于LiteGraph节点引擎实现,WebGLStudio.js 运行时内置 litegraph.js,组件与编辑器的集成代码见 graph.js、graphWidget.js;
- 图组件的完整序列化字段、执行逻辑与渲染绑定位于 litescene.js 的
GraphComponent(约 L44489 起)与FXGraphComponent(约 L44927 起); - 更多关于节点系统本身的机制(节点类型注册、图序列化、运行状态机等)可参考 LiteGraph 项目文档;
- 编辑器的整体架构说明见 guides/editor_architecture.md,其他脚本模块清单见 guides/editor_scripts.md。
- 图形学
- 前端
- 开发工具
【免费下载链接】webglstudio.js
A full open source 3D graphics editor in the browser, with scene editor, coding pad, graph editor, virtual file system, and many features more.
相关推荐
XYFlow项目中ConnectionLine组件toHandle属性的行为解析
XYFlow项目中ConnectionLine组件toHandle属性的行为解析 在React Flow/Svelte Flow这类可视化图表库中,Connec
前端UI组件图表库Godot ColorRect 节点完全指南:纯色矩形控件的属性、用法与实战场景
Godot ColorRect 节点完全指南:纯色矩形控件的属性、用法与实战场景 ColorRect 是 Godot 引擎中最简单的 UI 控件之一:它只负责绘
文档教程游戏开发CC Switch快速上手教程:从0到1,如何一键切换Claude Code与Codex的API供应商
CC Switch快速上手教程:从0到1,如何一键切换Claude Code与Codex的API供应商 CC Switch 是一款跨平台的 AI 编程工具管理助
AI 应用开发者工具桌面应用
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考