三角形の各頂点が値を持つときに、三角形内の任意の位置でその値を線形補間します。
三角形の各頂点位置を$\boldsymbol{p}_0, \boldsymbol{p}_1, \boldsymbol{p}_2$とすると 、三角形内の任意の位置$\boldsymbol{p}$は次のように表現できます。
\boldsymbol{e}_u = \boldsymbol{p}_1 - \boldsymbol{p}_0 \\
\boldsymbol{e}_v = \boldsymbol{p}_2 - \boldsymbol{p}_0 \\
\boldsymbol{p} = \boldsymbol{p}_{0} + u\boldsymbol{e}_u + v\boldsymbol{e}_v\\
(u\geqq0,v\geqq0, u+v\leqq1)
ここで各頂点の補間したい値を$C_0,C_1,C_2$とすると、位置$\boldsymbol{p}$における補間値$C$は次のようになります。
C = C_0+u(C_1-C_0)+v(C_2-C_0)
ということで、$\boldsymbol{p}$に関して$u,v$が求まれば、補間値$C$が求まります。
先ほどの$\boldsymbol{p}$を各要素ごとに展開すると次のようになります(ここでは2次元の場合を考えますが、3次元でも同じだと思います)。
\boldsymbol{p}_0 = \left(\begin{array}{cc} p_{0x} \\ p_{0y}\\ \end{array} \right),
\boldsymbol{e}_u = \left(\begin{array}{cc} e_{ux} \\ e_{uy}\\ \end{array} \right),
\boldsymbol{e}_v = \left(\begin{array}{cc} e_{vx} \\ e_{vy}\\ \end{array} \right) \\
\boldsymbol{p} = \left(\begin{array}{cc} p_{x} \\ p_{y}\\ \end{array} \right) = \left(\begin{array}{cc} p_{0x}+ue_{ux}+ve_{vx} \\ p_{0y}+ue_{uy}+ve_{vy}\\ \end{array} \right)
これを$u,v$についての整理すると次のようになり、$u,v$に関する連立方程式となります。
\left\{
\begin{array}{l}
e_{ux}u+e_{vx}v = p_x - p_{0x} \\
e_{uy}u+e_{vy}v = p_y - p_{0y}
\end{array}
\right.
この連立方程式を解くと、$u,v$は次のように求まります。
\left\{
\begin{array}{l}
u=\frac{-e_{vx}(p_y-p_{0y})+e_{vy}(p_x-p_{0x})}{e_{ux}e_{vy}-e_{vx}e_{uy}} \\
v=\frac{e_{ux}(p_y-p_{0y})-e_{uy}(p_x-p_{0x})}{e_{ux}e_{vy}-e_{vx}e_{uy}}
\end{array}
\right.
これをGLSLで実装すると、以下のようになります。ここでは補間する値を三次元ベクトルにしています。
vec3 lerpTriangle(vec2 p, vec2 p0, vec2 p1, vec2 p2, vec3 c0, vec3 c1, vec3 c2) {
vec2 eu = p1 - p0;
vec2 ev = p2 - p0;
float d = eu.x * ev.y - ev.x * eu.y;
float a = p.y - p0.y;
float b = p.x - p0.x;
float u = (-ev.x * a + ev.y * b) / d;
float v = (eu.x * a - eu.y * b) / d;
return c0 + u * (c1 - c0) + v * (c2 - c0);
}
三角形の各頂点に赤、緑、青の値を持たせると次のように補間されます。
以下の記事を参考にしました。