MapV-Three實現擬真的天氣效果,比想象中簡單
做三維地圖可視化的時候,如果場景裏總是晴空萬里,看久了難免有點單調。加上點天氣效果——下點雨、飄點雪、來點霧——整個場景立馬生動起來。
以前實現這些效果得自己寫粒子系統、調光照參數,費時費力還不一定效果好。好在MapV-Three框架已經把這些封裝好了,就兩個組件:DynamicSky(動態天空)和 DynamicWeather(動態天氣),配合使用就能搞定。
今天就來聊聊怎麼用這兩個組件實現各種天氣效果。
一、核心組件介紹
DynamicSky - 動態天空
這是天氣效果的"舞台"。它能模擬真實的大氣散射、日出日落、日夜交替,還支持體積雲(就是那種看起來很真實的雲層)。
核心能力:
- 根據時間自動調整光照(早中晚不同)
- 大氣散射效果(地平線那種漸變)
- 體積雲渲染
- 環境光實時捕獲(讓場景中的物體也受天空光照影響)
DynamicWeather - 動態天氣
這是"演員"。基於DynamicSky,它能模擬各種天氣現象。
支持的天氣類型:
clear- 晴天partlyCloudy- 多雲cloudy- 陰天overcast- 陰沉foggy- 霧天rainy- 雨天snowy- 雪天
重點:DynamicWeather必須配合DynamicSky使用,單獨用是不行的。
二、快速上手:實現雨天效果
先來看一個完整的例子,實現雨天場景。
完整代碼
import {useRef} from 'react';
import {Engine, DynamicSky, DynamicWeather, BingImageryTileProvider} from '@baidu/mapv-three';
import {Mesh, SphereGeometry, MeshStandardMaterial} from 'three'
const ref = useRef();
const center = [105.9151758905, 29.32990056012];
async function callback(engine) {
const sky = engine.add(new DynamicSky());
const weather = engine.add(new DynamicWeather(sky));
weather.weather = 'rainy'; // clear | partlyCloudy | cloudy | overcast | foggy | rainy | snowy
const sphere = new SphereGeometry(100, 32, 32);
const material = new MeshStandardMaterial({
color: 0xffff00,
metalness: 0.8,
roughness: 0.5,
})
const mesh = engine.add(new Mesh(sphere, material));
const position = engine.map.projectArrayCoordinate(center);
mesh.position.set(position[0], position[1], position[2]);
return engine;
}
<App ref={ref} initConfig={{
map: {
provider: new BingImageryTileProvider(),
center: center,
heading: 90,
pitch: 80,
range: 1000,
projection: 'EPSG:3857',
},
rendering: {
sky: null,
enableAnimationLoop: true,
},
clock: {
currentTime: new Date('2025-05-15 14:30:00'),
}
}} callback={callback} />
代碼解析
第一步:創建動態天空
const sky = engine.add(new DynamicSky());
這是基礎,所有天氣效果都依賴它。
第二步:創建天氣實例
const weather = engine.add(new DynamicWeather(sky));
weather.weather = 'rainy';
注意要把 sky 傳進去。然後通過 weather.weather 屬性設置天氣類型。這裏設置為 'rainy',就會出現下雨效果。
第三步:添加測試物體(可選)
代碼里加了一個黃色球體,目的是看天氣對場景物體的光照影響。下雨時,光線會變暗,球體顏色也會跟着變。
關鍵配置
enableAnimationLoop: true:必須開啓動畫循環,不然雨滴不會動sky: null:初始化時不設置天空,因為我們要在callback裏手動添加DynamicSkycurrentTime:設置初始時間,影響光照效果。下午2點半光照比較充足
運行效果
跑起來之後,你會看到:
- 天空是灰濛濛的(陰雨天的感覺)
- 畫面上有雨滴飄落(粒子效果)
- 場景整體光線偏暗
- 球體表面有明顯的光照變化
三、切換不同天氣
天氣切換非常簡單,就改一個屬性值。
七種天氣效果
// 晴天 - 陽光明媚
weather.weather = 'clear';
// 多雲 - 有云但不影響光照
weather.weather = 'partlyCloudy';
// 陰天 - 雲層較厚,光線減弱
weather.weather = 'cloudy';
// 陰沉 - 更暗,像要下雨的樣子
weather.weather = 'overcast';
// 霧天 - 能見度降低,有霧氣效果
weather.weather = 'foggy';
// 雨天 - 下雨,天空灰暗
weather.weather = 'rainy';
// 雪天 - 下雪,比雨天更冷的感覺
weather.weather = 'snowy';
實時切換
如果想做一個天氣切換功能,可以這樣:
// 假設有個下拉框讓用户選擇天氣
const weatherSelect = document.querySelector('#weather-select');
weatherSelect.addEventListener('change', (e) => {
weather.weather = e.target.value;
});
就這麼簡單,用户選什麼天氣,場景就立即切換。
四、理解DynamicSky的作用
為什麼DynamicWeather一定要配合DynamicSky使用?因為DynamicSky提供了幾個關鍵能力:
1. 光照系統
DynamicSky會根據時間自動調整太陽光、環境光的強度和顏色。
比如:
- 早晨6點:太陽剛升起,光線偏橙紅色
- 中午12點:陽光最強,白色光
- 傍晚18點:夕陽西下,偏金黃色
- 晚上22點:只有微弱的環境光
這些光照變化會直接影響天氣效果的真實感。
2. 大氣散射
這是那種"地平線處天空泛藍,頭頂深藍"的效果。真實的大氣散射能讓整個場景更有層次感。
3. 體積雲
普通的天空盒用的是貼圖,看起來像一張平面照片。DynamicSky的體積雲是3D的,有厚度、有光影,看起來就是真的雲。
4. 環境光捕獲
這個比較厲害。DynamicSky會實時提取天空顏色,作為環境光影響場景中的物體。
舉個例子:
- 晴天時,天空是藍色的,場景物體表面也會帶點藍色反光
- 雨天時,天空是灰色的,物體也會顯得灰暗
這種細節讓整個場景的色調統一,看起來更協調。
五、初始化時直接設置天空
前面的例子是在callback裏手動添加DynamicSky,其實也可以在初始化時直接設置:
const initConfig = {
map: {
provider: new BingImageryTileProvider(),
center: center,
pitch: 88,
range: 1000,
},
rendering: {
sky: new DynamicSky(), // 直接在這裏設置
enableAnimationLoop: true,
}
};
async function callback(engine) {
// 從引擎獲取天空實例
const sky = engine.rendering.sky;
// 創建天氣
const weather = engine.add(new DynamicWeather(sky));
weather.weather = 'snowy';
return engine;
}
兩種方式都可以,看個人習慣。
六、常見問題與注意事項
問題1:看不到天氣效果
排查清單:
- 是否開啓了
enableAnimationLoop? - DynamicWeather是否傳入了DynamicSky實例?
- 相機視角是否合適?(太低或太高可能看不清)
- 天氣類型是否拼寫正確?
問題2:時間設置的作用
clock.currentTime 設置的是場景初始時間,它會影響光照效果。
- 設置白天時間(如14:00):光照充足
- 設置夜晚時間(如22:00):光照很暗
如果你想看雨天效果,建議設置在白天或傍晚,太暗的話雨滴看不清。
七、實用場景
場景1:天氣預報可視化
實時顯示某個地區的天氣狀況:
// 根據API獲取天氣數據
fetch('/api/weather').then(res => res.json()).then(data => {
// 假設API返回 {condition: 'rainy', temperature: 18}
weather.weather = data.condition;
});
場景2:場景氛圍烘托
遊戲或展示類項目中,用天氣烘托氛圍。比如懸疑場景用霧天,悲傷場景用雨天。
場景3:時間與天氣聯動
模擬真實的晝夜和天氣變化:
// 設置時間自動更新
sky.timeAnimation = true;
sky.timeAnimationSpeed = 240; // 加速播放
// 根據時間段自動調整天氣
setInterval(() => {
const hour = engine.clock.currentTime.getHours();
if (hour >= 6 && hour < 12) {
weather.weather = 'clear'; // 早晨晴天
} else if (hour >= 12 && hour < 18) {
weather.weather = 'partlyCloudy'; // 下午多雲
} else {
weather.weather = 'foggy'; // 晚上起霧
}
}, 5000);
八、總結
MapV-Three的天氣系統就兩個組件:
DynamicSky:提供動態光照、大氣散射、體積雲等基礎能力
DynamicWeather:基於DynamicSky,實現各種天氣效果
使用步驟:
- 創建DynamicSky實例
- 創建DynamicWeather實例,傳入sky
- 設置
weather.weather屬性切換天氣 - 記得開啓
enableAnimationLoop
七種天氣:clear、partlyCloudy、cloudy、overcast、foggy、rainy、snowy
代碼簡單,效果真實,性價比很高。如果你的項目需要天氣效果,不妨試試這個方案。