The words people use for WebGL, three.js and shaders, each shown rather than told: a live figure, a plain definition and a sentence showing how the word is used. Pick what you’re working on, open any figure to study it (← → to flip through), and use Practice to test yourself.
Everything you see is a surface built from points and triangles. These are the words for its parts.
A corner point with a position (x, y, z). Vertices can carry more data too: a normal, UVs, a color.
A straight line between two vertices. A hard edge is a sharp crease. A soft edge is smoothed by shading.
A flat surface bounded by edges. GPUs only draw triangles, so a quad (4 sides) is split into 2 triangles (see the dashed diagonal).
A connected surface of vertices and triangles. In three.js a Mesh is geometry (the shape) plus material (how it looks).
A unit-length arrow that sticks straight out of the surface and shows which way it faces. Lighting is computed from normals.
Wireframe draws only the edges. Topology is how the vertices are connected: the layout of the polygons, also called the edge flow.
Poly count is the number of triangles, so it measures detail and cost. LOD (Level of Detail) swaps in simpler meshes as objects get farther away.
The smallest Axis-Aligned Bounding Box that contains the object. It’s a cheap stand-in for culling, collisions and picking. There’s also the bounding sphere.
The order of a triangle’s vertices decides which side is the front. In WebGL, counter-clockwise as seen by the camera means front-facing.
Skipping triangles that face away from the camera. For closed objects that’s about half the work saved. Turn it off (side: DoubleSide) for thin things like leaves or paper.
List each vertex once, then describe triangles by indices into that list. Shared corners aren’t duplicated.
How the GPU groups vertices: as points, lines or triangles, and whether consecutive shapes share vertices (strips and fans).
A vertex passes through several coordinate systems on its way to the screen. Most 3D bugs come down to mixing these up.
Each arrow is a transform. The model matrix places the object in the world. The view matrix moves the world so the camera sits at the origin. The projection matrix applies perspective. The GPU then divides by w and maps the result to pixels. Together these are called the MVP.
WebGL and three.js use a right-handed, Y-up system. Blender is Z-up and Unity is left-handed, which is why imports can come in rotated. By convention, X/Y/Z axes are drawn red/green/blue.
Position, rotation and scale. Translate moves, rotate turns, scale resizes. Order matters: scale, then rotate, then translate.
The point an object rotates and scales around: its local (0,0,0). A wrong pivot makes things swing around a corner.
One grid of 16 numbers that holds a whole transform. Each column says where a local axis points, and the last column is the position. Multiplying matrices chains transforms.
The 4th number makes translation and perspective work with matrix math. After projection the GPU divides by w (the perspective divide), and that’s what makes far things smaller.
A tree of objects in which children inherit their parent’s transform. The moon orbits the earth, and the earth orbits the sun. A child’s local position is relative to its parent, and its world position comes from the whole chain.
A rotation stored as three angles (X, Y, Z), applied in a set order. They’re easy to read, but at some poses two axes line up and you lose one degree of freedom. That’s gimbal lock.
A 4-number way to store a rotation, built from an axis and an angle around it. It’s hard to read but robust, and slerp (spherical interpolation) blends two rotations smoothly.
A camera is a transform (where it is and where it looks) plus a projection (how 3D gets flattened onto 2D).
The shaded wedge is the view frustum. Objects fully outside it are frustum-culled (never sent to the GPU). Objects crossing the near or far plane get clipped (orange). The strip at the bottom is what the camera actually sees: with perspective, closer things are bigger. Switch to orthographic and every object keeps its size.
Perspective: far objects look smaller, like the eye sees. Orthographic: no shrinking, parallel lines stay parallel. It’s used for CAD, isometric games and shadow cameras.
The visible volume, shaped like a pyramid with its tip cut off. FOV (field of view) is the opening angle. Near and far planes limit the depth range. Keep near as large as you can, because depth precision depends on the far/near ratio.
camera.near.”Width ÷ height of the viewport. If you resize the canvas without updating the camera’s aspect, everything stretches.
camera.aspect on resize and call updateProjectionMatrix().”Point the camera at a target. The up vector sets which way is “up” on screen so the camera doesn’t roll.
Standard camera moves. Orbit circles a target. Pan slides sideways. Dolly physically moves closer. Zoom changes the lens (FOV). OrbitControls handles the first three.
Every frame, your data flows through these stages. You program two of them (the shaders) and configure the rest. Click a stage.
// vertex shader (GLSL)
attribute vec3 pos; // per vertex
uniform mat4 mvp; // same for all
varying vec2 vUv; // → fragment
void main() {
vUv = uv;
gl_Position = mvp*vec4(pos,1.);
}A small program that runs on the GPU, thousands of times in parallel. WebGL shaders are written in GLSL (WebGPU uses WGSL). The vertex shader positions each vertex.
// fragment shader (GLSL)
uniform sampler2D map;
varying vec2 vUv; // interpolated
void main() {
vec4 c = texture2D(map, vUv);
gl_FragColor = c;
}Runs once per covered pixel and decides its color: texture lookups, lighting, effects. It’s usually the most expensive part of the frame.
Per-vertex input data read from a buffer, such as position, normal, uv or color. Each vertex gets its own value.
A value set from JavaScript that stays the same for the whole draw call: time, color, matrices, light direction, a texture.
A value the vertex shader passes on to the fragment shader. The GPU interpolates it across the triangle. Three vertex colors become a smooth gradient this way. In WebGL2 it’s written out/in.
Turning a vector triangle into the grid of pixels it covers. Each covered pixel produces a fragment.
A fragment is a candidate pixel produced by one triangle. Several fragments can land on the same pixel. The depth test and blending decide what ends up there.
GPU memory holding vertex data. Interleaved buffers pack all attributes per vertex. Stride is the bytes per vertex. Offset is where an attribute starts. A VAO remembers this layout.
One command from the CPU telling the GPU to “draw this mesh with this material”. Each call has overhead, so hundreds are fine and thousands hurt. You reduce them with merging, batching and instancing.
Drawing the same mesh many times in one draw call, with a different transform or color per instance. It’s how you get forests, crowds and particles.
A hidden image that stores, per pixel, how far the closest surface is. New fragments that are farther away get discarded. This is the depth test, and it’s how objects hide each other correctly.
Two surfaces at almost the same depth fight over the pixels, which shows as flickering stripes. The cause is limited depth precision.
A per-pixel mask you can write to and test against. It’s used for portals, outlines, mirrors and cut-outs.
Mixing a new color with what’s already in the framebuffer, weighted by alpha (opacity). Transparent objects must be drawn back-to-front, otherwise they look wrong.
The set of images a draw call writes into: color, plus depth and stencil. The default one is the canvas. An offscreen one (an FBO or render target) lets you render into a texture.
WebGL is a low-level browser API (OpenGL ES in JavaScript). WebGPU is its modern successor. three.js is an engine on top that turns meshes and materials into those calls for you.
A texture is an image the GPU can sample very fast. UVs say which part of the image goes where on the mesh.
Every vertex gets a 2D coordinate (u, v) from 0 to 1 that points into the texture. Unwrapping flattens the 3D surface out like a paper model. Edges where it was cut are seams.
A texel is one pixel of a texture. Sampling means reading the texture at a (u,v) that usually falls between texels, so the GPU has to pick or blend.
How a magnified texture is filled in. Nearest keeps hard pixels, which is right for pixel art. Linear (bilinear) blends them smooth.
magFilter to Nearest to keep the pixel-art look.”What happens for UVs outside 0–1. Repeat tiles the image. Mirrored flips every other tile. Clamp-to-edge stretches the border pixels.
Pre-shrunk copies of a texture (½, ¼, …). Distant surfaces sample a smaller copy. Without them, many texels squeeze into one pixel, which causes moiré and shimmering. Trilinear filtering blends between mip levels.
Level 0 is full size, and each next level is half the width and height, already blurred. A full chain adds only about 33% memory.
At grazing angles one screen pixel covers a long, thin strip of texture. Regular mipmapping blurs that strip. Anisotropic filtering takes several samples along it so the texture stays sharp.
anisotropy to 8.”One material is often several textures that line up on the same UVs. Each texture controls one property. Color maps (albedo, emissive) are stored in sRGB. Data maps (normal, roughness, metalness, AO, height) are stored linear. The last tile combines them all under a moving light, on a perfectly flat square.
A texture whose RGB values store normal directions (flat = that typical lavender (128,128,255)). It fakes bumps on flat geometry by changing the lighting only. The silhouette stays flat.
Many small images packed into one big texture. Each object’s UVs point at its own rectangle, so many objects can share one material and one draw call.
Six square images forming a cube around the viewer. You sample it with a direction rather than a UV. It’s used for the skybox background and for environment reflections.
Render a scene (or a different camera view) into a texture, then use that texture somewhere else. All post-processing is built on this.
Shading means computing how bright and what color each point is, from its normal, the lights, the viewer and the material.
The same sphere in the debug views you’ll find in every engine. This whole scene is one fragment shader that ray-traces it, so it’s also a demo of what a shader can do.
The modern standard material model (MeshStandardMaterial, glTF). A few physically meaningful inputs: base color (albedo), roughness (sharp mirror → blurry, matte highlight) and metalness. Metals tint their reflections with the base color. Non-metals (plastic, wood, skin) reflect about 4% white and show their color through diffuse light.
Directional: parallel rays, like the sun. Point: shines in all directions, like a bulb. Spot: a cone. Ambient/hemisphere: cheap, even fill light with no direction.
The classic split of light. Diffuse (Lambert) is matte brightness from the angle to the light. Specular is the shiny highlight, which depends on where you look from (Phong/Blinn). Ambient is a constant fill.
Flat: one normal per face, so you see facets. Smooth: normals are averaged per vertex and interpolated, so curves look curved. Same geometry, different normals.
Surfaces reflect more when seen at a grazing angle. Think of a lake: transparent at your feet, a mirror toward the horizon. It also gives the glowing “rim light” look.
Render the scene once from the light’s point of view and store depths. Later, a pixel is in shadow if it’s farther from the light than what the light “saw”. Common artifacts are acne, peter-panning and blocky edges. The fixes are bias, a higher map size and PCF soft filtering.
Darkening in creases, corners and where objects touch, because less ambient light reaches there. It’s often baked into a texture, or approximated each frame in screen space (SSAO).
A color a surface gives off by itself, so it shows even in darkness. It doesn’t light other objects, though. Pair it with bloom for the glow.
A 360° image (often an HDRI) of the surroundings, used for reflections and soft ambient lighting. Lighting a scene from an image is IBL (Image-Based Lighting). It’s the quickest way to make PBR look real.
Geometry is the shape data. Material is the look, in high-level terms. A shader is the GPU program a material compiles into. A texture is an image a material uses. They’re easy to confuse, and this tree keeps them apart.
What happens to the finished image before it reaches the screen, and the artifacts you’ll want to name.
Jagged “staircase” edges come from sampling once per pixel. MSAA takes several samples on edges. FXAA/SMAA blur edges as a post-process. TAA accumulates samples over frames.
antialias: true. The edges are jaggy.”Render the scene to a texture, then run full-screen passes over it. Each pass is a shader that reads one image and writes the next.
Very bright areas bleed a soft glow into their surroundings, like a camera lens. You extract the bright parts, blur them, and add them back. A threshold sets what counts as bright.
Lighting is computed in HDR (High Dynamic Range: values above 1.0). Tone mapping (ACES, AgX, Reinhard) squeezes that into what a screen can show without blowing out to white. Exposure scales it first.
Lighting math must happen in linear space. Screens expect sRGB (gamma-encoded). Skip the conversion and lighting looks too dark and harsh. Get it wrong the other way and everything looks washed out.
Blurring things in front of and behind a focus distance, like a real camera lens. The out-of-focus blobs of light are called bokeh.
Overdraw is shading the same pixel several times because layers sit on top of each other. Heavy particles and transparency make the GPU fill-rate bound, where the number of pixels is the bottleneck.
Forward shades each object against every light as it’s drawn. That’s simple, it handles transparency, and it’s what three.js does. Deferred first writes albedo, normals and depth into a G-buffer, then lights the pixels, which is cheap even with hundreds of lights.
The time you have to produce one frame. Go over it and you drop frames (jank). Use delta time (the time since the last frame) so motion speed doesn’t depend on the refresh rate.
Making things move, react to the mouse, and a few rendering techniques you’ll hear about.
Shoot an invisible ray from the camera through the mouse position and find the first triangle it hits. That’s how you click or hover 3D objects. Move your mouse over the sphere.
Lerp (linear interpolation) blends between a and b by t ∈ [0,1]. Easing curves reshape t so motion speeds up, slows down or overshoots, which makes it feel natural.
You set values at a few moments (keyframes), and the engine interpolates between them. A named set of tracks (“walk”, “jump”) is a clip. A mixer plays and blends clips.
A hidden skeleton of bones deforms the mesh. Each vertex has weights that say how much each bone moves it. Smooth weights at a joint give a smooth bend.
Stored alternate positions for the same vertices, blended by a weight. They’re used for facial expressions, lip sync and shape transitions.
Lots of tiny short-lived elements (sparks, smoke, rain), each with a position, velocity and lifetime. Each is usually a billboard: a flat quad that always faces the camera.
An SDF (Signed Distance Field) returns the distance to the nearest surface. Raymarching steps along a ray by that distance (the circles) until it hits. You get whole scenes from math in a fragment shader, no triangles needed.
Rasterization (what WebGL does) projects triangles onto pixels, which is fast. Ray tracing fires rays per pixel and bounces them for true reflections and shadows. That’s slower, but path tracing gives photoreal results.
When something looks wrong, these are the words to search for, ask about, or put in a bug report.
| You see… | Call it | Usual fix |
|---|