Fix T45343: incorrect Cycles baking of bump maps from selected to active.

The differentials were incorrect, now they are properly transferred from the
low to the high poly mesh.
This commit is contained in:
Brecht Van Lommel 2016-02-18 01:35:52 +01:00
parent 1a676d4e0e
commit 0136046335
Notes: blender-bot 2023-02-14 10:14:07 +01:00
Referenced by issue #45343, Cycles bake -  high to lowpoly artifacts
3 changed files with 94 additions and 65 deletions

View File

@ -82,6 +82,10 @@ void vlr_set_uv_indices(struct VlakRen *vlr, int *i1, int *i2, int *i3);
void calc_R_ref(struct ShadeInput *shi);
void barycentric_differentials_from_position(
const float co[3], const float v1[3], const float v2[3], const float v3[3],
const float dxco[3], const float dyco[3], const float facenor[3], const bool differentials,
float *u, float *v, float *dx_u, float *dx_v, float *dy_u, float *dy_v);
/* shadeoutput. */
void shade_lamp_loop(struct ShadeInput *shi, struct ShadeResult *shr);

View File

@ -84,6 +84,7 @@
/* local include */
#include "render_types.h"
#include "shading.h"
#include "zbuf.h"
/* Remove when Cycles moves from MFace to MLoopTri */
@ -262,32 +263,15 @@ static void calc_point_from_barycentric_extrusion(
copy_v3_v3(r_dir, dir);
}
/**
* This function returns the barycentric u,v of a face for a coordinate. The face is defined by its index.
*/
static void calc_barycentric_from_point(
TriTessFace *triangles, const int index, const float co[3],
int *r_primitive_id, float r_uv[2])
{
TriTessFace *triangle = &triangles[index];
resolve_tri_uv_v3(r_uv, co,
triangle->mverts[0]->co,
triangle->mverts[1]->co,
triangle->mverts[2]->co);
*r_primitive_id = index;
}
/**
* This function populates pixel_array and returns TRUE if things are correct
*/
static bool cast_ray_highpoly(
BVHTreeFromMesh *treeData, TriTessFace *triangles[], BakePixel *pixel_array, BakeHighPolyData *highpoly,
const float co[3], const float dir[3], const int pixel_id, const int tot_highpoly,
const float du_dx, const float du_dy, const float dv_dx, const float dv_dy)
BVHTreeFromMesh *treeData, TriTessFace *triangle_low, TriTessFace *triangles[],
BakePixel *pixel_array_low, BakePixel *pixel_array, float mat_low[4][4], BakeHighPolyData *highpoly,
const float co[3], const float dir[3], const int pixel_id, const int tot_highpoly)
{
int i;
int primitive_id = -1;
float uv[2];
int hit_mesh = -1;
float hit_distance = FLT_MAX;
@ -333,17 +317,47 @@ static bool cast_ray_highpoly(
}
if (hit_mesh != -1) {
calc_barycentric_from_point(triangles[hit_mesh], hits[hit_mesh].index, hits[hit_mesh].co, &primitive_id, uv);
pixel_array[pixel_id].primitive_id = primitive_id;
pixel_array[pixel_id].object_id = hit_mesh;
copy_v2_v2(pixel_array[pixel_id].uv, uv);
int primitive_id_high = hits[hit_mesh].index;
TriTessFace *triangle_high = &triangles[hit_mesh][primitive_id_high];
/* the differentials are relative to the UV/image space, so the highpoly differentials
* are the same as the low poly differentials */
pixel_array[pixel_id].du_dx = du_dx;
pixel_array[pixel_id].du_dy = du_dy;
pixel_array[pixel_id].dv_dx = dv_dx;
pixel_array[pixel_id].dv_dy = dv_dy;
pixel_array[pixel_id].primitive_id = primitive_id_high;
pixel_array[pixel_id].object_id = hit_mesh;
/* ray direction in high poly object space */
float dir_high[3];
mul_v3_mat3_m4v3(dir_high, highpoly[hit_mesh].imat, dir);
normalize_v3(dir_high);
/* compute position differentials on low poly object */
float duco_low[3], dvco_low[3], dxco[3], dyco[3];
sub_v3_v3v3(duco_low, triangle_low->mverts[0]->co, triangle_low->mverts[2]->co);
sub_v3_v3v3(dvco_low, triangle_low->mverts[1]->co, triangle_low->mverts[2]->co);
mul_v3_v3fl(dxco, duco_low, pixel_array_low[pixel_id].du_dx);
madd_v3_v3fl(dxco, dvco_low, pixel_array_low[pixel_id].dv_dx);
mul_v3_v3fl(dyco, duco_low, pixel_array_low[pixel_id].du_dy);
madd_v3_v3fl(dyco, dvco_low, pixel_array_low[pixel_id].dv_dy);
/* transform from low poly to to high poly object space */
mul_mat3_m4_v3(mat_low, dxco);
mul_mat3_m4_v3(mat_low, dyco);
mul_mat3_m4_v3(highpoly[hit_mesh].imat, dxco);
mul_mat3_m4_v3(highpoly[hit_mesh].imat, dyco);
/* transfer position differentials */
float tmp[3];
mul_v3_v3fl(tmp, dir_high, 1.0f/dot_v3v3(dir_high, triangle_high->normal));
madd_v3_v3fl(dxco, tmp, -dot_v3v3(dxco, triangle_high->normal));
madd_v3_v3fl(dyco, tmp, -dot_v3v3(dyco, triangle_high->normal));
/* compute barycentric differentials from position differentials */
barycentric_differentials_from_position(
hits[hit_mesh].co, triangle_high->mverts[0]->co,
triangle_high->mverts[1]->co, triangle_high->mverts[2]->co,
dxco, dyco, triangle_high->normal, true,
&pixel_array[pixel_id].uv[0], &pixel_array[pixel_id].uv[1],
&pixel_array[pixel_id].du_dx, &pixel_array[pixel_id].dv_dx,
&pixel_array[pixel_id].du_dy, &pixel_array[pixel_id].dv_dy);
}
else {
pixel_array[pixel_id].primitive_id = -1;
@ -441,17 +455,17 @@ static TriTessFace *mesh_calc_tri_tessface(
triangles[i].tspace[0] = &tspace[lt->tri[0]];
triangles[i].tspace[1] = &tspace[lt->tri[1]];
triangles[i].tspace[2] = &tspace[lt->tri[2]];
}
if (calculate_normal) {
if (lt->poly != mpoly_prev) {
BKE_mesh_calc_poly_normal(mp, &me->mloop[mp->loopstart], me->mvert, no);
mpoly_prev = lt->poly;
}
copy_v3_v3(triangles[i].normal, no);
}
else {
copy_v3_v3(triangles[i].normal, &precomputed_normals[lt->poly]);
if (calculate_normal) {
if (lt->poly != mpoly_prev) {
BKE_mesh_calc_poly_normal(mp, &me->mloop[mp->loopstart], me->mvert, no);
mpoly_prev = lt->poly;
}
copy_v3_v3(triangles[i].normal, no);
}
else {
copy_v3_v3(triangles[i].normal, &precomputed_normals[lt->poly]);
}
}
@ -546,9 +560,9 @@ bool RE_bake_pixels_populate_from_objects(
}
/* cast ray */
if (!cast_ray_highpoly(treeData, tris_high, pixel_array_to, highpoly, co, dir, i, tot_highpoly,
pixel_array_from[i].du_dx, pixel_array_from[i].du_dy,
pixel_array_from[i].dv_dx, pixel_array_from[i].dv_dy)) {
if (!cast_ray_highpoly(treeData, &tris_low[primitive_id], tris_high,
pixel_array_from, pixel_array_to, mat_low,
highpoly, co, dir, i, tot_highpoly)) {
/* if it fails mask out the original pixel array */
pixel_array_from[i].primitive_id = -1;
}

View File

@ -705,6 +705,35 @@ void shade_input_set_viewco(ShadeInput *shi, float x, float y, float xs, float y
shade_input_calc_viewco(shi, xs, ys, z, shi->view, dxyview, shi->co, dxco, dyco);
}
void barycentric_differentials_from_position(
const float co[3], const float v1[3], const float v2[3], const float v3[3],
const float dxco[3], const float dyco[3], const float facenor[3], const bool differentials,
float *u, float *v, float *dx_u, float *dx_v, float *dy_u, float *dy_v)
{
/* find most stable axis to project */
int axis1, axis2;
axis_dominant_v3(&axis1, &axis2, facenor);
/* compute u,v and derivatives */
float t00 = v3[axis1] - v1[axis1];
float t01 = v3[axis2] - v1[axis2];
float t10 = v3[axis1] - v2[axis1];
float t11 = v3[axis2] - v2[axis2];
float detsh = (t00 * t11 - t10 * t01);
detsh = (detsh != 0.0f) ? 1.0f / detsh : 0.0f;
t00 *= detsh; t01 *= detsh;
t10 *= detsh; t11 *= detsh;
*u = (v3[axis1] - co[axis1]) * t11 - (v3[axis2] - co[axis2]) * t10;
*v = (v3[axis2] - co[axis2]) * t00 - (v3[axis1] - co[axis1]) * t01;
if (differentials) {
*dx_u = dxco[axis1] * t11 - dxco[axis2] * t10;
*dx_v = dxco[axis2] * t00 - dxco[axis1] * t01;
*dy_u = dyco[axis1] * t11 - dyco[axis2] * t10;
*dy_v = dyco[axis2] * t00 - dyco[axis1] * t01;
}
}
/* calculate U and V, for scanline (silly render face u and v are in range -1 to 0) */
void shade_input_set_uv(ShadeInput *shi)
{
@ -746,30 +775,12 @@ void shade_input_set_uv(ShadeInput *shi)
}
}
else {
/* most of this could become re-used for faces */
float detsh, t00, t10, t01, t11;
int axis1, axis2;
barycentric_differentials_from_position(
shi->co, v1, v2, v3, shi->dxco, shi->dyco, shi->facenor, shi->osatex,
&shi->u, &shi->v, &shi->dx_u, &shi->dx_v, &shi->dy_u, &shi->dy_v);
/* find most stable axis to project */
axis_dominant_v3(&axis1, &axis2, shi->facenor);
/* compute u,v and derivatives */
t00 = v3[axis1] - v1[axis1]; t01 = v3[axis2] - v1[axis2];
t10 = v3[axis1] - v2[axis1]; t11 = v3[axis2] - v2[axis2];
detsh = (t00 * t11 - t10 * t01);
detsh = (detsh != 0.0f) ? 1.0f / detsh : 0.0f;
t00 *= detsh; t01 *= detsh;
t10 *= detsh; t11 *= detsh;
shi->u = (shi->co[axis1] - v3[axis1]) * t11 - (shi->co[axis2] - v3[axis2]) * t10;
shi->v = (shi->co[axis2] - v3[axis2]) * t00 - (shi->co[axis1] - v3[axis1]) * t01;
if (shi->osatex) {
shi->dx_u = shi->dxco[axis1] * t11 - shi->dxco[axis2] * t10;
shi->dx_v = shi->dxco[axis2] * t00 - shi->dxco[axis1] * t01;
shi->dy_u = shi->dyco[axis1] * t11 - shi->dyco[axis2] * t10;
shi->dy_v = shi->dyco[axis2] * t00 - shi->dyco[axis1] * t01;
}
shi->u = -shi->u;
shi->v = -shi->v;
/* u and v are in range -1 to 0, we allow a little bit extra but not too much, screws up speedvectors */
CLAMP(shi->u, -2.0f, 1.0f);