2
votes

I have a Three.js scene consisting of many buildings which are formed by stacking ExtrudeGeometry meshes (think buildings in Mapbox GL JS):

Three.js scene with stacked ExtrudeGeometry meshes

I'm creating these meshes using THREE.Shape and THREE.ExtrudeGeometry (I'm using react-three-fiber):

function coordsToShape(coords) {
  const shape = new Shape();
  let [x, z] = coords[0];
  shape.moveTo(x, z);
  for (const [x, z] of coords.slice(1)) {
    shape.lineTo(x, z);
  }
  return shape;
}

function Floor(props) {
  const {coords, bottom, top, color} = props;

  const shape = coordsToShape(coords);
  const geom = new ExtrudeGeometry(shape, {depth: top - bottom, bevelEnabled: false});

  return (
    <mesh castShadow geometry={geom} position={[0, bottom, 0]} rotation-x={-Math.PI / 2}>
      <meshPhongMaterial color={color} />
    </mesh>
  )
}

Then I stack the floors to produce the scene:

export default function App() {
  return (
    <Canvas>
      { /* lights, controls, etc. */ }
      <GroundPlane />
      <Floor coords={coords1} bottom={0} top={1} color="skyblue" />
      <Floor coords={coords2} bottom={1} top={3} color="pink" />
      <Floor coords={coords3} bottom={0} top={1} color="aqua" />
      <Floor coords={coords4} bottom={1} top={3} color="orange" />
    </Canvas>
  )
}

Full code/demo here. This results in one mesh for the ground plane and one for each building section, so five total.

I've read that using instancing to reduce the number of meshes is a good idea. Is instancing relevant to this scene? Most instancing examples show identical geometries with colors, positions and rotations varying. But can the geometry vary? Should I be using mergeBufferGeometries? But if I do that, will I still get the performance wins? Since I have coordinate arrays already, I'd also be happy using them to construct a large buffer of coordinates directly.

1

1 Answers

2
votes

Is instancing relevant to this scene?

Instancing in general is applicable if you are going to render a large number of objects with the same geometry and material but with different transformations (and other per-instance properties like e.g. color).

Merging geometries only makes sense if they can all share the same material. So if you need different colors per objects you can achieve this by defining vertex color data. Besides, the geometries should be considered as static since it is complicated to perform individual transformations if the data are already merged.

Both approaches are intended to lower the number of draw calls in your app which is an important performance metric. Try to use them whenever possible.