关于 build-wireframe-scan-reveal
这项设计技能用于通过临时线框扫描揭示 3D 物体的实体表面,适合制作场景入场动画;同一世界空间波前负责协调线框与实体网格。
主要功能
- 01用同一扫描协调线框与实体表面
- 02让两种表现保持在世界空间
- 03动画化带延迟且不规则的扫描前沿
- 04移除并释放临时线框资源
- 05支持重播与减少动态效果状态
适用场景
- 01以线框先行的方式揭示 3D 形体
- 02协调经过缩放的场景组中的扫描效果
- 03提供重播并保留减少动态效果时的静态构图
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ mengto/ skills --skill build-wireframe-scan-reveal安装后在 Claude Code 中输入/build-wireframe-scan-reveal确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
agents/openai.yamldemo/index.htmlPROMPT.md详细介绍
构建线框扫描显现效果
让一个世界空间波前驱动两种表现:在前沿绘制拓扑,在其后方保留实体,然后移除临时线框。若线框是页面的永久视觉语言,请使用 technical-wireframe-info-layout;若驱动者是 DOM 滚动而非 3D 波,请使用 animation-on-scroll。
内容摘自 inner-green-3d.html:其中的扫描脉冲需要让程序化苔藓根系穿过卡片和文字生长,同时避免看起来像圆形遮罩。
配对两种表现
从同一源几何体创建实体网格和临时 LineSegments 线框。让两者的材质共享 uScanOrigin、uScanRadius 和时间。两者都保持在世界空间中;当组被缩放或嵌套时,局部空间距离会发生变化,导致两个前沿错位。
在前沿之外舍弃实体,并设置延迟,让线框先显现:
uniform vec3 uScanOrigin;
uniform float uScanRadius;
uniform float uScanEnabled;
bool unscanned(vec3 worldPosition, float lag) {
if (uScanEnabled < 0.5) return false;
float wobble =
sin(worldPosition.y * 0.011 + worldPosition.x * 0.007) * 36.0
+ sin(worldPosition.z * 0.021 + worldPosition.y * 0.013) * 17.0;
return distance(worldPosition, uScanOrigin)
> uScanRadius - lag + wobble;
}
// In the solid fragment shader:
if (unscanned(vWorldPosition, 520.0)) discard;
选择一个位于轮廓外部的原点,通常在左下方。居中的原点看起来像加载环。保留两个较长的正弦项;完美的圆形前沿看起来像剪切路径,而高频噪声会让边缘闪烁。
让线框跟随前沿移动
用相同半径测量每个线段片段:
float distanceFromOrigin = distance(vWorldPosition, uScanOrigin);
float rim = exp(-pow((distanceFromOrigin - uScanRadius) / 135.0, 2.0));
float trail = smoothstep(uScanRadius, uScanRadius - 950.0, distanceFromOrigin);
float alpha = (rim * 1.60 + trail * 0.34) * uWireOpacity;
使用加法混合、transparent: true、depthWrite: false,并选用场景强调色的浅色版本。除非必须让线框透过物体显示,否则保持深度测试开启。关闭深度测试会暴露稠密拓扑的后半部分,形成明亮且难以辨认的球体。
用一个驱动者控制动画
将已验证的时序作为起点:
| 参数 | 默认值 | 避免的问题 |
|---|---|---|
| 时长 | 3.4 s | 显现过快会像闪光 |
| 半径缓动 | 1 - (1 - t)^1.35 | 线性移动在视觉上会在远角附近停滞 |
| 实体延迟 | 520 世界单位 | 延迟为零会让线框和填充同时扫过 |
| 边缘宽度 | 135 单位 | 边缘过窄会产生混叠;过宽则会变成雾状 |
| 线框尾迹 | 950 单位 | 没有尾迹会让拓扑在可读之前就消失 |
| 线框淡出 | smoothstep(.72, 1, t) | 持续存在的线框会干扰完成后的表面 |
| 半径范围 | 场景对角线 × 1.3 + 900 | 完成后远角仍会被裁切 |
在时间线的前 6% 内让线框快速显现,然后在最后 28% 内淡出:
const e = Math.min(1, elapsed / 3.4);
scanRadius.value = easeOutPow(e) * maxRadius;
wireOpacity.value = Math.min(1, e / 0.06) * (1 - smoothstep(0.72, 1, e));
完成后,禁用舍弃分支,移除线框,并释放其几何体和材质。仅将其透明度设为零,会让重复几何体和着色器运算在页面剩余时间内继续占用资源。
布置场景并确定扫描尺寸
在布局完成且父级矩阵更新后计算 maxRadius。使用 ResizeObserver,对零尺寸根节点进行保护,更新相机投影,然后重新计算原点和最远范围。在字体或布局稳定之前只测量一次,会导致最后一个角落无法显现。
保持演示场景易于辨认:灰绿色背景、底部光池、白色编辑风格文字、浅色卡片,以及根系形状的造型。场景布置属于演示内容;可复用的技能仅包括配对两种表现和共享驱动者。
遵循动效偏好并管理生命周期
- 对于
prefers-reduced-motion: reduce,在约 62% 半径处渲染精心设计的诊断静帧,同时显示线框和实体。让重播控件重新组合该静帧并播报状态;不要隐藏场景。 - 将
dt限制为 1/30 s。隐藏标签页或屏幕外区块恢复时,重置时间基准。 - 当
document.hidden为真,或IntersectionObserver判定区块位于屏幕外时,暂停动画。 - 将设备像素比上限设为 2。
- 将重播控件实现为真正的按钮,提供可见的焦点样式和
aria-live状态区域。若画布仅用于装饰,则为其设置aria-hidden。 - 拆除时,取消动画帧、断开观察器、移除事件监听器,并释放几何体、材质、纹理和渲染器。
如实说明成本
额外的临时表示及其线条覆盖才是真正的成本。拓扑密度和过度绘制比半径计算更重要。只在入口处构建线框笼,使用能够保留轮廓的最粗边线图,并在扫描完成后立即释放。未经分析 GPU 在构建线框笼之前和期间的帧时间,不要声称性能有所提升。
验证
- 在 1440×900 分辨率下,将开始、中途和完成状态与源效果进行比较。
- 确认线框笼处处领先于实体,包括经过缩放的子组。
- 快进至完成,确认没有残留被裁切的孤岛。
- 重放两次,确认只有一个帧循环和一个线框笼。
- 在扫描期间分别调整为 390×844 和 1440×900 分辨率。
- 使用 Tab 键聚焦到重放按钮,确认焦点可见且状态会实时更新。
- 测试
?reduced=1或系统的减少动态效果设置:显示组合完成的静态画面,半径不再推进。 - 隐藏并重新显示标签页,然后离开并重新进入视口;确认时间不会跳跃。
- 确认控制台无错误,且完成后线框笼资源已释放。
将 demo/index.html 作为实际验证依据,并使用 demo/PROMPT.md 重新创建或改编。