Bugfix: normal mapping for textures wasn't rotated back to view space,
authorTon Roosendaal <ton@blender.org>
Sun, 5 Dec 2004 21:49:13 +0000 (21:49 +0000)
committerTon Roosendaal <ton@blender.org>
Sun, 5 Dec 2004 21:49:13 +0000 (21:49 +0000)
causing weird results on camera moves or object rotations.

Added: support for "normal maps". See for example:
http://members.shaw.ca/jimht03/normal.html

The Image panel in Texture buttons has new option "Normal Map" for it.
When this is used, normals are read straight from RGB values, and blended
with the current normal.

source/blender/blenkernel/intern/image.c
source/blender/makesdna/DNA_texture_types.h
source/blender/render/intern/source/texture.c
source/blender/src/buttons_shading.c
source/blender/src/previewrender.c

index 28254264f30d329e36393094bcfe8cd5680ce310..8f0893029e841c4623844223b91affeabb674db3 100644 (file)
@@ -693,25 +693,32 @@ int imagewrap(Tex *tex, float *texvec)
                Tb = ((float)rect[2])/255.0f;
                
                if(tex->nor) {
-                       /* bump: take three samples */
-                       val1= Tr+Tg+Tb;
-
-                       if(x<ibuf->x-1) {
-                               rect+=4;
-                               val2= ((float)(rect[0]+rect[1]+rect[2]))/255.0f;
-                               rect-=4;
+                       if(tex->imaflag & TEX_NORMALMAP) {
+                               tex->nor[0]= 0.5-Tr;
+                               tex->nor[1]= 0.5-Tg;
+                               tex->nor[2]= 0.5-Tb;
                        }
-                       else val2= val1;
+                       else {
+                               /* bump: take three samples */
+                               val1= Tr+Tg+Tb;
 
-                       if(y<ibuf->y-1) {
-                               rect+= 4*ibuf->x;
-                               val3= ((float)(rect[0]+rect[1]+rect[2]))/255.0f;
-                       }
-                       else val3= val1;
+                               if(x<ibuf->x-1) {
+                                       rect+=4;
+                                       val2= ((float)(rect[0]+rect[1]+rect[2]))/255.0f;
+                                       rect-=4;
+                               }
+                               else val2= val1;
+
+                               if(y<ibuf->y-1) {
+                                       rect+= 4*ibuf->x;
+                                       val3= ((float)(rect[0]+rect[1]+rect[2]))/255.0f;
+                               }
+                               else val3= val1;
 
-                       /* do not mix up x and y here! */
-                       tex->nor[0]= (val1-val2);
-                       tex->nor[1]= (val1-val3);
+                               /* do not mix up x and y here! */
+                               tex->nor[0]= (val1-val2);
+                               tex->nor[1]= (val1-val3);
+                       }
                }
 
                BRICONRGB;
@@ -1433,7 +1440,7 @@ int imagewraposa(Tex *tex, float *texvec, float *dxt, float *dyt)
                                if (miny < 0.5f / ima->ibuf->y) miny = 0.5f / ima->ibuf->y;
                        }
                        
-                       if(tex->nor) {
+                       if(tex->nor && (tex->imaflag & TEX_NORMALMAP)==0) {
                                /* a bit extra filter */
                                minx*= 1.35f;
                                miny*= 1.35f;
@@ -1473,7 +1480,6 @@ int imagewraposa(Tex *tex, float *texvec, float *dxt, float *dyt)
                                /* don't switch x or y! */
                                tex->nor[0]= (val1-val2);
                                tex->nor[1]= (val1-val3);
-
                        }
                        else {
                                maxx= fx+minx;
@@ -1508,7 +1514,7 @@ int imagewraposa(Tex *tex, float *texvec, float *dxt, float *dyt)
                                if (miny < 0.5f / ima->ibuf->y) miny = 0.5f / ima->ibuf->y;
                        }
 
-                       if(tex->nor) {
+                       if(tex->nor && (tex->imaflag & TEX_NORMALMAP)==0) {
                                
                                /* a bit extra filter */
                                minx*= 1.35f;
@@ -1526,12 +1532,10 @@ int imagewraposa(Tex *tex, float *texvec, float *dxt, float *dyt)
                                /* don't switch x or y! */
                                tex->nor[0]= (val1-val2);
                                tex->nor[1]= (val1-val3);
-                               
                        }
                        else {
                                boxsample(ibuf, fx-minx, fy-miny, fx+minx, fy+miny, &Tr, &Tg, &Tb, &Ta);
                        }
-
                }
                
                BRICONRGB;
@@ -1546,6 +1550,11 @@ int imagewraposa(Tex *tex, float *texvec, float *dxt, float *dyt)
                        ibuf->rect-= (ibuf->x*ibuf->y);
                }
 
+               if(tex->nor && (tex->imaflag & TEX_NORMALMAP)) {
+                       tex->nor[0]= 0.5-Tr;
+                       tex->nor[1]= 0.5-Tg;
+                       tex->nor[2]= 0.5-Tb;
+               }
        }
        else {
                Tin= 0.0f;
index 8e6ec495f521093d25c6a0e8fd1247f8ff673531..00e57f5e0822d566007c39ab263546bcbe3457e6 100644 (file)
@@ -220,6 +220,7 @@ typedef struct Tex {
 #define TEX_ANTIALI            256
 #define TEX_ANTISCALE  512
 #define TEX_STD_FIELD  1024
+#define TEX_NORMALMAP  2048
 
 #define TEX_LASOPPATCH 8192
 #define TEX_MORKPATCH  16384
index 6226cd9b4189c1c03634e2f38e717900537fb6b4..4e0e8382a65c237ea908c254e96f948af4291f52 100644 (file)
@@ -1256,7 +1256,6 @@ static float texture_value_blend(float tex, float out, float fact, float facg, i
 
 void do_material_tex(ShadeInput *shi)
 {
-       Object *ob;
        Material *mat_col, *mat_colspec, *mat_colmir, *mat_ref, *mat_amb;
        Material *mat_spec, *mat_har, *mat_emit, *mat_alpha, *mat_ray_mirr, *mat_translu;
        MTex *mtex;
@@ -1289,7 +1288,7 @@ void do_material_tex(ShadeInput *shi)
                                co= shi->sticky; dx= O.dxsticky; dy= O.dysticky;
                        }
                        else if(mtex->texco==TEXCO_OBJECT) {
-                               ob= mtex->object;
+                               Object *ob= mtex->object;
                                if(ob) {
                                        co= tempvec;
                                        dx= dxt;
@@ -1439,27 +1438,41 @@ void do_material_tex(ShadeInput *shi)
                                Tnor*= stencilTin;
                                Tin*= stencilTin;
                        }
-
-                       if(tex->nor && (rgbnor & TEX_NOR)==0) {
-                               /* make our own normal */
-                               if(rgbnor & TEX_RGB) {
-                                       tex->nor[0]= Tr;
-                                       tex->nor[1]= Tg;
-                                       tex->nor[2]= Tb;
+                       
+                       
+                       if(tex->nor) {
+                               if((rgbnor & TEX_NOR)==0) {
+                                       /* make our own normal */
+                                       if(rgbnor & TEX_RGB) {
+                                               tex->nor[0]= Tr;
+                                               tex->nor[1]= Tg;
+                                               tex->nor[2]= Tb;
+                                       }
+                                       else {
+                                               float co= 0.5*cos(Tin-0.5);
+                                               float si= 0.5*sin(Tin-0.5);
+                                               float f1, f2;
+
+                                               f1= shi->vn[0];
+                                               f2= shi->vn[1];
+                                               tex->nor[0]= f1*co+f2*si;
+                                               tex->nor[1]= f2*co-f1*si;
+                                               f1= shi->vn[1];
+                                               f2= shi->vn[2];
+                                               tex->nor[1]= f1*co+f2*si;
+                                               tex->nor[2]= f2*co-f1*si;
+                                       }
                                }
-                               else {
-                                       float co= 0.5*cos(Tin-0.5);
-                                       float si= 0.5*sin(Tin-0.5);
-                                       float f1, f2;
-
-                                       f1= shi->vn[0];
-                                       f2= shi->vn[1];
-                                       tex->nor[0]= f1*co+f2*si;
-                                       tex->nor[1]= f2*co-f1*si;
-                                       f1= shi->vn[1];
-                                       f2= shi->vn[2];
-                                       tex->nor[1]= f1*co+f2*si;
-                                       tex->nor[2]= f2*co-f1*si;
+                               // rotate to global coords
+                               if(mtex->texco==TEXCO_ORCO) {
+                                       if(shi->vlr && shi->vlr->ob) {
+                                               float len= Normalise(tex->nor);
+                                               // can be optimized... (ton)
+                                               Mat4Mul3Vecfl(shi->vlr->ob->obmat, tex->nor);
+                                               Mat4Mul3Vecfl(R.viewmat, tex->nor);
+                                               Normalise(tex->nor);
+                                               VecMulf(tex->nor, len);
+                                       }
                                }
                        }
 
@@ -1509,11 +1522,22 @@ void do_material_tex(ShadeInput *shi)
                                        
                                        if(mtex->maptoneg & MAP_NORM) tex->norfac= -mtex->norfac;
                                        else tex->norfac= mtex->norfac;
-
-                                       shi->vn[0]+= Tnor*tex->norfac*tex->nor[0];
-                                       shi->vn[1]+= Tnor*tex->norfac*tex->nor[1];
-                                       shi->vn[2]+= Tnor*tex->norfac*tex->nor[2];
                                        
+                                       /* 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;
+                                               facm= 1.0- fact;
+                                               shi->vn[0]= facm*shi->vn[0] + fact*tex->nor[0];
+                                               shi->vn[1]= facm*shi->vn[1] + fact*tex->nor[1];
+                                               shi->vn[2]= facm*shi->vn[2] + fact*tex->nor[2];
+                                       }
+                                       else {
+                                               shi->vn[0]+= Tnor*tex->norfac*tex->nor[0];
+                                               shi->vn[1]+= Tnor*tex->norfac*tex->nor[1];
+                                               shi->vn[2]+= Tnor*tex->norfac*tex->nor[2];
+                                       }                                       
                                        Normalise(shi->vn);
                                        
                                        /* this makes sure the bump is passed on to the next texture */
index 1e5ca8c6422471c155c59a43334a73487540bac4..b42f0b1eee9b28581af043c1b51c786dce7e0719 100644 (file)
@@ -1268,7 +1268,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, 0, "Sets the filter size used by mipmap and interpol");
+       uiDefButF(block, NUM, B_TEXPRV, "Filter :",                     10,92,150,19, &tex->filtersize, 0.1, 25.0, 0, 0, "Sets the filter size used by mipmap and interpol");
+       uiDefButS(block, TOG|BIT|11, B_NOP, "Normal Map",       160,92,150,19, &tex->imaflag, 0.1, 25.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");
        uiDefButS(block, ROW, B_TEXREDR_PRV, "Clip",                    73,70,48,19, &tex->extend, 4.0, 2.0, 0, 0, "Sets alpha 0.0 outside Image edges");
index b36483837d31cf2a0db9a805e26eb95ed66f279a..7bc19a87821634f1f5ec6e953ddf845e03246c94 100644 (file)
@@ -803,12 +803,12 @@ static void shade_preview_pixel(ShadeInput *shi, float *vec, int x, int y,char *
                shi->displace[0]= shi->displace[1]= shi->displace[2]= 0.0;
                
                /* normals flipped in render for smooth... */
-               if(smooth && (mat->mapto & MAP_NORM)) VecMulf(shi->vn, -1.0);
+               if( (mat->mapto & MAP_NORM)) VecMulf(shi->vn, -1.0);
                
                do_material_tex(shi);
 
                /* normals flipped in render... */
-               if(smooth && (mat->mapto & MAP_NORM)) VecMulf(shi->vn, -1.0);
+               if( (mat->mapto & MAP_NORM)) VecMulf(shi->vn, -1.0);
        
                if(mat->texco & TEXCO_REFL) {
                        /* normals in render are pointing different... rhm */
@@ -1075,7 +1075,7 @@ void BIF_previewrender(SpaceButs *sbuts)
                init_render_world();
                init_render_material(mat);
                
-               /* clear imats */
+               /* clear imats, flip normal... (hack because everything is inverted here) */
                for(x=0; x<MAX_MTEX; x++) {
                        if(mat->mtex[x]) {
                                if(mat->mtex[x]->tex) {
@@ -1083,6 +1083,8 @@ void BIF_previewrender(SpaceButs *sbuts)
                                        
                                        if(mat->mtex[x]->tex->env && mat->mtex[x]->tex->env->object) 
                                                MTC_Mat4One(mat->mtex[x]->tex->env->object->imat);
+                                       
+                                       mat->mtex[x]->maptoneg ^= MAP_NORM;
                                }
                                if(mat->mtex[x]->object) MTC_Mat4One(mat->mtex[x]->object->imat);
                                if(mat->mtex[x]->object) MTC_Mat4One(mat->mtex[x]->object->imat);
@@ -1280,8 +1282,11 @@ void BIF_previewrender(SpaceButs *sbuts)
        if(mat) {
                end_render_material(mat);
                for(x=0; x<MAX_MTEX; x++) {
-                       if(mat->mtex[x] && mat->mtex[x]->tex) end_render_texture(mat->mtex[x]->tex);
-               }       
+                       if(mat->mtex[x] && mat->mtex[x]->tex) {
+                               end_render_texture(mat->mtex[x]->tex);
+                               mat->mtex[x]->maptoneg ^= MAP_NORM;
+                       }       
+               }
        }
        else if(tex) {
                end_render_texture(tex);