Added improved exposure calculation
authorTon Roosendaal <ton@blender.org>
Tue, 30 Dec 2003 18:03:37 +0000 (18:03 +0000)
committerTon Roosendaal <ton@blender.org>
Tue, 30 Dec 2003 18:03:37 +0000 (18:03 +0000)
- based at 1.0-exp(-color) trick in Yafray. But to guarantee backwards
  compatibility, and some more control, Stefano Selleri hacked a useful
  formula for it.
- We now have 2 values to set:
  - "exp": the exponential correction value (0-1)
  - "range": the light range that maps on color 1.0 (0-5)
- Using exp(x) (is e^x) we can much better prevent overflows from render,
  which are currently hard-clipped in Blender. Setting a small 'exp' value
  wil efficiently smooth out high energy and map that back to a color for
  display.
- total formula:
  newcol= linfac*(1.0-exp(col*logfac))
    col, newcol are colors
  linfac= 1.0 + 1.0/((2.0*wrld.exp +0.5)^10)
  logfac= log( (linfac-1.0)/linfac )/wrld.range
    wrld.exp and wrld.range are the button values
- default setting: exp=0.0 and range=1.0 give results extremely close to
  previous rendering.
- graph: http://www.selleri.org/Blender/buffer/Image1.png  for 'exp' setting
  ranging from 0-1, and with 'range'=2

Thanks Stefano for the help!

source/blender/blenkernel/intern/world.c
source/blender/blenloader/intern/readfile.c
source/blender/makesdna/DNA_world_types.h
source/blender/render/intern/source/rendercore.c
source/blender/renderconverter/intern/convertBlenderScene.c
source/blender/src/buttons_shading.c

index b482140e3733aa0be6a94b01241c049c1f9a376c..ea4f9bd790b724786e605637484bd6f38d879bf6 100644 (file)
@@ -86,11 +86,13 @@ World *add_world(char *name)
        
        wrld->horb= 0.6f;
        wrld->skytype= WO_SKYBLEND;
-       wrld->exposure= 1.0f;
        wrld->stardist= 15.0f;
        wrld->starsize= 2.0f;
        wrld->gravity= 9.8f;
-               
+       
+       wrld->exposure= 0.0f;
+       wrld->range= 1.0f;
+
        return wrld;
 }
 
@@ -199,6 +201,10 @@ void init_render_world()
        }
        else {
                memset(&R.wrld, 0, sizeof(World));
-               R.wrld.exposure= 1.0;
+               R.wrld.exposure= 0.0;
+               R.wrld.range= 1.0;
        }
+
+       R.wrld.linfac= 1.0 + pow((2.0*R.wrld.exposure + 0.5), -10);
+       R.wrld.logfac= log( (R.wrld.linfac-1.0)/R.wrld.linfac )/R.wrld.range;
 }
index 8bb3ab9d5ff1790b86f9ad180b0cdca1ae049101..9631bcc958ab43a2800c3f712c8ebc6789efae61 100644 (file)
@@ -3929,6 +3929,7 @@ static void do_versions(Main *main)
                Material *ma= main->mat.first;
                Scene *sce;
                Lamp *la;
+               World *wrld;
                
                while(ma) {
                        if(ma->fresnel_tra_i==0.0) ma->fresnel_tra_i= 1.25;
@@ -3963,6 +3964,14 @@ static void do_versions(Main *main)
                        if(la->area_sizez==0.0) la->area_sizez= 1.0;
                        la= la->id.next;
                }
+               wrld= main->world.first;
+               while(wrld) {
+                       if(wrld->range==0.0) {
+                               wrld->range= 1.0/wrld->exposure;
+                               wrld->exposure= 0.0;
+                       }
+                       wrld= wrld->id.next;
+               }
        }
        /* don't forget to set version number in blender.c! */
 }
index 91e205e40385db2682f2444a2e2672221814ded9..fd367369bd5c75ea54abda70af0f6322b5efc20a 100644 (file)
@@ -56,8 +56,13 @@ typedef struct World {
        float ambr, ambg, ambb, ambk;
 
        unsigned int fastcol;   
-
-       float exposure;
+       
+       /**
+        * New exposure/range control. linfac & logfac are constants... don't belong in
+        * file, but allocating 8 bytes for temp mem isnt useful either.
+        */
+       float exposure, range;  
+       float linfac, logfac;
 
        /**
         * Gravitation constant for the game world
@@ -87,7 +92,6 @@ typedef struct World {
        
        short dofsta, dofend, dofmin, dofmax;
 
-       int pad1;
        struct Ipo *ipo;
        struct MTex *mtex[8];
 
index ba86ca6319f7caa8286e463210d566b33fa15f82..996487507810f2781987d688167450beecec328c 100644 (file)
@@ -1457,7 +1457,9 @@ float Toon_Diff( float *n, float *l, float *v, float size, float smooth )
 }
 
 /* Oren Nayar diffuse */
-/* nl is either dot product, or return value of area light */
+
+/* 'nl' is either dot product, or return value of area light */
+/* in latter case, only last multiplication uses 'nl' */
 float OrenNayar_Diff_i(float nl, float *n, float *l, float *v, float rough )
 {
        float i, nh, nv, vh, realnl, h[3];
@@ -1477,7 +1479,7 @@ float OrenNayar_Diff_i(float nl, float *n, float *l, float *v, float rough )
        
        realnl= n[0]*l[0]+n[1]*l[1]+n[2]*l[2]; /* Dot product between surface normal and light vector */
        if(realnl<=0.0) return 0.0;
-       if(nl<0.0) nl= 0.0;             /* value from area light */
+       if(nl<0.0) return 0.0;          /* value from area light */
        
        vh= v[0]*h[0]+v[1]*h[1]+v[2]*h[2]; /* Dot product between view vector and halfway vector */
        if(vh<=0.0) vh= 0.0;
@@ -1510,7 +1512,7 @@ float OrenNayar_Diff_i(float nl, float *n, float *l, float *v, float rough )
        A = 1 - (0.5 * ((rough * rough) / ((rough * rough) + 0.33)));
        B = 0.45 * ((rough * rough) / ((rough * rough) + 0.09));
        
-       b*= 0.95;       /* prevent tangens from shooting to inf, nl here can be not a dot product here. */
+       b*= 0.95;       /* prevent tangens from shooting to inf, 'nl' can be not a dot product here. */
                                /* overflow only happens with extreme size area light, and higher roughness */
        i = nl * ( A + ( B * t * sin(a) * tan(b) ) );
        
@@ -2441,6 +2443,13 @@ temp_y= floor(y);
                
                VecAddf(col, shr.diff, shr.spec);
                
+               /* exposure correction */
+               if(R.wrld.exposure!=0.0 || R.wrld.range!=1.0) {
+                       col[0]= R.wrld.linfac*(1.0-exp( col[0]*R.wrld.logfac) );
+                       col[1]= R.wrld.linfac*(1.0-exp( col[1]*R.wrld.logfac) );
+                       col[2]= R.wrld.linfac*(1.0-exp( col[2]*R.wrld.logfac) );
+               }
+               
                /* MIST */
                if( (R.wrld.mode & WO_MIST) && (shi.matren->mode & MA_NOMIST)==0 ){
                        alpha= mistfactor(shi.co);
index 185e8ca9c05477d3e8b68866097af87c4abd5f7e..b8738968db46fe94ee96ace41e9bc5031cfd5f7c 100644 (file)
@@ -1827,7 +1827,7 @@ void RE_add_render_lamp(Object *ob, int doshadbuf)
        lar->mode= la->mode;
 
        lar->energy= la->energy;
-       lar->energy= la->energy*R.wrld.exposure;
+       lar->energy= la->energy;
        if(la->mode & LA_NEG) lar->energy= -lar->energy;
 
        lar->vec[0]= -mat[2][0];
index 65d5dcadf2a1022f0d9f2bd52b86b46ac5874311..fa3428e0f5f9fc87b523cf7e1005e63fbe1d9dd6 100644 (file)
@@ -1531,8 +1531,9 @@ static void world_panel_mistaph(World *wrld)
 
        uiSetButLock(wrld->id.lib!=0, "Can't edit library data");
 
-       uiDefBut(block, MENU|SHO, 1, "Physics %t|None %x1|Sumo %x2|ODE %x3 |Dynamo %x4|",       
-                       10,180,140,19, &wrld->pad1, 0, 0, 0, 0, "Physics Engine");
+       /* disabled, pad1 should not be used even! */
+       // uiDefBut(block, MENU|SHO, 1, "Physics %t|None %x1|Sumo %x2|ODE %x3 |Dynamo %x4|",    
+       //              10,180,140,19, &wrld->pad1, 0, 0, 0, 0, "Physics Engine");
        
        /* Gravitation for the game worlds */
        uiDefButF(block, NUMSLI,0, "Grav ", 150,180,150,19,     &(wrld->gravity), 0.0, 25.0, 0, 0,  "Sets the gravitation constant of the game world");
@@ -1602,9 +1603,11 @@ static void world_panel_world(World *wrld)
        uiDefButF(block, NUMSLI,B_MATPRV,"AmbR ",       10,50,145,19,   &(wrld->ambr), 0.0, 1.0 ,0,0, "Sets the amount of red ambient colour");
        uiDefButF(block, NUMSLI,B_MATPRV,"AmbG ",       10,30,145,19,   &(wrld->ambg), 0.0, 1.0 ,0,0, "Sets the amount of green ambient colour");
        uiDefButF(block, NUMSLI,B_MATPRV,"AmbB ",       10,10,145,19,   &(wrld->ambb), 0.0, 1.0 ,0,0, "Sets the amount of blue ambient colour");
-       uiBlockEndAlign(block);
 
-       uiDefButF(block, NUMSLI,0, "Expos ",            160,10,145,19,  &(wrld->exposure), 0.2, 5.0, 0, 0, "Sets the lighting time and exposure");
+       uiBlockBeginAlign(block);
+       uiBlockSetCol(block, TH_BUT_SETTING1);
+       uiDefButF(block, NUMSLI,0, "Exp ",                      160,30,145,19,  &(wrld->exposure), 0.0, 1.0, 0, 2, "Sets amount of exponential color correction for light");
+       uiDefButF(block, NUMSLI,0, "Range ",            160,10,145,19,  &(wrld->range), 0.2, 5.0, 0, 2, "Sets the color amount that will be mapped on color 1.0");
 
 
 }