PluginBench
Skill
Review
Audit score 70

r3f-geometry

enzed/r3f-skills

Build React Three Fiber geometry, buffers, instanced meshes, and lines for shape construction and draw-call optimization.

What is r3f-geometry?

This skill covers constructing geometry in React Three Fiber, including native JSX shapes, custom BufferGeometry, instanced meshes, and line rendering. Use it when you need to define 3D topology, optimize draw calls through instancing, or work with large particle sets and custom buffer data.

  • Create native JSX geometry for ordinary shapes with Three.js constructor arguments
  • Build custom BufferGeometry with position, normal, UV, and index buffers
  • Declare instanced meshes using Drei Instances for reduced draw calls and shared geometry
  • Render large particle sets efficiently with buffer-based points
  • Generate and update custom buffer attributes with proper GPU synchronization
  • Create lines with configurable world-space or screen-space widths using Drei Line

How to install r3f-geometry

npx skills add https://github.com/enzed/r3f-skills --skill r3f-geometry
Prerequisites
  • React Three Fiber 9+ and Three.js r185+ installed
  • React 19+
  • Drei library for helper components (Instances, Line, Edges, Text3D)
Claude Code
Cursor
Windsurf
Cline

How to use r3f-geometry

  1. 1.Inspect your installed Three.js, Fiber, and Drei versions to match constructor arguments and props
  2. 2.Choose your geometry representation: native JSX for simple shapes, BufferGeometry for custom topology, or Drei Instances for batched rendering
  3. 3.For instanced geometry, wrap Instance components in an Instances provider with limit and range props
  4. 4.For custom buffers, construct JSX buffer attributes with typed arrays and correct itemSize (3 for position/normal, 2 for UVs)
  5. 5.After CPU buffer modifications, set attribute.needsUpdate = true and recompute bounding boxes if geometry bounds change
  6. 6.Test at your intended object count and verify draw calls, bounds, raycasting, and resource cleanup

Use cases

Good for
  • Optimize a scene with thousands of identical objects by switching to instanced rendering
  • Build a particle system with custom positions and colors stored in buffers
  • Create procedurally generated terrain or mesh topology with custom BufferGeometry
  • Render wireframe or edge outlines on complex geometry using Edges helper
  • Update vertex positions each frame while keeping topology fixed by modifying buffer attributes
Who it's for
  • React Three Fiber developers building 3D graphics
  • Performance-focused developers optimizing draw calls and GPU memory
  • Graphics programmers working with custom mesh topology and buffer management
  • Game or visualization developers rendering large object counts

r3f-geometry FAQ

When should I use Drei Instances vs. native InstancedMesh?

Use Drei Instances for convenient declarative syntax with per-instance events and props. For very large or frequently updated sets, read the native instancing guide to avoid per-instance React overhead.

How do I animate geometry without reconstructing it?

Animate transforms (position, rotation, scale) rather than constructor args. For deforming geometry, modify buffer attribute contents and set needsUpdate = true instead of rebuilding the geometry.

Do I need to manually compute normals?

Lit geometry needs normals. Use computeVertexNormals() when appropriate, but avoid recomputing every frame if a shader or analytic normals can express deformation more cheaply.

What is the difference between Drei Merged and geometry merging?

Drei Merged creates instancing abstractions from meshes, not BufferGeometry, and does not concatenate arbitrary static geometry. For actual merging, use mergeGeometries from three/addons/utils/BufferGeometryUtils.js.

How do I handle line width in WebGL?

Use Drei Line for useful line widths with worldUnits option for world-space vs. screen-space thickness. Native WebGL line width is platform-limited.

Full instructions (SKILL.md)

Source of truth, from enzed/r3f-skills.


name: r3f-geometry description: Build React Three Fiber geometry, custom buffers, instanced meshes, points, and lines. Use for shape construction and geometry draw-call optimization, rather than material appearance.

React Three Fiber geometry

Inspect installed Three.js, Fiber, and Drei versions before copying constructor arguments or helper props. Examples target Fiber 9 / React 19 and Three.js r185.

Choose the representation

  • Use native JSX geometry for ordinary shapes. args match the Three.js constructor; changing them reconstructs geometry, so animate transforms rather than constructor inputs.
  • Use BufferGeometry for custom topology and buffer-based points for large particle sets. Keep generated arrays stable and use deterministic generation when results must be reproducible.
  • Use Drei Instances for convenient declarative instances with events. For large or frequently updated sets, read native instancing to avoid per-instance React overhead.
  • Instancing shares geometry/material and reduces draw calls. Merely sharing a geometry among separate meshes does not batch their draws.
  • Drei Merged creates instancing abstractions from meshes, not BufferGeometry objects; it does not concatenate arbitrary static geometry. For actual merging, inspect mergeGeometries from three/addons/utils/BufferGeometryUtils.js and ensure compatible attributes/indexing.

Declarative instances

Mount below Canvas with lighting. Each Instance belongs to its nearest Instances provider.

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

export default function Example() {
  return (
    <Instances limit={3} range={3}>
      <boxGeometry args={[0.7, 0.7, 0.7]} />
      <meshStandardMaterial />
      <Instance position={[-1.2, 0, 0]} color="coral" />
      <Instance position={[0, 0, 0]} color="skyblue" />
      <Instance position={[1.2, 0, 0]} color="gold" />
    </Instances>
  )
}

Custom buffers and updates

  • position and normal attributes usually have item size 3; UVs have item size 2. Construct JSX buffer attributes with args={[typedArray, itemSize]} and the correct attach, not just array/count props with no constructor arguments.
  • Indices refer to vertices; winding determines the front face. Duplicate vertices at hard normals or UV seams. Indexed vertices share all attributes, not just positions.
  • Lit geometry needs normals. Use computeVertexNormals() when appropriate; do not recompute every frame if a shader or analytic normals can express the deformation more cheaply.
  • After CPU buffer writes, set attribute.needsUpdate = true. Choose dynamic usage before the first GPU upload when buffers will change often.
  • Recompute bounding boxes/spheres after geometry changes that affect them. GPU vertex displacement does not update CPU bounds or raycasting automatically.
  • UV selection is explicit on modern Three.js: texture.channel selects uv, uv1, uv2, or uv3. Do not unconditionally copy uv into uv2 for AO.
  • Avoid rebuilding buffers for pointer movement. If topology is fixed, change attribute contents or uniforms instead.

Helpers and tradeoffs

  • Drei Line supports useful line widths; native WebGL line width is limited by the platform. Check worldUnits when choosing screen-space versus world-space thickness.
  • Use Drei Text for flat text and Text3D for extruded geometry. Current TextGeometry uses depth, not the historical height; verify the helper's installed types and font format.
  • Use Edges for sharp-edge outlines, not as a replacement for screen-space selection effects.
  • Bounds and Center change framing/transforms; decide whether they should update after asset loading, resizing, or interaction.
  • Segment count should follow silhouette, deformation, and viewing distance. A “high quality” fixed count is not universally better.
  • Declaratively created geometry can be owned by R3F. Shared or cached geometry needs a shared lifetime; do not dispose it from one instance while others remain mounted.

Verify

Check bounds/culling after updates, raycast hit positions, resource cleanup, and draw calls. Test at the intended object count; three instances do not establish performance at ten thousand.

Sources