Rework of volume shading
authorMatt Ebb <matt@mke3.net>
Tue, 29 Sep 2009 22:01:32 +0000 (22:01 +0000)
committerMatt Ebb <matt@mke3.net>
Tue, 29 Sep 2009 22:01:32 +0000 (22:01 +0000)
After code review and experimentation, this commit makes some changes to the way that volumes are shaded. Previously, there were problems with the 'scattering' component, in that it wasn't physically correct - it didn't conserve energy and was just acting as a brightness multiplier. This has been changed to be more correct, so that as the light is scattered out of the volume, there is less remaining to penetrate through.

Since this behaviour is very similar to absorption but more useful, absorption has been removed and has been replaced by a 'transmission colour' - controlling the colour of light penetrating through the volume after it has been scattered/absorbed. As well as this, there's now 'reflection', a non-physically correct RGB multiplier for out-scattered light. This is handy for tweaking the overall colour of the volume, without having to worry about wavelength dependent absorption, and its effects on transmitted light. Now at least, even though there is the ability to tweak things non-physically, volume shading is physically based by default, and has a better combination of correctness and ease of use.

There's more detailed information and example images here:
http://wiki.blender.org/index.php/User:Broken/VolumeRendering

Also did some tweaks/optimisation:
* Removed shading step size (was a bit annoying, if it comes back, it will be in a different form)
* Removed phase function options, now just one asymmetry slider controls the range between back-scattering, isotropic scattering, and forward scattering. (note, more extreme values gives artifacts with light cache, will fix...)
* Disabled the extra 'bounce lights' from the preview render for volumes, speeds updates significantly
* Enabled voxeldata texture in preview render
* Fixed volume shadows (they were too dark, fixed by avoiding using the shadfac/AddAlphaLight stuff)

More revisions to come later...

18 files changed:
release/scripts/ui/buttons_material.py
release/scripts/ui/buttons_texture.py
source/blender/blenkernel/intern/material.c
source/blender/blenkernel/intern/texture.c
source/blender/blenloader/intern/readfile.c
source/blender/editors/render/render_preview.c
source/blender/makesdna/DNA_material_types.h
source/blender/makesdna/DNA_texture_types.h
source/blender/makesrna/intern/rna_material.c
source/blender/makesrna/intern/rna_texture.c
source/blender/render/intern/include/volume_precache.h
source/blender/render/intern/include/volumetric.h
source/blender/render/intern/source/convertblender.c
source/blender/render/intern/source/rayshade.c
source/blender/render/intern/source/texture.c
source/blender/render/intern/source/volume_precache.c
source/blender/render/intern/source/volumetric.c
source/blender/render/intern/source/voxeldata.c

index 448cb36e1305107abff88b393aa7766a8e02864e..ee7193da30135565122c7c1172d39f3ee49d26d8 100644 (file)
@@ -609,6 +609,23 @@ class VolumeButtonsPanel(bpy.types.Panel):
                mat = context.material
                engine = context.scene.render_data.engine
                return mat and (mat.type == 'VOLUME') and (engine in self.COMPAT_ENGINES)
                mat = context.material
                engine = context.scene.render_data.engine
                return mat and (mat.type == 'VOLUME') and (engine in self.COMPAT_ENGINES)
+
+class MATERIAL_PT_volume_density(VolumeButtonsPanel):
+       __label__ = "Density"
+       __default_closed__ = False
+       COMPAT_ENGINES = set(['BLENDER_RENDER'])
+
+       def draw(self, context):
+               layout = self.layout
+
+               mat = context.material
+               vol = context.material.volume
+               
+               split = layout.split()
+               row = split.row()
+               row.itemR(vol, "density")
+               row.itemR(vol, "density_scale")
+
                
 class MATERIAL_PT_volume_shading(VolumeButtonsPanel):
        __label__ = "Shading"
                
 class MATERIAL_PT_volume_shading(VolumeButtonsPanel):
        __label__ = "Shading"
@@ -620,22 +637,23 @@ class MATERIAL_PT_volume_shading(VolumeButtonsPanel):
 
                vol = context.material.volume
                
 
                vol = context.material.volume
                
-               row = layout.row()
-               row.itemR(vol, "density")
-               row.itemR(vol, "scattering")
-
                split = layout.split()
                
                col = split.column()
                split = layout.split()
                
                col = split.column()
-               col.itemR(vol, "absorption")
-               col.itemR(vol, "absorption_color", text="")
-
+               col.itemR(vol, "scattering")
+               col.itemR(vol, "asymmetry")
+               col.itemR(vol, "transmission_color")
+               
                col = split.column()
                col = split.column()
-               col.itemR(vol, "emission")
-               col.itemR(vol, "emission_color", text="")
+               sub = col.column(align=True)
+               sub.itemR(vol, "emission")
+               sub.itemR(vol, "emission_color", text="")
+               sub = col.column(align=True)
+               sub.itemR(vol, "reflection")
+               sub.itemR(vol, "reflection_color", text="")     
 
 
-class MATERIAL_PT_volume_scattering(VolumeButtonsPanel):
-       __label__ = "Scattering"
+class MATERIAL_PT_volume_lighting(VolumeButtonsPanel):
+       __label__ = "Lighting"
        __default_closed__ = False
        COMPAT_ENGINES = set(['BLENDER_RENDER'])
 
        __default_closed__ = False
        COMPAT_ENGINES = set(['BLENDER_RENDER'])
 
@@ -648,24 +666,26 @@ class MATERIAL_PT_volume_scattering(VolumeButtonsPanel):
                
                col = split.column()
                col.itemR(vol, "scattering_mode", text="")
                
                col = split.column()
                col.itemR(vol, "scattering_mode", text="")
+               
+               col = split.column()
+               
                if vol.scattering_mode == 'SINGLE_SCATTERING':
                        col.itemR(vol, "light_cache")
                        sub = col.column()
                        sub.active = vol.light_cache
                        sub.itemR(vol, "cache_resolution")
                elif vol.scattering_mode in ('MULTIPLE_SCATTERING', 'SINGLE_PLUS_MULTIPLE_SCATTERING'):
                if vol.scattering_mode == 'SINGLE_SCATTERING':
                        col.itemR(vol, "light_cache")
                        sub = col.column()
                        sub.active = vol.light_cache
                        sub.itemR(vol, "cache_resolution")
                elif vol.scattering_mode in ('MULTIPLE_SCATTERING', 'SINGLE_PLUS_MULTIPLE_SCATTERING'):
+                       sub = col.column()
+                       sub.enabled = True
+                       sub.active = False
+                       sub.itemR(vol, "light_cache")
                        col.itemR(vol, "cache_resolution")
                        
                        sub = col.column(align=True)
                        sub.itemR(vol, "ms_diffusion")
                        sub.itemR(vol, "ms_spread")
                        sub.itemR(vol, "ms_intensity")
                        col.itemR(vol, "cache_resolution")
                        
                        sub = col.column(align=True)
                        sub.itemR(vol, "ms_diffusion")
                        sub.itemR(vol, "ms_spread")
                        sub.itemR(vol, "ms_intensity")
-               
-               col = split.column()
-               # col.itemL(text="Anisotropic Scattering:")
-               col.itemR(vol, "phase_function", text="")
-               if vol.phase_function in ('SCHLICK', 'HENYEY-GREENSTEIN'):
-                       col.itemR(vol, "asymmetry")
+
 
 class MATERIAL_PT_volume_transp(VolumeButtonsPanel):
        __label__= "Transparency"
 
 class MATERIAL_PT_volume_transp(VolumeButtonsPanel):
        __label__= "Transparency"
@@ -693,16 +713,15 @@ class MATERIAL_PT_volume_integration(VolumeButtonsPanel):
                col = split.column()
                col.itemL(text="Step Calculation:")
                col.itemR(vol, "step_calculation", text="")
                col = split.column()
                col.itemL(text="Step Calculation:")
                col.itemR(vol, "step_calculation", text="")
-               sub = col.column(align=True)
-               sub.itemR(vol, "step_size")
-               sub.itemR(vol, "shading_step_size")
+               col = col.column(align=True)
+               col.itemR(vol, "step_size")
                
                col = split.column()
                col.itemL()
                col.itemR(vol, "depth_cutoff")
                
                col = split.column()
                col.itemL()
                col.itemR(vol, "depth_cutoff")
-               col.itemR(vol, "density_scale")
 
 
+bpy.types.register(MATERIAL_PT_volume_density)
 bpy.types.register(MATERIAL_PT_volume_shading)
 bpy.types.register(MATERIAL_PT_volume_shading)
-bpy.types.register(MATERIAL_PT_volume_scattering)
+bpy.types.register(MATERIAL_PT_volume_lighting)
 bpy.types.register(MATERIAL_PT_volume_transp)
 bpy.types.register(MATERIAL_PT_volume_integration)
 bpy.types.register(MATERIAL_PT_volume_transp)
 bpy.types.register(MATERIAL_PT_volume_integration)
index c95fa266aaa0553a88db68e3a6f3c6278394b103..9765aa93ca4c485af1cd8a2fc7a19e0612c153c4 100644 (file)
@@ -246,13 +246,14 @@ class TEXTURE_PT_influence(TextureSlotPanel):
                                col = split.column()
                                factor_but(col, tex.map_density, "map_density", "density_factor", "Density")
                                factor_but(col, tex.map_emission, "map_emission", "emission_factor", "Emission")
                                col = split.column()
                                factor_but(col, tex.map_density, "map_density", "density_factor", "Density")
                                factor_but(col, tex.map_emission, "map_emission", "emission_factor", "Emission")
-                               factor_but(col, tex.map_absorption, "map_absorption", "absorption_factor", "Absorption")
                                factor_but(col, tex.map_scattering, "map_scattering", "scattering_factor", "Scattering")
                                factor_but(col, tex.map_scattering, "map_scattering", "scattering_factor", "Scattering")
+                               factor_but(col, tex.map_reflection, "map_reflection", "reflection_factor", "Reflection")
                                
                                col = split.column()
                                col.itemL(text=" ")
                                factor_but(col, tex.map_alpha, "map_coloremission", "coloremission_factor", "Emission Color")
                                
                                col = split.column()
                                col.itemL(text=" ")
                                factor_but(col, tex.map_alpha, "map_coloremission", "coloremission_factor", "Emission Color")
-                               factor_but(col, tex.map_colorabsorption, "map_colorabsorption", "colorabsorption_factor", "Absorption Color")
+                               factor_but(col, tex.map_colortransmission, "map_colortransmission", "colortransmission_factor", "Transmission Color")
+                               factor_but(col, tex.map_colorreflection, "map_colorreflection", "colorreflection_factor", "Reflection Color")
 
                elif la:
                        row = layout.row()
 
                elif la:
                        row = layout.row()
@@ -642,6 +643,7 @@ class TEXTURE_PT_voxeldata(TextureButtonsPanel):
                row.itemR(vd, "still_frame_number")
                
                layout.itemR(vd, "interpolation")
                row.itemR(vd, "still_frame_number")
                
                layout.itemR(vd, "interpolation")
+               layout.itemR(vd, "extension")
                layout.itemR(vd, "intensity")
                
 class TEXTURE_PT_pointdensity(TextureButtonsPanel):
                layout.itemR(vd, "intensity")
                
 class TEXTURE_PT_pointdensity(TextureButtonsPanel):
index 1667bd971025d619df3f4a31e1820a66f5c81712..cbd306f6d8747548a69092c5ebd09701be1e3bbb 100644 (file)
@@ -172,15 +172,15 @@ void init_material(Material *ma)
 
        ma->vol.density = 1.0f;
        ma->vol.emission = 0.0f;
 
        ma->vol.density = 1.0f;
        ma->vol.emission = 0.0f;
-       ma->vol.absorption = 1.0f;
        ma->vol.scattering = 1.0f;
        ma->vol.scattering = 1.0f;
+       ma->vol.reflection = 1.0f;
+       ma->vol.transmission_col[0] = ma->vol.transmission_col[1] = ma->vol.transmission_col[2] = 1.0f;
+       ma->vol.reflection_col[0] = ma->vol.reflection_col[1] = ma->vol.reflection_col[2] = 1.0f;
        ma->vol.emission_col[0] = ma->vol.emission_col[1] = ma->vol.emission_col[2] = 1.0f;
        ma->vol.emission_col[0] = ma->vol.emission_col[1] = ma->vol.emission_col[2] = 1.0f;
-       ma->vol.absorption_col[0] = ma->vol.absorption_col[1] = ma->vol.absorption_col[2] = 0.0f;
        ma->vol.density_scale = 1.0f;
        ma->vol.depth_cutoff = 0.01f;
        ma->vol.stepsize_type = MA_VOL_STEP_RANDOMIZED;
        ma->vol.stepsize = 0.2f;
        ma->vol.density_scale = 1.0f;
        ma->vol.depth_cutoff = 0.01f;
        ma->vol.stepsize_type = MA_VOL_STEP_RANDOMIZED;
        ma->vol.stepsize = 0.2f;
-       ma->vol.shade_stepsize = 0.2f;
        ma->vol.shade_type = MA_VOL_SHADE_SINGLE;
        ma->vol.shadeflag |= MA_VOL_PRECACHESHADING;
        ma->vol.precache_resolution = 50;
        ma->vol.shade_type = MA_VOL_SHADE_SINGLE;
        ma->vol.shadeflag |= MA_VOL_PRECACHESHADING;
        ma->vol.precache_resolution = 50;
index d7616ec8a9ab40e4013353d106366732d6c03b43..287396a85c8c53ae2d4f782e8c882493310ce309 100644 (file)
@@ -984,6 +984,7 @@ struct VoxelData *BKE_add_voxeldata(void)
        vd->interp_type= TEX_VD_LINEAR;
        vd->file_format= TEX_VD_SMOKE;
        vd->int_multiplier = 1.0;
        vd->interp_type= TEX_VD_LINEAR;
        vd->file_format= TEX_VD_SMOKE;
        vd->int_multiplier = 1.0;
+       vd->extend = TEX_CLIP;
        vd->object = NULL;
        
        return vd;
        vd->object = NULL;
        
        return vd;
index 114ec9095b15025baac4171e67b1f4efd487b1fe..94478b0d235d2e42a1428f23222d52f395458ff3 100644 (file)
@@ -9573,15 +9573,12 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
                        if (ma->vol.stepsize < 0.0001f) {
                                ma->vol.density = 1.0f;
                                ma->vol.emission = 0.0f;
                        if (ma->vol.stepsize < 0.0001f) {
                                ma->vol.density = 1.0f;
                                ma->vol.emission = 0.0f;
-                               ma->vol.absorption = 1.0f;
                                ma->vol.scattering = 1.0f;
                                ma->vol.emission_col[0] = ma->vol.emission_col[1] = ma->vol.emission_col[2] = 1.0f;
                                ma->vol.scattering = 1.0f;
                                ma->vol.emission_col[0] = ma->vol.emission_col[1] = ma->vol.emission_col[2] = 1.0f;
-                               ma->vol.absorption_col[0] = ma->vol.absorption_col[1] = ma->vol.absorption_col[2] = 0.0f;
                                ma->vol.density_scale = 1.0f;
                                ma->vol.depth_cutoff = 0.01f;
                                ma->vol.stepsize_type = MA_VOL_STEP_RANDOMIZED;
                                ma->vol.stepsize = 0.2f;
                                ma->vol.density_scale = 1.0f;
                                ma->vol.depth_cutoff = 0.01f;
                                ma->vol.stepsize_type = MA_VOL_STEP_RANDOMIZED;
                                ma->vol.stepsize = 0.2f;
-                               ma->vol.shade_stepsize = 0.2f;
                                ma->vol.shade_type = MA_VOL_SHADE_SINGLE;
                                ma->vol.shadeflag |= MA_VOL_PRECACHESHADING;
                                ma->vol.precache_resolution = 50;
                                ma->vol.shade_type = MA_VOL_SHADE_SINGLE;
                                ma->vol.shadeflag |= MA_VOL_PRECACHESHADING;
                                ma->vol.precache_resolution = 50;
@@ -9703,6 +9700,8 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
        {
                Scene *sce;
                Object *ob;
        {
                Scene *sce;
                Object *ob;
+               Material *ma;
+               Tex *tex;
 
                for(sce = main->scene.first; sce; sce = sce->id.next)
                        if(sce->unit.scale_length == 0.0f)
 
                for(sce = main->scene.first; sce; sce = sce->id.next)
                        if(sce->unit.scale_length == 0.0f)
@@ -9716,7 +9715,21 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
                        /* rotation modes were added, but old objects would now default to being 'quaternion based' */
                        ob->rotmode= ROT_MODE_EUL;
                }
                        /* rotation modes were added, but old objects would now default to being 'quaternion based' */
                        ob->rotmode= ROT_MODE_EUL;
                }
+               
+               for (ma = main->mat.first; ma; ma=ma->id.next) {
+                       if (ma->vol.reflection == 0.f) {
+                               ma->vol.reflection = 1.f;
+                               ma->vol.transmission_col[0] = ma->vol.transmission_col[1] = ma->vol.transmission_col[2] = 1.0f;
+                               ma->vol.reflection_col[0] = ma->vol.reflection_col[1] = ma->vol.reflection_col[2] = 1.0f;
+                       }
+               }
 
 
+               for (tex = main->tex.first; tex; tex=tex->id.next) {
+                       if (tex->vd) {
+                               if (tex->vd->extend == 0) tex->vd->extend = TEX_CLIP;
+                       }
+               }
+               
                for(sce= main->scene.first; sce; sce= sce->id.next)
                {
                        if(sce->audio.main == 0.0)
                for(sce= main->scene.first; sce; sce= sce->id.next)
                {
                        if(sce->audio.main == 0.0)
index 81f6badc24b91b225111770acf9156f8ac1e5d26..7dc04a47c511ad5b8a2f99fad14404d56e809c85 100644 (file)
@@ -334,6 +334,19 @@ static Scene *preview_prepare_scene(Scene *scene, ID *id, int id_type, ShaderPre
                                                }
                                        }
                                }
                                                }
                                        }
                                }
+                               
+                               /* turn off bounce lights for volume, 
+                                * doesn't make much visual difference and slows it down too */
+                               if(mat->material_type == MA_TYPE_VOLUME) {
+                                       for(base= sce->base.first; base; base= base->next) {
+                                               if(base->object->type == OB_LAMP) {
+                                                       /* if doesn't match 'Lamp.002' --> main key light */
+                                                       if( strcmp(base->object->id.name+2, "Lamp.002") != 0 ) {
+                                                               base->object->restrictflag |= OB_RESTRICT_RENDER;
+                                                       }
+                                               }
+                                       }
+                               }
 
                                
                                if(sp->pr_method==PR_ICON_RENDER) {
 
                                
                                if(sp->pr_method==PR_ICON_RENDER) {
@@ -363,6 +376,8 @@ static Scene *preview_prepare_scene(Scene *scene, ID *id, int id_type, ShaderPre
 
                                                if(matar && actcol < base->object->totcol)
                                                        (*matar)[actcol]= mat;
 
                                                if(matar && actcol < base->object->totcol)
                                                        (*matar)[actcol]= mat;
+                                       } else if (base->object->type == OB_LAMP) {
+                                               base->object->restrictflag &= ~OB_RESTRICT_RENDER;
                                        }
                                }
                        }
                                        }
                                }
                        }
index 55e3c9107e49c787ae8019d64ed3635a443374f2..b3a7e74e91dfd71982200e179f9c5085b016c6ee 100644 (file)
@@ -50,26 +50,23 @@ struct Ipo;
 typedef struct VolumeSettings {
        float density;
        float emission;
 typedef struct VolumeSettings {
        float density;
        float emission;
-       float absorption;
        float scattering;
        float scattering;
+       float reflection;
 
        float emission_col[3];
 
        float emission_col[3];
-       float absorption_col[3];
+       float transmission_col[3];
+       float reflection_col[3];
+
        float density_scale;
        float depth_cutoff;
        float density_scale;
        float depth_cutoff;
-
-       short phasefunc_type;
-       short vpad[3];
-       float phasefunc_g;
-       
-       float stepsize;
-       float shade_stepsize;
+       float asymmetry;
        
        short stepsize_type;
        short shadeflag;
        short shade_type;
        short precache_resolution;
        
        short stepsize_type;
        short shadeflag;
        short shade_type;
        short precache_resolution;
-       
+
+       float stepsize;
        float ms_diff;
        float ms_intensity;
        int ms_steps;
        float ms_diff;
        float ms_intensity;
        int ms_steps;
@@ -160,9 +157,8 @@ typedef struct Material {
        float sss_front, sss_back;
        short sss_flag, sss_preset;
 
        float sss_front, sss_back;
        short sss_flag, sss_preset;
 
-       /* yafray: absorption color, dispersion parameters and material preset menu */
-       float YF_ar, YF_ag, YF_ab, YF_dscale, YF_dpwr;
-       int YF_dsmp, YF_preset, YF_djit;
+       int mapto_textured;     /* render-time cache to optimise texture lookups */
+       int pad4;
 
        ListBase gpumaterial;           /* runtime */
 } Material;
 
        ListBase gpumaterial;           /* runtime */
 } Material;
@@ -320,12 +316,14 @@ typedef struct Material {
 #define MAP_LAYER              16384
 
 /* volume mapto - reuse definitions for now - a bit naughty! */
 #define MAP_LAYER              16384
 
 /* volume mapto - reuse definitions for now - a bit naughty! */
-#define MAP_DENSITY                    128
-#define MAP_EMISSION           64
-#define MAP_EMISSION_COL       1
-#define MAP_ABSORPTION         512
-#define MAP_ABSORPTION_COL     8
-#define MAP_SCATTERING         16
+#define MAP_DENSITY                            128
+#define MAP_EMISSION                   64
+#define MAP_EMISSION_COL               1
+#define MAP_SCATTERING                 16
+#define MAP_TRANSMISSION_COL   8
+#define MAP_REFLECTION_COL             4
+#define MAP_REFLECTION                 32
+
 
 /* mapto for halo */
 //#define MAP_HA_COL           1
 
 /* mapto for halo */
 //#define MAP_HA_COL           1
@@ -386,13 +384,5 @@ typedef struct Material {
 #define MA_VOL_SHADE_MULTIPLE                          2
 #define MA_VOL_SHADE_SINGLEPLUSMULTIPLE                3
 
 #define MA_VOL_SHADE_MULTIPLE                          2
 #define MA_VOL_SHADE_SINGLEPLUSMULTIPLE                3
 
-/* vol_phasefunc_type */
-#define MA_VOL_PH_ISOTROPIC            0
-#define MA_VOL_PH_MIEHAZY              1
-#define MA_VOL_PH_MIEMURKY             2
-#define MA_VOL_PH_RAYLEIGH             3
-#define MA_VOL_PH_HG                   4
-#define MA_VOL_PH_SCHLICK              5
-
 #endif
 
 #endif
 
index c13c0522004cec8b444883a95642629db912af49..c8f35b4306fac93e9f7ddc9dc952fc6dfef740c9 100644 (file)
@@ -167,7 +167,8 @@ typedef struct VoxelData {
        int interp_type;
        short file_format;
        short flag;
        int interp_type;
        short file_format;
        short flag;
-       int pad;
+       short extend;
+       short pad;
        
        struct Object *object; /* for rendering smoke sims */
        float int_multiplier;   
        
        struct Object *object; /* for rendering smoke sims */
        float int_multiplier;   
index 9f7b97dfa0530beef693a01c0b69bc0335a4cc4b..593fc2e5935457d84588fa2fd30c8e6972884b0d 100644 (file)
@@ -537,14 +537,19 @@ static void rna_def_material_mtex(BlenderRNA *brna)
        /* volume material */
        prop= RNA_def_property(srna, "map_coloremission", PROP_BOOLEAN, PROP_NONE);
        RNA_def_property_boolean_sdna(prop, NULL, "mapto", MAP_EMISSION_COL);
        /* volume material */
        prop= RNA_def_property(srna, "map_coloremission", PROP_BOOLEAN, PROP_NONE);
        RNA_def_property_boolean_sdna(prop, NULL, "mapto", MAP_EMISSION_COL);
-       RNA_def_property_ui_text(prop, "Emission Color", "Causes the texture to affect the colour of emission");
+       RNA_def_property_ui_text(prop, "Emission Color", "Causes the texture to affect the color of emission");
        RNA_def_property_update(prop, 0, "rna_Material_update");
        
        RNA_def_property_update(prop, 0, "rna_Material_update");
        
-       prop= RNA_def_property(srna, "map_colorabsorption", PROP_BOOLEAN, PROP_NONE);
-       RNA_def_property_boolean_sdna(prop, NULL, "mapto", MAP_ABSORPTION_COL);
-       RNA_def_property_ui_text(prop, "Absorption Color", "Causes the texture to affect the result colour after absorption");
+       prop= RNA_def_property(srna, "map_colorreflection", PROP_BOOLEAN, PROP_NONE);
+       RNA_def_property_boolean_sdna(prop, NULL, "mapto", MAP_REFLECTION_COL);
+       RNA_def_property_ui_text(prop, "Reflection Color", "Causes the texture to affect the color of scattered light");
        RNA_def_property_update(prop, 0, "rna_Material_update");
        
        RNA_def_property_update(prop, 0, "rna_Material_update");
        
+       prop= RNA_def_property(srna, "map_colortransmission", PROP_BOOLEAN, PROP_NONE);
+       RNA_def_property_boolean_sdna(prop, NULL, "mapto", MAP_TRANSMISSION_COL);
+       RNA_def_property_ui_text(prop, "Transmission Color", "Causes the texture to affect the result color after other light has been scattered/absorbed");
+       RNA_def_property_update(prop, NC_TEXTURE, NULL);
+       
        prop= RNA_def_property(srna, "map_density", PROP_BOOLEAN, PROP_NONE);
        RNA_def_property_boolean_sdna(prop, NULL, "mapto", MAP_DENSITY);
        RNA_def_property_ui_text(prop, "Density", "Causes the texture to affect the volume's density");
        prop= RNA_def_property(srna, "map_density", PROP_BOOLEAN, PROP_NONE);
        RNA_def_property_boolean_sdna(prop, NULL, "mapto", MAP_DENSITY);
        RNA_def_property_ui_text(prop, "Density", "Causes the texture to affect the volume's density");
@@ -555,28 +560,34 @@ static void rna_def_material_mtex(BlenderRNA *brna)
        RNA_def_property_ui_text(prop, "Emission", "Causes the texture to affect the volume's emission");
        RNA_def_property_update(prop, 0, "rna_Material_update");
        
        RNA_def_property_ui_text(prop, "Emission", "Causes the texture to affect the volume's emission");
        RNA_def_property_update(prop, 0, "rna_Material_update");
        
-       prop= RNA_def_property(srna, "map_absorption", PROP_BOOLEAN, PROP_NONE);
-       RNA_def_property_boolean_sdna(prop, NULL, "mapto", MAP_ABSORPTION);
-       RNA_def_property_ui_text(prop, "Absorption", "Causes the texture to affect the volume's absorption");
-       RNA_def_property_update(prop, 0, "rna_Material_update");
-       
        prop= RNA_def_property(srna, "map_scattering", PROP_BOOLEAN, PROP_NONE);
        RNA_def_property_boolean_sdna(prop, NULL, "mapto", MAP_SCATTERING);
        RNA_def_property_ui_text(prop, "Scattering", "Causes the texture to affect the volume's scattering");
        RNA_def_property_update(prop, 0, "rna_Material_update");
        
        prop= RNA_def_property(srna, "map_scattering", PROP_BOOLEAN, PROP_NONE);
        RNA_def_property_boolean_sdna(prop, NULL, "mapto", MAP_SCATTERING);
        RNA_def_property_ui_text(prop, "Scattering", "Causes the texture to affect the volume's scattering");
        RNA_def_property_update(prop, 0, "rna_Material_update");
        
+       prop= RNA_def_property(srna, "map_reflection", PROP_BOOLEAN, PROP_NONE);
+       RNA_def_property_boolean_sdna(prop, NULL, "mapto", MAP_REFLECTION);
+       RNA_def_property_ui_text(prop, "Reflection", "Causes the texture to affect the reflected light's brightness");
+       RNA_def_property_update(prop, NC_TEXTURE, NULL);
+       
        prop= RNA_def_property(srna, "coloremission_factor", PROP_FLOAT, PROP_NONE);
        RNA_def_property_float_sdna(prop, NULL, "colfac");
        RNA_def_property_ui_range(prop, 0, 1, 10, 3);
        RNA_def_property_ui_text(prop, "Emission Color Factor", "Amount texture affects emission color.");
        RNA_def_property_update(prop, 0, "rna_Material_update");
        
        prop= RNA_def_property(srna, "coloremission_factor", PROP_FLOAT, PROP_NONE);
        RNA_def_property_float_sdna(prop, NULL, "colfac");
        RNA_def_property_ui_range(prop, 0, 1, 10, 3);
        RNA_def_property_ui_text(prop, "Emission Color Factor", "Amount texture affects emission color.");
        RNA_def_property_update(prop, 0, "rna_Material_update");
        
-       prop= RNA_def_property(srna, "colorabsorption_factor", PROP_FLOAT, PROP_NONE);
+       prop= RNA_def_property(srna, "colorreflection_factor", PROP_FLOAT, PROP_NONE);
        RNA_def_property_float_sdna(prop, NULL, "colfac");
        RNA_def_property_ui_range(prop, 0, 1, 10, 3);
        RNA_def_property_float_sdna(prop, NULL, "colfac");
        RNA_def_property_ui_range(prop, 0, 1, 10, 3);
-       RNA_def_property_ui_text(prop, "Absorpion Color Factor", "Amount texture affects diffuse color.");
+       RNA_def_property_ui_text(prop, "Reflection Color Factor", "Amount texture affects color of out-scattered light");
        RNA_def_property_update(prop, 0, "rna_Material_update");
        
        RNA_def_property_update(prop, 0, "rna_Material_update");
        
+       prop= RNA_def_property(srna, "colortransmission_factor", PROP_FLOAT, PROP_NONE);
+       RNA_def_property_float_sdna(prop, NULL, "colfac");
+       RNA_def_property_ui_range(prop, 0, 1, 10, 3);
+       RNA_def_property_ui_text(prop, "Transmission Color Factor", "Amount texture affects result color after light has been scattered/absorbed.");
+       RNA_def_property_update(prop, NC_TEXTURE, NULL);
+       
        prop= RNA_def_property(srna, "density_factor", PROP_FLOAT, PROP_NONE);
        RNA_def_property_float_sdna(prop, NULL, "varfac");
        RNA_def_property_ui_range(prop, 0, 1, 10, 3);
        prop= RNA_def_property(srna, "density_factor", PROP_FLOAT, PROP_NONE);
        RNA_def_property_float_sdna(prop, NULL, "varfac");
        RNA_def_property_ui_range(prop, 0, 1, 10, 3);
@@ -589,16 +600,16 @@ static void rna_def_material_mtex(BlenderRNA *brna)
        RNA_def_property_ui_text(prop, "Emission Factor", "Amount texture affects emission.");
        RNA_def_property_update(prop, 0, "rna_Material_update");
        
        RNA_def_property_ui_text(prop, "Emission Factor", "Amount texture affects emission.");
        RNA_def_property_update(prop, 0, "rna_Material_update");
        
-       prop= RNA_def_property(srna, "absorption_factor", PROP_FLOAT, PROP_NONE);
+       prop= RNA_def_property(srna, "scattering_factor", PROP_FLOAT, PROP_NONE);
        RNA_def_property_float_sdna(prop, NULL, "varfac");
        RNA_def_property_ui_range(prop, 0, 1, 10, 3);
        RNA_def_property_float_sdna(prop, NULL, "varfac");
        RNA_def_property_ui_range(prop, 0, 1, 10, 3);
-       RNA_def_property_ui_text(prop, "Absorption Factor", "Amount texture affects absorption.");
+       RNA_def_property_ui_text(prop, "Scattering Factor", "Amount texture affects scattering.");
        RNA_def_property_update(prop, 0, "rna_Material_update");
        RNA_def_property_update(prop, 0, "rna_Material_update");
-       
-       prop= RNA_def_property(srna, "scattering_factor", PROP_FLOAT, PROP_NONE);
+                                                                 
+       prop= RNA_def_property(srna, "reflection_factor", PROP_FLOAT, PROP_NONE);
        RNA_def_property_float_sdna(prop, NULL, "varfac");
        RNA_def_property_ui_range(prop, 0, 1, 10, 3);
        RNA_def_property_float_sdna(prop, NULL, "varfac");
        RNA_def_property_ui_range(prop, 0, 1, 10, 3);
-       RNA_def_property_ui_text(prop, "Scattering Factor", "Amount texture affects scattering.");
+       RNA_def_property_ui_text(prop, "Reflection Factor", "Amount texture affects brightness of out-scattered light.");
        RNA_def_property_update(prop, 0, "rna_Material_update");
        
        /* end volume material */
        RNA_def_property_update(prop, 0, "rna_Material_update");
        
        /* end volume material */
@@ -955,15 +966,6 @@ static void rna_def_material_volume(BlenderRNA *brna)
                //{MA_VOL_STEP_ADAPTIVE, "ADAPTIVE", 0, "Adaptive", ""},
                {0, NULL, 0, NULL, NULL}};
                
                //{MA_VOL_STEP_ADAPTIVE, "ADAPTIVE", 0, "Adaptive", ""},
                {0, NULL, 0, NULL, NULL}};
                
-       static EnumPropertyItem prop_phasefunction_items[] = {
-               {MA_VOL_PH_ISOTROPIC, "ISOTROPIC", 0, "Isotropic", ""},
-               {MA_VOL_PH_MIEHAZY, "MIE_HAZY", 0, "Mie Hazy", ""},
-               {MA_VOL_PH_MIEMURKY, "MIE_MURKY", 0, "Mie Murky", ""},
-               {MA_VOL_PH_RAYLEIGH, "RAYLEIGH", 0, "Rayleigh", ""},
-               {MA_VOL_PH_HG, "HENYEY-GREENSTEIN", 0, "Henyey-Greenstein", ""},
-               {MA_VOL_PH_SCHLICK, "SCHLICK", 0, "Schlick", ""},
-               {0, NULL, 0, NULL, NULL}};
-
        srna= RNA_def_struct(brna, "MaterialVolume", NULL);
        RNA_def_struct_sdna(srna, "VolumeSettings");
        RNA_def_struct_nested(brna, srna, "Material");
        srna= RNA_def_struct(brna, "MaterialVolume", NULL);
        RNA_def_struct_sdna(srna, "VolumeSettings");
        RNA_def_struct_nested(brna, srna, "Material");
@@ -982,13 +984,6 @@ static void rna_def_material_volume(BlenderRNA *brna)
        RNA_def_property_ui_text(prop, "Step Size", "Distance between subsequent volume depth samples.");
        RNA_def_property_update(prop, 0, "rna_Material_update");
        
        RNA_def_property_ui_text(prop, "Step Size", "Distance between subsequent volume depth samples.");
        RNA_def_property_update(prop, 0, "rna_Material_update");
        
-       prop= RNA_def_property(srna, "shading_step_size", PROP_FLOAT, PROP_NONE);
-       RNA_def_property_float_sdna(prop, NULL, "shade_stepsize");
-       RNA_def_property_range(prop, 0.0f, FLT_MAX);
-       RNA_def_property_ui_range(prop, 0.0f, 1.0f, 1, 3);
-       RNA_def_property_ui_text(prop, "Shading Step Size", "Distance between subsequent volume shading samples.");
-       RNA_def_property_update(prop, 0, "rna_Material_update");
-       
        prop= RNA_def_property(srna, "scattering_mode", PROP_ENUM, PROP_NONE);
        RNA_def_property_enum_sdna(prop, NULL, "shade_type");
        RNA_def_property_enum_items(prop, prop_scattering_items);
        prop= RNA_def_property(srna, "scattering_mode", PROP_ENUM, PROP_NONE);
        RNA_def_property_enum_sdna(prop, NULL, "shade_type");
        RNA_def_property_enum_items(prop, prop_scattering_items);
@@ -1043,31 +1038,30 @@ static void rna_def_material_volume(BlenderRNA *brna)
        RNA_def_property_ui_text(prop, "Density Scale", "Multiplier for the material's density");
        RNA_def_property_update(prop, 0, "rna_Material_update");
        
        RNA_def_property_ui_text(prop, "Density Scale", "Multiplier for the material's density");
        RNA_def_property_update(prop, 0, "rna_Material_update");
        
-       prop= RNA_def_property(srna, "absorption", PROP_FLOAT, PROP_NONE);
-       RNA_def_property_float_sdna(prop, NULL, "absorption");
+       prop= RNA_def_property(srna, "scattering", PROP_FLOAT, PROP_NONE);
+       RNA_def_property_float_sdna(prop, NULL, "scattering");
        RNA_def_property_range(prop, 0.0f, FLT_MAX);
        RNA_def_property_range(prop, 0.0f, FLT_MAX);
-       RNA_def_property_ui_range(prop, 0.0f, 10.0f, 13);
-       RNA_def_property_ui_text(prop, "Absorption", "Amount of light that gets absorbed by the volume - higher values mean light travels less distance");
+       RNA_def_property_ui_range(prop, 0.0f, 10.0f, 1 ,3);
+       RNA_def_property_ui_text(prop, "Scattering", "Amount of light that gets scattered out by the volume - the more out-scattering, the shallower the light will penetrate ");
        RNA_def_property_update(prop, 0, "rna_Material_update");
        
        RNA_def_property_update(prop, 0, "rna_Material_update");
        
-       prop= RNA_def_property(srna, "absorption_color", PROP_FLOAT, PROP_COLOR);
-       RNA_def_property_float_sdna(prop, NULL, "absorption_col");
+       prop= RNA_def_property(srna, "transmission_color", PROP_FLOAT, PROP_COLOR);
+       RNA_def_property_float_sdna(prop, NULL, "transmission_col");
        RNA_def_property_array(prop, 3);
        RNA_def_property_array(prop, 3);
-       RNA_def_property_ui_text(prop, "Absorption Color", "");
+       RNA_def_property_ui_text(prop, "Transmission Color", "Result color of the volume, after other light has been scattered/absorbed");
        RNA_def_property_update(prop, 0, "rna_Material_draw_update");
        
        RNA_def_property_update(prop, 0, "rna_Material_draw_update");
        
-       prop= RNA_def_property(srna, "scattering", PROP_FLOAT, PROP_NONE);
-       RNA_def_property_float_sdna(prop, NULL, "scattering");
-       RNA_def_property_range(prop, 0.0f, FLT_MAX);
-       RNA_def_property_ui_range(prop, 0.0f, 10.0f, 1 ,3);
-       RNA_def_property_ui_text(prop, "Scattering", "Amount of light that gets scattered by the volume - values > 1.0 are non-physical");
-       RNA_def_property_update(prop, 0, "rna_Material_update");
+       prop= RNA_def_property(srna, "reflection_color", PROP_FLOAT, PROP_COLOR);
+       RNA_def_property_float_sdna(prop, NULL, "reflection_col");
+       RNA_def_property_array(prop, 3);
+       RNA_def_property_ui_text(prop, "Reflection Color", "Colour of light scattered out of the volume (does not affect transmission)");
+       RNA_def_property_update(prop, NC_MATERIAL|ND_SHADING_DRAW, NULL);
        
        
-       prop= RNA_def_property(srna, "emission", PROP_FLOAT, PROP_NONE);
-       RNA_def_property_float_sdna(prop, NULL, "emission");
+       prop= RNA_def_property(srna, "reflection", PROP_FLOAT, PROP_NONE);
+       RNA_def_property_float_sdna(prop, NULL, "reflection");
        RNA_def_property_range(prop, 0.0f, FLT_MAX);
        RNA_def_property_range(prop, 0.0f, FLT_MAX);
-       RNA_def_property_ui_range(prop, 0.0f, 10.0f, 1, 3);
-       RNA_def_property_ui_text(prop, "Emission", "Amount of light that gets emitted by the volume");
+       RNA_def_property_ui_range(prop, 0.0f, 100.0f, 1 ,3);
+       RNA_def_property_ui_text(prop, "Reflection", "Multiplier to make out-scattered light brighter or darker (non-physically correct)");
        RNA_def_property_update(prop, 0, "rna_Material_update");
        
        prop= RNA_def_property(srna, "emission_color", PROP_FLOAT, PROP_COLOR);
        RNA_def_property_update(prop, 0, "rna_Material_update");
        
        prop= RNA_def_property(srna, "emission_color", PROP_FLOAT, PROP_COLOR);
@@ -1076,16 +1070,17 @@ static void rna_def_material_volume(BlenderRNA *brna)
        RNA_def_property_ui_text(prop, "Emission Color", "");
        RNA_def_property_update(prop, 0, "rna_Material_draw_update");
        
        RNA_def_property_ui_text(prop, "Emission Color", "");
        RNA_def_property_update(prop, 0, "rna_Material_draw_update");
        
-       prop= RNA_def_property(srna, "phase_function", PROP_ENUM, PROP_NONE);
-       RNA_def_property_enum_sdna(prop, NULL, "phasefunc_type");
-       RNA_def_property_enum_items(prop, prop_phasefunction_items);
-       RNA_def_property_ui_text(prop, "Phase Function", "Isotropic/Anisotropic scattering");
+       prop= RNA_def_property(srna, "emission", PROP_FLOAT, PROP_NONE);
+       RNA_def_property_float_sdna(prop, NULL, "emission");
+       RNA_def_property_range(prop, 0.0f, FLT_MAX);
+       RNA_def_property_ui_range(prop, 0.0f, 10.0f, 1, 3);
+       RNA_def_property_ui_text(prop, "Emission", "Amount of light that gets emitted by the volume");
        RNA_def_property_update(prop, 0, "rna_Material_update");
        RNA_def_property_update(prop, 0, "rna_Material_update");
-       
+               
        prop= RNA_def_property(srna, "asymmetry", PROP_FLOAT, PROP_NONE);
        prop= RNA_def_property(srna, "asymmetry", PROP_FLOAT, PROP_NONE);
-       RNA_def_property_float_sdna(prop, NULL, "phasefunc_g");
+       RNA_def_property_float_sdna(prop, NULL, "asymmetry");
        RNA_def_property_range(prop, -1.0f, 1.0f);
        RNA_def_property_range(prop, -1.0f, 1.0f);
-       RNA_def_property_ui_text(prop, "Asymmetry", "Continuum between forward scattering and back scattering");
+       RNA_def_property_ui_text(prop, "Asymmetry", "Back scattering (-1.0) to Forward scattering (1.0) and the range in between.");
        RNA_def_property_update(prop, 0, "rna_Material_update");
 }
 
        RNA_def_property_update(prop, 0, "rna_Material_update");
 }
 
index d63f5823b2ef52670309b718e38f1f61ff04518f..7bc8570ce133f72ef079038ebc579d053642e0e5 100644 (file)
@@ -955,11 +955,11 @@ static void rna_def_texture_image(BlenderRNA *brna)
        PropertyRNA *prop;
 
        static EnumPropertyItem prop_image_extension[] = {
        PropertyRNA *prop;
 
        static EnumPropertyItem prop_image_extension[] = {
-               {1, "EXTEND", 0, "Extend", "Extends by repeating edge pixels of the image"},
-               {2, "CLIP", 0, "Clip", "Clips to image size and sets exterior pixels as transparent"},
-               {4, "CLIP_CUBE", 0, "Clip Cube", "Clips to cubic-shaped area around the image and sets exterior pixels as transparent"},
-               {3, "REPEAT", 0, "Repeat", "Causes the image to repeat horizontally and vertically"},
-               {5, "CHECKER", 0, "Checker", "Causes the image to repeat in checker board pattern"},
+               {TEX_EXTEND, "EXTEND", 0, "Extend", "Extends by repeating edge pixels of the image"},
+               {TEX_CLIP, "CLIP", 0, "Clip", "Clips to image size and sets exterior pixels as transparent"},
+               {TEX_CLIPCUBE, "CLIP_CUBE", 0, "Clip Cube", "Clips to cubic-shaped area around the image and sets exterior pixels as transparent"},
+               {TEX_REPEAT, "REPEAT", 0, "Repeat", "Causes the image to repeat horizontally and vertically"},
+               {TEX_CHECKER, "CHECKER", 0, "Checker", "Causes the image to repeat in checker board pattern"},
                {0, NULL, 0, NULL, NULL}};
 
        srna= RNA_def_struct(brna, "ImageTexture", "Texture");
                {0, NULL, 0, NULL, NULL}};
 
        srna= RNA_def_struct(brna, "ImageTexture", "Texture");
@@ -1016,7 +1016,7 @@ static void rna_def_texture_image(BlenderRNA *brna)
        prop= RNA_def_property(srna, "extension", PROP_ENUM, PROP_NONE);
        RNA_def_property_enum_sdna(prop, NULL, "extend");
        RNA_def_property_enum_items(prop, prop_image_extension);
        prop= RNA_def_property(srna, "extension", PROP_ENUM, PROP_NONE);
        RNA_def_property_enum_sdna(prop, NULL, "extend");
        RNA_def_property_enum_items(prop, prop_image_extension);
-       RNA_def_property_ui_text(prop, "Extension", "Sets how the image is stretched in the texture");
+       RNA_def_property_ui_text(prop, "Extension", "Sets how the image is extrapolated past its original bounds");
        RNA_def_property_update(prop, 0, "rna_Texture_update");
 
        prop= RNA_def_property(srna, "repeat_x", PROP_INT, PROP_NONE);
        RNA_def_property_update(prop, 0, "rna_Texture_update");
 
        prop= RNA_def_property(srna, "repeat_x", PROP_INT, PROP_NONE);
@@ -1562,6 +1562,12 @@ static void rna_def_texture_voxeldata(BlenderRNA *brna)
                {TEX_VD_IMAGE_SEQUENCE, "IMAGE_SEQUENCE", 0, "Image Sequence", "Generate voxels from a sequence of image slices"},
                {TEX_VD_SMOKE, "SMOKE", 0, "Smoke", "Render voxels from a Blender smoke simulation"},
                {0, NULL, 0, NULL, NULL}};
                {TEX_VD_IMAGE_SEQUENCE, "IMAGE_SEQUENCE", 0, "Image Sequence", "Generate voxels from a sequence of image slices"},
                {TEX_VD_SMOKE, "SMOKE", 0, "Smoke", "Render voxels from a Blender smoke simulation"},
                {0, NULL, 0, NULL, NULL}};
+       
+       static EnumPropertyItem voxeldata_extension[] = {
+               {TEX_EXTEND, "EXTEND", 0, "Extend", "Extends by repeating edge pixels of the image"},
+               {TEX_CLIP, "CLIP", 0, "Clip", "Clips to image size and sets exterior pixels as transparent"},
+               {TEX_REPEAT, "REPEAT", 0, "Repeat", "Causes the image to repeat horizontally and vertically"},
+               {0, NULL, 0, NULL, NULL}};
 
        srna= RNA_def_struct(brna, "VoxelData", NULL);
        RNA_def_struct_sdna(srna, "VoxelData");
 
        srna= RNA_def_struct(brna, "VoxelData", NULL);
        RNA_def_struct_sdna(srna, "VoxelData");
@@ -1573,6 +1579,12 @@ static void rna_def_texture_voxeldata(BlenderRNA *brna)
        RNA_def_property_ui_text(prop, "Interpolation", "Method to interpolate/smooth values between voxel cells");
        RNA_def_property_update(prop, 0, "rna_Texture_update");
        
        RNA_def_property_ui_text(prop, "Interpolation", "Method to interpolate/smooth values between voxel cells");
        RNA_def_property_update(prop, 0, "rna_Texture_update");
        
+       prop= RNA_def_property(srna, "extension", PROP_ENUM, PROP_NONE);
+       RNA_def_property_enum_sdna(prop, NULL, "extend");
+       RNA_def_property_enum_items(prop, voxeldata_extension);
+       RNA_def_property_ui_text(prop, "Extension", "Sets how the texture is extrapolated past its original bounds");
+       RNA_def_property_update(prop, 0, "rna_Texture_update");
+       
        prop= RNA_def_property(srna, "intensity", PROP_FLOAT, PROP_NONE);
        RNA_def_property_float_sdna(prop, NULL, "int_multiplier");
        RNA_def_property_range(prop, 0.01, FLT_MAX);
        prop= RNA_def_property(srna, "intensity", PROP_FLOAT, PROP_NONE);
        RNA_def_property_float_sdna(prop, NULL, "int_multiplier");
        RNA_def_property_range(prop, 0.01, FLT_MAX);
index 9d87a219c829f076510999374488a7a83334bd40..368d60ee7f003ba71635c33c653fd6d508b5aade 100644 (file)
@@ -30,4 +30,4 @@ void volume_precache(Render *re);
 void free_volume_precache(Render *re);
 int point_inside_volume_objectinstance(ObjectInstanceRen *obi, float *co);
 
 void free_volume_precache(Render *re);
 int point_inside_volume_objectinstance(ObjectInstanceRen *obi, float *co);
 
-#define VOL_MS_TIMESTEP        0.1f
\ No newline at end of file
+#define VOL_MS_TIMESTEP        0.1f
index 026b4840ea33bb92a46c817573ddf2432b854bbd..97e7e022fa0bb95c3ad43645d57280bf3f1cf503 100644 (file)
@@ -26,9 +26,8 @@
  * ***** END GPL LICENSE BLOCK *****
  */
 
  * ***** END GPL LICENSE BLOCK *****
  */
 
-float vol_get_stepsize(struct ShadeInput *shi, int context);
 float vol_get_density(struct ShadeInput *shi, float *co);
 float vol_get_density(struct ShadeInput *shi, float *co);
-void vol_get_scattering(ShadeInput *shi, float *scatter_col, float *co, float stepsize, float density);
+void vol_get_scattering(ShadeInput *shi, float *scatter_col, float *co_);
 
 void shade_volume_outside(ShadeInput *shi, ShadeResult *shr);
 void shade_volume_inside(ShadeInput *shi, ShadeResult *shr);
 
 void shade_volume_outside(ShadeInput *shi, ShadeResult *shr);
 void shade_volume_inside(ShadeInput *shi, ShadeResult *shr);
index 48a7c003c9f86362d38ba026fcda1c8a503aadef..b3784f260487ab80cebf6a7187c9da7892f3de77 100644 (file)
@@ -889,6 +889,28 @@ static void free_mesh_orco_hash(Render *re)
        }
 }
 
        }
 }
 
+static void check_material_mapto(Material *ma)
+{
+       int a;
+       ma->mapto_textured = 0;
+       
+       /* cache which inputs are actually textured.
+        * this can avoid a bit of time spent iterating through all the texture slots, map inputs and map tos
+        * every time a property which may or may not be textured is accessed */
+       
+       for(a=0; a<MAX_MTEX; a++) {
+               if(ma->mtex[a] && ma->mtex[a]->tex) {
+                       /* currently used only in volume render, so we'll check for those flags */
+                       if(ma->mtex[a]->mapto & MAP_DENSITY) ma->mapto_textured |= MAP_DENSITY;
+                       if(ma->mtex[a]->mapto & MAP_EMISSION) ma->mapto_textured |= MAP_EMISSION;
+                       if(ma->mtex[a]->mapto & MAP_EMISSION_COL) ma->mapto_textured |= MAP_EMISSION_COL;
+                       if(ma->mtex[a]->mapto & MAP_SCATTERING) ma->mapto_textured |= MAP_SCATTERING;
+                       if(ma->mtex[a]->mapto & MAP_TRANSMISSION_COL) ma->mapto_textured |= MAP_TRANSMISSION_COL;
+                       if(ma->mtex[a]->mapto & MAP_REFLECTION) ma->mapto_textured |= MAP_REFLECTION;
+                       if(ma->mtex[a]->mapto & MAP_REFLECTION_COL) ma->mapto_textured |= MAP_REFLECTION_COL;
+               }
+       }
+}
 static void flag_render_node_material(Render *re, bNodeTree *ntree)
 {
        bNode *node;
 static void flag_render_node_material(Render *re, bNodeTree *ntree)
 {
        bNode *node;
@@ -930,6 +952,8 @@ static Material *give_render_material(Render *re, Object *ob, int nr)
        if(ma->nodetree && ma->use_nodes)
                flag_render_node_material(re, ma->nodetree);
        
        if(ma->nodetree && ma->use_nodes)
                flag_render_node_material(re, ma->nodetree);
        
+       check_material_mapto(ma);
+       
        return ma;
 }
 
        return ma;
 }
 
index c1d0c943ca9cfa89b9634304a66a50a70d3312ed..cce99d64b3942f9a79ded9ef933531808c5e2cec 100644 (file)
@@ -1343,7 +1343,8 @@ static void ray_trace_shadow_tra(Isect *is, ShadeInput *origshi, int depth, int
                        /* mix colors based on shadfac (rgb + amount of light factor) */
                        addAlphaLight(is->col, shr.diff, shr.alpha, d*shi.mat->filter);
                } else if (shi.mat->material_type == MA_TYPE_VOLUME) {
                        /* mix colors based on shadfac (rgb + amount of light factor) */
                        addAlphaLight(is->col, shr.diff, shr.alpha, d*shi.mat->filter);
                } else if (shi.mat->material_type == MA_TYPE_VOLUME) {
-                       addAlphaLight(is->col, shr.combined, shr.alpha, 1.0f);
+                       QUATCOPY(is->col, shr.combined);
+                       is->col[3] = 1.f;
                }
                
                if(depth>0 && is->col[3]>0.0f) {
                }
                
                if(depth>0 && is->col[3]>0.0f) {
index 4830dab7d3793bda14a50df85add63b516cd5f24..02b7f6aad86caa4fed8541677e76a05bb7d4ffb0 100644 (file)
@@ -2385,7 +2385,7 @@ void do_volume_tex(ShadeInput *shi, float *xyz, int mapto_flag, float *col, floa
                        }
                        
                        
                        }
                        
                        
-                       if((mapto_flag & (MAP_EMISSION_COL+MAP_ABSORPTION_COL)) && (mtex->mapto & (MAP_EMISSION_COL+MAP_ABSORPTION_COL))) {
+                       if((mapto_flag & (MAP_EMISSION_COL+MAP_TRANSMISSION_COL+MAP_REFLECTION_COL)) && (mtex->mapto & (MAP_EMISSION_COL+MAP_TRANSMISSION_COL+MAP_REFLECTION_COL))) {
                                float tcol[3], colfac;
                                
                                /* stencil maps on the texture control slider, not texture intensity value */
                                float tcol[3], colfac;
                                
                                /* stencil maps on the texture control slider, not texture intensity value */
@@ -2413,8 +2413,11 @@ void do_volume_tex(ShadeInput *shi, float *xyz, int mapto_flag, float *col, floa
                                        texture_rgb_blend(col, tcol, col, texres.tin, colfac, mtex->blendtype);
                                }
                                
                                        texture_rgb_blend(col, tcol, col, texres.tin, colfac, mtex->blendtype);
                                }
                                
-                               /* MAP_COLMIR is abused for absorption colour at the moment */
-                               if((mapto_flag & MAP_ABSORPTION_COL) && (mtex->mapto & MAP_ABSORPTION_COL)) {
+                               if((mapto_flag & MAP_REFLECTION_COL) && (mtex->mapto & MAP_REFLECTION_COL)) {
+                                       texture_rgb_blend(col, tcol, col, texres.tin, colfac, mtex->blendtype);
+                               }
+                               
+                               if((mapto_flag & MAP_TRANSMISSION_COL) && (mtex->mapto & MAP_TRANSMISSION_COL)) {
                                        texture_rgb_blend(col, tcol, col, texres.tin, colfac, mtex->blendtype);
                                }
                        }
                                        texture_rgb_blend(col, tcol, col, texres.tin, colfac, mtex->blendtype);
                                }
                        }
@@ -2443,14 +2446,14 @@ void do_volume_tex(ShadeInput *shi, float *xyz, int mapto_flag, float *col, floa
                                        *val = texture_value_blend(mtex->def_var, *val, texres.tin, varfac, mtex->blendtype, flip);
                                        CLAMP(*val, 0.0, 1.0);
                                }
                                        *val = texture_value_blend(mtex->def_var, *val, texres.tin, varfac, mtex->blendtype, flip);
                                        CLAMP(*val, 0.0, 1.0);
                                }
-                               if((mapto_flag & MAP_ABSORPTION) && (mtex->mapto & MAP_ABSORPTION)) {
-                                       int flip= mtex->maptoneg & MAP_ABSORPTION;
+                               if((mapto_flag & MAP_SCATTERING) && (mtex->mapto & MAP_SCATTERING)) {
+                                       int flip= mtex->maptoneg & MAP_SCATTERING;
                                        
                                        *val = texture_value_blend(mtex->def_var, *val, texres.tin, varfac, mtex->blendtype, flip);
                                        CLAMP(*val, 0.0, 1.0);
                                }
                                        
                                        *val = texture_value_blend(mtex->def_var, *val, texres.tin, varfac, mtex->blendtype, flip);
                                        CLAMP(*val, 0.0, 1.0);
                                }
-                               if((mapto_flag & MAP_SCATTERING) && (mtex->mapto & MAP_SCATTERING)) {
-                                       int flip= mtex->maptoneg & MAP_SCATTERING;
+                               if((mapto_flag & MAP_REFLECTION) && (mtex->mapto & MAP_REFLECTION)) {
+                                       int flip= mtex->maptoneg & MAP_REFLECTION;
                                        
                                        *val = texture_value_blend(mtex->def_var, *val, texres.tin, varfac, mtex->blendtype, flip);
                                        CLAMP(*val, 0.0, 1.0);
                                        
                                        *val = texture_value_blend(mtex->def_var, *val, texres.tin, varfac, mtex->blendtype, flip);
                                        CLAMP(*val, 0.0, 1.0);
index 15d8643fea441ffa8ee77e8c7ad939cdeb1cb4dd..7ecaf83ae27eda97933b4abe5c19f6117f3cf0a5 100644 (file)
@@ -185,9 +185,9 @@ static float get_avg_surrounds(float *cache, int *res, int xx, int yy, int zz)
                }
        }
        
                }
        }
        
-       tot /= added;
+       if (added > 0) tot /= added;
        
        
-       return ((added>0)?tot:0.0f);
+       return tot;
 }
 
 /* function to filter the edges of the light cache, where there was no volume originally.
 }
 
 /* function to filter the edges of the light cache, where there was no volume originally.
@@ -202,17 +202,54 @@ static void lightcache_filter(VolumePrecache *vp)
                for (y=0; y < vp->res[1]; y++) {
                        for (x=0; x < vp->res[0]; x++) {
                                /* trigger for outside mesh */
                for (y=0; y < vp->res[1]; y++) {
                        for (x=0; x < vp->res[0]; x++) {
                                /* trigger for outside mesh */
-                               if (vp->data_r[ V_I(x, y, z, vp->res) ] < -0.5f)
+                               if (vp->data_r[ V_I(x, y, z, vp->res) ] < -0.f)
                                        vp->data_r[ V_I(x, y, z, vp->res) ] = get_avg_surrounds(vp->data_r, vp->res, x, y, z);
                                        vp->data_r[ V_I(x, y, z, vp->res) ] = get_avg_surrounds(vp->data_r, vp->res, x, y, z);
-                               if (vp->data_g[ V_I(x, y, z, vp->res) ] < -0.5f)
+                               if (vp->data_g[ V_I(x, y, z, vp->res) ] < -0.f)
                                        vp->data_g[ V_I(x, y, z, vp->res) ] = get_avg_surrounds(vp->data_g, vp->res, x, y, z);
                                        vp->data_g[ V_I(x, y, z, vp->res) ] = get_avg_surrounds(vp->data_g, vp->res, x, y, z);
-                               if (vp->data_b[ V_I(x, y, z, vp->res) ] < -0.5f)
+                               if (vp->data_b[ V_I(x, y, z, vp->res) ] < -0.f)
                                        vp->data_b[ V_I(x, y, z, vp->res) ] = get_avg_surrounds(vp->data_b, vp->res, x, y, z);
                        }
                }
        }
 }
 
                                        vp->data_b[ V_I(x, y, z, vp->res) ] = get_avg_surrounds(vp->data_b, vp->res, x, y, z);
                        }
                }
        }
 }
 
+static void lightcache_filter2(VolumePrecache *vp)
+{
+       int x, y, z;
+       float *new_r, *new_g, *new_b;
+       int field_size = vp->res[0]*vp->res[1]*vp->res[2]*sizeof(float);
+       
+       new_r = MEM_mallocN(field_size, "temp buffer for light cache filter r channel");
+       new_g = MEM_mallocN(field_size, "temp buffer for light cache filter g channel");
+       new_b = MEM_mallocN(field_size, "temp buffer for light cache filter b channel");
+       
+       memcpy(new_r, vp->data_r, field_size);
+       memcpy(new_g, vp->data_g, field_size);
+       memcpy(new_b, vp->data_b, field_size);
+       
+       for (z=0; z < vp->res[2]; z++) {
+               for (y=0; y < vp->res[1]; y++) {
+                       for (x=0; x < vp->res[0]; x++) {
+                               /* trigger for outside mesh */
+                               if (vp->data_r[ V_I(x, y, z, vp->res) ] < -0.f)
+                                       new_r[ V_I(x, y, z, vp->res) ] = get_avg_surrounds(vp->data_r, vp->res, x, y, z);
+                               if (vp->data_g[ V_I(x, y, z, vp->res) ] < -0.f)
+                                       new_g[ V_I(x, y, z, vp->res) ] = get_avg_surrounds(vp->data_g, vp->res, x, y, z);
+                               if (vp->data_b[ V_I(x, y, z, vp->res) ] < -0.f)
+                                       new_b[ V_I(x, y, z, vp->res) ] = get_avg_surrounds(vp->data_b, vp->res, x, y, z);
+                       }
+               }
+       }
+       
+       SWAP(float *, vp->data_r, new_r);
+       SWAP(float *, vp->data_g, new_g);
+       SWAP(float *, vp->data_b, new_b);
+       
+       if (new_r) { MEM_freeN(new_r); new_r=NULL; }
+       if (new_g) { MEM_freeN(new_g); new_g=NULL; }
+       if (new_b) { MEM_freeN(new_b); new_b=NULL; }
+}
+
 static inline int ms_I(int x, int y, int z, int *n) //has a pad of 1 voxel surrounding the core for boundary simulation
 { 
        return z*(n[1]+2)*(n[0]+2) + y*(n[0]+2) + x;
 static inline int ms_I(int x, int y, int z, int *n) //has a pad of 1 voxel surrounding the core for boundary simulation
 { 
        return z*(n[1]+2)*(n[0]+2) + y*(n[0]+2) + x;
@@ -423,11 +460,10 @@ static void *vol_precache_part(void *data)
        ObjectInstanceRen *obi = pa->obi;
        RayTree *tree = pa->tree;
        ShadeInput *shi = pa->shi;
        ObjectInstanceRen *obi = pa->obi;
        RayTree *tree = pa->tree;
        ShadeInput *shi = pa->shi;
-       float density, scatter_col[3] = {0.f, 0.f, 0.f};
+       float scatter_col[3] = {0.f, 0.f, 0.f};
        float co[3];
        int x, y, z;
        const int res[3]= {pa->res[0], pa->res[1], pa->res[2]};
        float co[3];
        int x, y, z;
        const int res[3]= {pa->res[0], pa->res[1], pa->res[2]};
-       const float stepsize = vol_get_stepsize(shi, STEPSIZE_VIEW);
 
        for (z= pa->minz; z < pa->maxz; z++) {
                co[2] = pa->bbmin[2] + (pa->voxel[2] * (z + 0.5f));
 
        for (z= pa->minz; z < pa->maxz; z++) {
                co[2] = pa->bbmin[2] + (pa->voxel[2] * (z + 0.5f));
@@ -448,8 +484,7 @@ static void *vol_precache_part(void *data)
                                
                                VecCopyf(shi->view, co);
                                Normalize(shi->view);
                                
                                VecCopyf(shi->view, co);
                                Normalize(shi->view);
-                               density = vol_get_density(shi, co);
-                               vol_get_scattering(shi, scatter_col, co, stepsize, density);
+                               vol_get_scattering(shi, scatter_col, co);
                        
                                obi->volume_precache->data_r[ V_I(x, y, z, res) ] = scatter_col[0];
                                obi->volume_precache->data_g[ V_I(x, y, z, res) ] = scatter_col[1];
                        
                                obi->volume_precache->data_r[ V_I(x, y, z, res) ] = scatter_col[0];
                                obi->volume_precache->data_g[ V_I(x, y, z, res) ] = scatter_col[1];
index b2692c25b996b213285e3468835eede3bb488b0f..381a32de02795d57d294565be2a44e631e5747e4 100644 (file)
@@ -170,29 +170,6 @@ static void vol_trace_behind(ShadeInput *shi, VlakRen *vlr, float *co, float *co
        }
 }
 
        }
 }
 
-/* input shader data */
-
-float vol_get_stepsize(struct ShadeInput *shi, int context)
-{
-       if (shi->mat->vol.stepsize_type == MA_VOL_STEP_RANDOMIZED) {
-               /* range between 0.75 and 1.25 */
-               const float rnd = 0.5f * BLI_thread_frand(shi->thread) + 0.75f;
-       
-               if (context == STEPSIZE_VIEW)
-                       return shi->mat->vol.stepsize * rnd;
-               else if (context == STEPSIZE_SHADE)
-                       return shi->mat->vol.shade_stepsize * rnd;
-       }
-       else {  // MA_VOL_STEP_CONSTANT
-               
-               if (context == STEPSIZE_VIEW)
-                       return shi->mat->vol.stepsize;
-               else if (context == STEPSIZE_SHADE)
-                       return shi->mat->vol.shade_stepsize;
-       }
-       
-       return shi->mat->vol.stepsize;
-}
 
 /* trilinear interpolation */
 static void vol_get_precached_scattering(ShadeInput *shi, float *scatter_col, float *co)
 
 /* trilinear interpolation */
 static void vol_get_precached_scattering(ShadeInput *shi, float *scatter_col, float *co)
@@ -212,9 +189,9 @@ static void vol_get_precached_scattering(ShadeInput *shi, float *scatter_col, fl
        sample_co[1] = ((co[1] - bbmin[1]) / dim[1]);
        sample_co[2] = ((co[2] - bbmin[2]) / dim[2]);
 
        sample_co[1] = ((co[1] - bbmin[1]) / dim[1]);
        sample_co[2] = ((co[2] - bbmin[2]) / dim[2]);
 
-       scatter_col[0] = voxel_sample_trilinear(vp->data_r, vp->res, sample_co);
-       scatter_col[1] = voxel_sample_trilinear(vp->data_g, vp->res, sample_co);
-       scatter_col[2] = voxel_sample_trilinear(vp->data_b, vp->res, sample_co);
+       scatter_col[0] = voxel_sample_triquadratic(vp->data_r, vp->res, sample_co);
+       scatter_col[1] = voxel_sample_triquadratic(vp->data_g, vp->res, sample_co);
+       scatter_col[2] = voxel_sample_triquadratic(vp->data_b, vp->res, sample_co);
 }
 
 /* Meta object density, brute force for now 
 }
 
 /* Meta object density, brute force for now 
@@ -270,7 +247,8 @@ float vol_get_density(struct ShadeInput *shi, float *co)
        float density = shi->mat->vol.density;
        float density_scale = shi->mat->vol.density_scale;
                
        float density = shi->mat->vol.density;
        float density_scale = shi->mat->vol.density_scale;
                
-       do_volume_tex(shi, co, MAP_DENSITY, NULL, &density);
+       if (shi->mat->mapto_textured & MAP_DENSITY)
+               do_volume_tex(shi, co, MAP_DENSITY, NULL, &density);
        
        // if meta-object, modulate by metadensity without increasing it
        if (shi->obi->obr->ob->type == OB_MBALL) {
        
        // if meta-object, modulate by metadensity without increasing it
        if (shi->obi->obr->ob->type == OB_MBALL) {
@@ -281,79 +259,110 @@ float vol_get_density(struct ShadeInput *shi, float *co)
        return density * density_scale;
 }
 
        return density * density_scale;
 }
 
-/* scattering multiplier, values above 1.0 are non-physical, 
- * but can be useful to tweak lighting */
-float vol_get_scattering_fac(ShadeInput *shi, float *co)
+
+/* Color of light that gets scattered out by the volume */
+/* Uses same physically based scattering parameter as in transmission calculations, 
+ * along with artificial reflection scale/reflection color tint */
+void vol_get_reflection_color(ShadeInput *shi, float *ref_col, float *co)
 {
        float scatter = shi->mat->vol.scattering;
 {
        float scatter = shi->mat->vol.scattering;
-       float col[3] = {0.0, 0.0, 0.0};
+       float reflection= shi->mat->vol.reflection;
+       VECCOPY(ref_col, shi->mat->vol.reflection_col);
+       
+       if (shi->mat->mapto_textured & (MAP_SCATTERING+MAP_REFLECTION_COL))
+               do_volume_tex(shi, co, MAP_SCATTERING+MAP_REFLECTION_COL, ref_col, &scatter);
        
        
-       do_volume_tex(shi, co, MAP_SCATTERING, col, &scatter);
+       /* only one single float parameter at a time... :s */
+       if (shi->mat->mapto_textured & (MAP_REFLECTION))
+               do_volume_tex(shi, co, MAP_REFLECTION, NULL, &reflection);
        
        
-       return scatter;
+       ref_col[0] = reflection * ref_col[0] * scatter;
+       ref_col[1] = reflection * ref_col[1] * scatter;
+       ref_col[2] = reflection * ref_col[2] * scatter;
 }
 
 /* compute emission component, amount of radiance to add per segment
  * can be textured with 'emit' */
 }
 
 /* compute emission component, amount of radiance to add per segment
  * can be textured with 'emit' */
-void vol_get_emission(ShadeInput *shi, float *emission_col, float *co, float density)
+void vol_get_emission(ShadeInput *shi, float *emission_col, float *co)
 {
        float emission = shi->mat->vol.emission;
        VECCOPY(emission_col, shi->mat->vol.emission_col);
        
 {
        float emission = shi->mat->vol.emission;
        VECCOPY(emission_col, shi->mat->vol.emission_col);
        
-       do_volume_tex(shi, co, MAP_EMISSION+MAP_EMISSION_COL, emission_col, &emission);
+       if (shi->mat->mapto_textured & (MAP_EMISSION+MAP_EMISSION_COL))
+               do_volume_tex(shi, co, MAP_EMISSION+MAP_EMISSION_COL, emission_col, &emission);
        
        
-       emission_col[0] = emission_col[0] * emission * density;
-       emission_col[1] = emission_col[1] * emission * density;
-       emission_col[2] = emission_col[2] * emission * density;
+       emission_col[0] = emission_col[0] * emission;
+       emission_col[1] = emission_col[1] * emission;
+       emission_col[2] = emission_col[2] * emission;
 }
 
 }
 
-void vol_get_absorption(ShadeInput *shi, float *absorb_col, float *co)
+
+/* A combination of scattering and absorption -> known as sigma T.
+ * This can possibly use a specific scattering colour, 
+ * and absorption multiplier factor too, but these parameters are left out for simplicity.
+ * It's easy enough to get a good wide range of results with just these two parameters. */
+void vol_get_sigma_t(ShadeInput *shi, float *sigma_t, float *co)
 {
 {
-       float absorption = shi->mat->vol.absorption;
-       VECCOPY(absorb_col, shi->mat->vol.absorption_col);
+       /* technically absorption, but named transmission color 
+        * since it describes the effect of the coloring *after* absorption */
+       float transmission_col[3] = {shi->mat->vol.transmission_col[0], shi->mat->vol.transmission_col[1], shi->mat->vol.transmission_col[2]};
+       float scattering = shi->mat->vol.scattering;
        
        
-       do_volume_tex(shi, co, MAP_ABSORPTION+MAP_ABSORPTION_COL, absorb_col, &absorption);
+       if (shi->mat->mapto_textured & (MAP_SCATTERING+MAP_TRANSMISSION_COL))
+               do_volume_tex(shi, co, MAP_SCATTERING+MAP_TRANSMISSION_COL, transmission_col, &scattering);
        
        
-       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;
+       sigma_t[0] = (1.0f - transmission_col[0]) + scattering;
+       sigma_t[1] = (1.0f - transmission_col[1]) + scattering;
+       sigma_t[2] = (1.0f - transmission_col[2]) + scattering;
 }
 
 /* phase function - determines in which directions the light 
  * is scattered in the volume relative to incoming direction 
  * and view direction */
 }
 
 /* phase function - determines in which directions the light 
  * is scattered in the volume relative to incoming direction 
  * and view direction */
-float vol_get_phasefunc(ShadeInput *shi, short phasefunc_type, float g, float *w, float *wp)
+float vol_get_phasefunc(ShadeInput *shi, float g, float *w, float *wp)
 {
 {
-       const float costheta = Inpf(w, wp);
-       const float scale = M_PI;
-       
-       /*
-        * Scale constant is required, since Blender's shading system doesn't normalise for
-        * energy conservation - eg. scaling by 1/pi for a lambert shader.
-        * This makes volumes darker than other solid objects, for the same lighting intensity.
-        * To correct this, scale up the phase function values
+       const float normalize = 0.25f; // = 1.f/4.f = M_PI/(4.f*M_PI)
+       
+       /* normalization constant is 1/4 rather than 1/4pi, since
+        * Blender's shading system doesn't normalise for
+        * energy conservation - eg. multiplying by pdf ( 1/pi for a lambert brdf ).
+        * This means that lambert surfaces in Blender are pi times brighter than they 'should be'
+        * and therefore, with correct energy conservation, volumes will darker than other solid objects,
+        * for the same lighting intensity.
+        * To correct this, scale up the phase function values by pi
         * until Blender's shading system supports this better. --matt
         */
        
         * until Blender's shading system supports this better. --matt
         */
        
+       if (g == 0.f) { /* isotropic */
+               return normalize * 1.f;
+       } else {                /* schlick */
+               const float k = 1.55f * g - .55f * g * g * g;
+               const float kcostheta = k * Inpf(w, wp);
+               return normalize * (1.f - k*k) / ((1.f - kcostheta) * (1.f - kcostheta));
+       }
+       
+       /*
+        * not used, but here for reference:
        switch (phasefunc_type) {
                case MA_VOL_PH_MIEHAZY:
        switch (phasefunc_type) {
                case MA_VOL_PH_MIEHAZY:
-                       return scale * (0.5f + 4.5f * powf(0.5 * (1.f + costheta), 8.f)) / (4.f*M_PI);
+                       return normalize * (0.5f + 4.5f * powf(0.5 * (1.f + costheta), 8.f));
                case MA_VOL_PH_MIEMURKY:
                case MA_VOL_PH_MIEMURKY:
-                       return scale * (0.5f + 16.5f * powf(0.5 * (1.f + costheta), 32.f)) / (4.f*M_PI);
+                       return normalize * (0.5f + 16.5f * powf(0.5 * (1.f + costheta), 32.f));
                case MA_VOL_PH_RAYLEIGH:
                case MA_VOL_PH_RAYLEIGH:
-                       return scale * 3.f/(16.f*M_PI) * (1 + costheta * costheta);
+                       return normalize * 3.f/4.f * (1 + costheta * costheta);
                case MA_VOL_PH_HG:
                case MA_VOL_PH_HG:
-                       return scale * (1.f / (4.f * M_PI) * (1.f - g*g) / powf(1.f + g*g - 2.f * g * costheta, 1.5f));
+                       return normalize * (1.f - g*g) / powf(1.f + g*g - 2.f * g * costheta, 1.5f));
                case MA_VOL_PH_SCHLICK:
                {
                        const float k = 1.55f * g - .55f * g * g * g;
                        const float kcostheta = k * costheta;
                case MA_VOL_PH_SCHLICK:
                {
                        const float k = 1.55f * g - .55f * g * g * g;
                        const float kcostheta = k * costheta;
-                       return scale * (1.f / (4.f * M_PI) * (1.f - k*k) / ((1.f - kcostheta) * (1.f - kcostheta)));
+                       return normalize * (1.f - k*k) / ((1.f - kcostheta) * (1.f - kcostheta));
                }
                case MA_VOL_PH_ISOTROPIC:
                default:
                }
                case MA_VOL_PH_ISOTROPIC:
                default:
-                       return scale * (1.f / (4.f * M_PI));
+                       return normalize * 1.f;
        }
        }
+       */
 }
 
 /* Compute transmittance = e^(-attenuation) */
 }
 
 /* Compute transmittance = e^(-attenuation) */
@@ -361,15 +370,15 @@ void vol_get_transmittance_seg(ShadeInput *shi, float *tr, float stepsize, float
 {
        /* input density = density at co */
        float tau[3] = {0.f, 0.f, 0.f};
 {
        /* input density = density at co */
        float tau[3] = {0.f, 0.f, 0.f};
-       float absorb[3];
-       const float scatter_dens = vol_get_scattering_fac(shi, co) * density * stepsize;
-
-       vol_get_absorption(shi, absorb, co);
+       const float stepd = density * stepsize;
+       float sigma_t[3];
+       
+       vol_get_sigma_t(shi, sigma_t, co);
        
        /* homogenous volume within the sampled distance */
        
        /* homogenous volume within the sampled distance */
-       tau[0] += scatter_dens * absorb[0];
-       tau[1] += scatter_dens * absorb[1];
-       tau[2] += scatter_dens * absorb[2];
+       tau[0] += stepd * sigma_t[0];
+       tau[1] += stepd * sigma_t[1];
+       tau[2] += stepd * sigma_t[2];
        
        tr[0] *= exp(-tau[0]);
        tr[1] *= exp(-tau[1]);
        
        tr[0] *= exp(-tau[0]);
        tr[1] *= exp(-tau[1]);
@@ -381,31 +390,29 @@ static void vol_get_transmittance(ShadeInput *shi, float *tr, float *co, float *
 {
        float p[3] = {co[0], co[1], co[2]};
        float step_vec[3] = {endco[0] - co[0], endco[1] - co[1], endco[2] - co[2]};
 {
        float p[3] = {co[0], co[1], co[2]};
        float step_vec[3] = {endco[0] - co[0], endco[1] - co[1], endco[2] - co[2]};
-       //const float ambtau = -logf(shi->mat->vol.depth_cutoff);       // never zero
        float tau[3] = {0.f, 0.f, 0.f};
 
        float t0 = 0.f;
        float t1 = Normalize(step_vec);
        float pt0 = t0;
        
        float tau[3] = {0.f, 0.f, 0.f};
 
        float t0 = 0.f;
        float t1 = Normalize(step_vec);
        float pt0 = t0;
        
-       t0 += shi->mat->vol.shade_stepsize * ((shi->mat->vol.stepsize_type == MA_VOL_STEP_CONSTANT) ? 0.5f : BLI_thread_frand(shi->thread));
+       t0 += shi->mat->vol.stepsize * ((shi->mat->vol.stepsize_type == MA_VOL_STEP_CONSTANT) ? 0.5f : BLI_thread_frand(shi->thread));
        p[0] += t0 * step_vec[0];
        p[1] += t0 * step_vec[1];
        p[2] += t0 * step_vec[2];
        p[0] += t0 * step_vec[0];
        p[1] += t0 * step_vec[1];
        p[2] += t0 * step_vec[2];
-       VecMulf(step_vec, shi->mat->vol.shade_stepsize);
+       VecMulf(step_vec, shi->mat->vol.stepsize);
 
 
-       for (; t0 < t1; pt0 = t0, t0 += shi->mat->vol.shade_stepsize) {
-               float absorb[3];
+       for (; t0 < t1; pt0 = t0, t0 += shi->mat->vol.stepsize) {
                const float d = vol_get_density(shi, p);
                const float stepd = (t0 - pt0) * d;
                const float d = vol_get_density(shi, p);
                const float stepd = (t0 - pt0) * d;
-               const float scatter_dens = vol_get_scattering_fac(shi, p) * stepd;
-               vol_get_absorption(shi, absorb, p);
+               float sigma_t[3];
+               
+               vol_get_sigma_t(shi, sigma_t, co);
                
                
-               tau[0] += scatter_dens * absorb[0];
-               tau[1] += scatter_dens * absorb[1];
-               tau[2] += scatter_dens * absorb[2];
+               tau[0] += stepd * sigma_t[0];
+               tau[1] += stepd * sigma_t[1];
+               tau[2] += stepd * sigma_t[2];
                
                
-               //if (luminance(tau) >= ambtau) break;
                VecAddf(p, p, step_vec);
        }
        
                VecAddf(p, p, step_vec);
        }
        
@@ -420,8 +427,7 @@ void vol_shade_one_lamp(struct ShadeInput *shi, float *co, LampRen *lar, float *
        float visifac, lv[3], lampdist;
        float tr[3]={1.0,1.0,1.0};
        float hitco[3], *atten_co;
        float visifac, lv[3], lampdist;
        float tr[3]={1.0,1.0,1.0};
        float hitco[3], *atten_co;
-       float p;
-       float scatter_fac;
+       float p, ref_col[3];
        
        if (lar->mode & LA_LAYER) if((lar->lay & shi->obi->lay)==0) return;
        if ((lar->lay & shi->lay)==0) return;
        
        if (lar->mode & LA_LAYER) if((lar->lay & shi->obi->lay)==0) return;
        if ((lar->lay & shi->lay)==0) return;
@@ -475,15 +481,20 @@ void vol_shade_one_lamp(struct ShadeInput *shi, float *co, LampRen *lar, float *
                }
        }
        
                }
        }
        
-       p = vol_get_phasefunc(shi, shi->mat->vol.phasefunc_type, shi->mat->vol.phasefunc_g, shi->view, lv);
-       VecMulf(lacol, p);
+       if (luminance(lacol) < 0.001f) return;
+       
+       p = vol_get_phasefunc(shi, shi->mat->vol.asymmetry, shi->view, lv);
+       
+       /* physically based scattering with non-physically based RGB gain */
+       vol_get_reflection_color(shi, ref_col, co);
        
        
-       scatter_fac = vol_get_scattering_fac(shi, co);
-       VecMulf(lacol, scatter_fac);
+       lacol[0] *= p * ref_col[0];
+       lacol[1] *= p * ref_col[1];
+       lacol[2] *= p * ref_col[2];
 }
 
 /* single scattering only for now */
 }
 
 /* single scattering only for now */
-void vol_get_scattering(ShadeInput *shi, float *scatter_col, float *co, float stepsize, float density)
+void vol_get_scattering(ShadeInput *shi, float *scatter_col, float *co)
 {
        ListBase *lights;
        GroupObject *go;
 {
        ListBase *lights;
        GroupObject *go;
@@ -515,71 +526,69 @@ outgoing radiance from behind surface * beam transmittance/attenuation
        --> radiance for each segment = 
                (radiance added by scattering + radiance added by emission) * beam transmittance/attenuation
 */
        --> radiance for each segment = 
                (radiance added by scattering + radiance added by emission) * beam transmittance/attenuation
 */
+
+/* For ease of use, I've also introduced a 'reflection' and 'reflection color' parameter, which isn't 
+ * physically correct. This works as an RGB tint/gain on out-scattered light, but doesn't affect the light 
+ * that is transmitted through the volume. While having wavelength dependent absorption/scattering is more correct,
+ * it also makes it harder to control the overall look of the volume since colouring the outscattered light results
+ * in the inverse colour being transmitted through the rest of the volume.
+ */
 static void volumeintegrate(struct ShadeInput *shi, float *col, float *co, float *endco)
 {
 static void volumeintegrate(struct ShadeInput *shi, float *col, float *co, float *endco)
 {
-       float tr[3] = {1.0f, 1.0f, 1.0f};
-       float radiance[3] = {0.f, 0.f, 0.f}, d_radiance[3] = {0.f, 0.f, 0.f};
-       float stepsize = vol_get_stepsize(shi, STEPSIZE_VIEW);
-       int nsteps, s;
-       float emit_col[3], scatter_col[3] = {0.0, 0.0, 0.0};
-       float stepvec[3], step_sta[3], step_end[3], step_mid[3];
-       float density;
-       const float depth_cutoff = shi->mat->vol.depth_cutoff;
-
-       /* ray marching */
-       nsteps = (int)((VecLenf(co, endco) / stepsize) + 0.5);
-       
-       VecSubf(stepvec, endco, co);
-       VecMulf(stepvec, 1.0f / nsteps);
-       VecCopyf(step_sta, co);
-       VecAddf(step_end, step_sta, stepvec);
-       
-       /* get radiance from all points along the ray due to participating media */
-       for (s = 0; s < nsteps; s++) {
-
-               density = vol_get_density(shi, step_sta);
+       float radiance[3] = {0.f, 0.f, 0.f};
+       float tr[3] = {1.f, 1.f, 1.f};
+       float p[3] = {co[0], co[1], co[2]};
+       float step_vec[3] = {endco[0] - co[0], endco[1] - co[1], endco[2] - co[2]};
+       const float stepsize = shi->mat->vol.stepsize;
+       
+       float t0 = 0.f;
+       float pt0 = t0;
+       float t1 = Normalize(step_vec); /* returns vector length */
+       
+       t0 += stepsize * ((shi->mat->vol.stepsize_type == MA_VOL_STEP_CONSTANT) ? 0.5f : BLI_thread_frand(shi->thread));
+       p[0] += t0 * step_vec[0];
+       p[1] += t0 * step_vec[1];
+       p[2] += t0 * step_vec[2];
+       VecMulf(step_vec, stepsize);
+       
+       for (; t0 < t1; pt0 = t0, t0 += stepsize) {
+               const float density = vol_get_density(shi, p);
                
                
-               /* there's only any use in shading here if there's actually some density to shade! */
                if (density > 0.01f) {
                if (density > 0.01f) {
-               
+                       float scatter_col[3], emit_col[3];
+                       const float stepd = (t0 - pt0) * density;
+                       
                        /* transmittance component (alpha) */
                        vol_get_transmittance_seg(shi, tr, stepsize, co, density);
                        /* transmittance component (alpha) */
                        vol_get_transmittance_seg(shi, tr, stepsize, co, density);
-
-                       step_mid[0] = step_sta[0] + (stepvec[0] * 0.5);
-                       step_mid[1] = step_sta[1] + (stepvec[1] * 0.5);
-                       step_mid[2] = step_sta[2] + (stepvec[2] * 0.5);
-               
-                       /* incoming light via emission or scattering (additive) */
-                       vol_get_emission(shi, emit_col, step_mid, density);
                        
                        
-                       if (shi->obi->volume_precache)
-                               vol_get_precached_scattering(shi, scatter_col, step_mid);
-                       else
-                               vol_get_scattering(shi, scatter_col, step_mid, stepsize, density);
+                       if (luminance(tr) < shi->mat->vol.depth_cutoff) break;
                        
                        
-                       VecMulf(scatter_col, density);
-                       VecAddf(d_radiance, emit_col, scatter_col);
+                       vol_get_emission(shi, emit_col, p);
                        
                        
-                       /*   Lv += Tr * (Lve() + Ld) */
-                       VecMulVecf(d_radiance, tr, d_radiance);
-                       VecMulf(d_radiance, stepsize);
+                       if (shi->obi->volume_precache) {
+                               float p2[3];
+                               
+                               p2[0] = p[0] + (step_vec[0] * 0.5);
+                               p2[1] = p[1] + (step_vec[1] * 0.5);
+                               p2[2] = p[2] + (step_vec[2] * 0.5);
+                               
+                               vol_get_precached_scattering(shi, scatter_col, p2);
+                       } else
+                               vol_get_scattering(shi, scatter_col, p);
                        
                        
-                       VecAddf(radiance, radiance, d_radiance);        
+                       radiance[0] += stepd * tr[0] * (emit_col[0] + scatter_col[0]);
+                       radiance[1] += stepd * tr[1] * (emit_col[1] + scatter_col[1]);
+                       radiance[2] += stepd * tr[2] * (emit_col[2] + scatter_col[2]);
                }
                }
-
-               VecCopyf(step_sta, step_end);
-               VecAddf(step_end, step_end, stepvec);
-               
-               /* luminance rec. 709 */
-               if ((0.2126*tr[0] + 0.7152*tr[1] + 0.0722*tr[2]) < depth_cutoff) break; 
+               VecAddf(p, p, step_vec);
        }
        
        }
        
-       /* multiply original color (behind volume) with beam transmittance over entire distance */
-       VecMulVecf(col, tr, col);       
+       /* multiply original color (from behind volume) with transmittance over entire distance */
+       VecMulVecf(col, tr, col);
        VecAddf(col, col, radiance);
        
        /* alpha <-- transmission luminance */
        VecAddf(col, col, radiance);
        
        /* alpha <-- transmission luminance */
-       col[3] = 1.0f -(0.2126*tr[0] + 0.7152*tr[1] + 0.0722*tr[2]);
+       col[3] = 1.0f - luminance(tr);
 }
 
 /* the main entry point for volume shading */
 }
 
 /* the main entry point for volume shading */
@@ -606,7 +615,7 @@ static void volume_trace(struct ShadeInput *shi, struct ShadeResult *shr, int in
                /* don't render the backfaces of ztransp volume materials.
                 
                 * volume shading renders the internal volume from between the
                /* don't render the backfaces of ztransp volume materials.
                 
                 * volume shading renders the internal volume from between the
-                * near view intersection of the solid volume to the
+                * ' view intersection of the solid volume to the
                 * intersection on the other side, as part of the shading of
                 * the front face.
                 
                 * intersection on the other side, as part of the shading of
                 * the front face.
                 
@@ -709,8 +718,7 @@ void shade_volume_shadow(struct ShadeInput *shi, struct ShadeResult *shr, struct
        vol_get_transmittance(shi, tr, startco, endco);
        
        VecCopyf(shr->combined, tr);
        vol_get_transmittance(shi, tr, startco, endco);
        
        VecCopyf(shr->combined, tr);
-       shr->combined[3] = 1.0f -(0.2126*tr[0] + 0.7152*tr[1] + 0.0722*tr[2]);
-       shr->alpha = shr->combined[3];
+       shr->combined[3] = 1.0f - luminance(tr);
 }
 
 
 }
 
 
index 9318d37620cc953661a47a23f150e8b5c8335fa7..479f33c9ff2dbd397c008c204e57cd4aabd8ab12 100644 (file)
@@ -226,9 +226,6 @@ void make_voxeldata(struct Render *re)
 {
     Tex *tex;
        
 {
     Tex *tex;
        
-       if(re->scene->r.scemode & R_PREVIEWBUTS)
-               return;
-       
        re->i.infostr= "Loading voxel datasets";
        re->stats_draw(re->sdh, &re->i);
        
        re->i.infostr= "Loading voxel datasets";
        re->stats_draw(re->sdh, &re->i);
        
@@ -259,9 +256,6 @@ void free_voxeldata(Render *re)
 {
        Tex *tex;
        
 {
        Tex *tex;
        
-       if(re->scene->r.scemode & R_PREVIEWBUTS)
-               return;
-       
        for (tex= G.main->tex.first; tex; tex= tex->id.next) {
                if(tex->id.us && tex->type==TEX_VOXELDATA) {
                        free_voxeldata_one(re, tex);
        for (tex= G.main->tex.first; tex; tex= tex->id.next) {
                if(tex->id.us && tex->type==TEX_VOXELDATA) {
                        free_voxeldata_one(re, tex);