diff --git a/release/scripts/ui/buttons_material.py b/release/scripts/ui/buttons_material.py index ee7193da301..2415d636dab 100644 --- a/release/scripts/ui/buttons_material.py +++ b/release/scripts/ui/buttons_material.py @@ -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 diff --git a/source/blender/blenkernel/intern/material.c b/source/blender/blenkernel/intern/material.c index cbd306f6d87..7e742dc5631 100644 --- a/source/blender/blenkernel/intern/material.c +++ b/source/blender/blenkernel/intern/material.c @@ -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; diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index 9367e2f4247..a3a56e9a075 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -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; } diff --git a/source/blender/makesdna/DNA_material_types.h b/source/blender/makesdna/DNA_material_types.h index a925b60ac33..36de890e6dc 100644 --- a/source/blender/makesdna/DNA_material_types.h +++ b/source/blender/makesdna/DNA_material_types.h @@ -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 diff --git a/source/blender/makesrna/intern/rna_material.c b/source/blender/makesrna/intern/rna_material.c index 661b1c5e1c3..b05a7e59cc3 100644 --- a/source/blender/makesrna/intern/rna_material.c +++ b/source/blender/makesrna/intern/rna_material.c @@ -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); diff --git a/source/blender/render/intern/source/convertblender.c b/source/blender/render/intern/source/convertblender.c index b3784f26048..655c453eee7 100644 --- a/source/blender/render/intern/source/convertblender.c +++ b/source/blender/render/intern/source/convertblender.c @@ -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; diff --git a/source/blender/render/intern/source/volume_precache.c b/source/blender/render/intern/source/volume_precache.c index 7ecaf83ae27..2d5d38a394f 100644 --- a/source/blender/render/intern/source/volume_precache.c +++ b/source/blender/render/intern/source/volume_precache.c @@ -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) diff --git a/source/blender/render/intern/source/volumetric.c b/source/blender/render/intern/source/volumetric.c index 381a32de027..cbb74ab752f 100644 --- a/source/blender/render/intern/source/volumetric.c +++ b/source/blender/render/intern/source/volumetric.c @@ -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);