写点什么

JSAPIThree 之 Bloom 效果学习笔记:让我的 3D 场景发光发亮!

作者:map_3d_vis
  • 2025-11-20
    北京
  • 本文字数:5498 字

    阅读完需:约 18 分钟

作为一个刚开始学习 mapvthree 的小白,今天我要学习一个超酷的效果——Bloom(泛光)!听说这个效果能让场景里的物体发光,就像游戏里的特效一样,想想就激动!

第一次听说 Bloom

今天在文档里看到了 Bloom 这个词,查了一下才知道,原来这就是那种让物体周围有一圈光晕的效果!就像看太阳的时候,眼睛周围会有那种"溢出"的光晕一样。


文档说 Bloom 可以让:


  • 场景更有层次感(听起来很专业)

  • 氛围更好(这个我懂!)

  • 高亮区域更真实(比如太阳、灯光)

  • 重要元素更突出(这个实用!)


我的理解:简单说就是让亮的东西更亮,而且会"发光"!就像给物体加了个光环特效!

第一步:先看看怎么开启

作为一个初学者,我习惯先看最简单的例子。文档说可以通过 engine.rendering.features.bloom 来控制。

尝试 1:初始化时就开启

我照着文档写了个最简单的例子:


import * as mapvthree from '@baidumap/mapv-three';
// 先获取容器(这个我熟悉)const container = document.getElementById('container');
// 创建引擎,顺便把 Bloom 打开const engine = new mapvthree.Engine(container, { map: { center: [116.414, 39.915], range: 500, heading: 225, pitch: 70, }, rendering: { enableAnimationLoop: true, features: { bloom: { enabled: true, // 就这一行!开启 Bloom! }, }, },});
复制代码


我的想法:看起来很简单嘛!就是在配置里加个 enabled: true。但是...我运行了代码,怎么什么都没发生?

尝试 2:运行时开启

文档说也可以在创建引擎后再开启,我试试:


// 先创建引擎(不开启 Bloom)const engine = new mapvthree.Engine(container, {    // ... 其他配置});
// 然后手动开启engine.rendering.features.bloom.enabled = true;
复制代码


我的发现:原来可以动态控制!这样我就可以做个开关按钮了,想想就兴奋!

第二步:为什么没效果?

我开启了 Bloom,但是场景里什么都没变化...我开始怀疑是不是我理解错了。


看了文档才知道,开启 Bloom 只是第一步,还要让物体"足够亮"才会有效果!


文档说颜色值要超出 RGB 范围(0-1),比如颜色值可以是 10、20 这样的大数字!这刷新了我的认知,原来颜色值不一定是 0-1 啊!

第三步:第一次看到泛光效果!

我照着文档写了个测试代码:


import * as mapvthree from '@baidumap/mapv-three';import {Mesh, MeshBasicMaterial, IcosahedronGeometry, Color} from 'three';
const container = document.getElementById('container');
const engine = new mapvthree.Engine(container, { map: { provider: null, center: [0, 0], heading: 0, pitch: 85, range: 50, }, rendering: { sky: null, enableAnimationLoop: true, features: { bloom: { enabled: true, }, }, },});
// 创建一个超亮的红色球体(颜色值是 10!)const glowingBox = engine.add(new Mesh( new IcosahedronGeometry(5, 15), new MeshBasicMaterial({ color: new Color(10, 0, 0), // 红色值 10,超出正常范围! })));glowingBox.position.set(-10, 0, 0);
// 再创建一个正常颜色的球体(对比用)const normalBox = engine.add(new Mesh( new IcosahedronGeometry(5, 15), new MeshBasicMaterial({ color: new Color(0.5, 0, 0), // 正常颜色值 })));normalBox.position.set(0, 0, 0);
复制代码


我的反应:哇!真的发光了!那个红色的球体周围有一圈红色的光晕!太酷了!


对比一下,正常颜色的球体就没有光晕,只有超亮的那个才有。我终于理解了!

第四步:探索参数

看到效果后,我开始好奇:能不能调整光晕的强度?能不能控制哪些区域发光?


文档说有三个参数可以调:


  • strength:泛光强度(默认 0.1)

  • threshold:泛光阈值(默认 1)

  • radius:泛光半径(默认 0)

尝试调整 strength

我试着把强度调大:


engine.rendering.features.bloom.strength = 0.5; // 从 0.1 调到 0.5
复制代码


我的发现:光晕变强了!但是太强了有点刺眼...我又调回 0.2,感觉刚刚好。看来参数要慢慢调,找到合适的值。

尝试调整 threshold

文档说这个值控制"多亮才会发光"。我试了试:


engine.rendering.features.bloom.threshold = 0.5; // 降低阈值
复制代码


我的发现:降低阈值后,更多区域开始发光了!但是有些不太亮的地方也开始发光,感觉有点乱。我又调回 1.0,感觉这样只有真正亮的地方才发光,更自然。

尝试调整 radius

engine.rendering.features.bloom.radius = 0.5; // 增加半径
复制代码


我的发现:光晕扩散得更大了!看起来更柔和,但是也模糊了一些。我试了几个值,发现 0.2-0.3 之间比较舒服。


我的总结:调参数就像调音效一样,要慢慢试,找到自己觉得舒服的值!

第五步:发现新方法——PBR 材质!

我以为只有用超大的颜色值才能发光,结果文档说还有另一种方法:用 PBR 材质配合光照!


我试了试:


import * as mapvthree from '@baidumap/mapv-three';import {Mesh, MeshStandardMaterial, IcosahedronGeometry, Color} from 'three';
const container = document.getElementById('container');
const engine = new mapvthree.Engine(container, { map: { provider: null, center: [0, 0], heading: 0, pitch: 85, range: 50, }, rendering: { sky: null, enableAnimationLoop: true, features: { bloom: { enabled: true, }, }, },});
// 添加动态天空(提供光照)const sky = engine.add(new mapvthree.DynamicSky());
// 设置时间(这个我查了文档才知道怎么用)engine.clock.currentTime = new Date('2025-05-15 10:00:00');engine.clock.tickMode = engine.clock.TICK_NORMAL;
// 创建一个镜面反射的球体const reflectiveBox = engine.add(new Mesh( new IcosahedronGeometry(5, 15), new MeshStandardMaterial({ color: new Color(1, 0, 0), // 正常颜色值 roughness: 0, // 完全光滑(像镜子) metalness: 0.9, // 高金属度 })));reflectiveBox.position.set(10, 0, 0);
复制代码


我的惊喜:哇!这个球体也发光了!虽然颜色值是正常的 1,但是因为它是镜面的,反射的光经过计算后超出了 RGB 范围,所以也产生了泛光!


这太神奇了!原来不一定要手动设置超大颜色值,通过材质属性也能实现!

第六步:发现第三种方法——自发光!

文档还说可以用 emissive(自发光)属性,我赶紧试试:


import * as mapvthree from '@baidumap/mapv-three';import {Mesh, MeshStandardMaterial, SphereGeometry, Color} from 'three';
const container = document.getElementById('container');
const engine = new mapvthree.Engine(container, { map: { center: [116.414, 39.915], range: 500, }, rendering: { enableAnimationLoop: true, features: { bloom: { enabled: true, }, }, },});
// 创建一个自发光的球体const emissiveSphere = engine.add(new Mesh( new SphereGeometry(10, 32, 32), new MeshStandardMaterial({ color: new Color(0xffffff), emissive: new Color(0x00ffff), // 青色自发光 emissiveIntensity: 1.5, // 强度超过 1 })));
const position = engine.map.projectArrayCoordinate([116.414, 39.915]);emissiveSphere.position.set(position[0], position[1], 10);
复制代码


我的感受:这个球体看起来就像个发光的灯泡!emissive 属性让物体自己发光,配合 Bloom 效果,看起来特别真实!

第七步:做一个完整的对比测试

我想看看三种方法的效果对比,就写了个完整的测试:


import * as mapvthree from '@baidumap/mapv-three';import {Mesh, MeshBasicMaterial, MeshStandardMaterial, IcosahedronGeometry, Color} from 'three';
const container = document.getElementById('container');
const engine = new mapvthree.Engine(container, { map: { provider: null, center: [0, 0], heading: 0, pitch: 85, range: 50, }, rendering: { sky: null, enableAnimationLoop: true, features: { bloom: { enabled: true, strength: 0.1, threshold: 1, radius: 0, }, }, },});
// 添加动态天空const sky = engine.add(new mapvthree.DynamicSky());engine.clock.currentTime = new Date('2025-05-15 10:00:00');engine.clock.tickMode = engine.clock.TICK_NORMAL;
// 方法一:超大颜色值const box1 = engine.add(new Mesh( new IcosahedronGeometry(5, 15), new MeshBasicMaterial({ color: new Color(10, 0, 0), // 直接设置超大值 })));box1.position.set(-10, 0, 0);
// 方法二:正常颜色值(对比)const box2 = engine.add(new Mesh( new IcosahedronGeometry(5, 15), new MeshBasicMaterial({ color: new Color(0.5, 0, 0), // 正常值,不会发光 })));box2.position.set(0, 0, 0);
// 方法三:PBR 材质 + 光照const box3 = engine.add(new Mesh( new IcosahedronGeometry(5, 15), new MeshStandardMaterial({ color: new Color(1, 0, 0), roughness: 0, // 镜面 metalness: 0.9, // 金属 })));box3.position.set(10, 0, 0);
复制代码


我的观察


  • box1:直接发光,很亮很显眼

  • box2:不发光,就是普通的红色

  • box3:也发光,但是是反射光,看起来更自然


三种方法各有特点,看场景需求选择!

第八步:实际应用场景

学到这里,我开始想:这个效果能用在什么地方呢?

场景 1:城市夜景

我想做个夜景场景,让路灯发光:


import {Mesh, SphereGeometry, MeshStandardMaterial, Color} from 'three';
// 路灯const streetLight = engine.add(new Mesh( new SphereGeometry(2, 16, 16), new MeshStandardMaterial({ color: new Color(0xffffaa), emissive: new Color(0xffffaa), emissiveIntensity: 2.0, // 高强度的自发光 })));
复制代码


我的想法:这样路灯看起来就像真的在发光一样!如果做城市夜景,肯定很漂亮!

场景 2:数据可视化

我想突出显示重要的数据点:


import {Mesh, SphereGeometry, MeshBasicMaterial, Color} from 'three';
// 高亮数据点const dataPoint = engine.add(new Mesh( new SphereGeometry(5, 32, 32), new MeshBasicMaterial({ color: new Color(5, 2, 0), // 强烈的橙红色泛光 })));
复制代码


我的想法:这样重要的数据点会特别显眼,用户一眼就能看到!

场景 3:镜面反射

我想做个镜面效果:


import {Mesh, PlaneGeometry, MeshStandardMaterial, Color} from 'three';
// 镜面const mirror = engine.add(new Mesh( new PlaneGeometry(20, 20), new MeshStandardMaterial({ color: new Color(0.8, 0.8, 0.9), roughness: 0, // 完全光滑 metalness: 1.0, // 完全金属 })));
复制代码


我的想法:这样看起来就像真的镜子,反射的光也会有泛光效果!

第九步:性能注意事项

学得差不多了,我开始担心性能问题。文档说开启 Bloom 会增加性能开销,因为要用更高精度的类型存储颜色。


我的理解


  • 内存占用会增加

  • GPU 计算负担会增加

  • 低端设备可能会卡


我的策略


  1. 只在需要的时候开启

  2. 参数不要调太大

  3. 不是所有物体都要发光,只对关键元素用


毕竟效果再好,卡成幻灯片也不行啊!

第十步:踩过的坑

作为一个初学者,我踩了不少坑,记录下来避免再犯:

坑 1:开启了 Bloom 但没效果

原因:只开启了 Bloom,但物体的颜色值没有超出 RGB 范围。


解决:要么用超大颜色值,要么用 PBR 材质配合光照,要么用自发光属性。

坑 2:效果太强刺眼

原因strength 参数调太大了。


解决:慢慢调,找到合适的值,一般 0.1-0.5 比较舒服。

坑 3:太多地方发光,看起来很乱

原因threshold 值太小了。


解决:提高 threshold,让只有真正亮的地方才发光。

坑 4:用 MeshBasicMaterial 但没光照

原因MeshBasicMaterial 不参与光照计算,必须直接用超大颜色值。


解决:要么改用 MeshStandardMaterial,要么直接用超大颜色值。

我的学习总结

经过这一天的学习,我掌握了:


  1. 如何开启 Bloom:在配置里加 enabled: true 就行

  2. 三种产生泛光的方法

  3. 超大颜色值(最简单直接)

  4. PBR 材质 + 光照(更自然)

  5. 自发光属性(适合光源)

  6. 参数调整strengththresholdradius 要慢慢调

  7. 性能考虑:注意开销,合理使用


我的感受:Bloom 效果真的很酷!虽然刚开始有点懵,但是看到效果的那一刻,感觉所有的努力都值了!现在我的场景也能发光发亮了!


下一步计划:我想试试在城市夜景场景里用 Bloom,让整个城市亮起来!想想就兴奋!




学习笔记就到这里啦!作为一个初学者,我觉得 Bloom 效果虽然概念有点复杂,但是用起来其实不难。关键是多试、多调、多看效果。希望我的笔记能帮到其他初学者!大家一起加油!

用户头像

map_3d_vis

关注

还未添加个人签名 2025-11-17 加入

还未添加个人简介

评论

发布
暂无评论
JSAPIThree之Bloom 效果学习笔记:让我的 3D 场景发光发亮!_3D渲染_map_3d_vis_InfoQ写作社区