ThreeJS InstancedBufferGeometry 剔除问题?

Mar*_*341 2 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; 这很有帮助,但它与剔除并不完全相同,因为我有当前视口外的轨迹,但它仍然会影响性能

有什么建议?或想法?

Mar*_*fuß 5

对于实例几何,three.js 不能进行任何视锥体剔除,因为没有关于对象最终位置的信息。这将在顶点着色器中计算,而three.js 不知道那里发生了什么。

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

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

要进行可见性测试,最简单的方法可能是使用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;
Run Code Online (Sandbox Code Playgroud)

  • 好吧,由于我配置错误,我在顶部的 FPS 数字是错误的。但是我现在在查看所有曲目时获得了 27 FPS。当我使用这个灵魂时,我在查看所有曲目时仍然获得 27 FPS,但在查看没有曲目时获得 54 FPS(我还有其他内容渲染)所以它在我的情况下显示很少或没有开销。非常酷谢谢! (2认同)