add a UV Project material option so UV's are calculated taking into account perspective matrix - previously this gave artifacts with lower poly meshes.

This commit is contained in:
Campbell Barton 2012-09-22 04:57:55 +00:00
parent 1a1e37f4a8
commit b1ef5703d6
4 changed files with 108 additions and 32 deletions

@ -763,6 +763,7 @@ class MATERIAL_PT_options(MaterialButtonsPanel, Panel):
col.prop(mat, "use_vertex_color_paint")
col.prop(mat, "use_vertex_color_light")
col.prop(mat, "use_object_color")
col.prop(mat, "use_uv_project")
if simple_material(base_mat):
col.prop(mat, "pass_index")

@ -130,7 +130,10 @@ typedef struct Material {
/* for buttons and render*/
char rgbsel, texact, pr_type, use_nodes;
short pr_back, pr_lamp, pr_texture, ml_flag; /* ml_flag is for disable base material */
short pr_lamp, pr_texture, ml_flag; /* ml_flag is for disable base material */
/* mapping */
char mapflag, pad;
/* shaders */
short diff_shader, spec_shader;
@ -273,6 +276,9 @@ typedef struct Material {
#define MA_MODE_MASK 0x6fffffff /* all valid mode bits */
/* mapflag */
#define MA_MAPFLAG_UVPROJECT (1 << 0)
/* ray mirror fadeout */
#define MA_RAYMIR_FADETOSKY 0
#define MA_RAYMIR_FADETOMAT 1

@ -1937,6 +1937,12 @@ void RNA_def_material(BlenderRNA *brna)
"- for anisotropic shading effects");
RNA_def_property_update(prop, 0, "rna_Material_update");
prop = RNA_def_property(srna, "use_uv_project", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "mapflag", MA_MAPFLAG_UVPROJECT);
RNA_def_property_ui_text(prop, "UV Project",
"Use to ensure UV interpolation is correct for camera projections (use with UV project modifier)");
RNA_def_property_update(prop, 0, "rna_Material_update");
/* nested structs */
prop = RNA_def_property(srna, "raytrace_mirror", PROP_POINTER, PROP_NONE);
RNA_def_property_flag(prop, PROP_NEVER_NULL);

@ -1120,50 +1120,113 @@ void shade_input_set_shade_texco(ShadeInput *shi)
for (i = 0; (tface = RE_vlakren_get_tface(obr, vlr, i, &name, 0)); i++) {
ShadeInputUV *suv = &shi->uv[i];
float *uv1, *uv2, *uv3;
const float *uv1 = tface->uv[j1];
const float *uv2 = tface->uv[j2];
const float *uv3 = tface->uv[j3];
shi->totuv++;
suv->name = name;
uv1 = tface->uv[j1];
uv2 = tface->uv[j2];
uv3 = tface->uv[j3];
if ((shi->mat->mapflag & MA_MAPFLAG_UVPROJECT) && (shi->depth == 0)) {
float x = shi->xs;
float y = shi->ys;
suv->uv[0] = -1.0f + 2.0f * (l * uv3[0] - u * uv1[0] - v * uv2[0]);
suv->uv[1] = -1.0f + 2.0f * (l * uv3[1] - u * uv1[1] - v * uv2[1]);
suv->uv[2] = 0.0f; /* texture.c assumes there are 3 coords */
float s1[2] = {-1.0f + 2.0f * uv1[0], -1.0f + 2.0f * uv1[1]};
float s2[2] = {-1.0f + 2.0f * uv2[0], -1.0f + 2.0f * uv2[1]};
float s3[2] = {-1.0f + 2.0f * uv3[0], -1.0f + 2.0f * uv3[1]};
if (shi->osatex) {
float duv[2];
dl = shi->dx_u + shi->dx_v;
duv[0] = shi->dx_u;
duv[1] = shi->dx_v;
float obwinmat[4][4], winmat[4][4], ho1[4], ho2[4], ho3[4];
float Zmulx, Zmuly;
float hox, hoy, l, dl, u, v;
float s00, s01, s10, s11, detsh;
suv->dxuv[0] = 2.0f * (dl * uv3[0] - duv[0] * uv1[0] - duv[1] * uv2[0]);
suv->dxuv[1] = 2.0f * (dl * uv3[1] - duv[0] * uv1[1] - duv[1] * uv2[1]);
/* old globals, localized now */
Zmulx = ((float)R.winx) / 2.0f;
Zmuly = ((float)R.winy) / 2.0f;
dl = shi->dy_u + shi->dy_v;
duv[0] = shi->dy_u;
duv[1] = shi->dy_v;
zbuf_make_winmat(&R, winmat);
if (shi->obi->flag & R_TRANSFORMED)
mult_m4_m4m4(obwinmat, winmat, obi->mat);
else
copy_m4_m4(obwinmat, winmat);
suv->dyuv[0] = 2.0f * (dl * uv3[0] - duv[0] * uv1[0] - duv[1] * uv2[0]);
suv->dyuv[1] = 2.0f * (dl * uv3[1] - duv[0] * uv1[1] - duv[1] * uv2[1]);
}
zbuf_render_project(obwinmat, v1->co, ho1);
zbuf_render_project(obwinmat, v2->co, ho2);
zbuf_render_project(obwinmat, v3->co, ho3);
if ((mode & MA_FACETEXTURE) && i == obr->actmtface) {
if ((mode & (MA_VERTEXCOL | MA_VERTEXCOLP)) == 0) {
shi->vcol[0] = 1.0f;
shi->vcol[1] = 1.0f;
shi->vcol[2] = 1.0f;
shi->vcol[3] = 1.0f;
}
if (tface->tpage) {
render_realtime_texture(shi, tface->tpage);
s00 = ho3[0] / ho3[3] - ho1[0] / ho1[3];
s01 = ho3[1] / ho3[3] - ho1[1] / ho1[3];
s10 = ho3[0] / ho3[3] - ho2[0] / ho2[3];
s11 = ho3[1] / ho3[3] - ho2[1] / ho2[3];
detsh = s00 * s11 - s10 * s01;
detsh = (detsh != 0.0f) ? 1.0f / detsh : 0.0f;
s00 *= detsh; s01 *= detsh;
s10 *= detsh; s11 *= detsh;
/* recalc u and v again */
hox = x / Zmulx - 1.0f;
hoy = y / Zmuly - 1.0f;
u = (hox - ho3[0] / ho3[3]) * s11 - (hoy - ho3[1] / ho3[3]) * s10;
v = (hoy - ho3[1] / ho3[3]) * s00 - (hox - ho3[0] / ho3[3]) * s01;
l = 1.0f + u + v;
suv->uv[0] = l * s3[0] - u * s1[0] - v * s2[0];
suv->uv[1] = l * s3[1] - u * s1[1] - v * s2[1];
suv->uv[2] = 0.0f;
if (shi->osatex) {
float dxuv[2], dyuv[2];
dxuv[0] = s11 / Zmulx;
dxuv[1] = -s01 / Zmulx;
dyuv[0] = -s10 / Zmuly;
dyuv[1] = s00 / Zmuly;
dl = dxuv[0] + dxuv[1];
suv->dxuv[0] = dl * s3[0] - dxuv[0] * s1[0] - dxuv[1] * s2[0];
suv->dxuv[1] = dl * s3[1] - dxuv[0] * s1[1] - dxuv[1] * s2[1];
dl = dyuv[0] + dyuv[1];
suv->dyuv[0] = dl * s3[0] - dyuv[0] * s1[0] - dyuv[1] * s2[0];
suv->dyuv[1] = dl * s3[1] - dyuv[0] * s1[1] - dyuv[1] * s2[1];
}
}
else {
suv->uv[0] = -1.0f + 2.0f * (l * uv3[0] - u * uv1[0] - v * uv2[0]);
suv->uv[1] = -1.0f + 2.0f * (l * uv3[1] - u * uv1[1] - v * uv2[1]);
suv->uv[2] = 0.0f; /* texture.c assumes there are 3 coords */
if (shi->osatex) {
float duv[2];
dl = shi->dx_u + shi->dx_v;
duv[0] = shi->dx_u;
duv[1] = shi->dx_v;
suv->dxuv[0] = 2.0f * (dl * uv3[0] - duv[0] * uv1[0] - duv[1] * uv2[0]);
suv->dxuv[1] = 2.0f * (dl * uv3[1] - duv[0] * uv1[1] - duv[1] * uv2[1]);
dl = shi->dy_u + shi->dy_v;
duv[0] = shi->dy_u;
duv[1] = shi->dy_v;
suv->dyuv[0] = 2.0f * (dl * uv3[0] - duv[0] * uv1[0] - duv[1] * uv2[0]);
suv->dyuv[1] = 2.0f * (dl * uv3[1] - duv[0] * uv1[1] - duv[1] * uv2[1]);
}
if ((mode & MA_FACETEXTURE) && i == obr->actmtface) {
if ((mode & (MA_VERTEXCOL | MA_VERTEXCOLP)) == 0) {
shi->vcol[0] = 1.0f;
shi->vcol[1] = 1.0f;
shi->vcol[2] = 1.0f;
shi->vcol[3] = 1.0f;
}
if (tface->tpage) {
render_realtime_texture(shi, tface->tpage);
}
}
}
}
shi->dupliuv[0] = -1.0f + 2.0f * obi->dupliuv[0];