Babylon.js快速实现动态海浪、光照、天空场景

992 阅读2分钟

Babylon.js是微软开源的一款Web3D渲染引擎,他同时还是一款非常优秀的游戏引擎,相对于threejs来说,Babylon.js 相对更高级,同样的场景开发,Babylon的效率是threejs的好几倍。

此外他不仅仅可以在浏览器端运行,还可以编译为多个平台版本,一次编写实现,多平台共享运行。 所以我们重磅推出了Babylon Native,它可以用原有的Babylon.js代码在任意平台构建一个原生应用,充分释放本机设备的性能优势。 已经支持DirectX on Windows、 Metal on iOS/MacOS、 OpenGL on Android等平台

官方网站

www.babylonjs.com/

小试牛刀,加载较慢请耐心等待

以下是我较短时间开发出来的一个小场景,主要构成为天空、大海、和企业方块,三维场景渲染帧率始终保持60fps,可见其性能强大。

测试代码沙盒方式体验地址:code.juejin.cn/pen/7273689…

实现源码

参考代码中WaterMaterial材质的使用,几行代码即可实现海面巨浪的效果,可以了解到Babylon.js 引擎强大之处,使用threejs 实现此功能是非常复杂的,需要写大量的着色器程序,除水材质之外,其还内置了火焰、熔岩、毛皮、地面、地形、渐变、天空。网格、单元格底纹、混合纹理等材质,,使用非常方便,开箱即用。

<canvas id="renderCanvas"></canvas>
  html, body {
            overflow: hidden;
            width: 100%;
            height: 100%;
            margin: 0;
            padding: 0;
        }

        #renderCanvas {
            width: 100%;
            height: 100%;
            touch-action: none;
        }
  window.onload=()=>{
   
            var canvas = document.getElementById("renderCanvas");
           
            var engine = new BABYLON.Engine(canvas, true);

         
    

        var createScene = function (engine) {
            // 创建场景
            var scene = new BABYLON.Scene(engine);

            // 创建相机
            var camera = new BABYLON.ArcRotateCamera("Camera", 3 * Math.PI / 2, Math.PI / 2.5, 50, BABYLON.Vector3.Zero(), scene);
            camera.attachControl(canvas, true);

            // 创建一个光源
            var light = new BABYLON.HemisphericLight("light1", new BABYLON.Vector3(0, 1, 0), scene);

            // 设置天空盒子
            var skybox = BABYLON.Mesh.CreateBox("skyBox", 5000.0, scene);
            var 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;

            // 设置海浪的材质
            var waterMaterial = new BABYLON.WaterMaterial("waterMaterial", scene, new BABYLON.Vector2(512, 512));
            waterMaterial.bumpTexture = new BABYLON.Texture("https://minio.cnbabylon.com/public/Assets/waterbump.png", scene);
            waterMaterial.windForce = 15; // 风速,表示施加在水面上的风力
            waterMaterial.waveHeight = 0.9; // 浪高
            waterMaterial.bumpHeight = 0.1; // 颠簸高度
            waterMaterial.waveLength = 0.1; // 浪长度
            waterMaterial.waveSpeed = 10.0; // 流速
            waterMaterial.waterColor = new BABYLON.Color3(0, 0, 1); // 海水的颜色
            waterMaterial.colorBlendFactor = -0.01; // 混色量,决定水色如何与反射和折射世界混合的因素
            waterMaterial.windDirection = new BABYLON.Vector2(1, 1); // 风向 

            // 海底地面纹理
            var groundTexture = new BABYLON.Texture("https://minio.cnbabylon.com/public/Assets/sand.jpg", scene);
            groundTexture.vScale = groundTexture.uScale = 100.0;
            // 海底地面材质
            var groundMaterial = new BABYLON.StandardMaterial("groundMaterial", scene);
            groundMaterial.diffuseTexture = groundTexture;
            // 创建海底地面
            var ground = BABYLON.Mesh.CreateGround("ground", 512, 512, 32, scene, false);
            ground.position.y = -2;
            ground.material = groundMaterial;

            // 创建海水地形
            var waterMesh = BABYLON.Mesh.CreateGround("waterMesh", 512, 512, 32, scene, false);
            waterMesh.material = waterMaterial;

            // 初始化盒子材质
            var boxMaterial = new BABYLON.StandardMaterial("boxMaterial", scene);
            boxMaterial.diffuseTexture = new BABYLON.Texture("", scene);
    //创建盒子
            var box = BABYLON.Mesh.CreateBox("box", 8, scene);
            box.position.y = 20;
            box.material = boxMaterial;

            // 要反射和折射世界,您只需将所需的网格添加到渲染列表中
            waterMaterial.addToRenderList(ground);
            waterMaterial.addToRenderList(skybox);
            waterMaterial.addToRenderList(box);

            // 渲染前获取海浪的高度,并设置盒子y的位置
            let i = 0;
            scene.registerBeforeRender(function () {
                let time = waterMaterial._lastTime / 100000;
                let x = box.position.x;
                let z = box.position.z;
                box.position.y = 8 + Math.abs((Math.sin(((x / 0.05) + time * waterMaterial.waveSpeed)) * waterMaterial.waveHeight * waterMaterial.windDirection.x * 5.0) + (Math.cos(((z / 0.05) + time * waterMaterial.waveSpeed)) * waterMaterial.waveHeight * waterMaterial.windDirection.y * 5.0));
            });

            return scene;
        };
           var scene = createScene(engine); 

            engine.runRenderLoop(function () {
                scene.render();
            });

            window.addEventListener("resize", function () {
                engine.resize();
            });
        }