* Volume colour absorption
authorMatt Ebb <matt@mke3.net>
Tue, 23 Sep 2008 07:05:06 +0000 (07:05 +0000)
committerMatt Ebb <matt@mke3.net>
Tue, 23 Sep 2008 07:05:06 +0000 (07:05 +0000)
Rather than a single absorption value to control how much light is absorbed as it
travels through a volume, there's now an additional absorption colour. This is
used to absorb different R/G/B components of light at different amounts. For
example, if a white light shines on a volume which absorbs green and blue
components, the volume will appear red.

To make it easier to use, the colour set in the UI is actually the inverse of the
absorption colour, so the colour you set is the colour that the volume will
appear as.

Here's an example of how it works:
http://mke3.net/blender/devel/rendering/volumetrics/vol_col_absorption.jpg

And this can be textured too:
http://mke3.net/blender/devel/rendering/volumetrics/vol_absorb_textured.png

Keep in mind, this doesn't use accurate spectral light wavelength mixing (just
R/G/B channels) so in cases where the absorption colour is fully red green or
blue, you'll get non-physical results.

Todo: refactor the volume texturing internal interface...

source/blender/blenkernel/intern/material.c
source/blender/blenloader/intern/readfile.c
source/blender/makesdna/DNA_material_types.h
source/blender/render/intern/include/texture.h
source/blender/render/intern/source/texture.c
source/blender/render/intern/source/volumetric.c
source/blender/src/buttons_shading.c

index 5c20858ec63763c4854fa3dc449842943d9a56f2..473a035eccebdba590ee53e6dfe43702a49abbd5 100644 (file)
@@ -171,6 +171,7 @@ void init_material(Material *ma)
        ma->vol_shade_stepsize = 0.2f;
        ma->vol_absorption = 1.0f;
        ma->vol_scattering = 1.0f;
+       ma->vol_absorption_col[0] = ma->vol_absorption_col[1] = ma->vol_absorption_col[2] = 0.0f;
 
        ma->mode= MA_TRACEBLE|MA_SHADBUF|MA_SHADOW|MA_RADIO|MA_RAYBIAS|MA_TANGENT_STR;
 
index 63f3f88da500dec5be94295fdccf89c85fdbe59b..41035b1c373be2fba623c639f992a8b39ab5e1d3 100644 (file)
@@ -7737,10 +7737,14 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
                }
                
                for(ma=main->mat.first; ma; ma= ma->id.next) {
-                       if (ma->vol_shade_stepsize < 0.001f) ma->vol_shade_stepsize = 0.2f;
-                       if (ma->vol_stepsize < 0.001f) ma->vol_stepsize = 0.2f;
-                       if (ma->vol_absorption < 0.001f) ma->vol_absorption = 1.0f;
-                       if (ma->vol_scattering < 0.001f) ma->vol_scattering = 1.0f;
+                       /* trigger for non-volumetric file */
+                       if (ma->vol_shade_stepsize < 0.0001f) {
+                               ma->vol_shade_stepsize = 0.2f;
+                               ma->vol_stepsize = 0.2f;
+                               ma->vol_absorption = 1.0f;
+                               ma->vol_scattering = 1.0f;
+                               ma->vol_absorption_col[0] = ma->vol_absorption_col[1] = ma->vol_absorption_col[2] = 0.0f;
+                       }
                }
        }
        
index 98ddc0aa7d33ba8b5903d006cdd9404d58c99842..c322295fff90f37157ed6a72893d17ba9a7e55c3 100644 (file)
@@ -302,7 +302,7 @@ typedef struct Material {
 #define MAP_AMB                        2048
 #define MAP_DISPLACE   4096
 #define MAP_WARP               8192
-#define MAP_LAYER              16384
+#define MAP_LAYER              16384   
 
 /* mapto for halo */
 //#define MAP_HA_COL           1
index 64b88c050d2908f12b7f46d972193f7f5aa97f23..eee4ad7069a012c51e38d8bde3ea3157f142138d 100644 (file)
@@ -56,7 +56,7 @@ void do_halo_tex(struct HaloRen *har, float xn, float yn, float *colf);
 void do_sky_tex(float *rco, float *lo, float *dxyview, float *hor, float *zen, float *blend, int skyflag);
 void do_material_tex(struct ShadeInput *shi);
 void do_lamp_tex(LampRen *la, float *lavec, struct ShadeInput *shi, float *colf, int effect);
-void do_volume_tex(ShadeInput *shi, float *xyz, float *col, float *alpha, float *emit);
+void do_volume_tex(ShadeInput *shi, float *xyz, float *col, float *absorb_col, float *alpha, float *emit);
 
 void init_render_textures(Render *re);
 
index 6d3cc57cd3267e3a1f677b062c0e7a2d2166bb9a..1bcefb049aead4087da95aacfa4cddeea723fc3b 100644 (file)
@@ -1451,7 +1451,7 @@ float texture_value_blend(float tex, float out, float fact, float facg, int blen
        return in;
 }
 
-void do_volume_tex(ShadeInput *shi, float *xyz, float *col, float *alpha, float *emit)
+void do_volume_tex(ShadeInput *shi, float *xyz, float *col, float *absorb_col, float *alpha, float *emit)
 {
        MTex *mtex;
        Tex *tex;
@@ -1550,7 +1550,7 @@ void do_volume_tex(ShadeInput *shi, float *xyz, float *col, float *alpha, float
                        }
                        
                        
-                       if(mtex->mapto & (MAP_COL)) {
+                       if(mtex->mapto & (MAP_COL+MAP_COLMIR)) {
                                float tcol[3], colfac;
                                
                                /* stencil maps on the texture control slider, not texture intensity value */
@@ -1571,6 +1571,11 @@ void do_volume_tex(ShadeInput *shi, float *xyz, float *col, float *alpha, float
                                if(mtex->mapto & MAP_COL) {
                                        texture_rgb_blend(col, tcol, col, texres.tin, colfac, mtex->blendtype);
                                }
+                               
+                               /* MAP_COLMIR is abused for absorption colour at the moment */
+                               if(mtex->mapto & MAP_COLMIR) {
+                                       texture_rgb_blend(absorb_col, tcol, absorb_col, texres.tin, colfac, mtex->blendtype);
+                               }
                        }
                        
                        if(mtex->mapto & MAP_VARS) {
index 298b08c3545008cd8cdc645a06d4bb194861211e..5966e10e1dd2f1d7aa2593524055d54971f422e8 100644 (file)
@@ -115,10 +115,11 @@ float vol_get_density(struct ShadeInput *shi, float *co)
        float density = shi->mat->alpha;
        float emit_fac=0.0f;
        float col[3] = {0.0, 0.0, 0.0};
+       float absorb_col[3] = {0.0, 0.0, 0.0};
        
        /* do any density gain stuff here */
        if (shi->mat->flag & MA_IS_TEXTURED)
-               do_volume_tex(shi, co, col, &density, &emit_fac);
+               do_volume_tex(shi, co, col, absorb_col, &density, &emit_fac);
        
        return density;
 }
@@ -131,15 +132,32 @@ void vol_get_emission(ShadeInput *shi, float *em, float *co, float density)
        float emission = shi->mat->emit;
        float col[3];
        float dens_dummy = 1.0f;
+       float absorb_col[3] = {0.0, 0.0, 0.0};
        
        VECCOPY(col, &shi->mat->r);
        
-       do_volume_tex(shi, co, col, &dens_dummy, &emission);
+       do_volume_tex(shi, co, col, absorb_col, &dens_dummy, &emission);
        
        em[0] = em[1] = em[2] = emission;
        VecMulVecf(em, em, col);
 }
 
+void vol_get_absorption(ShadeInput *shi, float *absorb_col, float *co)
+{
+       float col[3];
+       float dummy = 1.0f;
+       float vec_one[3] = {1.0f, 1.0f, 1.0f};
+       float absorption = shi->mat->vol_absorption;
+       
+       VECCOPY(absorb_col, shi->mat->vol_absorption_col);
+       
+       if (shi->mat->flag & MA_IS_TEXTURED)
+               do_volume_tex(shi, co, col, absorb_col, &dummy, &dummy);
+       
+       absorb_col[0] = (1.0f - absorb_col[0]) * absorption;
+       absorb_col[1] = (1.0f - absorb_col[1]) * absorption;
+       absorb_col[2] = (1.0f - absorb_col[2]) * absorption;
+}
 
 /* Compute attenuation, otherwise known as 'optical thickness', extinction, or tau.
  * Used in the relationship Transmittance = e^(-attenuation)
@@ -148,18 +166,20 @@ void vol_get_attenuation(ShadeInput *shi, float *tau, float *co, float *endco, f
 {
        /* input density = density at co */
        float dist;
-       float absorption = shi->mat->vol_absorption;
+       float absorb_col[3];
        int s, nsteps;
        float step_vec[3], step_sta[3], step_end[3];
 
-       dist = VecLenf(co, endco);
+       vol_get_absorption(shi, absorb_col, co);
 
+       dist = VecLenf(co, endco);
        nsteps = (int)ceil(dist / stepsize);
        
        if (nsteps == 1) {
                /* homogenous volume within the sampled distance */
                tau[0] = tau[1] = tau[2] = dist * density;
-               VecMulf(tau, absorption);
+               
+               VecMulVecf(tau, tau, absorb_col);
                return;
        } else {
                tau[0] = tau[1] = tau[2] = 0.0;
@@ -173,7 +193,8 @@ void vol_get_attenuation(ShadeInput *shi, float *tau, float *co, float *endco, f
        
        for (s = 0;  s < nsteps; s++) {
                
-               if (s > 0) density = vol_get_density(shi, step_sta);
+               if (s > 0)
+                       density = vol_get_density(shi, step_sta);
                
                tau[0] += stepsize * density;
                tau[1] += stepsize * density;
@@ -184,7 +205,7 @@ void vol_get_attenuation(ShadeInput *shi, float *tau, float *co, float *endco, f
                        VecAddf(step_end, step_end, step_vec);
                }
        }
-       VecMulf(tau, absorption);       
+       VecMulVecf(tau, tau, absorb_col);
 }
 
 void vol_shade_one_lamp(struct ShadeInput *shi, float *co, LampRen *lar, float *col, float stepsize, float density)
index eaf432f2397c943ef0c036a95c16a4b8d0f56d6f..7db44e4c0eb3fb038cb70f269234d3cee975e5d0 100644 (file)
@@ -3404,6 +3404,7 @@ static void material_panel_map_to(Object *ob, Material *ma, int from_nodes)
                uiDefButBitS(block, TOG3, MAP_ALPHA, B_MATPRV, "Density",               10,180,60,19, &(mtex->mapto), 0, 0, 0, 0, "Causes the texture to affect the alpha value");
                uiDefButBitS(block, TOG3, MAP_EMIT, B_MATPRV, "Emit",           70,180,50,19, &(mtex->mapto), 0, 0, 0, 0, "Causes the texture to affect the emit value");
                uiDefButBitS(block, TOG, MAP_COL, B_MATPRV, "Emit Col",         120,180,80,19, &(mtex->mapto), 0, 0, 0, 0, "Causes the texture to affect basic color of the material");
+               uiDefButBitS(block, TOG, MAP_COLMIR, B_MATPRV, "Absorb Col",            200,180,80,19, &(mtex->mapto), 0, 0, 0, 0, "Causes the texture to affect basic color of the material");
        }
        else {
                uiDefButBitS(block, TOG, MAP_COL, B_MATPRV, "Col",              10,180,40,19, &(mtex->mapto), 0, 0, 0, 0, "Causes the texture to affect basic color of the material");
@@ -4250,9 +4251,9 @@ static void material_panel_material_volume(Material *ma)
        uiBlockBeginAlign(block);
        uiDefButF(block, NUM, B_MATPRV, "Absorption: ",
                X2CLM1, yco-=BUTH, BUTW2, BUTH, &(ma->vol_absorption), 0.0, 5.0, 0, 0, "Multiplier for absorption");
-       /* uiDefButF(block, COL, B_MATPRV, "",
+       uiDefButF(block, COL, B_MATPRV, "",
                X2CLM1, yco-=BUTH, BUTW2, BUTH, &(ma->vol_absorption_col), 0, 0, 0, B_MATCOL, "");
-               */
+       
        uiBlockEndAlign(block);
        
        yco -= YSPACE;