diff options
author | Matt Ebb <matt@mke3.net> | 2009-10-05 06:59:47 +0400 |
---|---|---|
committer | Matt Ebb <matt@mke3.net> | 2009-10-05 06:59:47 +0400 |
commit | af522abf33bd3b8caf61f596d1e0a35285e45f9a (patch) | |
tree | 309cd8215c8cca566338a25355db1446fee78384 /source/blender | |
parent | 89df4a46fcbbe11ca478418af59161c87ddbb9f1 (diff) |
* changes/additions to volume lighting
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).
Diffstat (limited to 'source/blender')
-rw-r--r-- | source/blender/blenkernel/intern/material.c | 2 | ||||
-rw-r--r-- | source/blender/blenloader/intern/readfile.c | 2 | ||||
-rw-r--r-- | source/blender/makesdna/DNA_material_types.h | 12 | ||||
-rw-r--r-- | source/blender/makesrna/intern/rna_material.c | 20 | ||||
-rw-r--r-- | source/blender/render/intern/source/convertblender.c | 5 | ||||
-rw-r--r-- | source/blender/render/intern/source/volume_precache.c | 8 | ||||
-rw-r--r-- | source/blender/render/intern/source/volumetric.c | 67 |
7 files changed, 95 insertions, 21 deletions
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); |