Babylonjs 在场景中优化处于实体墙后面的大量模型
作者:互联网
Babylonjs 的摄像机转向时,如果镜头内有一面墙,墙不透明,墙后面一堆资源,比如花草树木无数个,会掉帧严重。
这时候镜头内虽然看着只有墙,但是BJS的引擎把墙后面的模型也渲染了。
例如墙后面有1000个球体,那么就可以隐藏这些球体模型。(表示1000个不同模型,否则同模型可用instance优化)
先说总结,可以使用AssetContainer进行资源管理,removeAllFromScene后,场景内totals总模型数量就下降了,帧率就提高。
测试用例截图和分析如下:
1.墙后面有1000个球,顶视图“看不到”这些球,但是绝对帧率和前视图一样,只有118帧率。
inspector也提示active meshes为1002,说明镜头内所有模型都被渲染了,无论是否只看到一面墙。
2.如果镜头内的1000个球体模型不加载,那么帧率可高达5800帧,所以目的为通过隐藏墙后“看不到”的模型,提高帧率。
3.隐藏模型方法 :mesh.isVisible = false,帧率1300,有成效,但是距离5800还太远,说明引擎是通过计算后渲染这些模型消失的。
4.隐藏方法:mesh.renderingGroupId=10,判断和camera的renderingGroupId交集,交集为0就在镜头内隐藏模型(具体使用方法可以查阅sandbox的inspector讲解)
但是帧率580左右,越优化越卡,说明计算每个模型的交集值太耗费内存资源了。
5. 隐藏方法:babylon有自己计算遮罩查询的方法occlusionQuery,用于判断模型边框是否镜头内(具体使用方法查阅官方API文档)
顶视图110帧,前视图45帧,引擎计算量更大了,每个模型都计算边框值,负优化。
6.隐藏方法:setEnable(fals),模型在inspector中可以勾选enable选项,用这个方法可以隐藏模型,
效果为3000帧,如图当前活动的模型只有2个,总模型1002个,隐藏的模型就没有被渲染,但是还处于场景计算内。
7. 隐藏方法:container.removeAllFromScene(),可以看到帧率5400,总模型和活动模型都为2,
所以可以通过AssetContainer管理模型,远处或者隔壁房间看不见、不需要的模型就从场景移除
测试排行榜
- removeAllFromScene() FPS 5600
– only two sphere FPS 5200 - setEnabled FPS 3000
- isVisible FPS 1350
- renderingGroupId FPS 570
- default show FPS 120
- occlusionQuery FPS 110~45 (will be used together with AssetContainer )
我的电脑 2600x+1660ti
测试代码 https://playground.babylonjs.com/#IC6IRV#2
var createScene = function () {
var scene = new BABYLON.Scene(this.engine);
var camera = new BABYLON.ArcRotateCamera('Camera', 0, 0, 10, null, scene);
camera.minZ = 0.01;
camera.setTarget(BABYLON.Vector3.Zero());
camera.attachControl(canvas, false);
var light = new BABYLON.HemisphericLight('light1', new BABYLON.Vector3(0, 1, 0), scene);
var sharedGeometry = BABYLON.MeshBuilder.CreateSphere('sphere', {
segments: 64,
diameter: 0.8
}, scene).geometry;
var gridSize = 10;//10x10x10
var meshList = [];
var ground = BABYLON.Mesh.CreateGround('ground1', gridSize * 1.5, gridSize * 1.5, 2, scene);
ground.position.y = gridSize / 2;
var container = new BABYLON.AssetContainer(scene);
for (var x = 0; x < gridSize; x++)
for (var y = 0; y < gridSize; y++)
for (var z = 0; z < gridSize; z++) {
// var mesh = BABYLON.MeshBuilder.CreateSphere('sphere '+ x + '_' + y + '_' + z, {
// segments: 64,
// diameter: 0.8
// }, scene);
var mesh = new BABYLON.Mesh('sphere '+ x + '_' + y + '_' + z, scene);
sharedGeometry.applyToMesh(mesh);
mesh.position.set(-gridSize / 2 + x, -gridSize / 2 + y, -gridSize / 2 + z);
// mesh.occlusionQueryAlgorithmType = BABYLON.AbstractMesh.OCCLUSION_ALGORITHM_TYPE_CONSERVATIVE;
// mesh.occlusionType = BABYLON.AbstractMesh.OCCLUSION_TYPE_OPTIMISTIC;
// mesh.occlusionRetryCount = -1;
// mesh.isOccluded = true;
// mesh.isVisible = false; //FPS 1670
// mesh.renderingGroupId = 10; //FPS 620
// mesh.freezeWorldMatrix(); //FPS 124
// mesh.setEnabled(false); //FPS 3000
// gridSize==1 FPS 4500
//default absolute FPS 121
container.meshes.push(mesh) //FPS 4500
meshList.push(mesh);
}
container.removeAllFromScene()
// oom crash
// var mergeMesh = BABYLON.Mesh.MergeMeshes(meshList, true, true, undefined, false, true);
camera.setPosition(new BABYLON.Vector3(gridSize, gridSize, gridSize));
scene.registerBeforeRender(() => {
});
return scene;
};
善用Playground,可以查inspector,也可以根据代码查别人写过的用例
标签:实体墙,场景,模型,Babylonjs,mesh,FPS,var,gridSize,BABYLON 来源: https://blog.csdn.net/maki077/article/details/110847109