平面扫描

Three.js 平面扫描效果 | 三维可视化 / AI 提示词
📋 AI 提示词
prompt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
使用 Three.js 实现【平面扫描效果】,具体要求:
【核心特效】
- 圆形扫描动画
- 透明度渐变效果
- 纹理遮罩处理
【场景与光照】
- 深灰色背景
- 纹理贴图应用
- 平面几何体
【交互与控制】
- OrbitControls 视角控制
- 扫描速度可调
【技术要求】
- Three.js 版本
- onBeforeCompile 着色器修改
- TextureLoader 纹理加载
🖼️ 效果预览
🎮 案例演示
📖 效果拆解
| 层次 | 视觉效果 | 技术实现 |
|---|---|---|
| 基础 | 平面几何体 | PlaneGeometry |
| 核心特效 | 圆形扫描动画 | onBeforeCompile 修改 |
| 增强细节 | 纹理遮罩 | 透明度检测 discard |
| 动画效果 | 扫描线移动 | 时间驱动的半径变化 |
🔧 核心技术点
1. onBeforeCompile 修改
在现有材质上动态修改着色器:
javascript
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
material.onBeforeCompile = (shader) => {
// 添加自定义 uniforms
Object.keys(uniforms).forEach((key) => shader.uniforms[key] = uniforms[key]);
// 修改顶点着色器
shader.vertexShader = shader.vertexShader.replace(`void main() {`,
`varying vec2 vUv;
varying vec3 v_position;
void main() {
vUv = uv;
v_position = position;`
);
// 修改片段着色器
shader.fragmentShader = shader.fragmentShader.replace(
/#include <common>/,
Object.keys(uniforms).map(i => 'uniform ' + uniforms[i].unit + ' ' + i + ';').join('\n') +
'\n' + 'varying vec3 v_position; varying vec2 vUv;\n' + '\n#include <common>\n'
);
}
2. 扫描效果实现
在片段着色器中实现圆形扫描:
glsl
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
float dis = length(v_position - center);
vec4 diffuseColor;
if(dis < (innerCircleWidth + circleWidth) && dis > innerCircleWidth) {
float r = (dis - innerCircleWidth) / circleWidth;
float cOpacity = reverseOpacity ? (innerCircleWidth / circleMax) : 1. - (innerCircleWidth / circleMax);
#ifdef USE_MAP
vec3 textureColor = texture2D(map, vUv).rgb;
if(isDisCard && textureColor.r < 0.1 && textureColor.g < 0.1 && textureColor.b < 0.1) discard;
#endif
diffuseColor = vec4(mix(diff, color3, r) * vec3(intensity, intensity, intensity),
opacity * cOpacity * opacityScale);
} else {
if(isDisCard) discard;
else diffuseColor = vec4(diffuse, opacity);
}
3. 动态扫描控制
在动画循环中更新扫描半径:
javascript
1
2
3
4
5
6
7
8
9
function animate() {
// 扫描半径循环变化
uniforms.innerCircleWidth.value < uniforms.circleMax.value
? uniforms.innerCircleWidth.value += uniforms.circleSpeed.value
: uniforms.innerCircleWidth.value = 0;
requestAnimationFrame(animate);
controls.update();
renderer.render(scene, camera);
}
💡 调试与优化
| 问题类型 | 表现形式 | 解决方案 |
|---|---|---|
| 着色器替换失败 | 材质无变化 | 打印 shader 源码确认替换锚点 |
| 纹理加载失败 | 纹理不显示 | 检查纹理路径和跨域设置 |
| 透明度异常 | 扫描区域不透明 | 调整 opacityScale 参数 |
| 动画卡顿 | 帧率下降 | 减少 uniforms 更新频率 |
🚀 扩展思路
| 变体效果 | 核心改动 | 难度 |
|---|---|---|
| 多色扫描 | 添加多种颜色过渡 | ⭐⭐ |
| 椭圆扫描 | 修改扫描形状为椭圆 | ⭐⭐ |
| 交互控制 | 鼠标控制扫描位置 | ⭐⭐ |
| 发光边缘 | 添加扫描线发光效果 | ⭐⭐⭐ |
本文档由 ThreeLab 编辑整理,如需转载,请注明出处。







京公网安备 11010502038735号
💬 评论区
评论功能即将上线,敬请期待!