* changes/additions to volume lighting
authorMatt Ebb <matt@mke3.net>
Mon, 5 Oct 2009 02:59:47 +0000 (02:59 +0000)
committerMatt Ebb <matt@mke3.net>
Mon, 5 Oct 2009 02:59:47 +0000 (02:59 +0000)
Volumes can now receive shadows from external objects, either raytraced shadows or shadow maps.

To use external shadows, enable 'external shadows' in volume material 'lighting' panel. This an extra toggle since it causes a performance hit, but this can probably be revisited/optimised when the new raytrace accelerator is integrated. For shadow maps at least, it's still very quick.

Renamed 'scattering mode' to 'lighting mode' (a bit simpler to understand), and the options inside. Now there's:

- Shadeless
  takes light contribution, but without shadowing or self-shading (fast)
  good for fog-like volumes, such as mist, or underwater effects

- Shadowed (new)
  takes light contribution with shadows, but no self-shading. (medium)
  good for mist etc. with directional light sources
  eg. http://vimeo.com/6901636

- Shaded
  takes light contribution with internal/external shadows, and self shading (slower)
  good for thicker/textured volumes like smoke

- Multiple scattering etc (still doesn't work properly, on the todo).

release/scripts/ui/buttons_material.py
source/blender/blenkernel/intern/material.c
source/blender/blenloader/intern/readfile.c
source/blender/makesdna/DNA_material_types.h
source/blender/makesrna/intern/rna_material.c
source/blender/render/intern/source/convertblender.c
source/blender/render/intern/source/volume_precache.c
source/blender/render/intern/source/volumetric.c

index ee7193da30135565122c7c1172d39f3ee49d26d8..2415d636dab50d1551f89508b4786564d26c1996 100644 (file)
@@ -665,16 +665,17 @@ class MATERIAL_PT_volume_lighting(VolumeButtonsPanel):
                split = layout.split()
                
                col = split.column()
-               col.itemR(vol, "scattering_mode", text="")
+               col.itemR(vol, "lighting_mode", text="")
                
                col = split.column()
                
-               if vol.scattering_mode == 'SINGLE_SCATTERING':
+               if vol.lighting_mode == 'SHADED':
+                       col.itemR(vol, "external_shadows")
                        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'):
+               elif vol.lighting_mode in ('MULTIPLE_SCATTERING', 'SHADED_PLUS_MULTIPLE_SCATTERING'):
                        sub = col.column()
                        sub.enabled = True
                        sub.active = False
index cbd306f6d8747548a69092c5ebd09701be1e3bbb..7e742dc56314de9b059f82a6054899b220f69cd7 100644 (file)
@@ -181,7 +181,7 @@ void init_material(Material *ma)
        ma->vol.depth_cutoff = 0.01f;
        ma->vol.stepsize_type = MA_VOL_STEP_RANDOMIZED;
        ma->vol.stepsize = 0.2f;
-       ma->vol.shade_type = MA_VOL_SHADE_SINGLE;
+       ma->vol.shade_type = MA_VOL_SHADE_SHADED;
        ma->vol.shadeflag |= MA_VOL_PRECACHESHADING;
        ma->vol.precache_resolution = 50;
        
index 9367e2f42470f2ac484a0369db846196a3d737b0..a3a56e9a07530e00c941b4eda3d464d8cc51afe7 100644 (file)
@@ -9680,7 +9680,7 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
                                ma->vol.depth_cutoff = 0.01f;
                                ma->vol.stepsize_type = MA_VOL_STEP_RANDOMIZED;
                                ma->vol.stepsize = 0.2f;
-                               ma->vol.shade_type = MA_VOL_SHADE_SINGLE;
+                               ma->vol.shade_type = MA_VOL_SHADE_SHADED;
                                ma->vol.shadeflag |= MA_VOL_PRECACHESHADING;
                                ma->vol.precache_resolution = 50;
                        }
index a925b60ac336c56334c3dd60eec3a5f513c9aa49..36de890e6dc41541421017c4716bc6c542dfe495 100644 (file)
@@ -374,15 +374,15 @@ typedef struct Material {
 #define MA_VOL_STEP_ADAPTIVE   2
 
 /* vol_shadeflag */
-#define MA_VOL_SHADED          1
-#define MA_VOL_RECVSHADOW      4
+#define MA_VOL_RECV_EXT_SHADOW 1
 #define MA_VOL_PRECACHESHADING 8
 
 /* vol_shading_type */
-#define MA_VOL_SHADE_NONE                                      0
-#define MA_VOL_SHADE_SINGLE                                    1
-#define MA_VOL_SHADE_MULTIPLE                          2
-#define MA_VOL_SHADE_SINGLEPLUSMULTIPLE                3
+#define MA_VOL_SHADE_SHADELESS                                 0
+#define MA_VOL_SHADE_SHADOWED                                  2
+#define MA_VOL_SHADE_SHADED                                            1
+#define MA_VOL_SHADE_MULTIPLE                                  3
+#define MA_VOL_SHADE_SHADEDPLUSMULTIPLE                        4
 
 #endif
 
index 661b1c5e1c309e523af6424fe7ed52719cdbedd9..b05a7e59cc301880e68e32b42800f980129fcce8 100644 (file)
@@ -953,11 +953,12 @@ static void rna_def_material_volume(BlenderRNA *brna)
        StructRNA *srna;
        PropertyRNA *prop;
 
-       static EnumPropertyItem prop_scattering_items[] = {
-               {MA_VOL_SHADE_NONE, "NONE", 0, "None", ""},
-               {MA_VOL_SHADE_SINGLE, "SINGLE_SCATTERING", 0, "Single Scattering", ""},
+       static EnumPropertyItem prop_lighting_items[] = {
+               {MA_VOL_SHADE_SHADELESS, "SHADELESS", 0, "Shadeless", ""},
+               {MA_VOL_SHADE_SHADOWED, "SHADOWED", 0, "Shadowed", ""},
+               {MA_VOL_SHADE_SHADED, "SHADED", 0, "Shaded", ""},
                {MA_VOL_SHADE_MULTIPLE, "MULTIPLE_SCATTERING", 0, "Multiple Scattering", ""},
-               {MA_VOL_SHADE_SINGLEPLUSMULTIPLE, "SINGLE_PLUS_MULTIPLE_SCATTERING", 0, "Single + Multiple Scattering", ""},
+               {MA_VOL_SHADE_SHADEDPLUSMULTIPLE, "SHADED_PLUS_MULTIPLE_SCATTERING", 0, "Shaded + Multiple Scattering", ""},
                {0, NULL, 0, NULL, NULL}};
 
        static EnumPropertyItem prop_stepsize_items[] = {
@@ -984,10 +985,15 @@ 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");
        
-       prop= RNA_def_property(srna, "scattering_mode", PROP_ENUM, PROP_NONE);
+       prop= RNA_def_property(srna, "lighting_mode", PROP_ENUM, PROP_NONE);
        RNA_def_property_enum_sdna(prop, NULL, "shade_type");
-       RNA_def_property_enum_items(prop, prop_scattering_items);
-       RNA_def_property_ui_text(prop, "Scattering Mode", "Method of shading, attenuating, and scattering light through the volume");
+       RNA_def_property_enum_items(prop, prop_lighting_items);
+       RNA_def_property_ui_text(prop, "Lighting Mode", "Method of shading, attenuating, and scattering light through the volume");
+       RNA_def_property_update(prop, 0, "rna_Material_update");
+       
+       prop= RNA_def_property(srna, "external_shadows", PROP_BOOLEAN, PROP_NONE);
+       RNA_def_property_boolean_sdna(prop, NULL, "shadeflag", MA_VOL_RECV_EXT_SHADOW); /* use bitflags */
+       RNA_def_property_ui_text(prop, "External Shadows", "Receive shadows from sources outside the volume (temporary)");
        RNA_def_property_update(prop, 0, "rna_Material_update");
        
        prop= RNA_def_property(srna, "light_cache", PROP_BOOLEAN, PROP_NONE);
index b3784f260487ab80cebf6a7187c9da7892f3de77..655c453eee790dc25d8c1acf60b058bbfbc06a76 100644 (file)
@@ -942,7 +942,10 @@ static Material *give_render_material(Render *re, Object *ob, int nr)
        
        if(re->r.mode & R_SPEED) ma->texco |= NEED_UV;
        
-       if(ma->material_type == MA_TYPE_VOLUME) ma->mode |= MA_TRANSP;
+       if(ma->material_type == MA_TYPE_VOLUME) {
+               ma->mode |= MA_TRANSP;
+               ma->mode &= ~MA_SHADBUF;
+       }
        if((ma->mode & MA_TRANSP) && (ma->mode & MA_ZTRANSP))
                re->flag |= R_ZTRA;
        
index 7ecaf83ae27eda97933b4abe5c19f6117f3cf0a5..2d5d38a394fb7676904b304b7d974ff862090ec7 100644 (file)
@@ -401,7 +401,7 @@ void multiple_scattering_diffusion(Render *re, VolumePrecache *vp, Material *ma)
        fac *= (energy_ss / energy_ms);
        
        /* blend multiple scattering back in the light cache */
-       if (shade_type == MA_VOL_SHADE_SINGLEPLUSMULTIPLE) {
+       if (shade_type == MA_VOL_SHADE_SHADEDPLUSMULTIPLE) {
                /* conserve energy - half single, half multiple */
                origf = 0.5f;
                fac *= 0.5f;
@@ -713,7 +713,7 @@ void vol_precache_objectinstance_threads(Render *re, ObjectInstanceRen *obi, Mat
        
        lightcache_filter(obi->volume_precache);
        
-       if (ELEM(ma->vol.shade_type, MA_VOL_SHADE_MULTIPLE, MA_VOL_SHADE_SINGLEPLUSMULTIPLE))
+       if (ELEM(ma->vol.shade_type, MA_VOL_SHADE_MULTIPLE, MA_VOL_SHADE_SHADEDPLUSMULTIPLE))
        {
                multiple_scattering_diffusion(re, vp, ma);
        }
@@ -721,8 +721,8 @@ void vol_precache_objectinstance_threads(Render *re, ObjectInstanceRen *obi, Mat
 
 static int using_lightcache(Material *ma)
 {
-       return (((ma->vol.shadeflag & MA_VOL_PRECACHESHADING) && (ma->vol.shade_type == MA_VOL_SHADE_SINGLE))
-               || (ELEM(ma->vol.shade_type, MA_VOL_SHADE_MULTIPLE, MA_VOL_SHADE_SINGLEPLUSMULTIPLE)));
+       return (((ma->vol.shadeflag & MA_VOL_PRECACHESHADING) && (ma->vol.shade_type == MA_VOL_SHADE_SHADED))
+               || (ELEM(ma->vol.shade_type, MA_VOL_SHADE_MULTIPLE, MA_VOL_SHADE_SHADEDPLUSMULTIPLE)));
 }
 
 /* loop through all objects (and their associated materials)
index 381a32de02795d57d294565be2a44e631e5747e4..cbb74ab752ff864d70e0c2d88e443f182d6a7736 100644 (file)
@@ -51,6 +51,7 @@
 #include "render_types.h"
 #include "pixelshading.h"
 #include "shading.h"
+#include "shadbuf.h"
 #include "texture.h"
 #include "volumetric.h"
 #include "volume_precache.h"
@@ -73,6 +74,61 @@ inline float luminance(float* col)
 
 /* tracing */
 
+static int vlr_check_intersect_solid(Isect *is, int ob, RayFace *face)
+{
+       VlakRen *vlr = (VlakRen*)face;
+       
+       /* solid material types only */
+       if (vlr->mat->material_type == MA_TYPE_SURFACE)
+               return 1;
+       else
+               return 0;
+}
+
+static float vol_get_shadow(ShadeInput *shi, LampRen *lar, float *co)
+{
+       float visibility = 1.f;
+       
+       if(lar->shb) {
+               float dot=1.f;
+               float dxco[3]={0.f, 0.f, 0.f}, dyco[3]={0.f, 0.f, 0.f};
+               
+               visibility = testshadowbuf(&R, lar->shb, co, dxco, dyco, 1.0, 0.0);             
+       } else if (lar->mode & LA_SHAD_RAY) {
+               /* trace shadow manually, no good lamp api atm */
+               Isect is;
+               const float maxsize = RE_ray_tree_max_size(R.raytree);
+               
+               
+               VecCopyf(is.start, co);
+               if(lar->type==LA_SUN || lar->type==LA_HEMI) {
+                       is.end[0] = co[0] - lar->vec[0] * maxsize;
+                       is.end[1] = co[1] - lar->vec[1] * maxsize;
+                       is.end[2] = co[2] - lar->vec[2] * maxsize;
+               } else {
+                       VecCopyf(is.end, lar->co);
+               }
+
+               is.mode= RE_RAY_MIRROR;
+               if(lar->mode & (LA_LAYER|LA_LAYER_SHADOW))
+                       is.lay= lar->lay;       
+               else
+                       is.lay= -1;
+               is.face_last= (RayFace*)lar->vlr_last[shi->thread];
+               is.ob_last= RAY_OBJECT_SET(&R, lar->obi_last[shi->thread]);
+               is.faceorig= NULL;
+               is.oborig= RAY_OBJECT_SET(&R, shi->obi);
+               
+               if(RE_ray_tree_intersect_check(R.raytree, &is, vlr_check_intersect_solid)) {
+                       visibility = 0.f;
+               }
+               
+               lar->vlr_last[shi->thread]= (VlakRen*)is.face_last;
+               lar->obi_last[shi->thread]= RAY_OBJECT_GET(&R, is.ob_last);
+       }
+       return visibility;
+}
+
 static int vol_get_bounds(ShadeInput *shi, float *co, float *vec, float *hitco, Isect *isect, int intersect_type)
 {
        float maxsize = RE_ray_tree_max_size(R.raytree);
@@ -448,9 +504,18 @@ void vol_shade_one_lamp(struct ShadeInput *shi, float *co, LampRen *lar, float *
                VECCOPY(lv, lar->vec);
        VecMulf(lv, -1.0f);
        
-       if (shi->mat->vol.shade_type != MA_VOL_SHADE_NONE) {
+       if (shi->mat->vol.shade_type == MA_VOL_SHADE_SHADOWED) {
+               VecMulf(lacol, vol_get_shadow(shi, lar, co));
+       }
+       else if (shi->mat->vol.shade_type == MA_VOL_SHADE_SHADED)
+       {
                Isect is;
                
+               if (shi->mat->vol.shadeflag & MA_VOL_RECV_EXT_SHADOW) {
+                       VecMulf(lacol, vol_get_shadow(shi, lar, co));
+                       if (luminance(lacol) < 0.001f) return;
+               }
+               
                /* find minimum of volume bounds, or lamp coord */
                if (vol_get_bounds(shi, co, lv, hitco, &is, VOL_BOUNDS_SS)) {
                        float dist = VecLenf(co, hitco);