Computing Barycentric Coordinates in GLSL

This article explains how to compute barycentric coordinates for an arbitrary point relative to a triangle's vertices using OpenGL Shading Language (GLSL). Barycentric coordinates express any point on a triangle's plane as a weighted sum of the triangle's three vertices, providing an essential mechanism for attribute interpolation, ray-triangle intersection testing, and procedural geometric effects. Below is the mathematical formulation using Cramer's rule alongside an optimized, ready-to-use GLSL function.

The Mathematical Formulation

Given a triangle defined by three vertices \(A\), \(B\), and \(C\), any point \(P\) lying on the plane of the triangle can be expressed as:

\[P = uA + vB + wC\]

where \(u\), \(v\), and \(w\) are the barycentric coordinates satisfying the constraint:

\[u + v + w = 1 \implies u = 1 - v - w\]

Substituting \(u\) gives the vector formulation relative to vertex \(A\):

\[P - A = v(B - A) + w(C - A)\]

Let \(v_0 = B - A\), \(v_1 = C - A\), and \(v_2 = P - A\). This yields a linear system of two equations:

\[(v \cdot v_0 + w \cdot v_1) \cdot v_0 = v_2 \cdot v_0\] \[(v \cdot v_0 + w \cdot v_1) \cdot v_1 = v_2 \cdot v_1\]

Expanding these equations produces a \(2 \times 2\) system that can be solved directly for \(v\) and \(w\) using Cramer's rule via dot products.

GLSL Implementation

The dot-product method works reliably for both 2D points (vec2) and coplanar 3D points (vec3):

vec3 computeBarycentric(vec3 p, vec3 a, vec3 b, vec3 c) {
    vec3 v0 = b - a;
    vec3 v1 = c - a;
    vec3 v2 = p - a;

    float d00 = dot(v0, v0);
    float d01 = dot(v0, v1);
    float d11 = dot(v1, v1);
    float d20 = dot(v2, v0);
    float d21 = dot(v2, v1);

    float denom = d00 * d11 - d01 * d01;

    // Guard against degenerate triangles
    if (abs(denom) < 1e-6) {
        return vec3(-1.0);
    }

    float v = (d11 * d20 - d01 * d21) / denom;
    float w = (d00 * d21 - d01 * d20) / denom;
    float u = 1.0 - v - w;

    return vec3(u, v, w);
}

Interpreting the Results

The returned vec3(u, v, w) maps weights to vertices \(A\), \(B\), and \(C\) respectively:

  • Inside the Triangle: The point \(P\) is strictly inside the triangle if \(u \ge 0\), \(v \ge 0\), and \(w \ge 0\).
  • On an Edge or Vertex: If any coordinate equals \(0\), \(P\) lies on the edge opposite to that vertex. If two coordinates equal \(0\), \(P\) coincides with the remaining vertex.
  • Outside the Triangle: If any coordinate is negative, \(P\) lies outside the triangle boundary.