最近阅读3.2.1 的引擎源码
看了渲染流程的发现 3d model 和 2d batch 的渲染过程都是通过每个camera 去遍历所有的 对象去过滤所需渲染object。这种方式有点简单粗暴了,如果场景对象多 camera 多的情况下存在很多无效循环的开销。
建议
public addModel (m: Model) {
m.attachToScene(this);
this._models.push(m);
ModelArrayPool.push(this._modelArrayHandle, m.handle);
}
应该按model 所属 layer 去存储model
_models : Map<number, Array>
public addModel (m: Model) {
m.attachToScene(this);
let layer = m.node.layer;
let arr = this._models.get(layer);
if( arr == null){
arr = new Array();
this._models.set(layer, arr);
}
arr.push(m);
ModelArrayPool.push(this._modelArrayHandle, m.handle);
}
camera 寻找自己关心的 model 只需要根据visible 获取自己关心layer
const modelsmap = scene.models;
const visibility = camera.visibility;
const layer = 1;
while(layer <= visibility){
if(layer & visibility != 0){
let models = modelsmap.get(layer);
for (let i = 0; i < models.length; i++) {
const model = models[i];
// filter model by view visibility
if (model.enabled) {
if (model.node && ((visibility & model.node.layer) === model.node.layer)
|| (visibility & model.visFlags)) {
// shadow render Object
if (shadowObjects != null && model.castShadow && model.worldBounds) {
if (!_castBoundsInited) {
_castWorldBounds.copy(model.worldBounds);
_castBoundsInited = true;
}
AABB.merge(_castWorldBounds, _castWorldBounds, model.worldBounds);
shadowObjects.push(getCastShadowRenderObject(model, camera));
}
// frustum culling
if (model.worldBounds && !intersect.aabbFrustum(model.worldBounds, camera.frustum)) {
continue;
}
renderObjects.push(getRenderObject(model, camera));
}
}
}
}
layer <= 1;
}
这样能在 model 过多的场景情况下能节省大量的无效循环操作,另外2d 渲染的batch 也是同样的情况。
一般我们ui 摄像头和 3d 模型摄像头使用时都是独立的layer来的。目前底层的设计其实是会导致无效的循环。如果摄像头增加 模型数量增加的情况下这回导致我们渲染耗时浪费很大部分在这种无效的空循环过程。
