Babylon.js 入门 - 第 6 章 - 构建粒子喷泉
粒子喷泉
每个村庄都需要水,所以让我们安装一个喷泉。我们将使用一个旋转对称的网格来创建它。细颗粒将被回收以产生水效果。为了不浪费水,让我们添加一个开关事件来打开或关闭它。
车床加工的喷泉
是时候介绍创建网格的众多方法中的另一种了,即 CreateLathe
方法。我们从喷泉的轮廓开始。
使用 3D
矢量的 x
和 y
分量在数组中描述轮廓。
const fountainProfile = [
new BABYLON.Vector3(0, 0, 0),
new BABYLON.Vector3(10, 0, 0),
new BABYLON.Vector3(10, 4, 0),
new BABYLON.Vector3(8, 4, 0),
new BABYLON.Vector3(8, 1, 0),
new BABYLON.Vector3(1, 2, 0),
new BABYLON.Vector3(1, 15, 0),
new BABYLON.Vector3(3, 17, 0)
];
该数组用于 CreateLathe
方法中 options
参数的 shape
属性。
const fountain = BABYLON.MeshBuilder.CreateLathe("fountain", {
shape: fountainProfile,
sideOrientation: BABYLON.Mesh.DOUBLESIDE
}, scene);
和以前一样,场景参数是可选的。在这种情况下,网格设置为双面,因为由于顶部的斜率和中空的中间,内部是可见的。
基本车床喷泉的示例:
示例代码:
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Babylon.js sample code</title>
<!-- Babylon.js -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/dat-gui/0.6.2/dat.gui.min.js"></script>
<script src="https://preview.babylonjs.com/ammo.js"></script>
<script src="https://preview.babylonjs.com/cannon.js"></script>
<script src="https://preview.babylonjs.com/Oimo.js"></script>
<script src="https://preview.babylonjs.com/earcut.min.js"></script>
<script src="https://preview.babylonjs.com/babylon.js"></script>
<script src="https://preview.babylonjs.com/materialsLibrary/babylonjs.materials.min.js"></script>
<script src="https://preview.babylonjs.com/proceduralTexturesLibrary/babylonjs.proceduralTextures.min.js"></script>
<script src="https://preview.babylonjs.com/postProcessesLibrary/babylonjs.postProcess.min.js"></script>
<script src="https://preview.babylonjs.com/loaders/babylonjs.loaders.js"></script>
<script src="https://preview.babylonjs.com/serializers/babylonjs.serializers.min.js"></script>
<script src="https://preview.babylonjs.com/gui/babylon.gui.min.js"></script>
<script src="https://preview.babylonjs.com/inspector/babylon.inspector.bundle.js"></script>
<style>
html,
body {
overflow: hidden;
width: 100%;
height: 100%;
margin: 0;
padding: 0;
}
#renderCanvas {
width: 100%;
height: 100%;
touch-action: none;
}
</style>
</head>
<body>
<canvas id="renderCanvas"></canvas>
<script>
var canvas = document.getElementById("renderCanvas");
var startRenderLoop = function (engine, canvas) {
engine.runRenderLoop(function () {
if (sceneToRender && sceneToRender.activeCamera) {
sceneToRender.render();
}
});
}
var engine = null;
var scene = null;
var sceneToRender = null;
var createDefaultEngine = function () {
return new BABYLON.Engine(canvas, true, {
preserveDrawingBuffer: true,
stencil: true,
disableWebGL2Support: false
});
};
const createScene = function () {
const scene = new BABYLON.Scene(engine);
const camera = new BABYLON.ArcRotateCamera("Camera", 3 * Math.PI / 2, Math.PI / 2.5, 70, BABYLON.Vector3
.Zero());
camera.attachControl(canvas, true);
const light = new BABYLON.HemisphericLight("hemi", new BABYLON.Vector3(0, 1, 0));
const fountainProfile = [
new BABYLON.Vector3(0, 0, 0),
new BABYLON.Vector3(10, 0, 0),
new BABYLON.Vector3(10, 4, 0),
new BABYLON.Vector3(8, 4, 0),
new BABYLON.Vector3(8, 1, 0),
new BABYLON.Vector3(1, 2, 0),
new BABYLON.Vector3(1, 15, 0),
new BABYLON.Vector3(3, 17, 0)
];
// 创建车床
const fountain = BABYLON.MeshBuilder.CreateLathe("fountain", {
shape: fountainProfile,
sideOrientation: BABYLON.Mesh.DOUBLESIDE
}, scene);
return scene;
}
window.initFunction = async function () {
var asyncEngineCreation = async function () {
try {
return createDefaultEngine();
} catch (e) {
console.log(
"the available createEngine function failed. Creating the default engine instead"
);
return createDefaultEngine();
}
}
window.engine = await asyncEngineCreation();
if (!engine) throw 'engine should not be null.';
startRenderLoop(engine, canvas);
window.scene = createScene();
};
initFunction().then(() => {
sceneToRender = scene
});
// Resize
window.addEventListener("resize", function () {
engine.resize();
});
</script>
</body>
</html>
进行适当地缩放并改变其位置,把它放置在村庄里。
添加喷泉的示例:
示例代码:
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Babylon.js sample code</title>
<!-- Babylon.js -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/dat-gui/0.6.2/dat.gui.min.js"></script>
<script src="https://preview.babylonjs.com/ammo.js"></script>
<script src="https://preview.babylonjs.com/cannon.js"></script>
<script src="https://preview.babylonjs.com/Oimo.js"></script>
<script src="https://preview.babylonjs.com/earcut.min.js"></script>
<script src="https://preview.babylonjs.com/babylon.js"></script>
<script src="https://preview.babylonjs.com/materialsLibrary/babylonjs.materials.min.js"></script>
<script src="https://preview.babylonjs.com/proceduralTexturesLibrary/babylonjs.proceduralTextures.min.js"></script>
<script src="https://preview.babylonjs.com/postProcessesLibrary/babylonjs.postProcess.min.js"></script>
<script src="https://preview.babylonjs.com/loaders/babylonjs.loaders.js"></script>
<script src="https://preview.babylonjs.com/serializers/babylonjs.serializers.min.js"></script>
<script src="https://preview.babylonjs.com/gui/babylon.gui.min.js"></script>
<script src="https://preview.babylonjs.com/inspector/babylon.inspector.bundle.js"></script>
<style>
html,
body {
overflow: hidden;
width: 100%;
height: 100%;
margin: 0;
padding: 0;
}
#renderCanvas {
width: 100%;
height: 100%;
touch-action: none;
}
</style>
</head>
<body>
<canvas id="renderCanvas"></canvas>
<script>
var canvas = document.getElementById("renderCanvas");
var startRenderLoop = function (engine, canvas) {
engine.runRenderLoop(function () {
if (sceneToRender && sceneToRender.activeCamera) {
sceneToRender.render();
}
});
}
var engine = null;
var scene = null;
var sceneToRender = null;
var createDefaultEngine = function () {
return new BABYLON.Engine(canvas, true, {
preserveDrawingBuffer: true,
stencil: true,
disableWebGL2Support: false
});
};
const createScene = function () {
const scene = new BABYLON.Scene(engine);
const camera = new BABYLON.ArcRotateCamera("camera", -Math.PI / 1.5, Math.PI / 2.2, 15, new BABYLON
.Vector3(0, 0, 0));
camera.upperBetaLimit = Math.PI / 2.2;
camera.attachControl(canvas, true);
const light = new BABYLON.HemisphericLight("light", new BABYLON.Vector3(1, 1, 0));
const fountainOutline = [
new BABYLON.Vector3(0, 0, 0),
new BABYLON.Vector3(0.5, 0, 0),
new BABYLON.Vector3(0.5, 0.2, 0),
new BABYLON.Vector3(0.4, 0.2, 0),
new BABYLON.Vector3(0.4, 0.05, 0),
new BABYLON.Vector3(0.05, 0.1, 0),
new BABYLON.Vector3(0.05, 0.8, 0),
new BABYLON.Vector3(0.15, 0.9, 0)
];
// 创建车床喷泉
const fountain = BABYLON.MeshBuilder.CreateLathe("fountain", {
shape: fountainOutline,
sideOrientation: BABYLON.Mesh.DOUBLESIDE
});
fountain.position.x = -4;
fountain.position.z = -6;
// 天空盒
const skybox = BABYLON.MeshBuilder.CreateBox("skyBox", {
size: 150
}, scene);
const skyboxMaterial = new BABYLON.StandardMaterial("skyBox", scene);
skyboxMaterial.backFaceCulling = false;
skyboxMaterial.reflectionTexture = new BABYLON.CubeTexture("textures/skybox", scene);
skyboxMaterial.reflectionTexture.coordinatesMode = BABYLON.Texture.SKYBOX_MODE;
skyboxMaterial.diffuseColor = new BABYLON.Color3(0, 0, 0);
skyboxMaterial.specularColor = new BABYLON.Color3(0, 0, 0);
skybox.material = skyboxMaterial;
BABYLON.SceneLoader.ImportMeshAsync("", "https://assets.babylonjs.com/meshes/", "valleyvillage.glb");
return scene;
};
window.initFunction = async function () {
var asyncEngineCreation = async function () {
try {
return createDefaultEngine();
} catch (e) {
console.log(
"the available createEngine function failed. Creating the default engine instead"
);
return createDefaultEngine();
}
}
window.engine = await asyncEngineCreation();
if (!engine) throw 'engine should not be null.';
startRenderLoop(engine, canvas);
window.scene = createScene();
};
initFunction().then(() => {
sceneToRender = scene
});
// Resize
window.addEventListener("resize", function () {
engine.resize();
});
</script>
</body>
</html>
没有喷水的喷泉有点无聊,所以我们用粒子模拟喷水。
粒子喷雾
在这种情况下,粒子是在集群或云中发出的小精灵图,用于模拟用于模拟火、烟、水甚至仙气。
粒子云的基础是粒子系统。有了这个,我们指定要使用的粒子数:
// 场景是可选的
const particleSystem = new BABYLON.ParticleSystem("particles", 5000, scene);
粒子从特定定义的区域发射。每个粒子都有一个生命周期,当达到它时,它会被重复使用并重新发射。
它们被赋予一种质地,这决定了它们的外观,
particleSystem.particleTexture = new BABYLON.Texture("url to image", scene);
基本的发射极区域是一个围绕指定点的给定尺寸的盒子;
// 喷泉顶部的点
particleSystem.emitter = new BABYLON.Vector3(-4, 0.8, -6);
// 最小盒子尺寸
particleSystem.minEmitBox = new BABYLON.Vector3(-0.01, 0, -0.01);
// 最大盒子尺寸
particleSystem.maxEmitBox = new BABYLON.Vector3(0.01, 0, 0.01);
对于红色、绿色、蓝色和 alpha
,最多可以以 (r, g, b, a)
的形式给出三种颜色。 Alpha
从 0
到 1
。 前两者组合或混合以设置粒子的颜色。可以指定混合方法。第三个具有属性 colorDead
并且在粒子的回收设置为关闭时使用。我们的喷泉不需要第三个属性。
particleSystem.color1 = new BABYLON.Color4(0.7, 0.8, 1.0, 1.0);
particleSystem.color2 = new BABYLON.Color4(0.2, 0.5, 1.0, 1.0);
particleSystem.blendMode = BABYLON.ParticleSystem.BLENDMODE_ONEONE;
粒子的大小及其寿命在最小值和最大值设定的范围内。
particleSystem.minSize = 0.01;
particleSystem.maxSize = 0.05;
particleSystem.minLifeTime = 0.3;
particleSystem.maxLifeTime = 1.5;
我们还需要设置每秒发射的粒子数。过快的发射率和较长的寿命会导致粒子发射出现间隙。
particleSystem.emitRate = 1500;
我们还为粒子设置了两个可能的方向,并通过给出最小和最大功率值以及更新速度来影响粒子行进的速度。
particleSystem.direction1 = new BABYLON.Vector3(-1, 8, 1);
particleSystem.direction2 = new BABYLON.Vector3(1, 8, -1);
particleSystem.minEmitPower = 0.2;
particleSystem.maxEmitPower = 0.6;
particleSystem.updateSpeed = 0.01;
在 y
分量中为 graving
设置负值可确保粒子向下落:
particleSystem.gravity = new BABYLON.Vector3(0, -9.81, 0);
终于可以启动喷泉了:
particleSystem.start();
这是我们添加喷雾的示例:
示例代码:
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Babylon.js sample code</title>
<!-- Babylon.js -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/dat-gui/0.6.2/dat.gui.min.js"></script>
<script src="https://preview.babylonjs.com/ammo.js"></script>
<script src="https://preview.babylonjs.com/cannon.js"></script>
<script src="https://preview.babylonjs.com/Oimo.js"></script>
<script src="https://preview.babylonjs.com/earcut.min.js"></script>
<script src="https://preview.babylonjs.com/babylon.js"></script>
<script src="https://preview.babylonjs.com/materialsLibrary/babylonjs.materials.min.js"></script>
<script src="https://preview.babylonjs.com/proceduralTexturesLibrary/babylonjs.proceduralTextures.min.js"></script>
<script src="https://preview.babylonjs.com/postProcessesLibrary/babylonjs.postProcess.min.js"></script>
<script src="https://preview.babylonjs.com/loaders/babylonjs.loaders.js"></script>
<script src="https://preview.babylonjs.com/serializers/babylonjs.serializers.min.js"></script>
<script src="https://preview.babylonjs.com/gui/babylon.gui.min.js"></script>
<script src="https://preview.babylonjs.com/inspector/babylon.inspector.bundle.js"></script>
<style>
html,
body {
overflow: hidden;
width: 100%;
height: 100%;
margin: 0;
padding: 0;
}
#renderCanvas {
width: 100%;
height: 100%;
touch-action: none;
}
</style>
</head>
<body>
<canvas id="renderCanvas"></canvas>
<script>
var canvas = document.getElementById("renderCanvas");
var startRenderLoop = function (engine, canvas) {
engine.runRenderLoop(function () {
if (sceneToRender && sceneToRender.activeCamera) {
sceneToRender.render();
}
});
}
var engine = null;
var scene = null;
var sceneToRender = null;
var createDefaultEngine = function () {
return new BABYLON.Engine(canvas, true, {
preserveDrawingBuffer: true,
stencil: true,
disableWebGL2Support: false
});
};
const createScene = function () {
const scene = new BABYLON.Scene(engine);
const camera = new BABYLON.ArcRotateCamera("Camera", 3 * Math.PI / 2, Math.PI / 2, 70, BABYLON.Vector3
.Zero());
camera.attachControl(canvas, true);
const light = new BABYLON.HemisphericLight("hemi", new BABYLON.Vector3(0, 1, 0));
const fountainProfile = [
new BABYLON.Vector3(0, 0, 0),
new BABYLON.Vector3(10, 0, 0),
new BABYLON.Vector3(10, 4, 0),
new BABYLON.Vector3(8, 4, 0),
new BABYLON.Vector3(8, 1, 0),
new BABYLON.Vector3(1, 2, 0),
new BABYLON.Vector3(1, 15, 0),
new BABYLON.Vector3(3, 17, 0)
];
// 创建车床
const fountain = BABYLON.MeshBuilder.CreateLathe("fountain", {
shape: fountainProfile,
sideOrientation: BABYLON.Mesh.DOUBLESIDE
}, scene);
fountain.position.y = -5;
// 创建粒子系统
var particleSystem = new BABYLON.ParticleSystem("particles", 5000, scene);
// 每个粒子的纹理
particleSystem.particleTexture = new BABYLON.Texture("./3/textures/flare.png", scene);
// 粒子从何而来
particleSystem.emitter = new BABYLON.Vector3(0, 10, 0); // the starting object, the emitter
particleSystem.minEmitBox = new BABYLON.Vector3(-1, 0, 0); // Starting all from
particleSystem.maxEmitBox = new BABYLON.Vector3(1, 0, 0); // To...
// 所有粒子的颜色
particleSystem.color1 = new BABYLON.Color4(0.7, 0.8, 1.0, 1.0);
particleSystem.color2 = new BABYLON.Color4(0.2, 0.5, 1.0, 1.0);
particleSystem.colorDead = new BABYLON.Color4(0, 0, 0.2, 0.0);
// 每个粒子的大小(随机...
particleSystem.minSize = 0.1;
particleSystem.maxSize = 0.5;
// 每个粒子的寿命(随机...
particleSystem.minLifeTime = 2;
particleSystem.maxLifeTime = 3.5;
// 排放率
particleSystem.emitRate = 1500;
// 混合模式 : BLENDMODE_ONEONE, or BLENDMODE_STANDARD
particleSystem.blendMode = BABYLON.ParticleSystem.BLENDMODE_ONEONE;
// 设置所有粒子的重力
particleSystem.gravity = new BABYLON.Vector3(0, -9.81, 0);
// 每个粒子发射后的方向
particleSystem.direction1 = new BABYLON.Vector3(-2, 8, 2);
particleSystem.direction2 = new BABYLON.Vector3(2, 8, -2);
// 角速度,以弧度为单位
particleSystem.minAngularSpeed = 0;
particleSystem.maxAngularSpeed = Math.PI;
// 速度
particleSystem.minEmitPower = 1;
particleSystem.maxEmitPower = 3;
particleSystem.updateSpeed = 0.025;
// 启动粒子系统
particleSystem.start();
return scene;
}
window.initFunction = async function () {
var asyncEngineCreation = async function () {
try {
return createDefaultEngine();
} catch (e) {
console.log(
"the available createEngine function failed. Creating the default engine instead"
);
return createDefaultEngine();
}
}
window.engine = await asyncEngineCreation();
if (!engine) throw 'engine should not be null.';
startRenderLoop(engine, canvas);
window.scene = createScene();
};
initFunction().then(() => {
sceneToRender = scene
});
// Resize
window.addEventListener("resize", function () {
engine.resize();
});
</script>
</body>
</html>
现在让我们提供一个开关点击事件。
开启事件
当我们单击喷泉上的屏幕指针时,我们希望它开始。我们通过向 onPointerObservable
添加一个函数来处理指针点击事件,该事件在停止和启动之间切换粒子系统。
// 开启关闭标志
let switched = false;
scene.onPointerObservable.add((pointerInfo) => {
switch (pointerInfo.type) {
case BABYLON.PointerEventTypes.POINTERDOWN:
if (pointerInfo.pickInfo.hit) {
pointerDown(pointerInfo.pickInfo.pickedMesh)
}
break;
}
});
const pointerDown = (mesh) => {
// 检查选取的网格是否为喷泉
if (mesh === fountain) {
// 拨动开关
switched = !switched;
if (switched) {
particleSystem.start();
} else {
particleSystem.stop();
}
}
}
单击时开始/停止粒子的示例:
示例代码:
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Babylon.js sample code</title>
<!-- Babylon.js -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/dat-gui/0.6.2/dat.gui.min.js"></script>
<script src="https://preview.babylonjs.com/ammo.js"></script>
<script src="https://preview.babylonjs.com/cannon.js"></script>
<script src="https://preview.babylonjs.com/Oimo.js"></script>
<script src="https://preview.babylonjs.com/earcut.min.js"></script>
<script src="https://preview.babylonjs.com/babylon.js"></script>
<script src="https://preview.babylonjs.com/materialsLibrary/babylonjs.materials.min.js"></script>
<script src="https://preview.babylonjs.com/proceduralTexturesLibrary/babylonjs.proceduralTextures.min.js"></script>
<script src="https://preview.babylonjs.com/postProcessesLibrary/babylonjs.postProcess.min.js"></script>
<script src="https://preview.babylonjs.com/loaders/babylonjs.loaders.js"></script>
<script src="https://preview.babylonjs.com/serializers/babylonjs.serializers.min.js"></script>
<script src="https://preview.babylonjs.com/gui/babylon.gui.min.js"></script>
<script src="https://preview.babylonjs.com/inspector/babylon.inspector.bundle.js"></script>
<style>
html,
body {
overflow: hidden;
width: 100%;
height: 100%;
margin: 0;
padding: 0;
}
#renderCanvas {
width: 100%;
height: 100%;
touch-action: none;
}
</style>
</head>
<body>
<canvas id="renderCanvas"></canvas>
<script>
var canvas = document.getElementById("renderCanvas");
var startRenderLoop = function (engine, canvas) {
engine.runRenderLoop(function () {
if (sceneToRender && sceneToRender.activeCamera) {
sceneToRender.render();
}
});
}
var engine = null;
var scene = null;
var sceneToRender = null;
var createDefaultEngine = function () {
return new BABYLON.Engine(canvas, true, {
preserveDrawingBuffer: true,
stencil: true,
disableWebGL2Support: false
});
};
const createScene = function () {
const scene = new BABYLON.Scene(engine);
const camera = new BABYLON.ArcRotateCamera("Camera", 3 * Math.PI / 2, Math.PI / 2, 70, BABYLON.Vector3
.Zero());
camera.attachControl(canvas, true);
const light = new BABYLON.HemisphericLight("hemi", new BABYLON.Vector3(0, 1, 0));
// 打开和关闭喷泉
let switched = false;
const pointerDown = (mesh) => {
if (mesh === fountain) {
switched = !switched;
if (switched) {
// 启动粒子系统
particleSystem.start();
} else {
// 停止粒子系统
particleSystem.stop();
}
}
}
scene.onPointerObservable.add((pointerInfo) => {
switch (pointerInfo.type) {
case BABYLON.PointerEventTypes.POINTERDOWN:
if (pointerInfo.pickInfo.hit) {
pointerDown(pointerInfo.pickInfo.pickedMesh)
}
break;
}
});
const fountainProfile = [
new BABYLON.Vector3(0, 0, 0),
new BABYLON.Vector3(10, 0, 0),
new BABYLON.Vector3(10, 4, 0),
new BABYLON.Vector3(8, 4, 0),
new BABYLON.Vector3(8, 1, 0),
new BABYLON.Vector3(1, 2, 0),
new BABYLON.Vector3(1, 15, 0),
new BABYLON.Vector3(3, 17, 0)
];
// 创建车床
const fountain = BABYLON.MeshBuilder.CreateLathe("fountain", {
shape: fountainProfile,
sideOrientation: BABYLON.Mesh.DOUBLESIDE
}, scene);
fountain.position.y = -6;
// 创建粒子系统
var particleSystem = new BABYLON.ParticleSystem("particles", 5000, scene);
// 每个粒子的纹理
particleSystem.particleTexture = new BABYLON.Texture("./4/textures/flare.png", scene);
// 粒子从何而来
// 起始对象,发射器
particleSystem.emitter = new BABYLON.Vector3(0, 10, 0);
// 一切从
particleSystem.minEmitBox = new BABYLON.Vector3(-1, 0, 0);
// 到...
particleSystem.maxEmitBox = new BABYLON.Vector3(1, 0, 0);
// 所有粒子的颜色
particleSystem.color1 = new BABYLON.Color4(0.7, 0.8, 1.0, 1.0);
particleSystem.color2 = new BABYLON.Color4(0.2, 0.5, 1.0, 1.0);
particleSystem.colorDead = new BABYLON.Color4(0, 0, 0.2, 0.0);
// 每个粒子的大小(随机...
particleSystem.minSize = 0.1;
particleSystem.maxSize = 0.5;
// 每个粒子的寿命(随机...
particleSystem.minLifeTime = 2;
particleSystem.maxLifeTime = 3.5;
// 排放率
particleSystem.emitRate = 1500;
// 混合模式 : BLENDMODE_ONEONE, or BLENDMODE_STANDARD
particleSystem.blendMode = BABYLON.ParticleSystem.BLENDMODE_ONEONE;
// 设置所有粒子的重力
particleSystem.gravity = new BABYLON.Vector3(0, -9.81, 0);
// 每个粒子发射后的方向
particleSystem.direction1 = new BABYLON.Vector3(-2, 8, 2);
particleSystem.direction2 = new BABYLON.Vector3(2, 8, -2);
// 角速度,以弧度为单位
particleSystem.minAngularSpeed = 0;
particleSystem.maxAngularSpeed = Math.PI;
// 速度
particleSystem.minEmitPower = 1;
particleSystem.maxEmitPower = 3;
particleSystem.updateSpeed = 0.025;
return scene;
}
window.initFunction = async function () {
var asyncEngineCreation = async function () {
try {
return createDefaultEngine();
} catch (e) {
console.log(
"the available createEngine function failed. Creating the default engine instead"
);
return createDefaultEngine();
}
}
window.engine = await asyncEngineCreation();
if (!engine) throw 'engine should not be null.';
startRenderLoop(engine, canvas);
window.scene = createScene();
};
initFunction().then(() => {
sceneToRender = scene
});
// Resize
window.addEventListener("resize", function () {
engine.resize();
});
</script>
</body>
</html>
现在我们将它添加到村庄世界中。
将喷泉添加到村庄的示例:
示例代码:
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Babylon.js sample code</title>
<!-- Babylon.js -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/dat-gui/0.6.2/dat.gui.min.js"></script>
<script src="https://preview.babylonjs.com/ammo.js"></script>
<script src="https://preview.babylonjs.com/cannon.js"></script>
<script src="https://preview.babylonjs.com/Oimo.js"></script>
<script src="https://preview.babylonjs.com/earcut.min.js"></script>
<script src="https://preview.babylonjs.com/babylon.js"></script>
<script src="https://preview.babylonjs.com/materialsLibrary/babylonjs.materials.min.js"></script>
<script src="https://preview.babylonjs.com/proceduralTexturesLibrary/babylonjs.proceduralTextures.min.js"></script>
<script src="https://preview.babylonjs.com/postProcessesLibrary/babylonjs.postProcess.min.js"></script>
<script src="https://preview.babylonjs.com/loaders/babylonjs.loaders.js"></script>
<script src="https://preview.babylonjs.com/serializers/babylonjs.serializers.min.js"></script>
<script src="https://preview.babylonjs.com/gui/babylon.gui.min.js"></script>
<script src="https://preview.babylonjs.com/inspector/babylon.inspector.bundle.js"></script>
<style>
html,
body {
overflow: hidden;
width: 100%;
height: 100%;
margin: 0;
padding: 0;
}
#renderCanvas {
width: 100%;
height: 100%;
touch-action: none;
}
</style>
</head>
<body>
<canvas id="renderCanvas"></canvas>
<script>
var canvas = document.getElementById("renderCanvas");
var startRenderLoop = function (engine, canvas) {
engine.runRenderLoop(function () {
if (sceneToRender && sceneToRender.activeCamera) {
sceneToRender.render();
}
});
}
var engine = null;
var scene = null;
var sceneToRender = null;
var createDefaultEngine = function () {
return new BABYLON.Engine(canvas, true, {
preserveDrawingBuffer: true,
stencil: true,
disableWebGL2Support: false
});
};
const createScene = function () {
const scene = new BABYLON.Scene(engine);
const camera = new BABYLON.ArcRotateCamera("camera", -Math.PI / 1.5, Math.PI / 2.2, 15, new BABYLON
.Vector3(0, 0, 0));
camera.upperBetaLimit = Math.PI / 2.2;
camera.attachControl(canvas, true);
const light = new BABYLON.HemisphericLight("light", new BABYLON.Vector3(1, 1, 0));
// 打开和关闭喷泉
let switched = false;
const pointerDown = (mesh) => {
if (mesh === fountain) {
switched = !switched;
if (switched) {
// 启动粒子系统
particleSystem.start();
} else {
// 停止粒子系统
particleSystem.stop();
}
}
}
scene.onPointerObservable.add((pointerInfo) => {
switch (pointerInfo.type) {
case BABYLON.PointerEventTypes.POINTERDOWN:
if (pointerInfo.pickInfo.hit) {
pointerDown(pointerInfo.pickInfo.pickedMesh)
}
break;
}
});
// 创建粒子系统
const particleSystem = new BABYLON.ParticleSystem("particles", 5000);
// 每个粒子的纹理
particleSystem.particleTexture = new BABYLON.Texture("textures/flare.png");
// 粒子从何而来
// 从喷泉顶部喷出
particleSystem.emitter = new BABYLON.Vector3(-4, 0.8, -6);
// 一切从
particleSystem.minEmitBox = new BABYLON.Vector3(-0.01, 0, -0.01);
// 到...
particleSystem.maxEmitBox = new BABYLON.Vector3(0.01, 0, 0.01);
// 所有粒子的颜色
particleSystem.color1 = new BABYLON.Color4(0.7, 0.8, 1.0, 1.0);
particleSystem.color2 = new BABYLON.Color4(0.2, 0.5, 1.0, 1.0);
// 每个粒子的大小(随机...
particleSystem.minSize = 0.01;
particleSystem.maxSize = 0.05;
// 每个粒子的寿命(随机...
particleSystem.minLifeTime = 0.3;
particleSystem.maxLifeTime = 1.5;
// 排放率
particleSystem.emitRate = 1500;
// 混合模式 : BLENDMODE_ONEONE, or BLENDMODE_STANDARD
particleSystem.blendMode = BABYLON.ParticleSystem.BLENDMODE_ONEONE;
// 设置所有粒子的重力
particleSystem.gravity = new BABYLON.Vector3(0, -9.81, 0);
// 每个粒子发射后的方向
particleSystem.direction1 = new BABYLON.Vector3(-1, 8, 1);
particleSystem.direction2 = new BABYLON.Vector3(1, 8, -1);
// 力量和速度
particleSystem.minEmitPower = 0.2;
particleSystem.maxEmitPower = 0.6;
particleSystem.updateSpeed = 0.01;
const fountainProfile = [
new BABYLON.Vector3(0, 0, 0),
new BABYLON.Vector3(0.5, 0, 0),
new BABYLON.Vector3(0.5, 0.2, 0),
new BABYLON.Vector3(0.4, 0.2, 0),
new BABYLON.Vector3(0.4, 0.05, 0),
new BABYLON.Vector3(0.05, 0.1, 0),
new BABYLON.Vector3(0.05, 0.8, 0),
new BABYLON.Vector3(0.15, 0.9, 0)
];
// 创建车床喷泉
const fountain = BABYLON.MeshBuilder.CreateLathe("fountain", {
shape: fountainProfile,
sideOrientation: BABYLON.Mesh.DOUBLESIDE
});
fountain.position.x = -4;
fountain.position.z = -6;
// 天空盒
const skybox = BABYLON.MeshBuilder.CreateBox("skyBox", {
size: 150
}, scene);
const skyboxMaterial = new BABYLON.StandardMaterial("skyBox", scene);
skyboxMaterial.backFaceCulling = false;
skyboxMaterial.reflectionTexture = new BABYLON.CubeTexture("textures/skybox", scene);
skyboxMaterial.reflectionTexture.coordinatesMode = BABYLON.Texture.SKYBOX_MODE;
skyboxMaterial.diffuseColor = new BABYLON.Color3(0, 0, 0);
skyboxMaterial.specularColor = new BABYLON.Color3(0, 0, 0);
skybox.material = skyboxMaterial;
BABYLON.SceneLoader.ImportMeshAsync("", "https://assets.babylonjs.com/meshes/", "valleyvillage.glb");
return scene;
};
window.initFunction = async function () {
var asyncEngineCreation = async function () {
try {
return createDefaultEngine();
} catch (e) {
console.log(
"the available createEngine function failed. Creating the default engine instead"
);
return createDefaultEngine();
}
}
window.engine = await asyncEngineCreation();
if (!engine) throw 'engine should not be null.';
startRenderLoop(engine, canvas);
window.scene = createScene();
};
initFunction().then(() => {
sceneToRender = scene
});
// Resize
window.addEventListener("resize", function () {
engine.resize();
});
</script>
</body>
</html>
到目前为止,所有的行动都是在白天进行的,现在时间转移到了我们需要路灯的夜晚。