Babylon.js 入门 - 第 6 章 - 构建粒子喷泉

Babylon.js 入门 - 第 6 章 - 构建粒子喷泉

粒子喷泉

每个村庄都需要水,所以让我们安装一个喷泉。我们将使用一个旋转对称的网格来创建它。细颗粒将被回收以产生水效果。为了不浪费水,让我们添加一个开关事件来打开或关闭它。

车床加工的喷泉

是时候介绍创建网格的众多方法中的另一种了,即 CreateLathe 方法。我们从喷泉的轮廓开始。

图片地址

使用 3D 矢量的 xy 分量在数组中描述轮廓。

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) 的形式给出三种颜色。 Alpha01。 前两者组合或混合以设置粒子的颜色。可以指定混合方法。第三个具有属性 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>

到目前为止,所有的行动都是在白天进行的,现在时间转移到了我们需要路灯的夜晚。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

MossGrower

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值