yokewang Posted July 21, 2018 Share Posted July 21, 2018 I have written a simple demo to render 8000 cubes in BabylonJS. But found out it's quite slower than in ThreeJS. Demo in BabylonJs: https://jsfiddle.net/6ng7usmj/ Demo in ThreeJS: https://jsfiddle.net/pofq4827/ It does not make sense, because BabylonJS supports more performance related features like vao. Any help would be greatly appreciated. brianzinn 1 Quote Link to comment Share on other sites More sharing options...
brianzinn Posted July 21, 2018 Share Posted July 21, 2018 Great demos. Can you share your FPS or performance stats? On my machine with your jsfiddles: ThreeJS: ~21 FPS BabylonJS: ~13 FPS My BabylonJS: ~38 FPS You are re-using your geometry in ThreeJS when you create your meshes, I think that is essentially equivalent to instancing in BabylonJS, causing a ~3x difference in FPS: https://jsfiddle.net/6ng7usmj/10/ edit: BoxGeometry is used in Three.js, but not intended to be used as in your fiddle with BabylonJS. Perhaps the BabylonJS docs could be updated to guide people coming from other ecosystems to best practices. Hopefully this thread sheds some light for equivalence: http://www.html5gamedevs.com/topic/38981-why-parameters-on-geometries-have-no-effect/?tab=comments#comment-222588 NasimiAsl 1 Quote Link to comment Share on other sites More sharing options...
jerome Posted July 21, 2018 Share Posted July 21, 2018 Well, you don't really use the same features in both examples. In the ThreeJS one, you use the BufferGeometry. In 3JS, the BufferGeometry is under the hood a flat typed array to be passed directly to the GPU, what is faster than converting some JS objects in a first pass, and this geometry is shared among all the meshes. Actually, in the BJS example that you provided, you are trying to port line by line the 3JS code to BJS. But, this doesn't work that way because the frameworks don't have the same way or philosophy to implement same features... Doing this will always lead to misunderstandings and wrong results. As brianzinn suggested, you could investigate how BJS does to achieve the same result in other ways. In BJS, you can use, for example, instances of a single mesh. In this case, the geometry, and other properties like materials, are shared among instances : http://doc.babylonjs.com/how_to/how_to_use_instances You could either use a Solid Particle System (SPS) : http://doc.babylonjs.com/how_to/solid_particle_system https://jsfiddle.net/6ng7usmj/32/ => 60 fps If you want to tune things at buffer level, there's a way I just can remember now to to force to turn the buffers to be passed as flat ones (ie not related to indices ones) EDIT : this http://doc.babylonjs.com/how_to/optimizing_your_scene#using-unindexed-meshes aWeirdo, NasimiAsl and brianzinn 3 Quote Link to comment Share on other sites More sharing options...
jerome Posted July 21, 2018 Share Posted July 21, 2018 you can even animate all of them at a decent framerate : https://jsfiddle.net/6ng7usmj/43/ https://jsfiddle.net/6ng7usmj/47/ Quote Link to comment Share on other sites More sharing options...
aWeirdo Posted July 21, 2018 Share Posted July 21, 2018 Dat SPS. 422k boxes; https://jsfiddle.net/6ng7usmj/49/ 60 fps on my pc, even when moving the camera, yeah nah, i don't see the issue. jerome and brianzinn 1 1 Quote Link to comment Share on other sites More sharing options...
NasimiAsl Posted July 21, 2018 Share Posted July 21, 2018 i am sure if Graphic support 120 fs @jerome show us 121fps jerome 1 Quote Link to comment Share on other sites More sharing options...
brianzinn Posted July 21, 2018 Share Posted July 21, 2018 25 minutes ago, aWeirdo said: 60 fps on my pc 422K!! My slow laptop is only 30FPS maybe I should have got a gaming laptop This XPS 9560 is nearly a year old - still looking for something not too big with an amazing screen and at least nvidia 1080... Quote Link to comment Share on other sites More sharing options...
sable Posted July 21, 2018 Share Posted July 21, 2018 You can make up most of the performance difference just by freezing the material. https://jsfiddle.net/6ng7usmj/52/ Though the techniques above (instancing or sps) perform far better for scenes like this. It's certainly worth investigating these sorts of things though. Quote Link to comment Share on other sites More sharing options...
yokewang Posted July 21, 2018 Author Share Posted July 21, 2018 The frame rate improved by some optimizations from https://doc.babylonjs.com/how_to/optimizing_your_scene. https://jsfiddle.net/6ng7usmj/57/ optimized version. But still slower than ThreeJS version. https://jsfiddle.net/6ng7usmj original version. BTW: We should not compare an ONE DRAWCALL instance version with a 8000 DRAWCALL version. And ThreeJS supports instanced draw too. It's seems BabylonJs spends more time than ThreeJS to evaluate active meshes. I will try octree to see if it will help. Any help would be greatly appreciated. sable 1 Quote Link to comment Share on other sites More sharing options...
sable Posted July 21, 2018 Share Posted July 21, 2018 I agree that evaluate active meshes seems unreasonably slow, especially in the case where all the meshes in the scene are marked as always active. The difference between having all the meshes marked as always active, and freezing the active meshes array is 30 -> 45 fps for me. https://jsfiddle.net/6ng7usmj/65/ Quote Link to comment Share on other sites More sharing options...
NasimiAsl Posted July 21, 2018 Share Posted July 21, 2018 for (var x = 0; x < gridSize; x++) for (var y = 0; y < gridSize; y++) for (var z = 0; z < gridSize; z++) { var geometry = new THREE.BoxBufferGeometry(0.8, 0.8, 0.8); var boxMesh = new THREE.Mesh(geometry, material); } vs var geometry = new THREE.BoxBufferGeometry(0.8, 0.8, 0.8); for (var x = 0; x < gridSize; x++) for (var y = 0; y < gridSize; y++) for (var z = 0; z < gridSize; z++) { var boxMesh = new THREE.Mesh(geometry, material); } that is not good sample to test at all when we make a new Mesh we never use one GeometryBuffer for a lot mesh https://jsfiddle.net/pofq4827/5/ https://jsfiddle.net/6ng7usmj/68/ if you wanna make that type i think we do different in share geometryBuffer Quote Link to comment Share on other sites More sharing options...
jerome Posted July 21, 2018 Share Posted July 21, 2018 Another lead for the comparison : check that the 3JS phong material has the same default settings than the BJS standard material, like specular, etc ... I'm quite sure there's some difference here because when rotating the cam to the dark side of the big cube, both examples render differently : fully opaque for 3JS whereas still separated boxes for BJS Check also that the canvas in both samples have same size [EDIT] I changed the 3JS ambient light to a hemispereLight like in 3JS so the comparison is better : https://jsfiddle.net/pofq4827/11/ They still render differently in the dark side of the global cube, meaning there's still something different in the lights or in the materials, I suppose NasimiAsl 1 Quote Link to comment Share on other sites More sharing options...
Guest Posted July 21, 2018 Share Posted July 21, 2018 As Jerome stated, it is not a good idea to port directly from one framework to another. Here is something more Babylonjs wise to compare with your original demo: https://jsfiddle.net/6ng7usmj/89/ I also changed the hemi light (dynamic) by a ambient color like in original demo Also please not that this demo works badly with uniform buffer as only world matrix change (thus using instances would be far better). In this case we update an entire uniform buffer for just a matrix which is counter productive NasimiAsl and jerome 2 Quote Link to comment Share on other sites More sharing options...
yokewang Posted July 22, 2018 Author Share Posted July 22, 2018 The new version for 3JS: https://jsfiddle.net/pofq4827/16/ (disabled matrix auto updating and opaque objects sorting before rendering), its frame rate increased furtherly. The javascript computation time before indeed rendering(gl command) is within 2ms comparing to 10ms in BabylonJS. After inspecting the code for ThreeJS and BabylonJS, _evaluateActiveMeshes method costs too much for 8000 meshes. Quote Link to comment Share on other sites More sharing options...
jerome Posted July 22, 2018 Share Posted July 22, 2018 Reducing the 3JS example at the same window size as the BJS one, I get quite the same framerate (30-33 fps) with your two last demos (dk and yokewang's ones) on my laptop. The 3JS example is even slightly slower. Are you sure that you get still such a performance difference now ? Quote Link to comment Share on other sites More sharing options...
NasimiAsl Posted July 22, 2018 Share Posted July 22, 2018 both is 30fps for me for chrome firefox 5 - 6 fps Quote Link to comment Share on other sites More sharing options...
Guest Posted July 22, 2018 Share Posted July 22, 2018 Did you see my example? In my example evaluateActiveMeshes costs 0 (https://jsfiddle.net/6ng7usmj/89/) On my computer, my example is faster than your last 3js example. Here is the code of the _evaluateActiveMeshes: https://github.com/BabylonJS/Babylon.js/blob/master/src/babylon.scene.ts#L4190 Among all the code, the only things that could be slow are: - Frustum clipping (you can turn it of with mesh.alwaysSelectAsActiveMesh = true) - mesh.isReady (but we use the fatest version here as first parameter is set to false) And you can completely avoid the evaluate stage by calling scene.freezeActiveMeshes() like in my example (http://doc.babylonjs.com/api/classes/babylon.scene#freezeactivemeshes) Quote Link to comment Share on other sites More sharing options...
Dad72 Posted July 22, 2018 Share Posted July 22, 2018 I have the impression to see a publicity for 3js that tries to say that babylon is less efficient than 3js. Each engine has its characteristics and its way of doing things. Babylon is very effective if you use it with the tools that must. It still has other tools to optimize. In addition each engine has its strengths and if we must compare the two engines, Babylon has a lot of assets and is much more modern and easy to use. For my part, I never understood anything at 3js and the number of incompatible thing from one version to another made me totally abandon the 3D in browser until I found Babylon who has me to do much more than 3js. In fact with 3js I display a cube and I already had a lot of difficulty to create materials. with babylon i understood right away and is display a lot more stuff. when I imported a mesh it worked and in 3js, I had compatibility problems. So 3js vs Babylon. Babylon with no hesitation. Another important piece of information and the community. when i post questions on the 3js forum, i never got an answer. On babylon I had received in the minutes that followed my first posts because here there is an excellent community. Brief, A project with 8000 meshes is really a lot for a single scene. I can not believe that you need to create a project with 8000 meshes, but maybe you want to create a GTA V and you are surrounded by a team of 100 people. I do not know. When a project already reaches 500 to 1000 meshes it is already a project that has content to present, if then you add instances, clones, you can create projects large enough without ever reaching 8000 meshes and get fps between 45 and 60 fps. Quote Link to comment Share on other sites More sharing options...
sable Posted July 22, 2018 Share Posted July 22, 2018 It seems odd that there is not much of a performance boost when setting all meshes to alwaysSelectAsActiveMesh = true, but a big boost from freezing active meshes. http://www.babylonjs-playground.com/debug.html#QRIX4R#2 Intuitively I'd think they'd have similar results. Quote Link to comment Share on other sites More sharing options...
yokewang Posted July 23, 2018 Author Share Posted July 23, 2018 Freezing active meshes skip the step of checking 8000 mesh frustum clipping and state. if (mesh.alwaysSelectAsActiveMesh || mesh.isVisible && mesh.visibility > 0 && ((mesh.layerMask & this.activeCamera.layerMask) !== 0) && mesh.isInFrustum(this._frustumPlanes)) { this._activeMeshes.push(mesh); this.activeCamera._activeMeshes.push(mesh); mesh._activate(this._renderId); if (meshLOD !== mesh) { meshLOD._activate(this._renderId); } this._activeMesh(mesh, meshLOD); } this._activeMesh(mesh, meshLOD) costs time. And I got a little performance boost after below code replacement(BUT IT IS NOT A WISE SOLUTION). // this._totalVertices.addCount(mesh.getTotalVertices(), false); this._totalVertices.addCount(mesh._geometry._totalVertices, false); // if (mesh.alwaysSelectAsActiveMesh || mesh.isVisible && mesh.visibility > 0 && ((mesh.layerMask & this.activeCamera.layerMask) !== 0) && mesh.isInFrustum(this._frustumPlanes)) { if (mesh.alwaysSelectAsActiveMesh || mesh.isVisible && mesh.visibility > 0 && ((mesh.layerMask & this.activeCamera.layerMask) !== 0) && mesh._boundingInfo.boundingSphere.isInFrustum(this._frustumPlanes)) { Quote Link to comment Share on other sites More sharing options...
jerome Posted July 23, 2018 Share Posted July 23, 2018 The frustum check against boundingSpheres only is obviously faster but also less accurate. Not sure, but I think that 3JS computes the culling only with the bounding spheres : https://github.com/mrdoob/three.js/issues/11291 Well, if you tune your BJS demo so it's the same as the 3JS one, you'll get same perfs ? Maybe we could add a parameter in BJS to let the final user to choose whether he wants to limit the culling tests to boundingSpheres only. This already exists in the solid particle intersections http://doc.babylonjs.com/how_to/solid_particle_system#particle-intersections boundingSphereOnly : true Quote Link to comment Share on other sites More sharing options...
Guest Posted July 23, 2018 Share Posted July 23, 2018 I like the idea of having a way to define which culling algorithm you want. Will work on that Quote Link to comment Share on other sites More sharing options...
jerome Posted July 23, 2018 Share Posted July 23, 2018 https://github.com/BabylonJS/Babylon.js/issues/4812 Quote Link to comment Share on other sites More sharing options...
vijayxd Posted September 27, 2019 Share Posted September 27, 2019 used babylon createinstance fps rate is almost same Quote Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.