Course outline
Everything Is Triangles
In one line
Every 3D shape is a mesh of triangles joined at corner points called vertices. Triangles are used because three points are always flat, and the number of triangles is the first thing that decides how much a scene costs.
Think of it like this
A paper-craft model, such as a folded paper animal, is a lot of small flat paper pieces joined at the edges. The more pieces, the rounder and more detailed it looks, and the longer it takes to build. A 3D model on the GPU is the same, and its flat pieces are all triangles.
Words you'll meet
New words in this topic, in plain English. Come back here whenever one feels fuzzy.
- vertex
- A corner point of a shape, with a position (x, y, z) and sometimes a colour or a direction. The plural is vertices.
- edge
- A line between two vertices.
- face
- A flat surface bounded by edges. On the GPU every face is a triangle.
- mesh
- A shape made of many triangles joined at shared or matching vertices.
- segments
- The number of straight pieces used to make a curve. More segments look rounder and cost more triangles.
- index
- A list of numbers that says which three vertices form each triangle, so a vertex can be reused by many triangles.
Step by step
01One triangle
Three vertices, nine numbers: for example (−0.7, −0.5, 0), (0.7, −0.5, 0) and (0, 0.7, 0). Put them in a Float32Array (a list of 32-bit decimal numbers, the format the GPU likes) and wrap it in a BufferAttribute with 3 numbers per vertex. That is a complete shape.
02A square from two triangles
A square has four corners. The two triangles share a diagonal, so with an index you store 4 vertices and say "triangle 1 is vertices 0, 1, 2; triangle 2 is vertices 2, 1, 3". Without an index you would store 6 vertices and repeat two of them.
03A cube from twelve
Six squares, two triangles each. three.js's BoxGeometry makes 24 vertices (4 per face) and an index of 36 numbers (12 triangles × 3). geometry.index.count / 3 gives the triangle count.
04A sphere from segments
SphereGeometry(radius, widthSegments, heightSegments) builds rings from the top to the bottom. The rings next to the poles are made of triangles that meet at a point, the middle rings of squares cut in two. The result is w × (2h − 2) triangles.
05Ask the renderer
renderer.info.render.triangles is the number of triangles the last render() call sent to the GPU. It must match your own count. When it doesn't, something you didn't expect is in the scene (or something expected was skipped; Topic 1.4 shows how).
Try it yourself
- 1
Predict, then check
In "Count the triangles", add
"Sphere 16 x 8": new THREE.SphereGeometry(0.5, 16, 8),toshapes. Predict 16 × (2 × 8 − 2) = 224 triangles, then run: the new last line reads 153 vertices, 224 triangles andrenderer.info: 224. The vertices are (16 + 1) × (8 + 1) = 153, because each ring repeats its first vertex to close the seam. - 2
Make it round
Change the last scene to the 32 × 16 sphere (
shapes["Sphere 32 x 16 (default)"]) and watch the wireframe. The 8 × 6 sphere (80 triangles) has a visibly faceted outline made of straight edges. At 960 triangles the outline looks round and the lines are so dense that the ball looks almost solid orange.
Code & diagrams
Each count comes from the geometry's index and again from the renderer. The wireframe sphere (8 × 6) shows its 80 triangles.
Console
Run the scene to see its console.Expected console output
Plane 1 x 1 4 vertices 2 triangles | renderer.info: 2
Box 1 x 1 x 1 24 vertices 12 triangles | renderer.info: 12
Cylinder, 8 sides 52 vertices 32 triangles | renderer.info: 32
Cylinder, 64 sides 388 vertices 256 triangles | renderer.info: 256
Sphere 8 x 6 63 vertices 80 triangles | renderer.info: 80
Sphere 32 x 16 (default) 561 vertices 960 triangles | renderer.info: 960
Sphere 64 x 32 2145 vertices 3968 triangles | renderer.info: 3968The last line builds a sphere of about a million triangles. On a very old phone this example may take a moment to start. It is one draw call either way: a draw call is not a triangle.
Console
Run the scene to see its console.Expected console output
1 triangle draw calls 1, triangles 1, geometry data 36 bytes
12 triangles (a box) draw calls 1, triangles 12, geometry data 840 bytes
960 triangles (default sphere) draw calls 1, triangles 960, geometry data 23,712 bytes
about 1,000,000 triangles draw calls 1, triangles 1001112, geometry data 28,099,136 bytesBreak it on purpose
Errors are the best teachers. Make each change, read the error, guess what went wrong, then reveal the answer.
Break #1
Count a shape that has no index
In "Count the triangles", add "Bare": new THREE.BufferGeometry().setAttribute("position", new THREE.BufferAttribute(new Float32Array(9), 3)), to shapes.
Break #2
Ask for a sphere with too few segments
In "Count the triangles", add "Tiny": new THREE.SphereGeometry(0.5, 1, 1), to shapes.
Myth vs fact
Myth
More triangles always means a better picture.
Fact
Only up to the point where you can no longer see the corners at the size the shape is shown. Beyond that you only pay more.
Myth
A cube has 8 vertices on the GPU.
Fact
In three.js it has 24, because each face needs its own copy of every corner (they point different ways for lighting). The shape has 8 corners; the GPU data has 24 vertices.
Pro corner
Extra depth for experienced readers. New to this? Skip it for now and come back later.
- ▸
Vertex count matters as much as triangle count. The vertex program (Topic 1.3) runs once per vertex, and the data for every vertex is stored. An indexed mesh shares vertices between triangles, so it has fewer than
3 × trianglesof them;renderer.inforeports triangles, so also look atgeometry.attributes.position.count. - ▸
The index is a
Uint16Arraywhen the mesh has under 65,536 vertices and aUint32Arrayabove that. The million-triangle sphere here needs 32-bit indices, which is why its data is about 28 MB (positions, normals and UVs at 4 bytes per number, plus the index). - ▸
Geometry data lives twice: in JavaScript arrays and, after the first
render(), in GPU buffers. The28,099,136bytes above is the JavaScript side;renderer.info.memory.geometriescounts GPU copies. Freeing them isgeometry.dispose()(Topic 17.4).
Remember this
- 1
The problem this solves: when you ask for "a sphere" you get a shape made of flat pieces, and with too few you can see the corners. Knowing that every shape is a list of triangles tells you why detail has a price, why a model can be slow, and what the number in the status bar means.
- 2
Vertices, edges, faces. A vertex is one corner point with a position (x, y, z) and often more information such as a colour or a direction. An edge joins two vertices. A face is a flat surface bounded by edges. In the GPU's world every face is a triangle: three vertices and the flat surface between them.
- 3
Why triangles. Three points always lie in one flat plane, so a triangle can never be bent or twisted. Four points can be bent out of plane, and then it is not clear what "the surface between them" means. A flat triangle is easy for hardware to fill with pixels, and any other flat shape can be cut into triangles. That is why graphics chips are built around triangles.
- 4
Counting. A cube has 6 square faces, and each square is 2 triangles, so 12 triangles. In three.js
BoxGeometryhas 24 vertices, not 8, because each face keeps its own four corners (the corner is shared by three faces that need different directions for lighting). A sphere withwsegments around andhfrom top to bottom hasw × (2h − 2)triangles: the default 32 × 16 gives 960. - 5
Round things are not round. A cylinder with 8 sides is an octagon prism; with 64 sides it looks round. More segments means a better silhouette and more triangles, quickly: a sphere with twice the segments each way has about four times the triangles. You choose a number that looks round enough at the size it is shown on screen.
- 6
Cost. Each triangle must be processed by the GPU every frame, and its data (positions, colours, directions) sits in GPU memory. A few thousand triangles are nothing for any device; hundreds of thousands start to matter on a phone; a million makes a cheap phone struggle. The second live example prints real numbers for one triangle and for about one million.
Explain it without notes
Why does the GPU use triangles and not squares or other polygons?
A sphere has 32 segments around and 16 from top to bottom. How many triangles is that and how do you get the number?
Practice
A cylinder has 12 sides. Compute its triangles (sides plus two caps) and check with geometry.index.count / 3.
A designer's model has 2 million triangles and runs at 15 frames per second on a phone. Name two things you would try before asking for a new model.
Done when you can
Say what a vertex, an edge, a face and a mesh are
Explain why every GPU shape is made of triangles
Count the triangles of a box, a cylinder and a sphere and check them with
renderer.infoSay why a cube has 24 vertices in three.js