babylonjs天空盒
更新时间: 2025-08-19 14:14:23
项目中写到了白天黑夜变换,其实原理就是将天空盒换了一下,然后把路灯的自发光强度调高,利用GlowLayer实现路灯的光晕,先来看下效果:
# 实现
- 天空纹理对象:储存日夜贴图
const skyTexture = {
day:null,
night:null
}
1
2
3
4
2
3
4
- 创建天空盒并加载HDR纹理
function createSky() {
// 自动创建天空盒和环境光照
skyTexture.day = new HDRCubeTexture(
"/models/sky/qwantani_afternoon_puresky_2k.hdr", // HDR 文件路径(需放在 public 目录)
scene,
1024, // 贴图尺寸(512/1024/2048)
false, // 不生成多级渐远纹理(设为 true 可优化性能)
true, // 启用伽马校正(使颜色更自然)
false // 不反转 Y 轴
);
skyTexture.night = new HDRCubeTexture(
"/models/sky/kloppenheim2_4k.hdr", // HDR 文件路径(需放在 public 目录)
scene,
1024, // 贴图尺寸(512/1024/2048)
false, // 不生成多级渐远纹理(设为 true 可优化性能)
true, // 启用伽马校正
false // 不反转 Y 轴
);
// 设置曝光度(影响整体亮度)
skyTexture.day.exposure = 1.1;
skyTexture.night.exposure = 0.5;
// 创建天空盒(巨大的立方体)
skybox = Mesh.CreateBox("skyBox", 8000.0, scene);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
什么是HDR天空盒?
HDR (High Dynamic Range):高动态范围图像,能够显示比普通图像更广泛的亮度范围,更接近人眼对真实世界的感知。在3D场景中,HDR天空盒可以创建出逼真的天空、光照和反射效果。
- 天空盒原理:
创建一个非常大的立方体(代码中尺寸为8000)
将相机放置在立方体中心
立方体的内表面贴上全景天空纹理
由于立方体足够大,观察者会感觉被天空包围
- HDRCubeTexture API详解
HDRCubeTexture是Babylon.js中专门用于加载HDR立方体贴图的类,构造函数参数如下:
参数 | 作用 | 示例值 |
---|---|---|
url | HDR文件路径 | "/models/sky/afternoon.hdr" |
scene | 当前场景对象 | scene |
size | 纹理尺寸(分辨率) | 1024(常用值:512/1024/2048) |
noMipmap | 是否禁用多级渐远纹理 | false(天空盒通常不需要) |
gammaSpace | 是否启用伽马校正 | true(使颜色更自然) |
invertY | 是否反转Y轴 | false(根据纹理导出设置) |
注意
HDR文件需要放在项目的public目录下,确保路径正确,否则会出现404错误。
- 日夜切换
function switchDayNight(isDay) {
// 切换天空盒纹理
skyboxMaterial = new StandardMaterial("skyBox", scene);
// 关键设置:禁用背面剔除
skyboxMaterial.backFaceCulling = false;
// 设置反射纹理:根据日夜状态选择不同纹理
skyboxMaterial.reflectionTexture = isDay ? skyTexture.day : skyTexture.night;
// 设置纹理坐标模式为天空盒模式
skyboxMaterial.reflectionTexture.coordinatesMode = Texture.SKYBOX_MODE;
// 禁用材质自身颜色(使用反射纹理作为唯一颜色来源)
skyboxMaterial.diffuseColor = new Color3(0, 0, 0);
skyboxMaterial.specularColor = new Color3(0, 0, 0);
// 天空盒不受场景灯光影响
skyboxMaterial.disableLighting = true;
// 应用材质到天空盒
skybox.material = skyboxMaterial;
// 切换光源颜色
if (isDay) {
// 白天光源:白色,高强度
light.diffuseColor = new Color3(1, 1, 1);
light.groundColor = new Color3(0, 0, 0);
light.intensity = 1;
toggleRoadLight(false)
} else {
// 夜晚光源:蓝调,低强度
light.diffuseColor = new Color3(0.1, 0.15, 0.3); // 夜晚蓝色调
light.groundColor = new Color3(0.05, 0.05, 0.1);
light.intensity = 0.3;
toggleRoadLight(true)
}
}
// 道路灯光控制
function toggleRoadLight(isOpen) {
const material = roadLight.material;
if (isOpen) {
// 打开道路灯:设置白色自发光
material.emissiveColor = new Color3(1, 1, 1);
material.emissiveIntensity = 5;
} else {
// 关闭道路灯:关闭自发光
material.emissiveColor = new Color3(0, 0, 0);
material.emissiveIntensity = 0;
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47