three.jsreact-three-fiberreact-three-dreilevel-of-detail

Where is the threshold measured from in LOD rendering in three.js?


I'm doing LOD rendering for multiple meshes. I'm confused about where the threshold is measured from.

I have a demo that works, except the high and low resolution meshes are swapped out for both the red and blue dots at the same camera position, despite them having different bounding areas and origins.

import { Canvas } from "@react-three/fiber";
import { generateCubePoints } from "./generateCubePoints";
import {
  CameraControls,
  PerspectiveCamera,
  Detailed,
  GizmoHelper,
  GizmoViewport,
} from "@react-three/drei";

export const ITEMS_PER_ROW = 3;

const mockBounds = {
  minX: -40,
  maxX: 40,
  minY: -40,
  maxY: 40,
  minZ: -40,
  maxZ: 40,
};
const mockBounds1 = {
  minX: mockBounds.minX,
  maxX: 0,
  minY: mockBounds.minY,
  maxY: mockBounds.maxY,
  minZ: mockBounds.minZ,
  maxZ: mockBounds.maxZ,
};
const mockBounds2 = {
  minX: 0,
  maxX: mockBounds.maxX,
  minY: mockBounds.minY,
  maxY: mockBounds.maxY,
  minZ: mockBounds.minZ,
  maxZ: mockBounds.maxZ,
};

const mockPoints = [
  {
    color: "red",
    bounds: mockBounds1,
    points: [
      generateCubePoints({
        bounds: mockBounds1,
        numPoints: 1000,
      }),
      generateCubePoints({
        bounds: mockBounds1,
        numPoints: 100,
      }),
    ],
  },
  {
    color: "blue",
    bounds: mockBounds2,
    points: [
      generateCubePoints({
        bounds: mockBounds2,
        numPoints: 1000,
      }),
      generateCubePoints({
        bounds: mockBounds2,
        numPoints: 100,
      }),
    ],
  },
] as const;

function App() {
  return (
      <Canvas>
        {mockPoints.map((pGroup, pGroupI) => {
          return (
            <Detailed distances={[0, 100]} key={pGroupI}>
              {pGroup.points.map((p, pI) => {
                return (
                  <points key={`${pGroupI}-${pI}`} renderOrder={0}>
                    <bufferGeometry>
                      <bufferAttribute
                        attach="attributes-position"
                        args={[p, ITEMS_PER_ROW]}
                        count={p.length / ITEMS_PER_ROW}
                      />
                    </bufferGeometry>
                    <pointsMaterial size={4} color={pGroup.color} />
                  </points>
                );
              })}
            </Detailed>
          );
        })}
      </Canvas>
  );
}

https://codesandbox.io/p/devbox/damp-rgb-forked-57783t?workspaceId=ws_ER7skizgVvGCRcwppmiBu

enter image description here enter image description here

I got it working by setting position on the Detailed component, however this moved the points. So I then needed to set the negative of these values as the position on points:

{mockPoints.map((pGroup, pGroupI) => {
          const position = [
            (pGroup.bounds.minX + pGroup.bounds.maxX) / 2,
            (pGroup.bounds.minY + pGroup.bounds.maxY) / 2,
            (pGroup.bounds.minZ + pGroup.bounds.maxZ) / 2,
          ] as const;
          const positionNegative = [
            -position[0],
            -position[1],
            -position[2],
          ] as const;
          return (
            <Detailed distances={[0, 100]} key={pGroupI} position={position}>
              {pGroup.points.map((p, pI) => {
                return (
                  <points
                    key={`${pGroupI}-${pI}`}
                    renderOrder={0}
                    position={positionNegative}
                  >

https://codesandbox.io/p/devbox/damp-rgb-forked-r2z2fw?workspaceId=ws_ER7skizgVvGCRcwppmiBu

enter image description here

This seems to work but feels messy. Is there a better way?

Also I'm very concerned my performance. My real scene has over a million points and I'm really pushing the limits of what the browser can handle. So any performance savings I can do would be a great help.


Solution

  • To answer your question very directly, the distance is always measured as the distance between the world camera position and the origin of the object. Nothing else should have any influence, did you double check the origins? Other than that I'm no help.

    I've had a similar performance issue recently with meshes but the unfortunate truth is that other than LOD management, there isn't much to do. Three.js likes less objects in general so try to merge objects where you can but I don't think that applies to what you want to do.