yokewang Posted January 4, 2018 Share Posted January 4, 2018 It's very fast without scaling or the number of mesh is small(less than 1000). But with scaling, the more meshes, the slower. https://playground.babylonjs.com/#BU5QQR#4 it's fast with out scaling. 234ms for my computer. https://playground.babylonjs.com/#BU5QQR#3 it's very slow when scaling. 2607ms . And when size change to 30, it will be timeout. Why? Thanks. Quote Link to comment Share on other sites More sharing options...
GameMonetize Posted January 4, 2018 Share Posted January 4, 2018 It is slower because by changing the scaling you force the world matrix to update. So you end up with tons of math computation. Quote Link to comment Share on other sites More sharing options...
yokewang Posted January 5, 2018 Author Share Posted January 5, 2018 I have tested the performance for different number meshes. number no-scaling scaling 1000 31ms 61ms 3375 80ms 587ms 8000 291ms 3276ms 15625 470ms 20615ms The time of no-scaling is almost linear to the number of meshes. But with scaling, the time is exponential increasing. It's confused. Quote Link to comment Share on other sites More sharing options...
jerome Posted January 5, 2018 Share Posted January 5, 2018 Each time you set a new scaling value, the WM is marked as dirty, meaning it has to be recomputed from scratch what is a heavy operation. If don't set any scaling (nor position, nor rotation) value, the WM isn't recomputed but is got from the cache, even by calling computeWorldMatrix(). The fact that the performance falls down with the increasing number of meshes is not surprising : the more meshes, the more computations. The fact the time increasing is no linear isn't surprising either : this is the way it happens when it overcrosses the limits of the JS engine and the CPU capabilities. For you very example (a huge bunch of spheres with different scalings), I would recommand to use a SPS (single particle system) what uses a single global WM and a single draw call to be rendered instead of thousands of individual meshes. Quote Link to comment Share on other sites More sharing options...
GameMonetize Posted January 5, 2018 Share Posted January 5, 2018 Also: calling random() takes a lot of time Quote Link to comment Share on other sites More sharing options...
Pryme8 Posted January 5, 2018 Share Posted January 5, 2018 2 hours ago, Deltakosh said: Also: calling random() takes a lot of time Also, is a crappy way to do randomness... Quote Link to comment Share on other sites More sharing options...
yokewang Posted January 7, 2018 Author Share Posted January 7, 2018 I found some clues from the source code. If scaling.isNonUniform, it will iterate every mesh in the scene to _markAllSubMeshesAsDirty(I don't know why) when call computeWorldMatrix. Below is the stack detail. sphereMesh.computeWorldMatrix(); --> if (this.scaling.isNonUniform) { this._updateNonUniformScalingState(true); } --> AbstractMesh.prototype._updateNonUniformScalingState = function (value) { if (!_super.prototype._updateNonUniformScalingState.call(this, value)) { return false; } this._markSubMeshesAsMiscDirty(); return true; }; --> AbstractMesh.prototype._markSubMeshesAsMiscDirty = function () { if (!this.subMeshes) { return; } for (var _i = 0, _a = this.subMeshes; _i < _a.length; _i++) { var subMesh = _a[_i]; var material = subMesh.getMaterial(); if (material) { material.markAsDirty(BABYLON.Material.MiscDirtyFlag); } } }; --> Material.prototype.markAsDirty = function (flag) { if (flag & Material.TextureDirtyFlag) { this._markAllSubMeshesAsTexturesDirty(); } if (flag & Material.LightDirtyFlag) { this._markAllSubMeshesAsLightsDirty(); } if (flag & Material.FresnelDirtyFlag) { this._markAllSubMeshesAsFresnelDirty(); } if (flag & Material.AttributesDirtyFlag) { this._markAllSubMeshesAsAttributesDirty(); } if (flag & Material.MiscDirtyFlag) { this._markAllSubMeshesAsMiscDirty(); } this.getScene().resetCachedMaterial(); }; --> Material.prototype._markAllSubMeshesAsMiscDirty = function () { this._markAllSubMeshesAsDirty(function (defines) { return defines.markAsMiscDirty(); }); }; --> Material.prototype._markAllSubMeshesAsDirty = function (func) { for (var _i = 0, _a = this.getScene().meshes; _i < _a.length; _i++) { var mesh = _a[_i]; if (!mesh.subMeshes) { continue; } for (var _b = 0, _c = mesh.subMeshes; _b < _c.length; _b++) { var subMesh = _c[_b]; if (subMesh.getMaterial() !== this) { continue; } if (!subMesh._materialDefines) { continue; } func(subMesh._materialDefines); } } }; The last function _markAllSubMeshesAsDirty will iterate every mesh in the scene, so the performance will decrease dramatically. It's very confusing that changing scaling is related to the material and will iterate each mesh in the scene. BTW: My babylonjs version is 3.1.1 Quote Link to comment Share on other sites More sharing options...
Pryme8 Posted January 7, 2018 Share Posted January 7, 2018 what happens with you do this: var self = this;setTimeout(()=>{self._updateNonUniformScalingState(true);},0); doubt it will fix it, but Id like to see if its the thread loop that is doing the impact. Quote Link to comment Share on other sites More sharing options...
GameMonetize Posted January 8, 2018 Share Posted January 8, 2018 Hello, when scaling is non uniform we have to process the normals (in the shader) using a different (a slower) path. This is why we need to flag all materials as dirty. I can add a property on the mesh which could be mesh.ignoreNonUniformScalingUpdate. It should work flawlessly in your case as you are doing everything before the first frame 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.