ThreeJS InstancedBufferGeometry剔除问题?

时间:2018-07-12 18:32:49

标签: three.js

当我渲染我的模型的3000个实例并将它们保留在视图区域中时,我得到55FPS,但是如果我有5000个我的模型的实例但将它们中的2000个实例保留在视图区域之外,我仍然会得到40 FPS。

camera = new THREE.PerspectiveCamera(75,window.innerWidth / window.innerHeight,0.01,10000);

是否有可能正确剔除,但事实是它必须确定是否被剔除会减慢速度?我主要是从https://github.com/mrdoob/three.js/blob/master/examples/webgl_buffergeometry_instancing_dynamic.html

编辑*我知道我可以使用geometry.maxInstancedCount = trackCount;这很有用,但它与剔除并不完全相同,因为我已经跟踪了当前的视口,但仍然影响了性能

有什么建议吗?或想法?

1 个答案:

答案 0 :(得分:2)

对于实例化的几何体three.js不能进行任何平截头体剔除,因为没有有关对象最终位置的信息。这将在顶点着色器中进行计算,并且three.js不了解那里发生的事情。

最早进行剔除的时间是在为每个实例的每个顶点运行顶点着色器之后。这已经说明了您看到的帧率下降。尽管可以看到相同数量的对象/三角形,但顶点着色器调用的数量却高达166%。

如果要自己实施剔除,则可以尝试为每一帧重新排列属性缓冲区中的实例(跳过不可见的实例),并将max-instance计数调整为可见实例的数量。这可能有点违反直觉,但是在这里重新计算每个帧上的所有实例属性缓冲区实际上可以提供更好的性能。

要进行可见性测试,最简单的方法可能是使用THREE.Frustum()类和frustum.containsPoint()。看起来像这样

const frustum = new Frustum();
const projScreenMatrix = new Matrix();

// assume instances is an array of objects containing all the 
// relevant information for all instances
const instances = [
  // {position: ...}, {position: ...}, ...
];

// for every frame
projScreenMatrix.multiplyMatrices(
  camera.projectionMatrix, 
  camera.matrixWorldInverse 
);
frustum.setFromMatrix(projScreenMatrix);

let visibleInstanceCount = 0;

for (let i = 0; i < instanceCount; i++) {
  const pos = instances[i].position;

  if (!frustum.containsPoint(pos)) {
    continue;
  }

  // add instance to instance-attribute buffers
  pos.toArray(instancePositionBuffer, visibleInstanceCount * 3);
  visibleInstanceCount++;
}

geometry.maxInstanceCount = visibleInstanceCount;