CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-react-three--drei

Useful add-ons for react-three-fiber providing 100+ components for 3D web applications

Pending
Overview
Eval results
Files

performance.mddocs/

Performance

Optimization components for efficient rendering of large datasets and complex scenes. These components provide various strategies for maintaining smooth framerates while handling demanding 3D content.

Capabilities

Instances

Instanced mesh rendering for efficiently displaying large numbers of identical objects with individual transforms.

/**
 * Instanced mesh rendering for identical objects
 * @param props - Instances configuration
 * @returns JSX element for instanced mesh
 */
function Instances(props: InstancesProps): JSX.Element;

/**
 * Individual instance within an Instances component
 * @param props - Instance configuration  
 * @returns JSX element for single instance
 */
function Instance(props: InstanceProps): JSX.Element;

interface InstancesProps extends Omit<ThreeElements['instancedMesh'], 'ref' | 'args'> {
  /** Maximum number of instances */
  limit?: number;
  /** Instance range [start, count] */
  range?: [number, number];
  /** Frustum culling, true */
  frustumCulled?: boolean;
  /** Render order */
  renderOrder?: number;
}

interface InstanceProps {
  /** Instance position */
  position?: [number, number, number];
  /** Instance rotation */  
  rotation?: [number, number, number];
  /** Instance scale */
  scale?: [number, number, number] | number;
  /** Instance color */
  color?: ReactThreeFiber.Color;
  /** Instance matrix */
  matrix?: Matrix4;
}

Usage Examples:

import { Instances, Instance } from '@react-three/drei';

// Basic instancing
<Instances limit={1000} frustumCulled>
  <boxGeometry />
  <meshStandardMaterial />
  {Array.from({ length: 1000 }, (_, i) => (
    <Instance 
      key={i}
      position={[
        (Math.random() - 0.5) * 100,
        (Math.random() - 0.5) * 100, 
        (Math.random() - 0.5) * 100
      ]}
      rotation={[Math.random(), Math.random(), Math.random()]}
      scale={Math.random() * 0.5 + 0.5}
      color={`hsl(${Math.random() * 360}, 50%, 50%)`}
    />
  ))}
</Instances>

// Animated instances
function AnimatedInstances() {
  return (
    <Instances limit={100}>
      <sphereGeometry />
      <meshNormalMaterial />
      {Array.from({ length: 100 }, (_, i) => (
        <AnimatedInstance key={i} index={i} />
      ))}
    </Instances>
  );
}

function AnimatedInstance({ index }) {
  const ref = useRef();
  
  useFrame((state) => {
    const time = state.clock.elapsedTime;
    const angle = (index / 100) * Math.PI * 2;
    ref.current.position.set(
      Math.cos(angle + time) * 10,
      Math.sin(time) * 2,
      Math.sin(angle + time) * 10
    );
  });
  
  return <Instance ref={ref} />;
}

Points

Efficient point cloud rendering using GPU-based point systems for large datasets.

/**
 * Efficient point cloud rendering with GPU processing
 * @param props - Points configuration
 * @returns JSX element for point cloud
 */
function Points(props: PointsProps): JSX.Element;

interface PointsProps extends Omit<ThreeElements['points'], 'ref'> {
  /** Point positions array */
  positions?: Float32Array | number[];
  /** Point colors array */
  colors?: Float32Array | number[];
  /** Point sizes array */
  sizes?: Float32Array | number[];
  /** Point count limit */
  limit?: number;
  /** Frustum culling, true */
  frustumCulled?: boolean;
}

interface PointsInstancesProps extends PointsProps {
  /** Instanced rendering, false */
  instances?: boolean;
  /** Instance limit, 1000 */
  instanceLimit?: number;
}

interface PointsBuffersProps extends PointsProps {
  /** Use buffer geometry, true */
  buffer?: boolean;
  /** Buffer update frequency */
  updateFrequency?: number;
}

Usage Examples:

import { Points } from '@react-three/drei';

// Basic point cloud
function PointCloud() {
  const pointCount = 10000;
  const positions = new Float32Array(pointCount * 3);
  const colors = new Float32Array(pointCount * 3);
  
  for (let i = 0; i < pointCount; i++) {
    // Random positions
    positions[i * 3] = (Math.random() - 0.5) * 100;
    positions[i * 3 + 1] = (Math.random() - 0.5) * 100;
    positions[i * 3 + 2] = (Math.random() - 0.5) * 100;
    
    // Random colors
    colors[i * 3] = Math.random();
    colors[i * 3 + 1] = Math.random();
    colors[i * 3 + 2] = Math.random();
  }
  
  return (
    <Points positions={positions} colors={colors} limit={pointCount}>
      <pointsMaterial size={0.1} vertexColors />
    </Points>
  );
}

// Animated point cloud
function AnimatedPoints() {
  const pointsRef = useRef();
  const pointCount = 5000;
  
  useFrame((state) => {
    if (pointsRef.current?.geometry?.attributes?.position) {
      const positions = pointsRef.current.geometry.attributes.position.array;
      const time = state.clock.elapsedTime;
      
      for (let i = 0; i < pointCount; i++) {
        const i3 = i * 3;
        positions[i3 + 1] += Math.sin(time + i * 0.01) * 0.01;
      }
      
      pointsRef.current.geometry.attributes.position.needsUpdate = true;
    }
  });
  
  return (
    <Points ref={pointsRef} limit={pointCount}>
      <pointsMaterial size={0.05} color="hotpink" />
    </Points>
  );
}

Detailed

Level-of-detail (LOD) rendering component that switches between different representations based on distance.

/**
 * Level-of-detail rendering based on distance
 * @param props - LOD configuration
 * @returns JSX element for LOD system
 */
function Detailed(props: DetailedProps): JSX.Element;

interface DetailedProps extends Omit<ThreeElements['group'], 'ref'> {
  /** LOD distances array */
  distances: number[];
  /** Hysteresis factor, 0 */
  hysteresis?: number;
}

Usage Examples:

import { Detailed } from '@react-three/drei';

// LOD with multiple detail levels  
<Detailed distances={[0, 10, 20, 35, 60]}>
  {/* High detail - close up */}
  <mesh>
    <sphereGeometry args={[1, 64, 64]} />
    <meshStandardMaterial />
  </mesh>
  
  {/* Medium detail */}
  <mesh>
    <sphereGeometry args={[1, 32, 32]} />
    <meshStandardMaterial />
  </mesh>
  
  {/* Low detail */}
  <mesh>
    <sphereGeometry args={[1, 16, 16]} />
    <meshStandardMaterial />
  </mesh>
  
  {/* Very low detail */}
  <mesh>
    <sphereGeometry args={[1, 8, 8]} />
    <meshBasicMaterial />
  </mesh>
  
  {/* Billboard for far distances */}
  <sprite>
    <spriteMaterial map={billboardTexture} />
  </sprite>
</Detailed>

PerformanceMonitor

Performance monitoring system with automatic quality degradation and frame rate tracking.

/**
 * Performance monitoring with automatic degradation
 * @param props - Performance monitor configuration
 * @returns JSX element for performance monitoring
 */
function PerformanceMonitor(props: PerformanceMonitorProps): JSX.Element;

interface PerformanceMonitorProps {
  /** Target FPS, 60 */
  fps?: number;
  /** Performance factor [0-1], 1 */
  factor?: number;
  /** Flip performance, false */
  flipflops?: number;
  /** Step size for adjustments, 1 */
  step?: number;
  /** Monitor enabled, true */
  enabled?: boolean;
  /** Performance change callback */
  onIncline?: (api: PerformanceMonitorApi) => void;
  /** Performance decline callback */
  onDecline?: (api: PerformanceMonitorApi) => void;
  /** Frame drop callback */
  onFallback?: (api: PerformanceMonitorApi) => void;
}

interface PerformanceMonitorApi {
  /** Current performance factor */
  factor: number;
  /** Current FPS */
  fps: number;
  /** Render count */
  frames: number;
  /** Performance monitor enabled */
  enabled: boolean;
}

Usage Examples:

import { PerformanceMonitor } from '@react-three/drei';

function AdaptiveScene() {
  const [dpr, setDpr] = useState(1);
  const [quality, setQuality] = useState(1);
  
  return (
    <>
      <PerformanceMonitor
        onIncline={() => {
          setDpr(Math.min(2, dpr + 0.1));
          setQuality(Math.min(1, quality + 0.1));
        }}
        onDecline={() => {
          setDpr(Math.max(0.5, dpr - 0.1));
          setQuality(Math.max(0.3, quality - 0.1));
        }}
        onFallback={() => {
          setDpr(0.5);
          setQuality(0.3);
        }}
      />
      
      <Canvas dpr={dpr}>
        <AdaptiveContent quality={quality} />
      </Canvas>
    </>
  );
}

Preload

Asset preloading system for improving loading performance and user experience.

/**
 * Asset preloading system for better performance
 * @param props - Preload configuration
 * @returns JSX element for preloading assets
 */
function Preload(props: PreloadProps): JSX.Element;

interface PreloadProps {
  /** Preload all assets, true */
  all?: boolean;
  /** Asset scenes to preload */
  scene?: Object3D | Object3D[];
  /** Preload cameras, false */
  camera?: boolean;
  /** Include invisible objects, false */
  includeInvisible?: boolean;
}

Usage Examples:

import { Preload } from '@react-three/drei';

// Preload all scene assets
<Canvas>
  <Suspense fallback={<Loader />}>
    <Scene />
    <Preload all />
  </Suspense>
</Canvas>

// Selective preloading
<Preload scene={sceneRef.current} includeInvisible />

AdaptiveDpr

Adaptive device pixel ratio component for dynamic resolution scaling based on performance.

/**
 * Adaptive device pixel ratio for performance scaling
 * @param props - Adaptive DPR configuration
 * @returns JSX element for adaptive DPR
 */
function AdaptiveDpr(props: AdaptiveDprProps): JSX.Element;

interface AdaptiveDprProps {
  /** Lower DPR bound, 1 */
  pixelated?: number;
  /** Upper DPR bound, 2 */
  dpr?: number;
}

AdaptiveEvents

Adaptive event handling that reduces event frequency based on performance needs.

/**
 * Adaptive event handling for performance optimization
 * @param props - Adaptive events configuration
 * @returns JSX element for adaptive events
 */
function AdaptiveEvents(props: AdaptiveEventsProps): JSX.Element;

interface AdaptiveEventsProps {
  /** Event enabled, true */
  enabled?: boolean;
}

BakeShadows

Shadow map baking utility for static lighting performance optimization.

/**
 * Shadow map baking for static lighting optimization
 * @param props - Bake shadows configuration
 * @returns JSX element for shadow baking
 */
function BakeShadows(props: BakeShadowsProps): JSX.Element;

interface BakeShadowsProps {
  /** Baking enabled, true */
  enabled?: boolean;
}

meshBounds

Efficient mesh bounds calculation for optimized raycasting and collision detection.

/**
 * Efficient mesh bounds calculation for raycasting optimization
 * @param mesh - Target mesh for bounds calculation
 * @returns Bounds helper functions
 */
function meshBounds(mesh: Mesh): {
  raycast: (raycaster: Raycaster, intersects: Intersection[]) => void;
};

Usage Examples:

import { meshBounds } from '@react-three/drei';

function OptimizedMesh() {
  const meshRef = useRef();
  
  useLayoutEffect(() => {
    if (meshRef.current) {
      // Use efficient bounds-based raycasting
      meshRef.current.raycast = meshBounds(meshRef.current).raycast;
    }
  }, []);
  
  return (
    <mesh ref={meshRef}>
      <complexGeometry /> {/* Complex geometry with optimized raycasting */}
      <meshStandardMaterial />
    </mesh>
  );
}

Integration Patterns

Performance-Adaptive Rendering

function AdaptiveScene() {
  const [performanceLevel, setPerformanceLevel] = useState(1);
  
  return (
    <>
      <PerformanceMonitor
        onDecline={(api) => {
          if (api.factor < 0.5) setPerformanceLevel(0.3);
          else if (api.factor < 0.8) setPerformanceLevel(0.6); 
        }}
        onIncline={(api) => {
          if (api.factor > 0.9) setPerformanceLevel(1);
          else if (api.factor > 0.7) setPerformanceLevel(0.8);
        }}
      />
      
      <AdaptiveDpr pixelated={performanceLevel} />
      <AdaptiveEvents enabled={performanceLevel > 0.5} />
      
      {/* Render based on performance level */}
      {performanceLevel > 0.8 ? (
        <HighQualityContent />
      ) : performanceLevel > 0.5 ? (
        <MediumQualityContent />
      ) : (
        <LowQualityContent />
      )}
    </>
  );
}

Instanced Forest Example

function Forest() {
  const treeCount = 1000;
  const trees = useMemo(() => {
    return Array.from({ length: treeCount }, (_, i) => ({
      position: [
        (Math.random() - 0.5) * 200,
        0,
        (Math.random() - 0.5) * 200
      ],
      rotation: [0, Math.random() * Math.PI * 2, 0],
      scale: Math.random() * 0.5 + 0.5,
    }));
  }, []);
  
  return (
    <Instances limit={treeCount} frustumCulled>
      <cylinderGeometry args={[0.1, 0.3, 3]} />
      <meshStandardMaterial color="brown" />
      {trees.map((tree, i) => (
        <Instance
          key={i}
          position={tree.position}
          rotation={tree.rotation}
          scale={tree.scale}
        />
      ))}
    </Instances>
  );
}

Dynamic LOD System

function DynamicLOD({ position }) {
  const { camera } = useThree();
  const [distance, setDistance] = useState(0);
  
  useFrame(() => {
    const dist = camera.position.distanceTo(new Vector3(...position));
    setDistance(dist);
  });
  
  return (
    <Detailed distances={[0, 10, 25, 50]} hysteresis={2}>
      {/* Ultra high detail */}
      <ComplexModel vertices={50000} />
      
      {/* High detail */}
      <ComplexModel vertices={10000} />
      
      {/* Medium detail */}
      <SimpleModel vertices={1000} />
      
      {/* Low detail - billboard */}
      <Billboard>
        <Image url="/billboard.png" />
      </Billboard>
    </Detailed>
  );
}

Memory Management

function MemoryEfficientScene() {
  // Dispose of unused assets
  useEffect(() => {
    return () => {
      // Clean up geometries
      geometries.forEach(geo => geo.dispose());
      // Clean up materials  
      materials.forEach(mat => mat.dispose());
      // Clean up textures
      textures.forEach(tex => tex.dispose());
    };
  }, []);
  
  // Use object pooling for frequently created/destroyed objects
  const objectPool = useMemo(() => new ObjectPool(), []);
  
  return (
    <>
      <BakeShadows /> {/* Bake static shadows */}
      <PooledObjects pool={objectPool} />
    </>
  );
}

BakeShadows

Component that bakes static shadows for performance optimization.

/**
 * Bakes static shadows to improve rendering performance
 * @returns JSX element that disables shadow auto-update
 */
function BakeShadows(): JSX.Element;

Preload

Component for preloading and compiling shaders and materials.

/**
 * Preloads and compiles shaders and materials for smoother performance
 * @param props - Preload configuration props
 * @returns JSX element for preloading
 */
function Preload(props: PreloadProps): JSX.Element;

interface PreloadProps {
  /** Preload all objects, false */
  all?: boolean;
  /** Scene to preload */
  scene?: Object3D;
  /** Camera for preloading */
  camera?: Camera;
}

meshBounds

Utility function for efficient mesh bounds calculation.

/**
 * Efficient mesh bounds calculation for culling and optimization
 * @param mesh - Mesh to calculate bounds for
 * @returns Bounds helper
 */
function meshBounds(mesh: Mesh): BoundsApi;

interface BoundsApi {
  /** Get bounding box */
  getBox(): Box3;
  /** Get bounding sphere */
  getSphere(): Sphere;
  /** Check if point is inside bounds */
  containsPoint(point: Vector3): boolean;
}

Install with Tessl CLI

npx tessl i tessl/npm-react-three--drei

docs

abstractions.md

cameras.md

controls.md

gizmos.md

hooks.md

index.md

loaders.md

materials.md

performance.md

staging.md

web-integration.md

tile.json