Appearance
Effects API
u-space 提供了两个基于 Three.js 着色语言(TSL/WebGPU 节点)的静态特效工具:MaterialEffects 用于为对象应用高亮、呼吸等材质特效,TSLEffects 用于生成动态颜色节点模式和可组合的 Outline 输出效果。
MaterialEffects
静态工具类,将基于 TSL 的视觉特效直接应用于对象的材质。适用于任何 Object3D(支持单个或数组),会自动遍历所有子网格。 当对象是 InstanceObject(例如 SceneInstanceObject、FacilityInstanceObject 或楼层里的 FloorSemanticInstanceObject)时,highlightColor() / removeHighlightColor() 会通过 setInstanceHighlight() / clearInstanceHighlight() 改写该实例的颜色和透明度,而不是改动共享 batch 材质。 InstanceObject 支持 overwrite 的替换/染色语义;depthWrite 属于共享 batch 材质状态,不能按单个实例设置,因此对该类对象不会生效。
特性:
- 效果可叠加:高亮和呼吸效果可同时作用于同一对象,呼吸在高亮结果之上混合
- 共享材质安全:按材质跟踪引用计数,多个 Mesh 共享材质时互不干扰
- 完整还原:移除效果时自动恢复材质原始的
colorNode、opacityNode、transparent和depthWrite状态
MaterialEffects.highlightColor(object, options?)
为对象中所有网格应用颜色/透明度高亮。
typescript
import { MaterialEffects } from 'u-space';
// 以 50% 透明度高亮为红色(叠加模式)
MaterialEffects.highlightColor(myModel, {
color: 0xff0000,
opacity: 0.5,
overwrite: false, // false = 叠加(相乘),true = 完全替换颜色
});
// 半透明效果
MaterialEffects.highlightColor(myModel, { opacity: 0.3 });
// X 光效果(替换颜色 + 关闭深度写入)
MaterialEffects.highlightColor(myModel, {
color: 0x0088ff,
opacity: 0.25,
overwrite: true,
depthWrite: false,
});
// 支持数组
MaterialEffects.highlightColor([model1, model2], { color: 0x00ff00 });HighlightColorOptions
| 属性 | 类型 | 默认值 | 说明 |
|---|---|---|---|
color | ColorRepresentation | 0xff0000 | 高亮颜色。 |
opacity | number | 0.5 | 高亮时材质的透明度。 |
overwrite | boolean | false | false = 与原始颜色相乘(叠加);true = 完全替换颜色。 |
depthWrite | boolean | — | 可选。设为 false 可产生 X 光透视效果。不设置时保持原始值。 |
multiplyOpacity | boolean | false | 可选。设为 true 时高亮透明度会与材质原始透明度相乘,主要用于语义 fallback 模型内部。 |
MaterialEffects.removeHighlightColor(object)
移除高亮效果。当对象上所有效果都被移除后,材质将完整恢复到原始状态。
typescript
MaterialEffects.removeHighlightColor(myModel);MaterialEffects.breatheColor(object, options?)
为对象应用呼吸灯效果,颜色在材质原色与目标颜色之间随时间脉冲变化。需要 viewer.frameloop = 'always'。
typescript
MaterialEffects.breatheColor(myModel, {
color: 0x00ff00,
speed: 1.0,
intensity: 2.0,
});
viewer.frameloop = 'always';BreatheColorOptions
| 属性 | 类型 | 默认值 | 说明 |
|---|---|---|---|
color | ColorRepresentation | 0x00ff00 | 呼吸目标颜色。 |
speed | number | 1.0 | 振荡速度。 |
intensity | number | 2.0 | 控制峰值的锐度。 |
MaterialEffects.removeBreatheColor(object)
移除呼吸效果。
typescript
MaterialEffects.removeBreatheColor(myModel);MaterialEffects.wireframe(object, enabled?)
开启或关闭线框渲染模式。
typescript
MaterialEffects.wireframe(myModel); // 开启线框
MaterialEffects.wireframe(myModel, false); // 关闭线框
MaterialEffects.removeWireframe(myModel); // 等同于 wireframe(obj, false)MaterialEffects.fadeIn(object, options?) / MaterialEffects.fadeOut(object, options?)
淡入/淡出动画效果。返回 Promise,在动画完成后 resolve。淡出后对象材质保持透明状态。
typescript
// 淡出
await MaterialEffects.fadeOut(myModel, { duration: 1000 });
// 淡入
await MaterialEffects.fadeIn(myModel, { duration: 500 });动画期间需要持续渲染,建议配合
viewer.frameloop = 'always'使用。
FadeOptions
| 属性 | 类型 | 默认值 | 说明 |
|---|---|---|---|
duration | number | 500 | 动画时长(毫秒)。 |
TSLEffects
静态工厂类。flow()、breathe() 和 fluid() 返回可赋给 NodeMaterial.colorNode 的 TSL 颜色节点;outline() 返回接入 RenderPipeline 的输出效果。持续动画需要 viewer.frameloop = 'always'。
TSLEffects.outline(options?)
创建基于 Three.js OutlineNode 的屏幕空间描边效果。它不会修改对象材质,而是通过 RenderPipeline.addOutputEffect() 叠加在默认渲染结果上,因此可以与内置 Bloom、SSGI、SSR 以及其他 output effects 组合。
typescript
import { TSLEffects } from 'u-space';
const outline = TSLEffects.outline({
selectedObjects: [model],
edgeStrength: 3,
edgeThickness: 1.5,
edgeGlow: 0,
visibleEdgeColor: 0x00e5ff,
hiddenEdgeColor: 0xff4d6d,
downSampleRatio: 2,
instanceBoundsProxy: true,
instanceBoundsPadding: 0.05,
});
viewer.renderPipeline.addOutputEffect(outline);
// 替换当前描边对象,不需要重建后处理链。
outline.setSelectedObjects([anotherObject]);
// 运行时更新样式与 InstanceObject bounds proxy 参数。
outline.update({ edgeStrength: 4, edgeGlow: 0.25 });
viewer.render();
// 销毁前先从 RenderPipeline 移除。
viewer.renderPipeline.removeOutputEffect(outline);
outline.dispose();TSLOutlineOptions
| 属性 | 类型 | 默认值 | 说明 |
|---|---|---|---|
selectedObjects | readonly Object3D[] | [] | 初始描边对象。普通 Mesh、Group 与核心 InstanceObject 均可传入。 |
edgeStrength | number | 3 | 边缘颜色强度。 |
edgeThickness | number | 1 | 边缘厚度。 |
edgeGlow | number | 0 | 描边向外扩散的发光强度。 |
visibleEdgeColor | ColorRepresentation | 0xffffff | 可见边缘颜色。 |
hiddenEdgeColor | ColorRepresentation | 0x4e3636 | 被遮挡边缘颜色。 |
downSampleRatio | number | 2 | Outline pass 降采样比例;非有限值或 <= 0 时恢复为 2。值越大成本越低,但边缘精度也越低。 |
instanceBoundsProxy | boolean | true | InstanceObject 没有可直接描边的渲染子树时,是否用世界包围盒代理生成轮廓。 |
instanceBoundsPadding | number | 0 | bounds proxy 每个方向额外扩张的世界单位。 |
instanceBoundsMinSize | number | 0.001 | bounds proxy 每个轴向的最小尺寸,避免退化包围盒无法描边。 |
返回的 TSLOutlineEffect
| 成员 | 说明 |
|---|---|
selectedObjects | 当前逻辑选择对象的只读快照。 |
outlineNode | 当前内部 OutlineNode;在 RenderPipeline 首次构建前为 null,Scene 或 Camera 变化后可能被替换。 |
setSelectedObjects(objects) | 替换当前选择并返回自身,便于链式调用。空数组会清除描边。 |
update(options) | 更新除 selectedObjects 外的全部样式和 bounds proxy 选项,并返回自身。 |
dispose() | 释放内部 OutlineNode、代理 Geometry/Material 和 dirty 订阅。调用前应先 removeOutputEffect()。 |
对于 InstanceObject,效果会优先描边 getInstanceRenderObject() 返回的可渲染对象;如果逻辑对象自身包含 Mesh/Sprite,则直接使用该对象;只有两者都不可用时才根据 getInstanceBoundingBox() 创建不可见 bounds proxy。代理会监听 onInstanceRenderDirty(),在实例显隐、变换或包围盒变化后同步,而且不会参与拾取、颜色输出或阴影。
如果业务设置了自定义
viewer.renderPipeline.setOutputComposer(),RenderPipeline 会按自定义 composer 语义跳过所有 output effects,Outline 也不会显示。更新选择或参数后,frameloop = 'demand'的 Viewer 需要调用viewer.render()或viewer.invalidate()请求新帧。
TSLEffects.flow(parameters?)
沿网格 UV X 轴方向的定向光扫效果,适用于道路、管道和流线。
typescript
import { TSLEffects } from 'u-space';
myTubeMesh.material.colorNode = TSLEffects.flow({
baseColor: 0x001133,
flowColor: 0x00aaff,
speed: 1.5,
scale: 4.0,
intensity: 6.0,
});
viewer.frameloop = 'always';参数:
| 属性 | 类型 | 默认值 | 说明 |
|---|---|---|---|
baseColor | ColorRepresentation | 0xffffff | 背景/底色。 |
flowColor | ColorRepresentation | 0x00ff00 | 扫光高亮颜色。 |
speed | number | 1.0 | 动画速度(越高扫光越快)。 |
scale | number | 3.0 | 图案的空间频率。 |
intensity | number | 4.0 | 峰值锐度,值越高光束越细。 |
TSLEffects.breathe(parameters?)
在两种颜色之间随时间振荡的脉冲发光效果,适合状态指示器和警报。
typescript
myMesh.material.colorNode = TSLEffects.breathe({
baseColor: 0x333333,
breathColor: 0x00ff88,
speed: 2.0,
intensity: 3.0,
});参数:
| 属性 | 类型 | 默认值 | 说明 |
|---|---|---|---|
baseColor | ColorRepresentation | 0xffffff | 低/静息状态的颜色。 |
breathColor | ColorRepresentation | 0x00ff00 | 峰值亮度时的颜色。 |
speed | number | 1.0 | 振荡速度。 |
intensity | number | 2.0 | 控制峰值的锐度。 |
TSLEffects.fluid(parameters?)
噪声扭曲的流动效果,适用于水面、等离子体或有机流动材质。
typescript
myPlaneMesh.material.colorNode = TSLEffects.fluid({
baseColor: 0x002244,
flowColor: 0x0066ff,
speed: 0.5,
scale: 2.0,
intensity: 1.5,
distortion: 0.3,
});参数:
| 属性 | 类型 | 默认值 | 说明 |
|---|---|---|---|
baseColor | ColorRepresentation | 0xffffff | 基础颜色。 |
flowColor | ColorRepresentation | 0x0000ff | 流体高亮颜色。 |
speed | number | 1.0 | 动画速度。 |
scale | number | 1.0 | 噪声图案的 UV 缩放比例。 |
intensity | number | 1.0 | 流体图案的锐度。 |
distortion | number | 0.5 | 采样前噪声对 UV 的扭曲程度。 |