<script setup>import { ref, getCurrentInstance, onMounted, beforeUnmount } from 'vue'import * as BABYLON from '@babylonjs/core/Legacy/legacy' // 全部引入import '@babylonjs/loaders' // 模型加载loaderimport * as GUI from '@babylonjs/gui/2D' // 交互组件const { proxy } = getCurrentInstance()const emit = defineEmits(['customChange'])let engine = ref(null)let scene = ref(null)let camera = ref(null)// 模型加载进度百分比let progress = ref(0)// 是否完成模型渲染let isRendering = ref(false)// 是否展示视频let showVideo = ref(false)// 自适应渲染const engineResize = ()=> {engine.resize();}// 重置模型const reset = ()=> {scene.activeCamera.restoreState();}onMounted(() => {let canvas = document.getElementById('canvas');// 初始化 BABYLON 3D engineengine = new BABYLON.Engine(canvas, true, { preserveDrawingBuffer: true, stencil: true, disableWebGL2Support: false });// 自定义loading加载效果function customLoadingScreen() {console.log('customLoadingScreen creation');}customLoadingScreen.prototype.displayLoadingUI = function() {console.log('customLoadingScreen loading')};customLoadingScreen.prototype.hideLoadingUI = function() {window.document.getElementById('loadingScreen').style.display = 'none';};engine.loadingScreen = new customLoadingScreen();// 初始化一个场景 scenescene = new BABYLON.Scene(engine);// 设置背景色透明scene.clearColor = new BABYLON.Color4(0, 0, 0, 0);// 初始化相机 cameracamera = new BABYLON.ArcRotateCamera('Camera', 0, 0, 0, new BABYLON.Vector3(0, 0, 0), scene);/** 天空盒*/// 创建天空盒const skybox = BABYLON.Mesh.CreateBox('skyBox', 21000, scene),skyboxMaterial = new BABYLON.StandardMaterial('skyboxMaterial', scene);// 关闭掉材质的背面剔除(在盒子内部也可以看到盒子)skyboxMaterial.backFaceCulling = false;// 删除盒子上的反射光(天空不会反射太阳)skyboxMaterial.disableLighting = true;// 载入天空贴图(CubeTexture是贴图加载器,只能被应用到reflectionTexture)skyboxMaterial.reflectionTexture = new BABYLON.CubeTexture('textures/sky', scene);// 修改贴图模式(reflectionTexture是反射贴图,但我们需要天空盒贴图)skyboxMaterial.reflectionTexture.coordinatesMode = BABYLON.Texture.SKYBOX_MODE;skybox.material = skyboxMaterial;// 设置天空盒跟随相机位置移动(盒子不会收缩)skybox.infiniteDistance = true;/** 3D模型*/// 引入外部obj模型BABYLON.SceneLoader.Append('babylon/1/', 'model.glb', scene, (object) => {// 设置默认相机和灯光scene.createDefaultCameraOrLight(true, true, true);const light = new BABYLON.HemisphericLight('light', new BABYLON.Vector3(1, 1, 1));// 设置灯光亮度light.intensity = 1;// 镜面反射 漫反射 环境光颜色调整light.diffuse = new BABYLON.Color3(1, 1, 1);light.specular = new BABYLON.Color3(1, 1, 1);// 渲染模型后调整相机角度、位置、观察对象的三维坐标scene.activeCamera.alpha = 0.0239;scene.activeCamera.beta = 1.51;scene.activeCamera.radius = 51.9;scene.activeCamera.setPosition(new BABYLON.Vector3(51.85, 4.32, 4.45));scene.activeCamera.setTarget(new BABYLON.Vector3(0.04, 1.4, 3.2));// 设置横向旋转角度上下限scene.activeCamera.upperBetaLimit = Math.PI * 0.5;scene.activeCamera.lowerBetaLimit = 0;// 设置镜头到目标位置距离半径的最大值scene.activeCamera.upperRadiusLimit = 102;// 设置鼠标滚轮灵敏度(数值越小灵敏度越高)scene.activeCamera.wheelPrecision = 10;// 控制鼠标平移相机镜头灵敏度(数值越小灵敏度越高|为0的时候取消平移操作)scene.activeCamera.panningSensibility = 200;// 存储当前相机状态scene.activeCamera.storeState();// 关闭自定义loading效果、展示标题、展示按钮setTimeout(() => {engine.hideLoadingUI();emit('showTitle', true);isRendering = true;});}, (progressEvent) => {// 设置模型加载进度百分比progress = (progressEvent.loaded / progressEvent.total).toFixed(0) * 100;});// 注册渲染循环 runRenderLoopengine.runRenderLoop(() => {scene.render();});// 在 DOM 更新后执行回调nextTick(() => {console.log('DOM 已更新');// 注册resize监听事件window.addEventListener('resize', engineResize);});})beforeUnmount(() => {// 离开页面销毁resize监听事件window.removeEventListener('resize', engineResize, false);})</script><template><div :class="isRendering ? 'containor bg' : 'containor'"><div id="loadingScreen" class="flex_column_center"><span class="loading"></span><span class="progress">{{ progress }}%</span><span class="text">3D模型加载中...</span></div><canvas id="canvas"></canvas><div class="btn_list flex_middle" v-if="isRendering"><el-button type="warning" size="small" @click="reset"><i class="el-icon-refresh"></i> 重置</el-button></div></div></template><style lang="scss" scoped>/*scrollbar styles*/::-webkit-scrollbar {width: 12px;height: 12px;// border-radius: 100px;}::-webkit-scrollbar-thumb {// border-radius: 100px;background: var(--color-ref-kl-primary10);}::-webkit-scrollbar-track-piece {// border-radius: 100px;background: transparent;}::-webkit-scrollbar-corner {background: transparent;}/*scrollbar styles*/#app {height: 100%;color: #4b4b4b;font-size: 13px;font-family: 'Microsoft YaHei';-webkit-font-smoothing: antialiased;-moz-osx-font-smoothing: grayscale;}.flex {display: flex;}.flex_center {@extend .flex;align-items: center;}.flex_left {@extend .flex_center;justify-content: flex-start;}.flex_right {@extend .flex_center;justify-content: flex-end;}.flex_middle {@extend .flex_center;justify-content: center;}.flex_column {@extend .flex;flex-direction: column;justify-content: center;}.flex_column_center {@extend .flex_column;align-items: center;}.public_radius {border-radius: 8px;}.echarts {height: 100%;overflow: hidden;}.containor {position: relative;width: 100%;height: 100%;overflow: hidden;&.bg {background-color: #8ecbe3;}#loadingScreen {position: absolute;width: 100%;height: 100%;.loading {display: inline-block;position: relative;width: 100px;height: 100px;border: 8px solid #0934f7;border-radius: 50%;animation: rotate 1s linear infinite;&:after {position: absolute;left: 50%;top: 50%;width: 110px;height: 110px;content: '';transform: translate(-50%, -50%);border: 8px solid transparent;border-bottom-color: #00eaff;border-radius: 50%;}}.progress {margin-top: -60px;color: #6be031;font-size: 16px;font-weight: 700;}.text {margin-top: 60px;color: #f5a327;font-size: 14px;}}canvas {width: 100%;height: 100%;outline: none;cursor: pointer;}.btn_list {position: absolute;bottom: 0;width: 100%;height: 50px;z-index: 99;button {margin: 0 15px 0 0;&:last-child {margin: 0;}}}.video_main {position: absolute;top: 50%;left: 50%;transform: translate(-50%, -50%);width: 800px;height: 500px;z-index: 999;video {outline: none;}}}</style>
Useful links
- Official web site: www.babylonjs.com
- Online playground to learn by experimentating
- Online sandbox where you can test your .babylon and glTF scenes with a simple drag'n'drop
- Online shader creation tool where you can learn how to create GLSL shaders
- 3DS Max exporter can be used to generate a .babylon file from 3DS Max
- Maya exporter can be used to generate a .babylon file from Maya
- Blender exporter can be used to generate a .babylon file from Blender 3d
- Unity 5 (deprecated) exporter can be used to export your geometries from Unity 5 scene editor(animations are supported)
- glTF Tools by KhronosGroup
参见:
Babylon.js: Powerful, Beautiful, Simple, Open - Web-Based 3D At Its Best
Babylonjs中文网
GitHub - BabylonJS/Babylon.js: Babylon.js is a powerful, beautiful, simple, and open game and rendering engine packed into a friendly JavaScript framework.