Baking Differentials

Hi I was going through the code for the baking system and had to stop to learn barycentric coordinates and texture mapping. But I keep failing to trace a clear connection between the theory that I have found vs the implementation, specifically of the uv differentials. Here is the code:

static void bake_differentials(BakeDataZSpan *bd, const float *uv1, const float *uv2, const float *uv3)
{
float A;

/* assumes dPdu = P1 - P3 and dPdv = P2 - P3 */
A = (uv2[0] - uv1[0]) * (uv3[1] - uv1[1]) - (uv3[0] - uv1[0]) * (uv2[1] - uv1[1]);


if (fabsf(A) > FLT_EPSILON) {
	A = 0.5f / A;

	bd->du_dx = (uv2[1] - uv3[1]) * A;
	bd->dv_dx = (uv3[1] - uv1[1]) * A;

	bd->du_dy = (uv3[0] - uv2[0]) * A;
	bd->dv_dy = (uv1[0] - uv3[0]) * A;
}
else {
	bd->du_dx = bd->du_dy = 0.0f;
	bd->dv_dx = bd->dv_dy = 0.0f;
}

}

I’m failing to understand what those derivates come from and what they represent here. Don’t pull your punches, I prefer to know what I’m missing rather than understand the little I know.

1 Like

du_dx is the change in barycentric coordinate u when moving one pixel to the right (x + 1). This way the renderer can estimate the part of the triangle that the pixel it is baking covers, for texture filtering purposes.

It seems to work like this:

// Interpolation of triangle vertices with barycentric coordinates
P = u * P1 + v * P2 + (1 - u - v) * P3

// Partial derivatives of P w.r.t. barycentric coordinates
dPdu = P1 - P3 = uv1 - uv3
dPdv = P2 - P3 = uv2 - uv3

// We can relate the partial derivatives like this
dPdx = dPdu * dudx + dPdv * dvdx
dPdy = dPdu * dudy + dPdv * dvdy

// We want to know the difference when moving one pixel to the right / top
dPdx = (1, 0)
dPdy = (0, 1)

After that it’s a matter of solving a 2x2 linear system with Cramer’s rule.

2 Likes

Thank you for your response, I was trying to find an answer for at least two weeks with no luck.
Now, making some quick math that would mean that is not being properly calculated. Right now it is taking the derivates in regards to

dPdx = (0.5, 0)
dPdy = (0,-0.5)

I changed it and nothing seemed to change really. But I was wandering if it was intentional, given how uv coordinates are taken.

vec[a][0] = uv[0] * (float)bd.bk_image->width - (0.5f + 0.001f);
vec[a][1] = uv[1] * (float)bd.bk_image->height - (0.5f + 0.002f);

1 Like

The direction of the differentials doesn’t really matter, and I might have been wrong about the magnitude, maybe half a pixel is the convention here.

Alright thanks, just wanted to be sure