Geometry vs BufferGeometry in Three.js
In Three.js, the way 3D shapes are represented and rendered has
evolved significantly, transitioning from the user-friendly but
inefficient Geometry class to the high-performance
BufferGeometry class. This article explores the core
differences between these two classes, why Three.js deprecated the
original Geometry class, and how
BufferGeometry optimizes rendering performance by directly
interfacing with GPU memory.
Understanding the Legacy Geometry Class
The deprecated Geometry class was designed with
developer readability in mind. It stored 3D data using highly readable,
nested JavaScript objects:
- Vertices: Stored as an array of
THREE.Vector3objects. - Faces: Stored as an array of
THREE.Face3objects, which defined how vertices connected to form triangles.
While this structure made it easy for developers to programmatically read and modify vertices or faces, it was highly inefficient for modern web browsers and graphics hardware. Before rendering, Three.js had to translate this user-friendly object structure into flat arrays that the WebGL graphics pipeline could understand. This translation process consumed valuable CPU cycles and created a significant memory overhead, leading to frequent garbage collection spikes.
Understanding BufferGeometry
BufferGeometry is the modern, high-performance standard
in Three.js. Instead of using complex JavaScript objects, it stores all
vertex data—such as positions, normals, colors, and UV
coordinates—directly in flat, contiguous memory blocks called
typed arrays (such as Float32Array).
These arrays are wrapped in THREE.BufferAttribute
objects and sent directly to the GPU. Because the data is already in a
format native to the GPU, there is no need for costly translation steps
during the render loop.
Key Differences
The practical differences between the two classes boil down to performance, memory management, and ease of use:
1. Performance and Memory Efficiency
- Geometry: High memory overhead due to thousands of
individual
Vector3andFace3objects. It required CPU-side processing to convert data for the GPU. - BufferGeometry: Minimal memory footprint. It bypasses CPU translation, sending raw binary arrays directly to the GPU, resulting in faster load times and higher frame rates.
2. Developer Usability
- Geometry: Very easy to manipulate. If you wanted to
move a vertex, you could simply modify
geometry.vertices[0].x. - BufferGeometry: More complex to manipulate.
Developers must work with flat arrays, meaning you must calculate the
exact index offsets (e.g., index
i * 3for X,i * 3 + 1for Y, andi * 3 + 2for Z).
3. Deprecation Status
- Geometry: Deprecated in Three.js r125. It is no longer supported or included in the core library.
- BufferGeometry: The current standard for all mesh, line, and point representations in Three.js.
Conclusion
The deprecation of Geometry in favor of
BufferGeometry was a necessary step for Three.js to remain
competitive and performant in rendering complex 3D scenes. While
BufferGeometry requires a steeper learning curve due to its
reliance on flat typed arrays, the dramatic performance improvements and
reduced memory overhead make it the superior choice for modern web
graphics.