I was experiencing very low FPS (5-10) when using Vue instead of steady 60 FPS on the same scene using a plain HTML page. I was passing the engine object to the parent component to get the fps, that was the issue.
The solution is not to Ref and/or emit the BabylonJS engine and/or scene object. (in other words, do not make them reactive)
I didn’t dig deeper, but I think it causes multiple calls of the renderLoop or something similar.
You have to disconnect BJS from the VUE state and not let Vue touch any of the BJS objects or it will chain and try to make everything reactive every frame.
You have to make a communication bus that separates the BJS data from the react elements.
Just output the BJS object after you pass a param to make something on it reactive and look at the listeners its binding, you will see its toxic AF and its doing that every frame.
Hi there!
Yes, I did exactly the same. The GUI is based on Quasar/Vue2 and I introduced a Puppeteer class which serves as an interface between BJS and Quasar and simply translates method calls from the GUI to messages sent/received to/from the BJS part of the application. The GUI doesn’t know anything about BJS, and BJS doesn’t know anything about the GUI part, the Puppeteer is the bridge. The cool thing about this is, that I could move the BJS scene into a web worker.
How can I understand this (you must disconnect BJS from Vue state, and Vue is not allowed to touch any BJS object). Now I define all BJS objects in methods. I use Vue, and I don’t bind any this, but FPS is still very low. I can keep FPS stable at 60 with H5. Can you give me some guidance.
This is my code, from initialization to rendering are completed in this method, without binding any this
inittest () {
let canvas = document.getElementById(‘renderCanvas’)
let engine = new BABYLON.Engine(canvas, true, {
preserveDrawingBuffer: true,
stencil: true,
disableWebGL2Support: false
})
let target = new BABYLON.Vector3.Zero()
let position = new BABYLON.Vector3(0, 260, 300)
let scene1 = new BABYLON.Scene(engine)
scene1.useRightHandedSystem = true
// This creates and positions a free camera1 (non-mesh)
let arcCamera1 = new BABYLON.ArcRotateCamera('arcCamera1', 0, 2, 10, target, scene1)
// This positions the camera1
arcCamera1.setPosition(position)
// This targets the camera1 to scene1 origin
// arcCamera1.setTarget(BABYLON.Vector3.Zero());
// This attaches the camera1 to the canvas
arcCamera1.attachControl(canvas, true)
arcCamera1.allowUpsideDown = false
// arcCamera1.upperRadiusLimit = 400
// arcCamera1.lowerRadiusLimit = 5
// arcCamera1.maxCameraSpeed = 10
arcCamera1.panningSensibility = 50
arcCamera1.panningInertia = 0
// This creates a light, aiming 0,1,0 - to the sky (non-mesh)
let light1 = new BABYLON.HemisphericLight('light', new BABYLON.Vector3(0, 1, 0), scene1)
// let light2 = new BABYLON.HemisphericLight('hemi', new BABYLON.Vector3(0, 1, 0), _that.scene2);
// Default intensity is 1. Let's dim the light a small amount
// light1.intensity = 0.7;
let importMeshs = []
let gltfArr = [
'https://models.babylonjs.com/seagulf.glb'
]
// _that.createCameraSprite()
gltfArr.forEach(item => {
importMeshs.push(
BABYLON.SceneLoader.ImportMeshAsync(null, item, '', scene1).then(res => {
item.freezeWorldMatrix()
})
}))
})
Promise.all(importMeshs).then(res => {
scene1.freezeActiveMeshes()
})
scene1.debugLayer.show({
embedMode: true
})
const spriteManagerTrees = new BABYLON.SpriteManager('camerasManager', '/static/gltf/image/camera.png', 100, {
width: 1024,
height: 1024
}, scene1)
spriteManagerTrees.isPickable = true
for (let i = 0; i < 20; i++) {
// Mutliple trees
const myCamera = new BABYLON.Sprite('cameras', spriteManagerTrees)
myCamera.isPickable = true
myCamera.useAlphaForPicking = true
myCamera.position.x = i
myCamera.position.y = 0
myCamera.position.z = i
myCamera.actionManager = new BABYLON.ActionManager(scene1)
}
engine.runRenderLoop(function (res) {
scene1.render()
})
}
Hi!
The important part of the code is the Vue part, so the snippet you provided is no help at all. Can you provide a github repo? I will gladly have a look at it.
It doesn’t seem to be the problem
// Promise.all(importMeshs).then(res => {
// scene1.freezeActiveMeshes();
// });
I have created 300 new spheres, and the number of drawing times does not increase all the time. The number of frames remains at about 50. I don’t know if it’s the problem of sprites, but it’s not very similar. Because I draw 200000 sprites alone, and the number of frames can reach 60. As long as the sprites and the imported gltf are used together, the number of drawing times will increase all the time, and the number of frames will drop slowly, Until 0 to 1 frames per second
You’re right. It’s really that the rendering times have been rising. Now I have a new problem. After I add Scene1. Freezeactivemeshes(), my FPS has been improved. I don’t add Scene1. Freezeactivemeshes(); My FPS has only 12 frames. I don’t know how to optimize it now. Can you help me?
I don’t know how to upload the model, and it’s very big. I found someone else’s model. You see, the genie is rendering all the time. If you don’t add scene. Freezeactivemeshes(), it won’t render all the time https://playground.babylonjs.com/#IQJ1BZ#1
First of all, I import the gltf file. I have to use scene. Freezeactivemeshes() to increase my frame count. Then I use sprites. However, when using gltf and sprites together, the rendering times keep increasing, and then the frames will drop slowly. I can’t find a better way to improve my frame count except through scene. Freezeactivemeshes()
One more thing, you have low fps on this playground or in your Vue app? This is a very basic scene and there should be no performance problems so I assume there is a problem elsewhere.