news 2026/9/20 17:53:01

TiXL SelectVerticesWithSDF 详解:用 SDF 场在 3D 空间中批量选择与修改网格顶点

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
TiXL SelectVerticesWithSDF 详解:用 SDF 场在 3D 空间中批量选择与修改网格顶点
  • 音视频
  • 图形学
  • 桌面应用

【免费下载链接】t3

TiXL is an open source software to create realtime motion graphics.

项目地址:https://gitcode.com/GitHub_Trending/t3/t3
点击查看免费下载

导读:本文基于 TiXL 开源仓库中SelectVerticesWithSDF算子的官方文档与实现源码,系统讲解如何用 SDF 对象/场作为选择器,在 3D 空间中批量选中网格顶点并写入选择值(Selection),从而驱动位移、缩放等后续网格修改流程。读完本文,你将掌握该算子的全部输入参数与枚举取值、内部 compute shader 的取值与映射原理,以及它与SelectVerticesSelectPoints等邻近算子的分工,可直接在 TiXL 的节点图(Graph)中搭出「SDF 选择 → 选择性变形」的实战链路。

SelectVerticesWithSDF位于 TiXL 的Lib.mesh.modify算子库中(官方文档),功能是:通过 SDF 对象/场在 3D 空间中选择顶点,并为这些顶点添加(写入)数值。它与SelectPoints思路类似,但作用于网格顶点而非点云。它需要一个 SDF 输入(如BoxSDFChainLinkSDFFractalSDF)来选择点,以及任意形式的点/网格输入(如GridPointsRadialPointsSpherePointsPointsOnMesh等)。

一、算子定位:网格修改链路中的"选择"环节

在 Lib.mesh.modify 算子库 中,有一族算子负责修改网格顶点SelectVerticesWithSDF属于其中的"选择类"算子,其输出是一个带有Selection(选择值)属性MeshBuffers,可继续喂给后续依赖该属性的算子做选择性处理。

算子定位
SelectVertices体积(Volume)(盒体/球体等)设置顶点的选择属性
SelectVerticesWithSDF任意 SDF 场设置/累加顶点的选择属性
SelectPoints作用于点(Points)而非网格顶点,思路与前者一致
ScatterMeshFaces类似DisplaceMesh,但基于面中心散布

从 SelectVertices 文档 可见,两者目标一致,区别在于选择器来源:SelectVertices用内置体积形状(VolumeShapeCenterStretchScaleRotate等),SelectVerticesWithSDF则把选择器完全外包给任何实现了 SDF 的对象或场——这使它能够表达任意复杂的选区形状,并在运行时动态变化。

二、输入参数全解析

算子共暴露 13 个输入参数,其中前两个为必填(Required)。下表完整列出(默认值取自 SelectVerticesWithSDF.t3):

名称关联性与类型默认值说明
MeshMeshBuffers(Required)null待处理的输入网格
SdfFieldShaderGraphNode(Required)null用于选择顶点的 SDF 对象/场
StrengthSingle1.0写入强度,控制新值对原选择值的影响比例
StrengthFactorInt32(枚举 None/F1/F2)0强度系数来源:None=1,F1/F2 与顶点的既有选择值联动
WriteToInt32(枚举 None/F1/F2)1将结果写入顶点的哪个属性通道
ModeInt32(枚举 Override/Add/Sub/Multiply/Invert)0新选择值与原选择值的混合模式
MappingInt32(枚举 Centered/FromStart/PingPong/Repeat)0SDF 距离值到 0..1 选择值的映射方式
RangeSingle1.0SDF 距离的映射范围
OffsetSingle0.0映射偏移(对应 shader 中的 Center)
GainAndBiasVector2(0.5, 0.5)对映射结果的增益(gain)与偏置(bias)整形
ScatterSingle0.0每个顶点加入基于哈希的随机偏移,打散选择边界
ClampNegativeBooleantrue防止结果变为负值(负值可能导致顶点出现反向缩放)
DiscardNonSelectedBooleanfalse将选择值 ≤ 0 的顶点转为 Separator(Scale=NaN),使其不被渲染

对应的 C# 槽位定义见 SelectVerticesWithSDF.cs,其中的三个枚举类型(ModesFModesMappingModes)在源码中直接声明:

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

  • MeshT3.Core.DataTypes.MeshBuffers类型,即PbrVertex组成的顶点缓冲。算子只读取顶点位置(Position)与既有选择值(Selected),不改动拓扑。
  • SdfFieldT3.Core.DataTypes.ShaderGraphNode类型,可以是任何生成 SDF 场的节点(BoxSDFChainLinkSDFFractalSDF等)。它是真正的"选择器":以顶点位置为输入,返回该点到场表面的有符号距离(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 0ModeInvert 4(见 SelectVerticesWithField.hlsl):
    • Override:直接以新值覆盖;
    • Addf += org,在原有选择值上累加;
    • Subf = org - f,减去场贡献;
    • Multiplyf *= org,按原有选择值加权;
    • Invertf = 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

名称类型
ResultMeshT3.Core.DataTypes.MeshBuffers

输出仍是一个完整的MeshBuffers,顶点数、拓扑与输入一致,仅Selected通道被更新(以及 DiscardNonSelected 时的 Scale 标记)。因此它可直接串联到依赖选择值的后续节点,形成选择驱动的修改链。

四、内部实现:GPU Compute Shader 全流程

从 SelectVerticesWithSDF.t3 的内部子图结构看,该算子完全由现有节点组合而成,是一条典型的 GPU 处理链:

  1. 拆分网格_MeshBufferComponents从输入 Mesh 中取出顶点缓冲等组件;
  2. 字段函数生成GenerateShaderGraphCode读取模板SelectVerticesWithField.hlsl并注入 SDF 场代码(/*{FIELD_FUNCTIONS}*//*{FIELD_CALL}*/等占位符);
  3. 编译与调度ComputeShaderFromSource编译 HLSL,CalcDispatchCount依据顶点数计算 dispatch,ComputeShaderStage以 64 线程/组分发(见 .t3 中 Dispatch=(64,1,1));
  4. 参数打包FloatsToBuffer/IntsToBuffer把浮点与枚举参数写入常量缓冲(cbuffer Params : register(b0/b1/b2));
  5. 写回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 选区 + 选择性位移」链路

结合仓库中的邻近算子,一个典型的实战场链如下:

  1. 准备网格:任意网格算子输出MeshBuffers,接入SelectVerticesWithSDFMesh
  2. 准备选区:接入一个 SDF 节点(如BoxSDFChainLinkSDFFractalSDF)到SdfField,并调整Range(默认 1.0)控制选区范围、Offset(默认 0.0)平移选区;
  3. 选择与写入ModeOverride(0)以覆盖原值,Mapping按需选择Centered(0)或FromStart(1);若希望边界柔和,调节GainAndBias(默认 0.5, 0.5)与Scatter
  4. 处理ResultMesh接入依赖选择值的修改算子——例如DeformMesh(Spherize/Taper/Twist)或DisplaceMesh,从而实现"仅 SDF 内顶点被变形"的效果;
  5. 可选剔除:开启DiscardNonSelected,让选区外的顶点不被渲染,直接呈现"SDF 雕刻"结果;配合ClampNegative(默认 true)防止负选择值引发反向缩放。

若要复用SelectPoints的思路作用于点云,只需把输入替换为GridPointsRadialPointsSpherePointsPointsOnMesh等任意点生成器即可,选择与混合逻辑完全一致。

六、注意事项与限制

  • WriteTo目前仅实现写入Selected通道(shader 中仅case 1),枚举中的None/F2尚为扩展预留;
  • StrengthFactorF1/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.

项目地址:https://gitcode.com/GitHub_Trending/t3/t3
点击查看免费下载
上一篇:企业级图像修复解决方案:Restormer在生产环境中的规模化实践
下一篇:Buzz:企业级本地音频转录与翻译架构设计与性能优化实战指南

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/20 17:51:33

国家社科基金申请书成功样本拆解:评审视角下的申报书写作要点

简介:一份国家社科基金项目申请书的成功样本解读文档,面向高校科研人员、课题申报者和研究生,系统拆解申报书各模块的写作思路与填写规范。资源为1个doc文档,包体大小仅89KB,文件虽小却浓缩了完整申报书结构与关键要点…

作者头像 李华
网站建设 2026/9/20 17:51:33

DeskcommCRM自托管实战:中小企业客户管理与团队协作落地指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/20 17:49:58

电赛备战全景指南:从51单片机到STM32的系统设计与赛题实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/20 17:49:39

Minitab数据分析与六西格玛实践:从七个窗口到命令行模板

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/20 17:42:43

Logisim运算器设计:从串行进位到32位MIPS快速加法器

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/20 17:41:56

电子产品量产测试与烧录工具:从知识清单到产线实战的课程重构

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华