Introduction

Every frame your GPU renders is built out of triangles. Every triangle needs to be filled: given a pixel somewhere inside the triangle, what color should it have? The answer relies on a deceptively simple idea called barycentric coordinates.

The concept was introduced by the German mathematician August Ferdinand Möbius in 1827. His insight: instead of giving a point a position in x,yx, y space, express it as a weighted mixture of the triangle's three corners. If the triangle has vertices AA, BB, and CC, then every interior point PP can be written as

P=λ1A+λ2B+λ3CP = \lambda_1 A + \lambda_2 B + \lambda_3 C

where λ1+λ2+λ3=1\lambda_1 + \lambda_2 + \lambda_3 = 1 and each λi0\lambda_i \geq 0. The three numbers (λ1,λ2,λ3)(\lambda_1, \lambda_2, \lambda_3) are the barycentric coordinates of PP.

What makes this powerful is that the same weights apply to any attribute you attach to the vertices — color, depth, texture coordinates, surface normals. Interpolate the weights, and every attribute comes along for the ride.

Try It

The triangle below has a red vertex, a green vertex, and a blue vertex. Click or drag anywhere inside to place a point. The three barycentric weights λ1\lambda_1, λ2\lambda_2, λ3\lambda_3 are computed and used to mix the vertex colors — giving the point exactly the blend it deserves.

<!-- {{c_title_comment}} -->
<div class="hint" id="hint">{{hint_para}}</div>
<div class="canvas-wrap">
  <canvas id="cvs" width="360" height="300"></canvas>
</div>
<div class="coords" id="coords">{{coords_idle}}</div>
<div class="weights" id="weights"></div>
<button id="reset" type="button" class="ghost">{{btn_reset}}</button>
/* {{c_layout_comment}} */
* { box-sizing: border-box; }
body { font-family: system-ui, sans-serif; color: #222; margin: 0; padding: .5rem; }
.hint { font-size: .88rem; color: #444; margin: 0 0 .6rem; line-height: 1.45; }
.canvas-wrap { display: flex; justify-content: center; }
canvas { border-radius: 10px; cursor: crosshair; touch-action: none; display: block; max-width: 100%; }
.coords { font-size: .9rem; color: #555; margin: .5rem 0 .2rem; min-height: 1.3em; }
.weights { display: flex; gap: .6rem; flex-wrap: wrap; margin-bottom: .5rem; min-height: 1.6em; }
.w-chip { font-size: .85rem; font-weight: 600; padding: .2rem .55rem; border-radius: 999px; color: #fff; }
button { font: 600 13px system-ui, sans-serif; padding: .4rem .8rem; border: 1px solid #1d3557;
         background: #1d3557; color: #fff; border-radius: 8px; cursor: pointer; }
button.ghost { background: #fff; color: #1d3557; }
// Code not found

Notice that points near a corner look almost like that corner's color. Points near the center mix all three equally. The weights always sum to 1, so the blend is always a proper convex combination — it can never produce a color outside the triangle's palette.

The Math

How do you actually compute (λ1,λ2,λ3)(\lambda_1, \lambda_2, \lambda_3) for a given point PP?

The elegant answer uses signed triangle areas. Write SABCS_{ABC} for the (signed) area of the full triangle and define

λ1=SPBCSABC,λ2=SAPCSABC,λ3=SABPSABC\lambda_1 = \frac{S_{PBC}}{S_{ABC}}, \quad \lambda_2 = \frac{S_{APC}}{S_{ABC}}, \quad \lambda_3 = \frac{S_{ABP}}{S_{ABC}}

Each weight is the fraction of the total area occupied by the sub-triangle opposite to its vertex. Because the three sub-triangles tile the whole triangle, λ1+λ2+λ3=1\lambda_1 + \lambda_2 + \lambda_3 = 1 automatically.

In practice, each signed area is a 2D cross product (one subtraction and two multiplications). GPUs evaluate this for every pixel in the triangle's bounding box, discard pixels where any λi<0\lambda_i < 0 (outside the triangle), and pass the three weights to the fragment shader for every pixel that survives.

  • Cost per pixel: three cross products — constant time, fully parallelizable.
  • Perspective-correct interpolation: in 3D, the weights must be divided by the vertex depth ww before interpolating and re-multiplied after, a tweak handled automatically by the GPU pipeline.
  • Point-in-triangle test: a free by-product — PP is inside iff all three λi0\lambda_i \geq 0.

The barycentric machinery is so cheap and so general that it is the foundation of virtually every triangle rasterizer ever built, from classic software renderers to modern real-time GPUs.

Where It Matters

The same three-weight blend turns up in a surprising range of fields:

  • Real-time 3D graphics: every triangle rasterized by a GPU uses barycentric coordinates to interpolate vertex colors, normals, and UV texture coordinates across its surface. Without them, triangles would be flat, uniform patches — no shading gradients, no textures.
  • Texture mapping: UV coordinates are stored at vertices and blended barycentrically. Moving across a triangle smoothly scans the corresponding region of the texture.
  • Depth buffering: the zz-value of each pixel is interpolated barycentrically to decide which triangle is in front — the basis of the depth test.
  • Finite element analysis: in engineering simulations (stress, heat, fluid flow), the mesh is built from triangles or tetrahedra. A field value (temperature, displacement) is stored at nodes and interpolated barycentrically inside each element.
  • Animation and skinning: convex hull geometry is divided into triangles; vertex weights in skeletal animation are a direct analogue of barycentric blending.
  • Geographic information systems: elevation and other scalar fields are stored at sample points and interpolated across Delaunay triangulation cells using barycentric weights.

Wherever a smooth value must be spread across a triangulated surface, barycentric coordinates are the natural tool.

Conclusion

Barycentric coordinates are one of those ideas that, once you see them, you spot everywhere. Möbius's 1827 insight — express a point as a convex blend of the triangle's corners — turned into the universal language of triangle interpolation. Every vertex attribute (color, depth, texture, normal) rides those three weights across the triangle's surface.

The next time you look at a smooth gradient on a 3D model, a textured polygon in a game, or a temperature map in an engineering simulation, you are looking at barycentric coordinates in action. Three numbers. One triangle. Infinite surfaces.

Share this article

Pick a channel — or use your device's native share sheet.

Comments

Loading comments...

https://www.kipuhub.com/en/article/barycentric-coordinates/Content licensed under CC BY-NC 4.0.