Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlexander Romanov <a.romanov@blend4web.com>2016-04-26 11:43:02 +0300
committerCampbell Barton <ideasman42@gmail.com>2016-04-26 13:43:29 +0300
commit5abae51a6ef5b0f1b817ef5ce4bff34fef5001cd (patch)
treeca6d8f3595fd596fe978e4ad69a29bbc647be121 /source/blender/render
parent98babfa2b86f768ebc0cff6c0d8ec34e18afd2af (diff)
Support multiple tangents for BI render & viewport
Normal Map node support for GLSL mode and the internal render (multiple tangents support). The Normal Map node is a useful node which is present in the Cycles render. It makes it possible to use normal mapping without additional material node in a node tree. This patch implements Normal Map node for GLSL mode and the internal render. Previously only the active UV layer was used to calculate tangents.
Diffstat (limited to 'source/blender/render')
-rw-r--r--source/blender/render/extern/include/RE_shader_ext.h1
-rw-r--r--source/blender/render/intern/include/render_types.h2
-rw-r--r--source/blender/render/intern/include/renderdatabase.h4
-rw-r--r--source/blender/render/intern/source/bake_api.c2
-rw-r--r--source/blender/render/intern/source/convertblender.c60
-rw-r--r--source/blender/render/intern/source/multires_bake.c2
-rw-r--r--source/blender/render/intern/source/renderdatabase.c41
-rw-r--r--source/blender/render/intern/source/shadeinput.c37
8 files changed, 97 insertions, 52 deletions
diff --git a/source/blender/render/extern/include/RE_shader_ext.h b/source/blender/render/extern/include/RE_shader_ext.h
index 12b97aedbd3..8b6dfb88b73 100644
--- a/source/blender/render/extern/include/RE_shader_ext.h
+++ b/source/blender/render/extern/include/RE_shader_ext.h
@@ -139,6 +139,7 @@ typedef struct ShadeInput {
float refcol[4], displace[3];
float strandco, tang[3], nmapnorm[3], nmaptang[4], stress, winspeed[4];
float duplilo[3], dupliuv[3];
+ float tangents[8][4]; /* 8 = MAX_MTFACE */
ShadeInputUV uv[8]; /* 8 = MAX_MTFACE */
ShadeInputCol col[8]; /* 8 = MAX_MCOL */
diff --git a/source/blender/render/intern/include/render_types.h b/source/blender/render/intern/include/render_types.h
index cef3a073084..6de5da3795a 100644
--- a/source/blender/render/intern/include/render_types.h
+++ b/source/blender/render/intern/include/render_types.h
@@ -334,6 +334,8 @@ typedef struct ObjectRen {
char (*mcol)[MAX_CUSTOMDATA_LAYER_NAME];
int actmtface, actmcol, bakemtface;
+ char tangent_mask; /* which tangent layer should be calculated */
+
float obmat[4][4]; /* only used in convertblender.c, for instancing */
/* used on makeraytree */
diff --git a/source/blender/render/intern/include/renderdatabase.h b/source/blender/render/intern/include/renderdatabase.h
index 167ebc58030..b576d69d806 100644
--- a/source/blender/render/intern/include/renderdatabase.h
+++ b/source/blender/render/intern/include/renderdatabase.h
@@ -76,7 +76,7 @@ typedef struct VlakTableNode {
int *origindex;
int totmtface, totmcol;
float *surfnor;
- float *tangent;
+ float *tangent_arrays[MAX_MTFACE];
struct RadFace **radface;
} VlakTableNode;
@@ -137,7 +137,7 @@ struct MTFace *RE_vlakren_get_tface(struct ObjectRen *obr, VlakRen *ren, int n,
struct MCol *RE_vlakren_get_mcol(struct ObjectRen *obr, VlakRen *ren, int n, char **name, int verify);
int *RE_vlakren_get_origindex(struct ObjectRen *obr, VlakRen *vlak, int verify);
float *RE_vlakren_get_surfnor(struct ObjectRen *obr, VlakRen *ren, int verify);
-float *RE_vlakren_get_nmap_tangent(struct ObjectRen *obr, VlakRen *ren, int verify);
+float *RE_vlakren_get_nmap_tangent(ObjectRen *obr, VlakRen *vlak, int index, bool verify);
RadFace **RE_vlakren_get_radface(struct ObjectRen *obr, VlakRen *ren, int verify);
void RE_vlakren_get_normal(struct Render *re, struct ObjectInstanceRen *obi, struct VlakRen *vlr, float *nor);
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 ccf54cb6bcd..b6ee88de290 100644
--- a/source/blender/render/intern/source/convertblender.c
+++ b/source/blender/render/intern/source/convertblender.c
@@ -304,7 +304,7 @@ static void calc_tangent_vector(ObjectRen *obr, VlakRen *vlr, int do_tangent)
typedef struct {
ObjectRen *obr;
-
+ int mtface_index;
} SRenderMeshToTangent;
/* interface */
@@ -337,7 +337,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) {
@@ -371,7 +371,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;
@@ -457,7 +457,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);
+ }
+ }
}
}
@@ -3113,7 +3118,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;
@@ -3148,9 +3154,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;
}
}
}
@@ -3161,7 +3169,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
@@ -3274,14 +3282,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 */
@@ -3401,7 +3408,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;
@@ -3424,17 +3431,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) {
@@ -3542,7 +3556,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 e8db096c9a5..d3d26011a57 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 "DNA_particle_types.h"
#include "BKE_customdata.h"
@@ -380,19 +381,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)
@@ -415,7 +425,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;
@@ -447,9 +458,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);
}
@@ -790,8 +803,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 e60a5a70a7f..6e01921a6a7 100644
--- a/source/blender/render/intern/source/shadeinput.c
+++ b/source/blender/render/intern/source/shadeinput.c
@@ -884,7 +884,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) {
@@ -905,8 +908,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) {
@@ -943,14 +946,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]);
@@ -966,13 +973,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];
+ }
+ }
}
}
}