- 音视频
- 图形学
- 桌面应用
【免费下载链接】t3
TiXL is an open source software to create realtime motion graphics.
导读:本文基于 TiXL 开源仓库中
SelectVerticesWithSDF算子的官方文档与实现源码,系统讲解如何用 SDF 对象/场作为选择器,在 3D 空间中批量选中网格顶点并写入选择值(Selection),从而驱动位移、缩放等后续网格修改流程。读完本文,你将掌握该算子的全部输入参数与枚举取值、内部 compute shader 的取值与映射原理,以及它与SelectVertices、SelectPoints等邻近算子的分工,可直接在 TiXL 的节点图(Graph)中搭出「SDF 选择 → 选择性变形」的实战链路。
SelectVerticesWithSDF位于 TiXL 的Lib.mesh.modify算子库中(官方文档),功能是:通过 SDF 对象/场在 3D 空间中选择顶点,并为这些顶点添加(写入)数值。它与SelectPoints思路类似,但作用于网格顶点而非点云。它需要一个 SDF 输入(如BoxSDF、ChainLinkSDF、FractalSDF)来选择点,以及任意形式的点/网格输入(如GridPoints、RadialPoints、SpherePoints、PointsOnMesh等)。
一、算子定位:网格修改链路中的"选择"环节
在 Lib.mesh.modify 算子库 中,有一族算子负责修改网格顶点。SelectVerticesWithSDF属于其中的"选择类"算子,其输出是一个带有Selection(选择值)属性的MeshBuffers,可继续喂给后续依赖该属性的算子做选择性处理。
| 算子 | 定位 |
|---|---|
SelectVertices | 用体积(Volume)(盒体/球体等)设置顶点的选择属性 |
SelectVerticesWithSDF | 用任意 SDF 场设置/累加顶点的选择属性 |
SelectPoints | 作用于点(Points)而非网格顶点,思路与前者一致 |
ScatterMeshFaces | 类似DisplaceMesh,但基于面中心散布 |
从 SelectVertices 文档 可见,两者目标一致,区别在于选择器来源:SelectVertices用内置体积形状(VolumeShape、Center、Stretch、Scale、Rotate等),SelectVerticesWithSDF则把选择器完全外包给任何实现了 SDF 的对象或场——这使它能够表达任意复杂的选区形状,并在运行时动态变化。
二、输入参数全解析
算子共暴露 13 个输入参数,其中前两个为必填(Required)。下表完整列出(默认值取自 SelectVerticesWithSDF.t3):
| 名称 | 关联性与类型 | 默认值 | 说明 |
|---|---|---|---|
| Mesh | MeshBuffers(Required) | null | 待处理的输入网格 |
| SdfField | ShaderGraphNode(Required) | null | 用于选择顶点的 SDF 对象/场 |
| Strength | Single | 1.0 | 写入强度,控制新值对原选择值的影响比例 |
| StrengthFactor | Int32(枚举 None/F1/F2) | 0 | 强度系数来源:None=1,F1/F2 与顶点的既有选择值联动 |
| WriteTo | Int32(枚举 None/F1/F2) | 1 | 将结果写入顶点的哪个属性通道 |
| Mode | Int32(枚举 Override/Add/Sub/Multiply/Invert) | 0 | 新选择值与原选择值的混合模式 |
| Mapping | Int32(枚举 Centered/FromStart/PingPong/Repeat) | 0 | SDF 距离值到 0..1 选择值的映射方式 |
| Range | Single | 1.0 | SDF 距离的映射范围 |
| Offset | Single | 0.0 | 映射偏移(对应 shader 中的 Center) |
| GainAndBias | Vector2 | (0.5, 0.5) | 对映射结果的增益(gain)与偏置(bias)整形 |
| Scatter | Single | 0.0 | 每个顶点加入基于哈希的随机偏移,打散选择边界 |
| ClampNegative | Boolean | true | 防止结果变为负值(负值可能导致顶点出现反向缩放) |
| DiscardNonSelected | Boolean | false | 将选择值 ≤ 0 的顶点转为 Separator(Scale=NaN),使其不被渲染 |
对应的 C# 槽位定义见 SelectVerticesWithSDF.cs,其中的三个枚举类型(Modes、FModes、MappingModes)在源码中直接声明:
private enum Modes { Override, // 0 Add, // 1 Sub, // 2 Multiply, // 3 Invert, // 4 } private enum FModes { None, // 0 F1, // 1 F2, // 2 } private enum MappingModes { Centered, // 0 FromStart, // 1 PingPong, // 2 Repeat, // 3 }2.1 必填输入:Mesh 与 SdfField
- Mesh:
T3.Core.DataTypes.MeshBuffers类型,即PbrVertex组成的顶点缓冲。算子只读取顶点位置(Position)与既有选择值(Selected),不改动拓扑。 - SdfField:
T3.Core.DataTypes.ShaderGraphNode类型,可以是任何生成 SDF 场的节点(BoxSDF、ChainLinkSDF、FractalSDF等)。它是真正的"选择器":以顶点位置为输入,返回该点到场表面的有符号距离(SDF 值)。
从 .t3 文件的内部实现看,SdfField先进入GenerateShaderGraphCode节点(模板Lib:shaders/3d/mesh/modify/SelectVerticesWithField.hlsl),再经ComputeShaderFromSource编译成 compute shader 执行,见 SelectVerticesWithSDF.t3。
2.2 选择值混合:Mode 与 Strength
- Mode(SelectMode)控制"场计算出的 f"与"顶点原有选择值 org"的合成方式,对应 shader 中的
#define ModeOverride 0…ModeInvert 4(见 SelectVerticesWithField.hlsl):Override:直接以新值覆盖;Add:f += org,在原有选择值上累加;Sub:f = org - f,减去场贡献;Multiply:f *= org,按原有选择值加权;Invert:f = 1 - f * org,反向处理。
- Strength是最终写入的权重:shader 中
float strength = Strength * (StrengthFactor == 0 ? 1 : p.Selected);,即强度会被"强度系数"调制;最终结果通过lerp(org, f * abs(strength + 1), strength)在原值与新值之间插值。 - ClampNegative(shader 中
ClampResult)会执行result = max(0, result),避免负选择值导致顶点反向缩放。
2.3 距离映射:Mapping、Range、Offset、GainAndBias、Scatter
这是把「SDF 距离」转成「0..1 选择值」的核心环节。shader 中的关键代码:
float f0 = GetDistance(pos) + scatter * Range; switch (MappingMode) { case MAPPING_CENTERED: // 0 Centered f = (f0 + Range / 2) / Range - Center / (Range * 0.5f); break; case MAPPING_FORSTART: // 1 FromStart f = f0 / Range - Center; break; case MAPPING_PINGPONG: // 2 PingPong f = fmod((2 * f0 - 2 * Center * Range - 1) / Range, 2); f = abs(f - 1); break; case MAPPING_REPEAT: // 3 Repeat f = fmod(f0 / Range - 0.5 - Center, 1); break; } f = 1 - ApplyGainAndBias(f, GainAndBias);其中scatter = Scatter * (hash11u(i.x) - 0.5)用顶点索引哈希为每个顶点引入 ±0.5·Scatter 的随机扰动(乘以 Range 后叠加到距离上),可让选择边界呈现"毛边"效果;ApplyGainAndBias(来自shared/bias-functions.hlsl)对映射结果做增益/偏置整形,GainAndBias默认 (0.5, 0.5)。
2.4 输出控制:WriteTo、DiscardNonSelected
- WriteTo决定结果写入的通道,shader 中当前实现为
case 1: p.Selected = result;,即写入顶点的Selected属性(PbrVertex 的选择通道)。 - DiscardNonSelected(shader 中同名)把选择值 ≤ 0 的顶点转换为 Separator(Scale=NaN),使其在渲染阶段被剔除——常用于"只保留 SDF 内的部分"。
三、输出:ResultMesh
| 名称 | 类型 |
|---|---|
| ResultMesh | T3.Core.DataTypes.MeshBuffers |
输出仍是一个完整的MeshBuffers,顶点数、拓扑与输入一致,仅Selected通道被更新(以及 DiscardNonSelected 时的 Scale 标记)。因此它可直接串联到依赖选择值的后续节点,形成选择驱动的修改链。
四、内部实现:GPU Compute Shader 全流程
从 SelectVerticesWithSDF.t3 的内部子图结构看,该算子完全由现有节点组合而成,是一条典型的 GPU 处理链:
- 拆分网格:
_MeshBufferComponents从输入 Mesh 中取出顶点缓冲等组件; - 字段函数生成:
GenerateShaderGraphCode读取模板SelectVerticesWithField.hlsl并注入 SDF 场代码(/*{FIELD_FUNCTIONS}*/、/*{FIELD_CALL}*/等占位符); - 编译与调度:
ComputeShaderFromSource编译 HLSL,CalcDispatchCount依据顶点数计算 dispatch,ComputeShaderStage以 64 线程/组分发(见 .t3 中 Dispatch=(64,1,1)); - 参数打包:
FloatsToBuffer/IntsToBuffer把浮点与枚举参数写入常量缓冲(cbuffer Params : register(b0/b1/b2)); - 写回:
ExecuteBufferUpdate触发执行,_AssembleMeshBuffers把处理后的顶点重组为ResultMesh输出。
shader 主体 SelectVerticesWithField.hlsl 的核心流程可概括为:
- 通过
SourceVertices.GetDimensions取得顶点数并做越界保护; - 读取
PbrVertex p,取其Position作为场采样点; - 采样 SDF:
float f0 = GetDistance(pos),其中GetDistance调用注入的场函数并取返回值的.w分量作为有符号距离; - 按
MappingMode映射距离 → 0..1 的选择强度; - 按
SelectMode与既有p.Selected混合,Strength加权; ClampResult(ClampNegative)钳制非负;- 按
WriteTo写入p.Selected(或按DiscardNonSelected置 Scale=NaN); - 写回
ResultVertices[i.x]。
五、实战:搭建「SDF 选区 + 选择性位移」链路
结合仓库中的邻近算子,一个典型的实战场链如下:
- 准备网格:任意网格算子输出
MeshBuffers,接入SelectVerticesWithSDF的Mesh; - 准备选区:接入一个 SDF 节点(如
BoxSDF、ChainLinkSDF、FractalSDF)到SdfField,并调整Range(默认 1.0)控制选区范围、Offset(默认 0.0)平移选区; - 选择与写入:
Mode选Override(0)以覆盖原值,Mapping按需选择Centered(0)或FromStart(1);若希望边界柔和,调节GainAndBias(默认 0.5, 0.5)与Scatter; - 处理:
ResultMesh接入依赖选择值的修改算子——例如DeformMesh(Spherize/Taper/Twist)或DisplaceMesh,从而实现"仅 SDF 内顶点被变形"的效果; - 可选剔除:开启
DiscardNonSelected,让选区外的顶点不被渲染,直接呈现"SDF 雕刻"结果;配合ClampNegative(默认 true)防止负选择值引发反向缩放。
若要复用SelectPoints的思路作用于点云,只需把输入替换为GridPoints、RadialPoints、SpherePoints、PointsOnMesh等任意点生成器即可,选择与混合逻辑完全一致。
六、注意事项与限制
WriteTo目前仅实现写入Selected通道(shader 中仅case 1),枚举中的None/F2尚为扩展预留;StrengthFactor的F1/F2会读取顶点既有选择值调制强度,配合Multiply模式可做"叠加衰减"效果;Scatter依赖hash11u(见shared/hash-functions.hlsl),同一网格索引的随机值每帧稳定,因此动画不会闪烁;- 选择值最终会被下游算子消费,建议先接入
ColorVerticesWithField或直接预览Selected通道做可视化调试。
本文以 SelectVerticesWithSDF.md 为主干,结合 SelectVerticesWithSDF.cs、SelectVerticesWithSDF.t3 与 SelectVerticesWithField.hlsl 编写,算子库总览见 Lib.mesh.modify README。
- 音视频
- 图形学
- 桌面应用
【免费下载链接】t3
TiXL is an open source software to create realtime motion graphics.
相关推荐
TiXL 场空间算子 RotateAxis 深度指南:在 3D 空间中旋转 SDF 场
TiXL 场空间算子 RotateAxis 深度指南:在 3D 空间中旋转 SDF 场 本文是 TiXL(t3)场算子库中 RotateAxis 的完整技术指南
音视频图形学桌面应用TiXL SpatialDisplaceSDF 详解:用 Simplex 噪声实现 3D SDF 空间扭曲
TiXL SpatialDisplaceSDF 详解:用 Simplex 噪声实现 3D SDF 空间扭曲 导读 SpatialDisplaceSDF 是 Ti
音视频图形学桌面应用TiXL 中 RepeatFieldAtPoints 算子详解:在任意点阵上重复 SDF 场
TiXL 中 RepeatFieldAtPoints 算子详解:在任意点阵上重复 SDF 场 TiXL(t3)是面向实时动态图形(realtime motion
音视频图形学桌面应用
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考