diff --git a/release/ui/buttons_data_mesh.py b/release/ui/buttons_data_mesh.py index d4bf9698a89..757745d039e 100644 --- a/release/ui/buttons_data_mesh.py +++ b/release/ui/buttons_data_mesh.py @@ -49,6 +49,14 @@ class DATA_PT_normals(DataButtonsPanel): sub.itemR(mesh, "vertex_normal_flip") sub.itemR(mesh, "double_sided") + row = layout.row(align=True) + if context.edit_object: + row.itemO("MESH_OT_faces_shade_smooth") + row.itemO("MESH_OT_faces_shade_flat") + else: + row.itemO("OBJECT_OT_shade_smooth") + row.itemO("OBJECT_OT_shade_flat") + class DATA_PT_vertex_groups(DataButtonsPanel): __idname__ = "DATA_PT_vertex_groups" __label__ = "Vertex Groups" diff --git a/source/blender/blenkernel/intern/material.c b/source/blender/blenkernel/intern/material.c index 088b1b6e0c2..bee63f497ca 100644 --- a/source/blender/blenkernel/intern/material.c +++ b/source/blender/blenkernel/intern/material.c @@ -671,6 +671,7 @@ static void do_init_render_material(Material *ma, int r_mode, float *amb) ma->mapto |= mtex->mapto; if(r_mode & R_OSA) { if ELEM3(mtex->tex->type, TEX_IMAGE, TEX_PLUGIN, TEX_ENVMAP) ma->texco |= TEXCO_OSA; + else if(mtex->texflag & MTEX_NEW_BUMP) ma->texco |= TEXCO_OSA; // NEWBUMP: need texture derivatives for procedurals as well } if(ma->texco & (TEXCO_ORCO|TEXCO_REFL|TEXCO_NORM|TEXCO_STRAND|TEXCO_STRESS)) needuv= 1; diff --git a/source/blender/blenkernel/intern/texture.c b/source/blender/blenkernel/intern/texture.c index db864dc9f1e..1c7dab15d5c 100644 --- a/source/blender/blenkernel/intern/texture.c +++ b/source/blender/blenkernel/intern/texture.c @@ -534,7 +534,7 @@ void default_mtex(MTex *mtex) mtex->size[1]= 1.0; mtex->size[2]= 1.0; mtex->tex= 0; - mtex->texflag= 0; + mtex->texflag= MTEX_NEW_BUMP; mtex->colormodel= 0; mtex->r= 1.0; mtex->g= 0.0; @@ -543,7 +543,7 @@ void default_mtex(MTex *mtex) mtex->def_var= 1.0; mtex->blendtype= MTEX_BLEND; mtex->colfac= 1.0; - mtex->norfac= 0.5; + mtex->norfac= 1.0; mtex->varfac= 1.0; mtex->dispfac=0.2; mtex->normapspace= MTEX_NSPACE_TANGENT; diff --git a/source/blender/blenlib/intern/arithb.c b/source/blender/blenlib/intern/arithb.c index 03be10dd0b1..f7313c8b37a 100644 --- a/source/blender/blenlib/intern/arithb.c +++ b/source/blender/blenlib/intern/arithb.c @@ -2197,25 +2197,23 @@ void VecNegf(float *v1) void VecOrthoBasisf(float *v, float *v1, float *v2) { - float f = (float)sqrt(v[0]*v[0] + v[1]*v[1]); + const float f = (float)sqrt(v[0]*v[0] + v[1]*v[1]); if (f < 1e-35f) { // degenerate case - v1[0] = 0.0f; v1[1] = 1.0f; v1[2] = 0.0f; - if (v[2] > 0.0f) { - v2[0] = 1.0f; v2[1] = v2[2] = 0.0f; - } - else { - v2[0] = -1.0f; v2[1] = v2[2] = 0.0f; - } + v1[0] = (v[2] < 0.0f) ? -1.0f : 1.0f; + v1[1] = v1[2] = v2[0] = v2[2] = 0.0f; + v2[1] = 1.0f; } else { - f = 1.0f/f; - v1[0] = v[1]*f; - v1[1] = -v[0]*f; - v1[2] = 0.0f; + const float d= 1.0f/f; - Crossf(v2, v, v1); + v1[0] = v[1]*d; + v1[1] = -v[0]*d; + v1[2] = 0.0f; + v2[0] = -v[2]*v1[1]; + v2[1] = v[2]*v1[0]; + v2[2] = v[0]*v1[1] - v[1]*v1[0]; } } diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index 6da444bc88e..bbe85c5f378 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -9276,7 +9276,7 @@ static void do_versions(FileData *fd, Library *lib, Main *main) Tex *tex; Scene *sce; ToolSettings *ts; - int i; + int i, a; for(ob = main->object.first; ob; ob = ob->id.next) { @@ -9351,15 +9351,26 @@ static void do_versions(FileData *fd, Library *lib, Main *main) } /* texture filter */ - for(tex = main->tex.first; tex; tex = tex->id.next) + for(tex = main->tex.first; tex; tex = tex->id.next) { if(tex->afmax == 0) tex->afmax= 8; + } for(ma = main->mat.first; ma; ma = ma->id.next) { if(ma->mode & MA_HALO) { ma->material_type= MA_TYPE_HALO; ma->mode &= ~MA_HALO; } + + /* set new bump for unused slots */ + for(a=0; amtex[a]) { + if(!ma->mtex[a]->tex) + ma->mtex[a]->texflag |= MTEX_NEW_BUMP; + else if(((Tex*)newlibadr(fd, ma->id.lib, ma->mtex[a]->tex))->type == 0) + ma->mtex[a]->texflag |= MTEX_NEW_BUMP; + } + } } for(sce = main->scene.first; sce; sce = sce->id.next) { diff --git a/source/blender/makesdna/DNA_texture_types.h b/source/blender/makesdna/DNA_texture_types.h index e1dd21a8ccb..0760825670d 100644 --- a/source/blender/makesdna/DNA_texture_types.h +++ b/source/blender/makesdna/DNA_texture_types.h @@ -373,6 +373,7 @@ typedef struct TexMapping { #define MTEX_VIEWSPACE 16 #define MTEX_DUPLI_MAPTO 32 #define MTEX_OB_DUPLI_ORIG 64 +#define MTEX_NEW_BUMP 128 /* blendtype */ #define MTEX_BLEND 0 diff --git a/source/blender/makesrna/intern/rna_material.c b/source/blender/makesrna/intern/rna_material.c index 6686d43d075..fd54dd959b2 100644 --- a/source/blender/makesrna/intern/rna_material.c +++ b/source/blender/makesrna/intern/rna_material.c @@ -231,99 +231,122 @@ static void rna_def_material_mtex(BlenderRNA *brna) RNA_def_property_enum_sdna(prop, NULL, "texco"); RNA_def_property_enum_items(prop, prop_texture_coordinates_items); RNA_def_property_ui_text(prop, "Texture Coordinates", ""); + RNA_def_property_update(prop, NC_TEXTURE, NULL); prop= RNA_def_property(srna, "object", PROP_POINTER, PROP_NONE); RNA_def_property_pointer_sdna(prop, NULL, "object"); RNA_def_property_struct_type(prop, "Object"); RNA_def_property_flag(prop, PROP_EDITABLE); RNA_def_property_ui_text(prop, "Object", "Object to use for mapping with Object texture coordinates."); + RNA_def_property_update(prop, NC_TEXTURE, NULL); prop= RNA_def_property(srna, "uv_layer", PROP_STRING, PROP_NONE); RNA_def_property_string_sdna(prop, NULL, "uvname"); RNA_def_property_ui_text(prop, "UV Layer", "UV layer to use for mapping with UV texture coordinates."); + RNA_def_property_update(prop, NC_TEXTURE, NULL); prop= RNA_def_property(srna, "from_dupli", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "texflag", MTEX_DUPLI_MAPTO); RNA_def_property_ui_text(prop, "From Dupli", "Dupli's instanced from verts, faces or particles, inherit texture coordinate from their parent."); + RNA_def_property_update(prop, NC_TEXTURE, NULL); prop= RNA_def_property(srna, "from_original", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "texflag", MTEX_OB_DUPLI_ORIG); RNA_def_property_ui_text(prop, "From Original", "Dupli's derive their object coordinates from the original objects transformation."); + RNA_def_property_update(prop, NC_TEXTURE, NULL); prop= RNA_def_property(srna, "map_colordiff", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "mapto", MAP_COL); RNA_def_property_ui_text(prop, "Diffuse Color", "Causes the texture to affect basic color of the material"); + RNA_def_property_update(prop, NC_TEXTURE, NULL); prop= RNA_def_property(srna, "map_normal", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "mapto", MAP_NORM); RNA_def_property_ui_text(prop, "Normal", "Causes the texture to affect the rendered normal"); + RNA_def_property_update(prop, NC_TEXTURE, NULL); prop= RNA_def_property(srna, "map_colorspec", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "mapto", MAP_COLSPEC); RNA_def_property_ui_text(prop, "Specular Color", "Causes the texture to affect the specularity color"); + RNA_def_property_update(prop, NC_TEXTURE, NULL); prop= RNA_def_property(srna, "map_mirror", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "mapto", MAP_COLMIR); RNA_def_property_ui_text(prop, "Mirror", "Causes the texture to affect the mirror color"); + RNA_def_property_update(prop, NC_TEXTURE, NULL); prop= RNA_def_property(srna, "map_diffuse", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "mapto", MAP_REF); RNA_def_property_ui_text(prop, "Diffuse", "Causes the texture to affect the value of the materials diffuse reflectivity"); + RNA_def_property_update(prop, NC_TEXTURE, NULL); prop= RNA_def_property(srna, "map_specular", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "mapto", MAP_SPEC); RNA_def_property_ui_text(prop, "Specular", "Causes the texture to affect the value of specular reflectivity"); + RNA_def_property_update(prop, NC_TEXTURE, NULL); prop= RNA_def_property(srna, "map_ambient", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "mapto", MAP_AMB); RNA_def_property_ui_text(prop, "Ambient", "Causes the texture to affect the value of ambient"); + RNA_def_property_update(prop, NC_TEXTURE, NULL); prop= RNA_def_property(srna, "map_hardness", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "mapto", MAP_HAR); RNA_def_property_ui_text(prop, "Hardness", "Causes the texture to affect the hardness value"); + RNA_def_property_update(prop, NC_TEXTURE, NULL); prop= RNA_def_property(srna, "map_raymir", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "mapto", MAP_RAYMIRR); RNA_def_property_ui_text(prop, "Ray-Mirror", "Causes the texture to affect the ray-mirror value"); + RNA_def_property_update(prop, NC_TEXTURE, NULL); prop= RNA_def_property(srna, "map_alpha", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "mapto", MAP_ALPHA); RNA_def_property_ui_text(prop, "Alpha", "Causes the texture to affect the alpha value"); + RNA_def_property_update(prop, NC_TEXTURE, NULL); prop= RNA_def_property(srna, "map_emit", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "mapto", MAP_EMIT); RNA_def_property_ui_text(prop, "Emit", "Causes the texture to affect the emit value"); + RNA_def_property_update(prop, NC_TEXTURE, NULL); prop= RNA_def_property(srna, "map_translucency", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "mapto", MAP_TRANSLU); RNA_def_property_ui_text(prop, "Translucency", "Causes the texture to affect the translucency value"); + RNA_def_property_update(prop, NC_TEXTURE, NULL); prop= RNA_def_property(srna, "map_displacement", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "mapto", MAP_DISPLACE); RNA_def_property_ui_text(prop, "Displacement", "Let the texture displace the surface"); + RNA_def_property_update(prop, NC_TEXTURE, NULL); prop= RNA_def_property(srna, "map_warp", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "mapto", MAP_WARP); RNA_def_property_ui_text(prop, "Warp", "Let the texture warp texture coordinates of next channels"); + RNA_def_property_update(prop, NC_TEXTURE, NULL); prop= RNA_def_property(srna, "x_mapping", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "projx"); RNA_def_property_enum_items(prop, prop_x_mapping_items); RNA_def_property_ui_text(prop, "X Mapping", ""); + RNA_def_property_update(prop, NC_TEXTURE, NULL); prop= RNA_def_property(srna, "y_mapping", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "projy"); RNA_def_property_enum_items(prop, prop_y_mapping_items); RNA_def_property_ui_text(prop, "Y Mapping", ""); + RNA_def_property_update(prop, NC_TEXTURE, NULL); prop= RNA_def_property(srna, "z_mapping", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "projz"); RNA_def_property_enum_items(prop, prop_z_mapping_items); RNA_def_property_ui_text(prop, "Z Mapping", ""); + RNA_def_property_update(prop, NC_TEXTURE, NULL); prop= RNA_def_property(srna, "mapping", PROP_ENUM, PROP_NONE); RNA_def_property_enum_items(prop, prop_mapping_items); RNA_def_property_ui_text(prop, "Mapping", ""); + RNA_def_property_update(prop, NC_TEXTURE, NULL); /* XXX: pmapto, pmaptoneg */ @@ -331,6 +354,7 @@ static void rna_def_material_mtex(BlenderRNA *brna) RNA_def_property_enum_sdna(prop, NULL, "normapspace"); RNA_def_property_enum_items(prop, prop_normal_map_space_items); RNA_def_property_ui_text(prop, "Normal Map Space", ""); + RNA_def_property_update(prop, NC_TEXTURE, NULL); /* XXX: MTex.which_output */ @@ -340,11 +364,13 @@ static void rna_def_material_mtex(BlenderRNA *brna) RNA_def_property_float_sdna(prop, NULL, "dispfac"); RNA_def_property_ui_range(prop, 0, 1, 10, 3); RNA_def_property_ui_text(prop, "Displacement Factor", "Amount texture displaces the surface."); + RNA_def_property_update(prop, NC_TEXTURE, NULL); prop= RNA_def_property(srna, "warp_factor", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "warpfac"); RNA_def_property_ui_range(prop, 0, 1, 10, 3); RNA_def_property_ui_text(prop, "Warp Factor", "Amount texture affects texture coordinates of next channels."); + RNA_def_property_update(prop, NC_TEXTURE, NULL); prop= RNA_def_property(srna, "colorspec_factor", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "colfac"); @@ -417,10 +443,10 @@ static void rna_def_material_mtex(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Enabled", "Enable this material texture slot."); RNA_def_property_update(prop, NC_MATERIAL|ND_SHADING, NULL); - /*prop= RNA_def_property(srna, "new_bump", PROP_BOOLEAN, PROP_NONE); + prop= RNA_def_property(srna, "new_bump", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "texflag", MTEX_NEW_BUMP); RNA_def_property_ui_text(prop, "New Bump", "Use new, corrected bump mapping code (backwards compatibility option)."); - RNA_def_property_update(prop, NC_MATERIAL|ND_SHADING, NULL);*/ + RNA_def_property_update(prop, NC_MATERIAL|ND_SHADING, NULL); } static void rna_def_material_colors(StructRNA *srna) diff --git a/source/blender/render/intern/source/convertblender.c b/source/blender/render/intern/source/convertblender.c index da77d578efc..5853b51a6b1 100644 --- a/source/blender/render/intern/source/convertblender.c +++ b/source/blender/render/intern/source/convertblender.c @@ -2243,6 +2243,7 @@ static void displace_render_face(Render *re, ObjectRen *obr, VlakRen *vlr, float /* memset above means we dont need this */ /*shi.osatex= 0;*/ /* signal not to use dx[] and dy[] texture AA vectors */ + shi.obr= obr; shi.vlr= vlr; /* current render face */ shi.mat= vlr->mat; /* current input material */ shi.thread= 0; diff --git a/source/blender/render/intern/source/shadeinput.c b/source/blender/render/intern/source/shadeinput.c index 931595eae60..6b1d11be6f3 100644 --- a/source/blender/render/intern/source/shadeinput.c +++ b/source/blender/render/intern/source/shadeinput.c @@ -210,7 +210,6 @@ void shade_input_do_shade(ShadeInput *shi, ShadeResult *shr) /* add mist and premul color */ if(shr->alpha!=1.0f || alpha!=1.0f) { float fac= alpha*(shr->alpha); - shr->combined[3]= fac; shr->combined[0]*= fac; shr->combined[1]*= fac; @@ -1016,9 +1015,12 @@ void shade_input_set_shade_texco(ShadeInput *shi) MTC_Mat4MulVecfl(R.viewinv, shi->gl); if(shi->osatex) { VECCOPY(shi->dxgl, shi->dxco); - MTC_Mat3MulVecfl(R.imat, shi->dxco); + // TXF: bug was here, but probably should be in convertblender.c, R.imat only valid if there is a world + //MTC_Mat3MulVecfl(R.imat, shi->dxco); + MTC_Mat4Mul3Vecfl(R.viewinv, shi->dxco); VECCOPY(shi->dygl, shi->dyco); - MTC_Mat3MulVecfl(R.imat, shi->dyco); + //MTC_Mat3MulVecfl(R.imat, shi->dyco); + MTC_Mat4Mul3Vecfl(R.viewinv, shi->dyco); } } @@ -1121,6 +1123,8 @@ void shade_input_set_shade_texco(ShadeInput *shi) if(tface && tface->tpage) render_realtime_texture(shi, tface->tpage); } + + } shi->dupliuv[0]= -1.0f + 2.0f*obi->dupliuv[0]; diff --git a/source/blender/render/intern/source/texture.c b/source/blender/render/intern/source/texture.c index 9466bd45420..3f7ffc5b9bb 100644 --- a/source/blender/render/intern/source/texture.c +++ b/source/blender/render/intern/source/texture.c @@ -71,6 +71,8 @@ #include "shading.h" #include "texture.h" +#include "renderdatabase.h" /* needed for UV */ + /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ /* defined in pipeline.c, is hardcopy of active dynamic allocated Render */ /* only to be used here in this file, it's for speed */ @@ -1499,6 +1501,94 @@ float texture_value_blend(float tex, float out, float fact, float facg, int blen return in; } +static void texco_mapping(ShadeInput* shi, Tex* tex, MTex* mtex, float* co, float* dx, float* dy, float* texvec, float* dxt, float* dyt) +{ + // new: first swap coords, then map, then trans/scale + if (tex->type == TEX_IMAGE) { + // placement + texvec[0] = mtex->projx ? co[mtex->projx - 1] : 0.f; + texvec[1] = mtex->projy ? co[mtex->projy - 1] : 0.f; + texvec[2] = mtex->projz ? co[mtex->projz - 1] : 0.f; + + if (shi->osatex) { + if (mtex->projx) { + dxt[0] = dx[mtex->projx - 1]; + dyt[0] = dy[mtex->projx - 1]; + } + else dxt[0] = dyt[0] = 0.f; + if (mtex->projy) { + dxt[1] = dx[mtex->projy - 1]; + dyt[1] = dy[mtex->projy - 1]; + } + else dxt[1] = dyt[1] = 0.f; + if (mtex->projz) { + dxt[2] = dx[mtex->projz - 1]; + dyt[2] = dy[mtex->projz - 1]; + } + else dxt[2] = dyt[2] = 0.f; + } + do_2d_mapping(mtex, texvec, shi->vlr, shi->facenor, dxt, dyt); + + // translate and scale + texvec[0] = mtex->size[0]*(texvec[0] - 0.5f) + mtex->ofs[0] + 0.5f; + texvec[1] = mtex->size[1]*(texvec[1] - 0.5f) + mtex->ofs[1] + 0.5f; + if (shi->osatex) { + dxt[0] = mtex->size[0]*dxt[0]; + dxt[1] = mtex->size[1]*dxt[1]; + dyt[0] = mtex->size[0]*dyt[0]; + dyt[1] = mtex->size[1]*dyt[1]; + } + + /* problem: repeat-mirror is not a 'repeat' but 'extend' in imagetexture.c */ + // TXF: bug was here, only modify texvec when repeat mode set, old code affected other modes too. + // New texfilters solve mirroring differently so that it also works correctly when + // textures are scaled (sizeXYZ) as well as repeated. See also modification in do_2d_mapping(). + // (since currently only done in osa mode, results will look incorrect without osa TODO) + if (tex->extend == TEX_REPEAT && (tex->flag & TEX_REPEAT_XMIR)) { + if (tex->texfilter == TXF_DEFAULT) + texvec[0] -= floorf(texvec[0]); // this line equivalent to old code, same below + else if (texvec[0] < 0.f || texvec[0] > 1.f) { + const float tx = 0.5f*texvec[0]; + texvec[0] = 2.f*(tx - floorf(tx)); + if (texvec[0] > 1.f) texvec[0] = 2.f - texvec[0]; + } + } + if (tex->extend == TEX_REPEAT && (tex->flag & TEX_REPEAT_YMIR)) { + if (tex->texfilter == TXF_DEFAULT) + texvec[1] -= floorf(texvec[1]); + else if (texvec[1] < 0.f || texvec[1] > 1.f) { + const float ty = 0.5f*texvec[1]; + texvec[1] = 2.f*(ty - floorf(ty)); + if (texvec[1] > 1.f) texvec[1] = 2.f - texvec[1]; + } + } + + } + else { // procedural + // placement + texvec[0] = mtex->size[0]*(mtex->projx ? (co[mtex->projx - 1] + mtex->ofs[0]) : mtex->ofs[0]); + texvec[1] = mtex->size[1]*(mtex->projy ? (co[mtex->projy - 1] + mtex->ofs[1]) : mtex->ofs[1]); + texvec[2] = mtex->size[2]*(mtex->projz ? (co[mtex->projz - 1] + mtex->ofs[2]) : mtex->ofs[2]); + + if (shi->osatex) { + if (mtex->projx) { + dxt[0] = mtex->size[0]*dx[mtex->projx - 1]; + dyt[0] = mtex->size[0]*dy[mtex->projx - 1]; + } + else dxt[0] = 0.f; + if (mtex->projy) { + dxt[1] = mtex->size[1]*dx[mtex->projy - 1]; + dyt[1] = mtex->size[1]*dy[mtex->projy - 1]; + } + else dxt[1] = 0.f; + if (mtex->projz) { + dxt[2] = mtex->size[2]*dx[mtex->projz - 1]; + dyt[2] = mtex->size[2]*dy[mtex->projz - 1]; + } + else dxt[2]= 0.f; + } + } +} void do_material_tex(ShadeInput *shi) { @@ -1509,10 +1599,12 @@ void do_material_tex(ShadeInput *shi) float fact, facm, factt, facmm, stencilTin=1.0; float texvec[3], dxt[3], dyt[3], tempvec[3], norvec[3], warpvec[3]={0.0f, 0.0f, 0.0f}, Tnor=1.0; int tex_nr, rgbnor= 0, warpdone=0; + float nu[3], nv[3], nn[3] = {0,0,0}, dudnu = 1.f, dudnv = 0.f, dvdnu = 0.f, dvdnv = 1.f; // bump mapping + int nunvdone= 0; if (R.r.scemode & R_NO_TEX) return; /* here: test flag if there's a tex (todo) */ - + for(tex_nr=0; tex_nruv[shi->actuv]; - int i; + int i = shi->actuv; if(mtex->uvname[0] != 0) { for(i = 0; i < shi->totuv; i++) { @@ -1596,6 +1688,47 @@ void do_material_tex(ShadeInput *shi) co= suv->uv; dx= suv->dxuv; dy= suv->dyuv; + + // uvmapping only, calculation of normal tangent u/v partial derivatives + // (should not be here, dudnu, dudnv, dvdnu & dvdnv should probably be part of ShadeInputUV struct, + // nu/nv in ShadeInput and this calculation should then move to shadeinput.c, shade_input_set_shade_texco() func.) + // NOTE: test for shi->obr->ob here, since vlr/obr/obi can be 'fake' when called from fastshade(), another reason to move it.. + if ((mtex->texflag & MTEX_NEW_BUMP) && shi->obr && shi->obr->ob) { + if(mtex->mapto & (MAP_NORM|MAP_DISPLACE|MAP_WARP)) { + MTFace* tf = RE_vlakren_get_tface(shi->obr, shi->vlr, i, NULL, 0); + int j1 = shi->i1, j2 = shi->i2, j3 = shi->i3; + + vlr_set_uv_indices(shi->vlr, &j1, &j2, &j3); + + if (tf) { + float *uv1 = tf->uv[j1], *uv2 = tf->uv[j2], *uv3 = tf->uv[j3]; + const float an[3] = {fabsf(nn[0]), fabsf(nn[1]), fabsf(nn[2])}; + const int a1 = (an[0] > an[1] && an[0] > an[2]) ? 1 : 0; + const int a2 = (an[2] > an[0] && an[2] > an[1]) ? 1 : 2; + const float dp1_a1 = shi->v1->co[a1] - shi->v3->co[a1]; + const float dp1_a2 = shi->v1->co[a2] - shi->v3->co[a2]; + const float dp2_a1 = shi->v2->co[a1] - shi->v3->co[a1]; + const float dp2_a2 = shi->v2->co[a2] - shi->v3->co[a2]; + const float du1 = uv1[0] - uv3[0], du2 = uv2[0] - uv3[0]; + const float dv1 = uv1[1] - uv3[1], dv2 = uv2[1] - uv3[1]; + const float dpdu_a1 = dv2*dp1_a1 - dv1*dp2_a1; + const float dpdu_a2 = dv2*dp1_a2 - dv1*dp2_a2; + const float dpdv_a1 = du1*dp2_a1 - du2*dp1_a1; + const float dpdv_a2 = du1*dp2_a2 - du2*dp1_a2; + float d = dpdu_a1*dpdv_a2 - dpdv_a1*dpdu_a2; + float uvd = du1*dv2 - dv1*du2; + + if (uvd == 0.f) uvd = 1e-5f; + if (d == 0.f) d = 1e-5f; + d = uvd / d; + + dudnu = (dpdv_a2*nu[a1] - dpdv_a1*nu[a2])*d; + dvdnu = (dpdu_a1*nu[a2] - dpdu_a2*nu[a1])*d; + dudnv = (dpdv_a2*nv[a1] - dpdv_a1*nv[a2])*d; + dvdnv = (dpdu_a1*nv[a2] - dpdu_a2*nv[a1])*d; + } + } + } } } else if(mtex->texco==TEXCO_WINDOW) { @@ -1621,7 +1754,7 @@ void do_material_tex(ShadeInput *shi) } else continue; // can happen when texco defines disappear and it renders old files - /* de pointer defines if bumping happens */ + /* the pointer defines if bumping happens */ if(mtex->mapto & (MAP_NORM|MAP_DISPLACE|MAP_WARP)) { texres.nor= norvec; norvec[0]= norvec[1]= norvec[2]= 0.0; @@ -1632,95 +1765,150 @@ void do_material_tex(ShadeInput *shi) VECADD(tempvec, co, warpvec); co= tempvec; } - - if(tex->type==TEX_IMAGE) { - /* new: first swap coords, then map, then trans/scale */ + if(mtex->texflag & MTEX_NEW_BUMP) { + // compute ortho basis around normal + if(!nunvdone) { + // render normal is negated + nn[0] = -shi->vn[0]; + nn[1] = -shi->vn[1]; + nn[2] = -shi->vn[2]; + VecOrthoBasisf(nn, nu, nv); + nunvdone= 1; + } - /* placement */ - if(mtex->projx) texvec[0]= co[mtex->projx-1]; - else texvec[0]= 0.0; - if(mtex->projy) texvec[1]= co[mtex->projy-1]; - else texvec[1]= 0.0; - if(mtex->projz) texvec[2]= co[mtex->projz-1]; - else texvec[2]= 0.0; + if(texres.nor) { + TexResult ttexr = {0, 0, 0, 0, 0, texres.talpha, NULL}; // temp TexResult + float tco[3], texv[3], cd, ud, vd, du, dv, idu, idv; + const int fromrgb = ((tex->type == TEX_IMAGE) || ((tex->flag & TEX_COLORBAND)!=0)); + const float bf = 0.04f*Tnor*((mtex->maptoneg & MAP_NORM) ? -mtex->norfac : mtex->norfac); + // disable internal bump eval + float* nvec = texres.nor; + texres.nor = NULL; + // du & dv estimates, constant value defaults + du = dv = 0.01f; - if(shi->osatex) { - - if(mtex->projx) { - dxt[0]= dx[mtex->projx-1]; - dyt[0]= dy[mtex->projx-1]; + // two methods, either constant based on main image resolution, + // (which also works without osa, though of course not always good (or even very bad) results), + // or based on tex derivative max values (osa only). Not sure which is best... + + if (!shi->osatex && (tex->type == TEX_IMAGE) && tex->ima) { + // in case we have no proper derivatives, fall back to + // computing du/dv it based on image size + ImBuf* ibuf = BKE_image_get_ibuf(tex->ima, &tex->iuser); + if (ibuf) { + du = 1.f/(float)ibuf->x; + dv = 1.f/(float)ibuf->y; + } } - else dxt[0]= dyt[0]= 0.0f; - - if(mtex->projy) { - dxt[1]= dx[mtex->projy-1]; - dyt[1]= dy[mtex->projy-1]; + else if (shi->osatex) { + // we have derivatives, can compute proper du/dv + if (tex->type == TEX_IMAGE) { // 2d image, use u & v max. of dx/dy 2d vecs + const float adx[2] = {fabsf(dx[0]), fabsf(dx[1])}; + const float ady[2] = {fabsf(dy[0]), fabsf(dy[1])}; + du = MAX2(adx[0], ady[0]); + dv = MAX2(adx[1], ady[1]); + } + else { // 3d procedural, estimate from all dx/dy elems + const float adx[3] = {fabsf(dx[0]), fabsf(dx[1]), fabsf(dx[2])}; + const float ady[3] = {fabsf(dy[0]), fabsf(dy[1]), fabsf(dy[2])}; + du = MAX3(adx[0], adx[1], adx[2]); + dv = MAX3(ady[1], ady[1], ady[2]); + } } - else dxt[1]= dyt[1]= 0.0f; - if(mtex->projz) { - dxt[2]= dx[mtex->projz-1]; - dyt[2]= dy[mtex->projz-1]; - } - else dxt[2]= dyt[2]= 0.0; - } - - do_2d_mapping(mtex, texvec, shi->vlr, shi->facenor, dxt, dyt); - /* translate and scale */ - texvec[0]= mtex->size[0]*(texvec[0]-0.5) +mtex->ofs[0]+0.5; - texvec[1]= mtex->size[1]*(texvec[1]-0.5) +mtex->ofs[1]+0.5; - if(shi->osatex) { - dxt[0]= mtex->size[0]*dxt[0]; - dxt[1]= mtex->size[1]*dxt[1]; - dyt[0]= mtex->size[0]*dyt[0]; - dyt[1]= mtex->size[1]*dyt[1]; + // center, main return value + texco_mapping(shi, tex, mtex, co, dx, dy, texvec, dxt, dyt); + rgbnor = multitex(tex, texvec, dxt, dyt, shi->osatex, &texres, shi->thread, mtex->which_output); + cd = fromrgb ? (texres.tr + texres.tg + texres.tb)*0.33333333f : texres.tin; + + if (mtex->texco == TEXCO_UV) { + // for the uv case, use the same value for both du/dv, + // since individually scaling the normal derivatives makes them useless... + du = MIN2(du, dv); + idu = (du < 1e-6f) ? bf : (bf/du); + + // +u val + tco[0] = co[0] + dudnu*du; + tco[1] = co[1] + dvdnu*du; + tco[2] = 0.f; + texco_mapping(shi, tex, mtex, tco, dx, dy, texv, dxt, dyt); + multitex(tex, texv, dxt, dyt, shi->osatex, &ttexr, shi->thread, mtex->which_output); + ud = idu*(cd - (fromrgb ? (ttexr.tr + ttexr.tg + ttexr.tb)*0.33333333f : ttexr.tin)); + + // +v val + tco[0] = co[0] + dudnv*du; + tco[1] = co[1] + dvdnv*du; + tco[2] = 0.f; + texco_mapping(shi, tex, mtex, tco, dx, dy, texv, dxt, dyt); + multitex(tex, texv, dxt, dyt, shi->osatex, &ttexr, shi->thread, mtex->which_output); + vd = idu*(cd - (fromrgb ? (ttexr.tr + ttexr.tg + ttexr.tb)*0.33333333f : ttexr.tin)); + } + else { + float tu[3] = {nu[0], nu[1], nu[2]}, tv[3] = {nv[0], nv[1], nv[2]}; + + idu = (du < 1e-6f) ? bf : (bf/du); + idv = (dv < 1e-6f) ? bf : (bf/dv); + + if ((mtex->texco == TEXCO_ORCO) && shi->obr && shi->obr->ob) { + Mat4Mul3Vecfl(shi->obr->ob->imat, tu); + Mat4Mul3Vecfl(shi->obr->ob->imat, tv); + Normalize(tu); + Normalize(tv); + } + else if (mtex->texco == TEXCO_GLOB) { + Mat4Mul3Vecfl(R.viewinv, tu); + Mat4Mul3Vecfl(R.viewinv, tv); + } + else if (mtex->texco == TEXCO_OBJECT && mtex->object) { + Mat4Mul3Vecfl(mtex->object->imat, tu); + Mat4Mul3Vecfl(mtex->object->imat, tv); + Normalize(tu); + Normalize(tv); + } + + // +u val + tco[0] = co[0] + tu[0]*du; + tco[1] = co[1] + tu[1]*du; + tco[2] = co[2] + tu[2]*du; + texco_mapping(shi, tex, mtex, tco, dx, dy, texv, dxt, dyt); + multitex(tex, texv, dxt, dyt, shi->osatex, &ttexr, shi->thread, mtex->which_output); + ud = idu*(cd - (fromrgb ? (ttexr.tr + ttexr.tg + ttexr.tb)*0.33333333f : ttexr.tin)); + + // +v val + tco[0] = co[0] + tv[0]*dv; + tco[1] = co[1] + tv[1]*dv; + tco[2] = co[2] + tv[2]*dv; + texco_mapping(shi, tex, mtex, tco, dx, dy, texv, dxt, dyt); + multitex(tex, texv, dxt, dyt, shi->osatex, &ttexr, shi->thread, mtex->which_output); + vd = idv*(cd - (fromrgb ? (ttexr.tr + ttexr.tg + ttexr.tb)*0.33333333f : ttexr.tin)); + } + + // bumped normal + nu[0] += ud*nn[0]; + nu[1] += ud*nn[1]; + nu[2] += ud*nn[2]; + nv[0] += vd*nn[0]; + nv[1] += vd*nn[1]; + nv[2] += vd*nn[2]; + Crossf(nvec, nu, nv); + + nvec[0] = -nvec[0]; + nvec[1] = -nvec[1]; + nvec[2] = -nvec[2]; + texres.nor = nvec; + rgbnor |= TEX_NOR; } - - /* problem: repeat-mirror is not a 'repeat' but 'extend' in imagetexture.c */ - if(tex->flag & TEX_REPEAT_XMIR) { - if(texvec[0]>1.0f) texvec[0] -= (int)(texvec[0]); - else if(texvec[0]<0.0f) texvec[0]+= 1-(int)(texvec[0]); + else { + texco_mapping(shi, tex, mtex, co, dx, dy, texvec, dxt, dyt); + rgbnor = multitex(tex, texvec, dxt, dyt, shi->osatex, &texres, shi->thread, mtex->which_output); } - if(tex->flag & TEX_REPEAT_YMIR) { - if(texvec[1]>1.0f) texvec[1] -= (int)(texvec[1]); - else if(texvec[1]<0.0f) texvec[1]+= 1-(int)(texvec[1]); - } - } else { - - /* placement */ - if(mtex->projx) texvec[0]= mtex->size[0]*(co[mtex->projx-1]+mtex->ofs[0]); - else texvec[0]= mtex->size[0]*(mtex->ofs[0]); - - if(mtex->projy) texvec[1]= mtex->size[1]*(co[mtex->projy-1]+mtex->ofs[1]); - else texvec[1]= mtex->size[1]*(mtex->ofs[1]); - - if(mtex->projz) texvec[2]= mtex->size[2]*(co[mtex->projz-1]+mtex->ofs[2]); - else texvec[2]= mtex->size[2]*(mtex->ofs[2]); - - if(shi->osatex) { - if(mtex->projx) { - dxt[0]= mtex->size[0]*dx[mtex->projx-1]; - dyt[0]= mtex->size[0]*dy[mtex->projx-1]; - } - else dxt[0]= 0.0; - if(mtex->projy) { - dxt[1]= mtex->size[1]*dx[mtex->projy-1]; - dyt[1]= mtex->size[1]*dy[mtex->projy-1]; - } - else dxt[1]= 0.0; - if(mtex->projz) { - dxt[2]= mtex->size[2]*dx[mtex->projz-1]; - dyt[2]= mtex->size[2]*dy[mtex->projz-1]; - } - else dxt[2]= 0.0; - } + texco_mapping(shi, tex, mtex, co, dx, dy, texvec, dxt, dyt); + rgbnor = multitex(tex, texvec, dxt, dyt, shi->osatex, &texres, shi->thread, mtex->which_output); } - rgbnor= multitex(tex, texvec, dxt, dyt, shi->osatex, &texres, shi->thread, mtex->which_output); - /* texture output */ if( (rgbnor & TEX_RGB) && (mtex->texflag & MTEX_RGBTOINT)) { @@ -1785,7 +1973,7 @@ void do_material_tex(ShadeInput *shi) if(mtex->texflag & MTEX_VIEWSPACE) { // rotate to global coords if(mtex->texco==TEXCO_ORCO || mtex->texco==TEXCO_UV) { - if(shi->vlr && shi->obr->ob) { + if(shi->vlr && shi->obr && shi->obr->ob) { float len= Normalize(texres.nor); // can be optimized... (ton) Mat4Mul3Vecfl(shi->obr->ob->obmat, texres.nor); @@ -1897,25 +2085,32 @@ void do_material_tex(ShadeInput *shi) } } else { - float nor[3], dot; - - if(shi->mat->mode & MA_TANGENT_V) { - shi->tang[0]+= Tnor*tex->norfac*texres.nor[0]; - shi->tang[1]+= Tnor*tex->norfac*texres.nor[1]; - shi->tang[2]+= Tnor*tex->norfac*texres.nor[2]; + if (mtex->texflag & MTEX_NEW_BUMP) { + shi->vn[0] = texres.nor[0]; + shi->vn[1] = texres.nor[1]; + shi->vn[2] = texres.nor[2]; } - - /* prevent bump to become negative normal */ - nor[0]= Tnor*tex->norfac*texres.nor[0]; - nor[1]= Tnor*tex->norfac*texres.nor[1]; - nor[2]= Tnor*tex->norfac*texres.nor[2]; - - dot= 0.5f + 0.5f*INPR(nor, shi->vn); - - shi->vn[0]+= dot*nor[0]; - shi->vn[1]+= dot*nor[1]; - shi->vn[2]+= dot*nor[2]; - } + else { + float nor[3], dot; + + if(shi->mat->mode & MA_TANGENT_V) { + shi->tang[0]+= Tnor*tex->norfac*texres.nor[0]; + shi->tang[1]+= Tnor*tex->norfac*texres.nor[1]; + shi->tang[2]+= Tnor*tex->norfac*texres.nor[2]; + } + + /* prevent bump to become negative normal */ + nor[0]= Tnor*tex->norfac*texres.nor[0]; + nor[1]= Tnor*tex->norfac*texres.nor[1]; + nor[2]= Tnor*tex->norfac*texres.nor[2]; + + dot= 0.5f + 0.5f*INPR(nor, shi->vn); + + shi->vn[0]+= dot*nor[0]; + shi->vn[1]+= dot*nor[1]; + shi->vn[2]+= dot*nor[2]; + } + } Normalize(shi->vn); /* this makes sure the bump is passed on to the next texture */ @@ -2628,7 +2823,7 @@ void render_realtime_texture(ShadeInput *shi, Image *ima) texr.nor= NULL; - if(shi->osatex) imagewraposa(tex, ima, NULL, texvec, dx, dy, &texr); + if(shi->osatex) imagewraposa(tex, ima, NULL, texvec, dx, dy, &texr); else imagewrap(tex, ima, NULL, texvec, &texr); shi->vcol[0]*= texr.tr;