diff options
Diffstat (limited to 'source/blender/render/intern/source')
5 files changed, 92 insertions, 50 deletions
diff --git a/source/blender/render/intern/source/bake_api.c b/source/blender/render/intern/source/bake_api.c index eff021c9b14..1a0ef4e64d4 100644 --- a/source/blender/render/intern/source/bake_api.c +++ b/source/blender/render/intern/source/bake_api.c @@ -425,7 +425,7 @@ static TriTessFace *mesh_calc_tri_tessface( if (tangent) { DM_ensure_normals(dm); - DM_calc_loop_tangents(dm); + DM_calc_loop_tangents(dm, true, NULL, 0); tspace = dm->getLoopDataArray(dm, CD_TANGENT); BLI_assert(tspace); diff --git a/source/blender/render/intern/source/convertblender.c b/source/blender/render/intern/source/convertblender.c index a02c262d58d..69ae7433fff 100644 --- a/source/blender/render/intern/source/convertblender.c +++ b/source/blender/render/intern/source/convertblender.c @@ -302,7 +302,7 @@ static void calc_tangent_vector(ObjectRen *obr, VlakRen *vlr, int do_tangent) typedef struct { ObjectRen *obr; - + int mtface_index; } SRenderMeshToTangent; /* interface */ @@ -335,7 +335,7 @@ static void GetTextureCoordinate(const SMikkTSpaceContext *pContext, float r_uv[ //assert(vert_index>=0 && vert_index<4); SRenderMeshToTangent *pMesh = (SRenderMeshToTangent *) pContext->m_pUserData; VlakRen *vlr= RE_findOrAddVlak(pMesh->obr, face_num); - MTFace *tface= RE_vlakren_get_tface(pMesh->obr, vlr, pMesh->obr->actmtface, NULL, 0); + MTFace *tface= RE_vlakren_get_tface(pMesh->obr, vlr, pMesh->mtface_index, NULL, 0); const float *coord; if (tface != NULL) { @@ -369,7 +369,7 @@ static void SetTSpace(const SMikkTSpaceContext *pContext, const float fvTangent[ //assert(vert_index>=0 && vert_index<4); SRenderMeshToTangent *pMesh = (SRenderMeshToTangent *) pContext->m_pUserData; VlakRen *vlr = RE_findOrAddVlak(pMesh->obr, face_num); - float *ftang = RE_vlakren_get_nmap_tangent(pMesh->obr, vlr, 1); + float *ftang = RE_vlakren_get_nmap_tangent(pMesh->obr, vlr, pMesh->mtface_index, true); if (ftang!=NULL) { copy_v3_v3(&ftang[iVert*4+0], fvTangent); ftang[iVert*4+3]=fSign; @@ -455,7 +455,12 @@ static void calc_vertexnormals(Render *UNUSED(re), ObjectRen *obr, bool do_verte sInterface.m_getNormal = GetNormal; sInterface.m_setTSpaceBasic = SetTSpace; - genTangSpaceDefault(&sContext); + for (a = 0; a < MAX_MTFACE; a++) { + if (obr->tangent_mask & 1 << a) { + mesh2tangent.mtface_index = a; + genTangSpaceDefault(&sContext); + } + } } } @@ -1969,7 +1974,8 @@ static void init_render_mesh(Render *re, ObjectRen *obr, int timeoffset) float xn, yn, zn, imat[3][3], mat[4][4]; //nor[3], float *orco = NULL; short (*loop_nors)[4][3] = NULL; - bool need_orco = false, need_stress = false, need_nmap_tangent = false, need_tangent = false, need_origindex = false; + bool need_orco = false, need_stress = false, need_tangent = false, need_origindex = false; + bool need_nmap_tangent_concrete = false; int a, a1, ok, vertofs; int end, totvert = 0; bool do_autosmooth = false, do_displace = false; @@ -2004,9 +2010,11 @@ static void init_render_mesh(Render *re, ObjectRen *obr, int timeoffset) if (ma->mode_l & MA_NORMAP_TANG) { if (me->mtpoly==NULL) { need_orco= 1; - need_tangent= 1; } - need_nmap_tangent= 1; + need_tangent= 1; + } + if (ma->mode2_l & MA_TANGENT_CONCRETE) { + need_nmap_tangent_concrete = true; } } } @@ -2017,7 +2025,7 @@ static void init_render_mesh(Render *re, ObjectRen *obr, int timeoffset) need_orco= 1; need_tangent= 1; } - need_nmap_tangent= 1; + need_nmap_tangent_concrete = true; } /* check autosmooth and displacement, we then have to skip only-verts optimize @@ -2130,14 +2138,13 @@ static void init_render_mesh(Render *re, ObjectRen *obr, int timeoffset) /* store customdata names, because DerivedMesh is freed */ RE_set_customdata_names(obr, &dm->faceData); - /* add tangent layer if we need one */ - if (need_nmap_tangent!=0 && CustomData_get_layer_index(&dm->faceData, CD_TANGENT) == -1) { - bool generate_data = false; - if (CustomData_get_layer_index(&dm->loopData, CD_TANGENT) == -1) { - dm->calcLoopTangents(dm); - generate_data = true; - } - DM_generate_tangent_tessface_data(dm, generate_data); + /* add tangent layers if we need */ + if ((ma->nmap_tangent_names_count && need_nmap_tangent_concrete) || need_tangent) { + dm->calcLoopTangents( + dm, need_tangent, + (const char (*)[MAX_NAME])ma->nmap_tangent_names, ma->nmap_tangent_names_count); + obr->tangent_mask = dm->tangent_mask; + DM_generate_tangent_tessface_data(dm, need_nmap_tangent_concrete || need_tangent); } /* still to do for keys: the correct local texture coordinate */ @@ -2257,7 +2264,7 @@ static void init_render_mesh(Render *re, ObjectRen *obr, int timeoffset) CustomDataLayer *layer; MTFace *mtface, *mtf; MCol *mcol, *mc; - int index, mtfn= 0, mcn= 0, mtng=0, mln = 0, vindex; + int index, mtfn= 0, mcn= 0, mln = 0, vindex; char *name; int nr_verts = v4!=0 ? 4 : 3; @@ -2280,17 +2287,24 @@ static void init_render_mesh(Render *re, ObjectRen *obr, int timeoffset) for (vindex=0; vindex<nr_verts; vindex++) mc[vindex]=mcol[a*4+rev_tab[vindex]]; } - else if (layer->type == CD_TANGENT && mtng < 1) { - if (need_nmap_tangent != 0) { - const float * tangent = (const float *) layer->data; - float * ftang = RE_vlakren_get_nmap_tangent(obr, vlr, 1); + else if (layer->type == CD_TANGENT) { + if (need_nmap_tangent_concrete || need_tangent) { + int uv_start = CustomData_get_layer_index(&dm->faceData, CD_MTFACE); + int uv_index = CustomData_get_named_layer_index(&dm->faceData, CD_MTFACE, layer->name); + BLI_assert(uv_start >= 0 && uv_index >= 0); + if ((uv_start < 0 || uv_index < 0)) + continue; + int n = uv_index - uv_start; + + const float *tangent = (const float *) layer->data; + float *ftang = RE_vlakren_get_nmap_tangent(obr, vlr, n, true); + for (vindex=0; vindex<nr_verts; vindex++) { copy_v4_v4(ftang+vindex*4, tangent+a*16+rev_tab[vindex]*4); mul_mat3_m4_v3(mat, ftang+vindex*4); normalize_v3(ftang+vindex*4); } } - mtng++; } else if (layer->type == CD_TESSLOOPNORMAL && mln < 1) { if (loop_nors) { @@ -2398,7 +2412,7 @@ static void init_render_mesh(Render *re, ObjectRen *obr, int timeoffset) } if (recalc_normals!=0 || need_tangent!=0) - calc_vertexnormals(re, obr, recalc_normals, need_tangent, need_nmap_tangent); + calc_vertexnormals(re, obr, recalc_normals, need_tangent, need_nmap_tangent_concrete); } MEM_SAFE_FREE(loop_nors); diff --git a/source/blender/render/intern/source/multires_bake.c b/source/blender/render/intern/source/multires_bake.c index 8eb6e7000ab..8c6d9c5f951 100644 --- a/source/blender/render/intern/source/multires_bake.c +++ b/source/blender/render/intern/source/multires_bake.c @@ -456,7 +456,7 @@ static void do_multires_bake(MultiresBakeRender *bkr, Image *ima, bool require_t if (require_tangent) { if (CustomData_get_layer_index(&dm->loopData, CD_TANGENT) == -1) - DM_calc_loop_tangents(dm); + DM_calc_loop_tangents(dm, true, NULL, 0); pvtangent = DM_get_loop_data_layer(dm, CD_TANGENT); } diff --git a/source/blender/render/intern/source/renderdatabase.c b/source/blender/render/intern/source/renderdatabase.c index 39e4e7b048a..de08ea8d11c 100644 --- a/source/blender/render/intern/source/renderdatabase.c +++ b/source/blender/render/intern/source/renderdatabase.c @@ -70,6 +70,7 @@ #include "DNA_material_types.h" #include "DNA_meshdata_types.h" #include "DNA_texture_types.h" +#include "DNA_listBase.h" #include "BKE_customdata.h" #include "BKE_DerivedMesh.h" @@ -379,19 +380,28 @@ float *RE_vlakren_get_surfnor(ObjectRen *obr, VlakRen *vlak, int verify) return surfnor + (vlak->index & 255)*RE_SURFNOR_ELEMS; } -float *RE_vlakren_get_nmap_tangent(ObjectRen *obr, VlakRen *vlak, int verify) +float *RE_vlakren_get_nmap_tangent(ObjectRen *obr, VlakRen *vlak, int index, bool verify) { - float *tangent; + float **tangents; int nr= vlak->index>>8; - tangent= obr->vlaknodes[nr].tangent; - if (tangent==NULL) { - if (verify) - tangent= obr->vlaknodes[nr].tangent= MEM_callocN(256*RE_NMAP_TANGENT_ELEMS*sizeof(float), "tangent table"); + tangents = obr->vlaknodes[nr].tangent_arrays; + + if (index + 1 > 8) { + return NULL; + } + + index = index < 0 ? 0: index; + + if (tangents[index] == NULL) { + if (verify) { + tangents[index] = MEM_callocN(256*RE_NMAP_TANGENT_ELEMS*sizeof(float), "tangent table"); + } else return NULL; } - return tangent + (vlak->index & 255)*RE_NMAP_TANGENT_ELEMS; + + return tangents[index] + (vlak->index & 255)*RE_NMAP_TANGENT_ELEMS; } RadFace **RE_vlakren_get_radface(ObjectRen *obr, VlakRen *vlak, int verify) @@ -414,7 +424,8 @@ VlakRen *RE_vlakren_copy(ObjectRen *obr, VlakRen *vlr) VlakRen *vlr1 = RE_findOrAddVlak(obr, obr->totvlak++); MTFace *mtface, *mtface1; MCol *mcol, *mcol1; - float *surfnor, *surfnor1, *tangent, *tangent1; + float *surfnor, *surfnor1; + float *tangent, *tangent1; int *origindex, *origindex1; RadFace **radface, **radface1; int i, index = vlr1->index; @@ -446,9 +457,11 @@ VlakRen *RE_vlakren_copy(ObjectRen *obr, VlakRen *vlr) copy_v3_v3(surfnor1, surfnor); } - tangent= RE_vlakren_get_nmap_tangent(obr, vlr, 0); - if (tangent) { - tangent1= RE_vlakren_get_nmap_tangent(obr, vlr1, 1); + for (i=0; i < MAX_MTFACE; i++) { + tangent = RE_vlakren_get_nmap_tangent(obr, vlr, i, false); + if (!tangent) + continue; + tangent1 = RE_vlakren_get_nmap_tangent(obr, vlr1, i, true); memcpy(tangent1, tangent, sizeof(float)*RE_NMAP_TANGENT_ELEMS); } @@ -789,8 +802,10 @@ void free_renderdata_vlaknodes(VlakTableNode *vlaknodes) MEM_freeN(vlaknodes[a].origindex); if (vlaknodes[a].surfnor) MEM_freeN(vlaknodes[a].surfnor); - if (vlaknodes[a].tangent) - MEM_freeN(vlaknodes[a].tangent); + for (int b = 0; b < MAX_MTFACE; b++) { + if (vlaknodes[a].tangent_arrays[b]) + MEM_freeN(vlaknodes[a].tangent_arrays[b]); + } if (vlaknodes[a].radface) MEM_freeN(vlaknodes[a].radface); } diff --git a/source/blender/render/intern/source/shadeinput.c b/source/blender/render/intern/source/shadeinput.c index d5fdcb2423a..bfdeed1e354 100644 --- a/source/blender/render/intern/source/shadeinput.c +++ b/source/blender/render/intern/source/shadeinput.c @@ -883,7 +883,10 @@ void shade_input_set_shade_texco(ShadeInput *shi) float u = shi->u, v = shi->v; float l = 1.0f + u + v, dl; int mode = shi->mode; /* or-ed result for all nodes */ + int mode2 = shi->mode2; short texco = shi->mat->texco; + const bool need_mikk_tangent = (mode & MA_NORMAP_TANG || R.flag & R_NEED_TANGENT); + const bool need_mikk_tangent_concrete = (mode2 & MA_TANGENT_CONCRETE) != 0; /* calculate dxno */ if (shi->vlr->flag & R_SMOOTH) { @@ -904,8 +907,8 @@ void shade_input_set_shade_texco(ShadeInput *shi) } /* calc tangents */ - if (mode & (MA_TANGENT_V | MA_NORMAP_TANG) || R.flag & R_NEED_TANGENT) { - const float *tangent, *s1, *s2, *s3; + if (mode & (MA_TANGENT_V | MA_NORMAP_TANG) || mode2 & MA_TANGENT_CONCRETE || R.flag & R_NEED_TANGENT) { + const float *s1, *s2, *s3; float tl, tu, tv; if (shi->vlr->flag & R_SMOOTH) { @@ -942,14 +945,18 @@ void shade_input_set_shade_texco(ShadeInput *shi) } } - if (mode & MA_NORMAP_TANG || R.flag & R_NEED_TANGENT) { - tangent = RE_vlakren_get_nmap_tangent(obr, shi->vlr, 0); + if (need_mikk_tangent || need_mikk_tangent_concrete) { + int j1 = shi->i1, j2 = shi->i2, j3 = shi->i3; + float c0[3], c1[3], c2[3]; + int acttang = obr->actmtface; - if (tangent) { - int j1 = shi->i1, j2 = shi->i2, j3 = shi->i3; - float c0[3], c1[3], c2[3]; + vlr_set_uv_indices(shi->vlr, &j1, &j2, &j3); - vlr_set_uv_indices(shi->vlr, &j1, &j2, &j3); + /* cycle through all tangent in vlakren */ + for (int i = 0; i < MAX_MTFACE; i++) { + const float *tangent = RE_vlakren_get_nmap_tangent(obr, shi->vlr, i, false); + if (!tangent) + continue; copy_v3_v3(c0, &tangent[j1 * 4]); copy_v3_v3(c1, &tangent[j2 * 4]); @@ -965,13 +972,19 @@ void shade_input_set_shade_texco(ShadeInput *shi) /* we don't normalize the interpolated TBN tangent * corresponds better to how it's done in game engines */ - shi->nmaptang[0] = (tl * c2[0] - tu * c0[0] - tv * c1[0]); - shi->nmaptang[1] = (tl * c2[1] - tu * c0[1] - tv * c1[1]); - shi->nmaptang[2] = (tl * c2[2] - tu * c0[2] - tv * c1[2]); + shi->tangents[i][0] = (tl * c2[0] - tu * c0[0] - tv * c1[0]); + shi->tangents[i][1] = (tl * c2[1] - tu * c0[1] - tv * c1[1]); + shi->tangents[i][2] = (tl * c2[2] - tu * c0[2] - tv * c1[2]); /* the sign is the same for all 3 vertices of any * non degenerate triangle. */ - shi->nmaptang[3] = tangent[j1 * 4 + 3]; + shi->tangents[i][3] = tangent[j1 * 4 + 3]; + + if (acttang == i && need_mikk_tangent) { + for (int m = 0; m < 4; m++) { + shi->nmaptang[m] = shi->tangents[i][m]; + } + } } } } |