使用百度地图JSAPIThree实现 Bloom 泛光效果

Bloom(泛光、辉光)是一种重要的后处理效果,能够显著提升 3D 场景的视觉质量和真实感。本教程将详细介绍如何在 mapvthree(JSAPIThree)中实现和使用 Bloom 效果。
在这里插入图片描述

什么是 Bloom 效果

Bloom 是一种后处理效果,用来模拟强光源在真实世界中的"溢出"现象。当场景中某些区域的亮度超过正常显示范围时,Bloom 会让这些区域产生柔和的光晕效果,从而:

  • 增强视觉层次感
  • 提升场景氛围
  • 让高亮区域(如太阳、灯光、反光表面)看起来更真实
  • 突出重要元素,增强视觉焦点

在 mapvthree 中启用 Bloom

在 mapvthree 引擎中,Bloom 效果通过 engine.rendering.features.bloom 属性进行控制。

初始化时启用

在创建引擎实例时,可以通过配置项启用 Bloom:

import * as mapvthree from '@baidu/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 效果
            },
        },
    },
});

运行时启用

也可以在引擎创建后动态启用或修改 Bloom 配置:

// 启用 Bloom
engine.rendering.features.bloom.enabled = true;

Bloom 参数配置

Bloom 效果提供了多个可调参数,用于精细控制泛光效果:

// 完整配置示例
engine.rendering.features.bloom.enabled = true;
engine.rendering.features.bloom.strength = 0.1;   // 泛光强度,默认 0.1
engine.rendering.features.bloom.threshold = 1;  // 泛光阈值,默认 1
engine.rendering.features.bloom.radius = 0;     // 泛光半径,默认 0

参数说明

strength - 泛光强度
  • 类型: number
  • 默认值: 0.1
  • 说明: 控制泛光效果的强度。值越大,泛光效果越明显
  • 建议范围: 0.1 - 2.0
  • 使用场景:
    • 较小值(0.1-0.5):适合微妙的泛光效果,如轻微的反光
    • 较大值(0.5-2.0):适合强烈的光源效果,如太阳、霓虹灯
threshold - 泛光阈值
  • 类型: number
  • 默认值: 1
  • 说明: 亮度阈值,只有亮度超过此值的区域才会产生泛光效果
  • 建议范围: 0.5 - 2.0
  • 使用场景:
    • 较小值(0.5-1.0):更多区域会产生泛光,效果更广泛
    • 较大值(1.0-2.0):只有非常亮的区域才会泛光,效果更集中
radius - 泛光半径
  • 类型: number
  • 默认值: 0
  • 说明: 控制泛光扩散的范围
  • 建议范围: 0 - 1.0
  • 使用场景:
    • 较小值(0-0.5):泛光范围较小,更集中
    • 较大值(0.5-1.0):泛光范围较大,更柔和

如何产生 Bloom 效果

要让场景中的物体产生 Bloom 效果,需要让物体的颜色值超出正常的 RGB 范围(0-1)。mapvthree 支持两种方式:

方式一:直接使用超出 RGB 范围的颜色

对于不参与光照计算的材质(如 MeshBasicMaterial),可以直接设置超出 RGB 范围的颜色值:

import * as mapvthree from '@baidu/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,
                strength: 0.5,
                threshold: 1,
            },
        },
    },
});

// 使用超出 RGB 范围的颜色,会产生泛光效果
const glowingBox = engine.add(new Mesh(
    new IcosahedronGeometry(5, 15), 
    new MeshBasicMaterial({
        color: new Color(10, 0, 0), // 红色值超出 1,会产生泛光
    })
));
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), // 颜色在 RGB 范围内
    })
));
normalBox.position.set(0, 0, 0);

方式二:使用 PBR 材质配合光照

对于参与光照计算的材质(如 MeshStandardMaterial),即使颜色值在正常范围内,通过调整 PBR 属性(如 roughnessmetalness),经过光照计算后颜色也会超出 RGB 范围,从而产生泛光效果:

import * as mapvthree from '@baidu/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,
                strength: 0.5,
                threshold: 1,
            },
        },
    },
});

// 添加动态天空以提供光照
const sky = engine.add(new mapvthree.DynamicSky());

// 设置当前时间为上午 10 点
engine.clock.currentTime = new Date('2025-05-15 10:00:00');
// 设置时钟模式为循环模式,使时间自动流逝
engine.clock.tickMode = engine.clock.TICK_NORMAL;

// 使用 PBR 材质,通过光照计算产生泛光
const reflectiveBox = engine.add(new Mesh(
    new IcosahedronGeometry(5, 15), 
    new MeshStandardMaterial({
        color: new Color(1, 0, 0), // 颜色在正常范围内
        roughness: 0,              // 低粗糙度,高反射
        metalness: 0.9,             // 高金属度
        // 经过光照计算后,反射光会超出 RGB 范围,产生泛光
    })
));
reflectiveBox.position.set(10, 0, 0);

方式三:使用 emissive(自发光)属性

对于支持 emissive 属性的材质,可以通过设置自发光颜色来产生 Bloom 效果:

import * as mapvthree from '@baidu/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);

完整示例

下面是一个完整的示例,展示不同材质和配置下的 Bloom 效果:

import * as mapvthree from '@baidu/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());

// 设置当前时间为上午 10 点
engine.clock.currentTime = new Date('2025-05-15 10:00:00');
// 设置时钟模式为循环模式,使时间自动流逝
engine.clock.tickMode = engine.clock.TICK_NORMAL;

// 示例 1: MeshBasicMaterial + 超出 RGB 范围的颜色
const box1 = engine.add(new Mesh(
    new IcosahedronGeometry(5, 15), 
    new MeshBasicMaterial({
        color: new Color(10, 0, 0), // 超出 RGB 范围,产生泛光
    })
));
box1.position.set(-10, 0, 0);

// 示例 2: MeshBasicMaterial + 正常颜色(不产生泛光)
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);

// 示例 3: MeshStandardMaterial + 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);

实际应用场景

1. 城市夜景场景

在城市夜景中,使用 Bloom 效果可以让灯光、霓虹灯等光源更加真实:

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. 科技感界面

在数据可视化场景中,使用 Bloom 可以突出重要数据点:

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 后,引擎内部会采用更高精度的 HalfFloat 类型来存储颜色,这会产生额外的性能开销:

  • 内存占用增加: 使用 HalfFloat 类型会增加显存占用
  • 渲染性能: 后处理效果会增加 GPU 计算负担
  • 帧率影响: 在低端设备上可能影响帧率

优化建议

  1. 按需启用: 只在需要 Bloom 效果的场景中启用
  2. 合理配置参数: 使用较小的 strengthradius 值可以降低性能开销
  3. 选择性应用: 不是所有物体都需要 Bloom,只对关键元素应用
  4. 性能监控: 使用 engine.rendering.stats 监控渲染性能

常见问题

Q: 为什么设置了 Bloom 但没有效果?

A: 检查以下几点:

  1. 确认 engine.rendering.features.bloom.enabled = true
  2. 确认物体的颜色值超出了 RGB 范围(> 1),或者使用了 PBR 材质配合光照
  3. 确认 threshold 值设置合理,不会过滤掉所有泛光
  4. 对于 MeshBasicMaterial,必须直接设置超出 RGB 范围的颜色

Q: 如何调整 Bloom 的强度?

A: 通过 strength 参数控制:

engine.rendering.features.bloom.strength = 0.5; // 增加强度

Q: Bloom 效果太强/太弱怎么办?

A: 可以同时调整多个参数:

  • 降低 strength 可以减弱泛光强度
  • 提高 threshold 可以让只有更亮的区域产生泛光
  • 调整 radius 可以控制泛光扩散范围

Q: 可以在运行时动态调整 Bloom 参数吗?

A: 可以,所有参数都可以在运行时动态修改:

// 动态调整
engine.rendering.features.bloom.strength = 0.2;
engine.rendering.features.bloom.threshold = 0.8;

总结

Bloom 效果是提升 3D 场景视觉质量的重要工具。在 mapvthree 中:

  1. 启用方式: 通过 engine.rendering.features.bloom.enabled = true 启用
  2. 参数控制: 使用 strengththresholdradius 精细调整效果
  3. 产生方式:
    • 直接使用超出 RGB 范围的颜色
    • 使用 PBR 材质配合光照
    • 使用 emissive 自发光属性
  4. 性能考虑: 注意性能开销,合理使用

通过合理配置和使用 Bloom 效果,可以让你的 3D 场景更加生动、真实,提升用户体验。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值