水材质以及倒影
更新时间: 2025-07-22 08:30:13
WaterMaterial是Babylon.js材质库中专门用于创建逼真水面效果的高级材质,支持波浪动画,反射,折射等特性,无需手动编写复杂着色器。其核心优势在于开箱即用的物理效果模拟,适用于湖泊,海洋,池塘等场景,广泛应用于游戏,数字孪生,虚拟展厅等领域。
# 引入
安装依赖:
npm install @babylonjs/core @babylonjs/materials
1
在代码中导入:
import { Scene, Engine } from "@babylonjs/core";
import { WaterMaterial } from "@babylonjs/materials/water"; // 导入 WaterMaterial
1
2
2
# 核心API详解
# 构造函数
创建WaterMaterial实例,需指定名称,场景和渲染目标尺寸(影响反射/折射清晰度)
new BABYLON.WaterMaterial(name: string, scene: Scene, renderTargetSize?: Vector2);
1
- name: 材质名称,取什么名字无所谓
- scene: 所属场景对象
- renderTargetSize: 反射/折射纹理分辨率(默认 new BABYLON.Vector2(512, 512),值越高越清晰但性能消耗越大)
# 常用属性
属性名 | 类型 | 作用 | 取值范围 / 示例 |
---|---|---|---|
bumpTexture | Texture | 必选,波浪法线贴图(决定波浪细节) | new BABYLON.Texture("waterbump.png", scene) |
windForce | number | 风力大小(控制波浪运动速度) | 正数 / 负数(如 15 或 -5) |
waveHeight | number | 波浪高度(值越大波浪越陡峭) | 0~5(平静湖面 0.1,巨浪 2) |
waveLength | number | 波长(值越小波浪越密集) | 0.1~2(小波浪 0.1,长波浪 1) |
windDirection | Vector2 | 风向(x/y 方向分量) | new BABYLON.Vector2(1, 1)(右上风向) |
waterColor | Color3 | 水的基础颜色(与反射 / 折射混合) | new BABYLON.Color3(0, 0.3, 0.8)(蓝色) |
colorBlendFactor | number | 颜色混合因子(控制水色与反射的占比) | 0~2(值越大水色越明显) |
bumpHeight | number | 法线贴图影响强度(控制波浪扰动程度) | 0~1(值越大波纹越明显) |
# 常用方法
方法名 | 作用 | 示例 |
---|---|---|
addToRenderList(mesh) | 添加需要反射 / 折射的物体(如天空盒、地面) | water.addToRenderList(skybox); |
enableRenderTargets() | 启用反射 / 折射(默认启用) | water.enableRenderTargets(true); |
# 案例
简单水面,设置基本波浪属性,实现平静湖面效果。
// 初始化引擎和场景
const canvas = document.getElementById("renderCanvas");
const engine = new BABYLON.Engine(canvas, true);
const scene = new BABYLON.Scene(engine);
// 1. 创建相机和光源
const camera = new BABYLON.ArcRotateCamera("camera", -Math.PI/2, Math.PI/2.5, 10, BABYLON.Vector3.Zero(), scene);
camera.attachControl(canvas, true);
const light = new BABYLON.HemisphericLight("light", new BABYLON.Vector3(0, 1, 0), scene);
// 2. 创建水面网格(地面)
const waterMesh = BABYLON.Mesh.CreateGround("waterMesh", 10, 10, 32, scene); // 宽10、高10、细分32
// 3. 创建 WaterMaterial
const water = new BABYLON.WaterMaterial("water", scene, new BABYLON.Vector2(512, 512)); // 反射分辨率512x512
// 4. 设置必选属性:法线贴图(波浪细节来源)
water.bumpTexture = new BABYLON.Texture("https://minio.cnbabylon.com/public/Assets/waterbump.png", scene);
// 5. 设置波浪属性(调整为平静湖面)
water.windForce = 5; // 风力
water.waveHeight = 0.1; // 波浪高度
water.waveLength = 0.5; // 波长
water.windDirection = new BABYLON.Vector2(1, 1); // 风向
water.waterColor = new BABYLON.Color3(0, 0.3, 0.8); // 水色(蓝色)
water.colorBlendFactor = 0.5; // 水色与反射混合比例
// 6. 将材质应用到网格
waterMesh.material = water;
// 7. 启动渲染循环
engine.runRenderLoop(() => scene.render());
window.addEventListener("resize", () => engine.resize());
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
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
高级水面(带天空盒和海底)
const canvas = document.getElementById("renderCanvas");
const engine = new BABYLON.Engine(canvas, true);
const scene = new BABYLON.Scene(engine);
// 1. 相机和光源
const camera = new BABYLON.ArcRotateCamera("camera", 3*Math.PI/2, Math.PI/2.5, 20, BABYLON.Vector3.Zero(), scene);
camera.attachControl(canvas, true);
const light = new BABYLON.HemisphericLight("light", new BABYLON.Vector3(0, 1, 0), scene);
// 2. 创建天空盒(用于反射)
const skybox = BABYLON.Mesh.CreateBox("skybox", 1000, scene);
const skyboxMaterial = new BABYLON.StandardMaterial("skybox", scene);
skyboxMaterial.backFaceCulling = false; // 禁用背面剔除(天空盒内部可见)
skyboxMaterial.reflectionTexture = new BABYLON.CubeTexture("https://minio.cnbabylon.com/public/Assets/skybox/TropicalSunnyDay", scene);
skyboxMaterial.reflectionTexture.coordinatesMode = BABYLON.Texture.SKYBOX_MODE; // 天空盒模式
skyboxMaterial.disableLighting = true; // 禁用光照(自发光)
skybox.material = skyboxMaterial;
// 3. 创建海底地面
const ground = BABYLON.Mesh.CreateGround("ground", 100, 100, 32, scene);
ground.position.y = -5; // 置于水下5单位
const groundMaterial = new BABYLON.StandardMaterial("groundMat", scene);
groundMaterial.diffuseTexture = new BABYLON.Texture("https://minio.cnbabylon.com/public/Assets/sand.jpg", scene); // 沙子纹理
groundMaterial.diffuseTexture.uScale = groundMaterial.diffuseTexture.vScale = 10; // 纹理重复10次
ground.material = groundMaterial;
// 4. 创建水面
const waterMesh = BABYLON.Mesh.CreateGround("waterMesh", 100, 100, 64, scene); // 更高细分(64)
const water = new BABYLON.WaterMaterial("water", scene, new BABYLON.Vector2(1024, 1024)); // 高分辨率反射
// 5. 配置水材质属性
water.bumpTexture = new BABYLON.Texture("https://minio.cnbabylon.com/public/Assets/waterbump.png", scene);
water.windForce = 15; // 强风
water.waveHeight = 0.8; // 中高波浪
water.waveLength = 0.5; // 密集波浪
water.windDirection = new BABYLON.Vector2(1, 1); // 右上风向
water.waterColor = new BABYLON.Color3(0, 0.2, 0.7); // 深海蓝色
water.colorBlendFactor = 0.3; // 反射为主,水色为辅
// 6. 添加反射/折射物体(天空盒、地面、海底)
water.addToRenderList(skybox); // 反射天空盒
water.addToRenderList(ground); // 折射海底
// 7. 应用材质
waterMesh.material = water;
// 渲染循环
engine.runRenderLoop(() => scene.render());
window.addEventListener("resize", () => engine.resize());
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
48
49
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
48
49
- 天空盒反射:通过 addToRenderList(skybox) 让水面反射天空,提升真实感。
- 海底折射:添加海底地面并置于水下,水面会折射出海底纹理。
- 高分辨率反射:renderTargetSize=1024 使反射更清晰,但需注意性能(低配置设备可降为 512)。