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:
authorTon Roosendaal <ton@blender.org>2006-09-05 17:28:59 +0400
committerTon Roosendaal <ton@blender.org>2006-09-05 17:28:59 +0400
commit6f47e5fa84f80739e5fb19e08cbe472eb42f7f32 (patch)
treefba3ccdc10360d2bf5d8b501be3cbc5408afa957
parentd4616b56ecd1240beccf405d95c35385f48d2c73 (diff)
New stuff!
- Tangent vectors now can also be derived from orcos (No UV needed) - Normalmaps now properly support tangent space as well (Patch provided by Alfredo de Greef) Full log is here: http://www.blender3d.org/cms/New_Render_features.774.0.html
-rw-r--r--source/blender/makesdna/DNA_material_types.h4
-rw-r--r--source/blender/render/intern/source/convertblender.c149
-rw-r--r--source/blender/render/intern/source/imagetexture.c14
-rw-r--r--source/blender/render/intern/source/rendercore.c29
-rw-r--r--source/blender/render/intern/source/texture.c31
-rw-r--r--source/blender/src/buttons_shading.c7
6 files changed, 156 insertions, 78 deletions
diff --git a/source/blender/makesdna/DNA_material_types.h b/source/blender/makesdna/DNA_material_types.h
index 6d31db900a7..77820a80aeb 100644
--- a/source/blender/makesdna/DNA_material_types.h
+++ b/source/blender/makesdna/DNA_material_types.h
@@ -168,8 +168,10 @@ typedef struct Material {
#define MA_SHADBUF 0x2000000
/* note; we drop MA_TANGENT_STR later to become tangent_u */
#define MA_TANGENT_V 0x4000000
+/* qdn: a bit clumsy this, tangents needed for normal maps separated from shading */
+#define MA_NORMAP_TANG 0x8000000
-#define MA_MODE_MASK 0x3ffffff /* all valid mode bits */
+#define MA_MODE_MASK 0xbffffff /* all valid mode bits */
/* diff_shader */
#define MA_DIFF_LAMBERT 0
diff --git a/source/blender/render/intern/source/convertblender.c b/source/blender/render/intern/source/convertblender.c
index 94b2fb8b0c8..67908f96b8a 100644
--- a/source/blender/render/intern/source/convertblender.c
+++ b/source/blender/render/intern/source/convertblender.c
@@ -432,66 +432,89 @@ static void calc_edge_stress(Render *re, Mesh *me, int startvert, int startvlak)
MEM_freeN(accum);
}
-static void calc_tangent_vector(Render *re, VlakRen *vlr, float fac1, float fac2, float fac3, float fac4)
+/* gets tangent from tface or orco */
+static void calc_tangent_vector(Render *re, VlakRen *vlr)
{
TFace *tface= vlr->tface;
+ VertRen *v1=vlr->v1, *v2=vlr->v2, *v3=vlr->v3, *v4=vlr->v4;
+ float tang[3], tangv[3], ct[3], e1[3], e2[3], *tav;
+ float *uv1, *uv2, *uv3, *uv4;
+ float s1, s2, t1, t2, det;
+ float uv[4][2];
if(tface) {
- VertRen *v1=vlr->v1, *v2=vlr->v2, *v3=vlr->v3, *v4=vlr->v4;
- float *uv1= tface->uv[0], *uv2= tface->uv[1], *uv3= tface->uv[2], *uv4= tface->uv[3];
- float tang[3], *tav;
- float s1, s2, t1, t2, det;
-
- /* we calculate quads as two triangles, so weight for diagonal gets halved */
- if(v4) {
- fac1*= 0.5f;
- fac3*= 0.5f;
- }
-
- /* first tria, we use the V now */
- s1= uv2[0] - uv1[0];
- s2= uv3[0] - uv1[0];
- t1= uv2[1] - uv1[1];
- t2= uv3[1] - uv1[1];
+ uv1= tface->uv[0];
+ uv2= tface->uv[1];
+ uv3= tface->uv[2];
+ uv4= tface->uv[3];
+ }
+ else if(v1->orco) {
+ uv1= uv[0]; uv2= uv[1]; uv3= uv[2]; uv4= uv[3];
+ spheremap(v1->orco[0], v1->orco[1], v1->orco[2], &uv[0][0], &uv[0][1]);
+ spheremap(v2->orco[0], v2->orco[1], v2->orco[2], &uv[1][0], &uv[1][1]);
+ spheremap(v3->orco[0], v3->orco[1], v3->orco[2], &uv[2][0], &uv[2][1]);
+ if(v4)
+ spheremap(v4->orco[0], v4->orco[1], v4->orco[2], &uv[3][0], &uv[3][1]);
+ }
+ else return;
+
+ s1= uv2[0] - uv1[0];
+ s2= uv3[0] - uv1[0];
+ t1= uv2[1] - uv1[1];
+ t2= uv3[1] - uv1[1];
+ det= 1.0f / (s1 * t2 - s2 * t1);
+
+ /* normals in render are inversed... */
+ VecSubf(e1, v1->co, v2->co);
+ VecSubf(e2, v1->co, v3->co);
+ tang[0] = (t2*e1[0] - t1*e2[0])*det;
+ tang[1] = (t2*e1[1] - t1*e2[1])*det;
+ tang[2] = (t2*e1[2] - t1*e2[2])*det;
+ tangv[0] = (s1*e2[0] - s2*e1[0])*det;
+ tangv[1] = (s1*e2[1] - s2*e1[1])*det;
+ tangv[2] = (s1*e2[2] - s2*e1[2])*det;
+ Crossf(ct, tang, tangv);
+ /* qdn: check flip */
+ if ((ct[0]*vlr->n[0] + ct[1]*vlr->n[1] + ct[2]*vlr->n[2]) < 0.f)
+ VecMulf(tang, -1.f);
+
+ tav= RE_vertren_get_tangent(re, v1, 1);
+ VECADD(tav, tav, tang);
+ tav= RE_vertren_get_tangent(re, v2, 1);
+ VECADD(tav, tav, tang);
+ tav= RE_vertren_get_tangent(re, v3, 1);
+ VECADD(tav, tav, tang);
+
+ if(v4) {
+ s1= uv3[0] - uv1[0];
+ s2= uv4[0] - uv1[0];
+ t1= uv3[1] - uv1[1];
+ t2= uv4[1] - uv1[1];
det= 1.0f / (s1 * t2 - s2 * t1);
/* normals in render are inversed... */
- tang[0]= (t2 * (v1->co[0]-v2->co[0]) - t1 * (v1->co[0]-v3->co[0]));
- tang[1]= (t2 * (v1->co[1]-v2->co[1]) - t1 * (v1->co[1]-v3->co[1]));
- tang[2]= (t2 * (v1->co[2]-v2->co[2]) - t1 * (v1->co[2]-v3->co[2]));
+ VecSubf(e1, v1->co, v3->co);
+ VecSubf(e2, v1->co, v4->co);
+ tang[0] = (t2*e1[0] - t1*e2[0])*det;
+ tang[1] = (t2*e1[1] - t1*e2[1])*det;
+ tang[2] = (t2*e1[2] - t1*e2[2])*det;
+ tangv[0] = (s1*e2[0] - s2*e1[0])*det;
+ tangv[1] = (s1*e2[1] - s2*e1[1])*det;
+ tangv[2] = (s1*e2[2] - s2*e1[2])*det;
+ Crossf(ct, tang, tangv);
+ if ((ct[0]*vlr->n[0] + ct[1]*vlr->n[1] + ct[2]*vlr->n[2]) < 0.f)
+ VecMulf(tang, -1.f);
tav= RE_vertren_get_tangent(re, v1, 1);
- VECADDFAC(tav, tav, tang, fac1);
- tav= RE_vertren_get_tangent(re, v2, 1);
- VECADDFAC(tav, tav, tang, fac2);
+ VECADD(tav, tav, tang);
tav= RE_vertren_get_tangent(re, v3, 1);
- VECADDFAC(tav, tav, tang, fac3);
-
- if(v4) {
- /* 2nd tria, we use the V now */
- s1= uv3[0] - uv1[0];
- s2= uv4[0] - uv1[0];
- t1= uv3[1] - uv1[1];
- t2= uv4[1] - uv1[1];
- det= 1.0f / (s1 * t2 - s2 * t1);
-
- /* normals in render are inversed... */
- tang[0]= (t2 * (v1->co[0]-v3->co[0]) - t1 * (v1->co[0]-v4->co[0]));
- tang[1]= (t2 * (v1->co[1]-v3->co[1]) - t1 * (v1->co[1]-v4->co[1]));
- tang[2]= (t2 * (v1->co[2]-v3->co[2]) - t1 * (v1->co[2]-v4->co[2]));
-
- Normalise(tang);
-
- tav= RE_vertren_get_tangent(re, v1, 1);
- VECADDFAC(tav, tav, tang, fac1);
- tav= RE_vertren_get_tangent(re, v3, 1);
- VECADDFAC(tav, tav, tang, fac3);
- tav= RE_vertren_get_tangent(re, v4, 1);
- VECADDFAC(tav, tav, tang, fac4);
- }
- }
+ VECADD(tav, tav, tang);
+ tav= RE_vertren_get_tangent(re, v4, 1);
+ VECADD(tav, tav, tang);
+ }
}
+
static void calc_vertexnormals(Render *re, int startvert, int startvlak, int do_tangent)
{
int a;
@@ -564,8 +587,11 @@ static void calc_vertexnormals(Render *re, int startvert, int startvlak, int do_
v3->n[1] +=fac3*vlr->n[1];
v3->n[2] +=fac3*vlr->n[2];
- if(do_tangent)
- calc_tangent_vector(re, vlr, fac1, fac2, fac3, fac4);
+ }
+ if(do_tangent) {
+ /* qdn: tangents still need to be calculated for flat faces too */
+ /* weighting removed, they are not vertexnormals */
+ calc_tangent_vector(re, vlr);
}
}
@@ -582,7 +608,7 @@ static void calc_vertexnormals(Render *re, int startvert, int startvlak, int do_
if(vlr->v4) {
f1= vlr->v4->n;
if(f1[0]==0.0 && f1[1]==0.0 && f1[2]==0.0) VECCOPY(f1, vlr->n);
- }
+ }
}
}
@@ -592,7 +618,14 @@ static void calc_vertexnormals(Render *re, int startvert, int startvlak, int do_
Normalise(ver->n);
if(do_tangent) {
float *tav= RE_vertren_get_tangent(re, ver, 0);
- if(tav) Normalise(tav);
+ if (tav) {
+ /* qdn: orthonorm. */
+ float tdn = tav[0]*ver->n[0] + tav[1]*ver->n[1] + tav[2]*ver->n[2];
+ tav[0] -= ver->n[0]*tdn;
+ tav[1] -= ver->n[1]*tdn;
+ tav[2] -= ver->n[2]*tdn;
+ Normalise(tav);
+ }
}
}
@@ -664,8 +697,13 @@ static void calc_fluidsimnormals(Render *re, int startvert, int startvlak, int d
}
}
- if(do_tangent)
- calc_tangent_vector(re, vlr, fac1, fac2, fac3, fac4);
+ //if(do_tangent)
+ // calc_tangent_vector(re, vlr, fac1, fac2, fac3, fac4);
+ }
+ if(do_tangent) {
+ /* qdn: tangents still need to be calculated for flat faces too */
+ /* weighting removed, they are not vertexnormals */
+ calc_tangent_vector(re, vlr);
}
}
@@ -1789,7 +1827,8 @@ static void init_render_mesh(Render *re, Object *ob, Object *par, int only_verts
need_orco= 1;
if(ma->texco & TEXCO_STRESS)
need_stress= 1;
- if(ma->mode & MA_TANGENT_V)
+ /* qdn: normalmaps, test if tangents needed, separated from shading */
+ if ((ma->mode & MA_TANGENT_V) || (ma->mode & MA_NORMAP_TANG))
need_tangent= 1;
/* radio faces need autosmooth, to separate shared vertices in corners */
if(re->r.mode & R_RADIO)
diff --git a/source/blender/render/intern/source/imagetexture.c b/source/blender/render/intern/source/imagetexture.c
index b819181606b..94e917c1917 100644
--- a/source/blender/render/intern/source/imagetexture.c
+++ b/source/blender/render/intern/source/imagetexture.c
@@ -193,9 +193,10 @@ int imagewrap(Tex *tex, Image *ima, float *texvec, TexResult *texres)
if(texres->nor) {
if(tex->imaflag & TEX_NORMALMAP) {
- texres->nor[0]= 0.5-texres->tr;
- texres->nor[1]= 0.5-texres->tg;
- texres->nor[2]= -texres->tb;
+ // qdn: normal from color
+ texres->nor[0] = 2.f*(texres->tr - 0.5f);
+ texres->nor[1] = 2.f*(0.5f - texres->tg);
+ texres->nor[2] = 2.f*(texres->tb - 0.5f);
}
else {
/* bump: take three samples */
@@ -948,9 +949,10 @@ int imagewraposa(Tex *tex, Image *ima, float *texvec, float *dxt, float *dyt, Te
}
if(texres->nor && (tex->imaflag & TEX_NORMALMAP)) {
- texres->nor[0]= 0.5-texres->tr;
- texres->nor[1]= 0.5-texres->tg;
- texres->nor[2]= -texres->tb;
+ // qdn: normal from color
+ texres->nor[0] = 2.f*(texres->tr - 0.5f);
+ texres->nor[1] = 2.f*(0.5f - texres->tg);
+ texres->nor[2] = 2.f*(texres->tb - 0.5f);
}
}
else {
diff --git a/source/blender/render/intern/source/rendercore.c b/source/blender/render/intern/source/rendercore.c
index 2ae9ccc8527..2eb9ce8c43d 100644
--- a/source/blender/render/intern/source/rendercore.c
+++ b/source/blender/render/intern/source/rendercore.c
@@ -1365,7 +1365,7 @@ static void shade_one_light(LampRen *lar, ShadeInput *shi, ShadeResult *shr, int
/* dot product and reflectivity */
/* inp = dotproduct, is = shader result, i = lamp energy (with shadow) */
- /* tangent case; calculate fake face normal, aligned with lampvector */
+ /* tangent case; calculate fake face normal, aligned with lampvector */
if(vlr->flag & R_TANGENT) {
float cross[3];
Crossf(cross, lv, vn);
@@ -1373,7 +1373,7 @@ static void shade_one_light(LampRen *lar, ShadeInput *shi, ShadeResult *shr, int
vnor[0]= -vnor[0];vnor[1]= -vnor[1];vnor[2]= -vnor[2];
vn= vnor;
}
- else if(ma->mode & MA_TANGENT_V) {
+ else if (ma->mode & MA_TANGENT_V) {
float cross[3];
Crossf(cross, lv, shi->tang);
Crossf(vnor, cross, shi->tang);
@@ -2051,7 +2051,7 @@ void shade_input_set_coords(ShadeInput *shi, float u, float v, int i1, int i2, i
l= 1.0+u+v;
/* calculate punos (vertexnormals) */
- if(vlr->flag & R_SMOOTH) {
+ if(vlr->flag & R_SMOOTH) {
float n1[3], n2[3], n3[3];
if(shi->puno & p1) {
@@ -2089,7 +2089,8 @@ void shade_input_set_coords(ShadeInput *shi, float u, float v, int i1, int i2, i
}
- if(mode & MA_TANGENT_V) {
+ /* qdn: normalmap tangent space separated from shading */
+ if (mode & (MA_TANGENT_V|MA_NORMAP_TANG)) {
float *s1, *s2, *s3;
s1= RE_vertren_get_tangent(&R, v1, 0);
@@ -2099,14 +2100,28 @@ void shade_input_set_coords(ShadeInput *shi, float u, float v, int i1, int i2, i
shi->tang[0]= (l*s3[0] - u*s1[0] - v*s2[0]);
shi->tang[1]= (l*s3[1] - u*s1[1] - v*s2[1]);
shi->tang[2]= (l*s3[2] - u*s1[2] - v*s2[2]);
+ /* qdn: normalize just in case */
+ Normalise(shi->tang);
}
else shi->tang[0]= shi->tang[1]= shi->tang[2]= 0.0f;
- }
+ }
}
else {
VECCOPY(shi->vn, shi->facenor);
- if(mode & MA_TANGENT_V)
- shi->tang[0]= shi->tang[1]= shi->tang[2]= 0.0f;
+ /* qdn: normalmap tangent space separated from shading */
+ if (mode & (MA_TANGENT_V|MA_NORMAP_TANG)) {
+ /* qdn: flat faces have tangents too,
+ could pick either one, using average here */
+ float *s1 = RE_vertren_get_tangent(&R, v1, 0);
+ float *s2 = RE_vertren_get_tangent(&R, v2, 0);
+ float *s3 = RE_vertren_get_tangent(&R, v3, 0);
+ if (s1 && s2 && s3) {
+ shi->tang[0] = (s1[0] + s2[0] + s3[0]);
+ shi->tang[1] = (s1[1] + s2[1] + s3[1]);
+ shi->tang[2] = (s1[2] + s2[2] + s3[2]);
+ Normalise(shi->tang);
+ }
+ }
}
/* used in nodes */
diff --git a/source/blender/render/intern/source/texture.c b/source/blender/render/intern/source/texture.c
index 08281dbd23d..fdd1ce274df 100644
--- a/source/blender/render/intern/source/texture.c
+++ b/source/blender/render/intern/source/texture.c
@@ -1737,16 +1737,31 @@ void do_material_tex(ShadeInput *shi)
/* we need to code blending modes for normals too once.. now 1 exception hardcoded */
- if(tex->type==TEX_IMAGE && (tex->imaflag & TEX_NORMALMAP)) {
- fact= Tnor*tex->norfac;
- if(fact>1.0) fact= 1.0; else if(fact<-1.0) fact= -1.0;
- facm= 1.0- fact;
- if(shi->mat->mode & MA_TANGENT_V) {
- shi->tang[0]= facm*shi->tang[0] + fact*texres.nor[0];
- shi->tang[1]= facm*shi->tang[1] + fact*texres.nor[1];
- shi->tang[2]= facm*shi->tang[2] + fact*texres.nor[2];
+ if ((tex->type==TEX_IMAGE) && (tex->imaflag & TEX_NORMALMAP)) {
+ /* qdn: for normalmaps, to invert the normalmap vector,
+ it is better to negate x & y instead of subtracting the vector as was done before */
+ tex->norfac = mtex->norfac;
+ if (mtex->maptoneg & MAP_NORM) {
+ texres.nor[0] = -texres.nor[0];
+ texres.nor[1] = -texres.nor[1];
+ }
+ fact = Tnor*tex->norfac;
+ if (fact>1.f) fact = 1.f;
+ facm = 1.f-fact;
+ if (shi->mat->mode & MA_NORMAP_TANG) {
+ /* qdn: tangent space */
+ float B[3], tv[3];
+ Crossf(B, shi->vn, shi->tang); /* bitangent */
+ /* transform norvec from tangent space to object surface in camera space */
+ tv[0] = texres.nor[0]*shi->tang[0] + texres.nor[1]*B[0] + texres.nor[2]*shi->vn[0];
+ tv[1] = texres.nor[0]*shi->tang[1] + texres.nor[1]*B[1] + texres.nor[2]*shi->vn[1];
+ tv[2] = texres.nor[0]*shi->tang[2] + texres.nor[1]*B[2] + texres.nor[2]*shi->vn[2];
+ shi->vn[0]= facm*shi->vn[0] + fact*tv[0];
+ shi->vn[1]= facm*shi->vn[1] + fact*tv[1];
+ shi->vn[2]= facm*shi->vn[2] + fact*tv[2];
}
else {
+ /* qdn: worldspace */
shi->vn[0]= facm*shi->vn[0] + fact*texres.nor[0];
shi->vn[1]= facm*shi->vn[1] + fact*texres.nor[1];
shi->vn[2]= facm*shi->vn[2] + fact*texres.nor[2];
diff --git a/source/blender/src/buttons_shading.c b/source/blender/src/buttons_shading.c
index 255c7869c44..af98d947e71 100644
--- a/source/blender/src/buttons_shading.c
+++ b/source/blender/src/buttons_shading.c
@@ -1047,7 +1047,9 @@ static void texture_panel_image(Tex *tex)
/* crop extend clip */
uiDefButF(block, NUM, B_TEXPRV, "Filter :", 10,92,150,19, &tex->filtersize, 0.1, 25.0, 0, 3, "Sets the filter size used by mipmap and interpol");
- uiDefButBitS(block, TOG, TEX_NORMALMAP, B_NOP, "Normal Map", 160,92,150,19, &tex->imaflag, 0.1, 25.0, 0, 0, "Use image RGB values for normal mapping");
+
+ uiDefButBitS(block, TOG, TEX_NORMALMAP, B_NOP, "Normal Map", 160,92,150,19, &tex->imaflag,
+ 0, 0, 0, 0, "Use image RGB values for normal mapping");
uiBlockBeginAlign(block);
uiDefButS(block, ROW, B_TEXREDR_PRV, "Extend", 10,70,63,19, &tex->extend, 4.0, 1.0, 0, 0, "Extends the colour of the edge pixels");
@@ -3021,6 +3023,9 @@ static void material_panel_shading(Material *ma)
uiBlockSetCol(block, TH_BUT_SETTING1);
uiDefButBitI(block, TOG, MA_TANGENT_V, B_MATPRV, "Tangent V", 245,180,65,19, &(ma->mode), 0, 0, 0, 0, "Use the tangent vector in V direction for shading");
+
+ /* qdn: normalmap tangents separated from shading */
+ uiDefButBitI(block, TOG, MA_NORMAP_TANG, B_MATPRV, "NMap TS", 245,160,65,19, &(ma->mode), 0, 0, 0, 0, "Enable Tangent Space normal mapping");
uiBlockBeginAlign(block);
uiDefButBitI(block, TOG, MA_SHADOW, B_MATPRV, "Shadow", 245,140,65,19, &(ma->mode), 0, 0, 0, 0, "Makes material receive shadows");