diff options
author | Matt Ebb <matt@mke3.net> | 2008-10-13 09:22:31 +0400 |
---|---|---|
committer | Matt Ebb <matt@mke3.net> | 2008-10-13 09:22:31 +0400 |
commit | d6808c2b4b9d53f5481e96d4041e67b20f1d56f0 (patch) | |
tree | e6b753203124e3f52bdc1dd859ee5d320dc3b2eb | |
parent | c0ddd5fd4914f7876cdf36225566d795e415bbf1 (diff) |
* Raytraced shadow casting for volumes
This is a first version and still has a couple of things undefined or
unimplemented, such as external objects casting shadows on or within volumes,
however volume->solid shadows are going ok.
http://mke3.net/blender/devel/rendering/volumetrics/shadows_test_02.mov
http://mke3.net/blender/devel/rendering/volumetrics/vol_test_shad3.blend
As with other transparent raytraced shadows in Blender ,in order to make it work,
you must enable 'TraShad' on the material *receiving* the shadow. It would be
nice to make this a bit easier to use, since there's not much chance you want a
volume material to be casting solid shadows, but that's a bigger issue in the
renderer outside this scope.
The volume shadows are working from the same physical basis of absorption, and
support coloured absorption:
http://mke3.net/blender/devel/rendering/volumetrics/vol_shad_absorption.png
They also work properly with multi-sampled (i.e. QMC) soft shadows:
http://mke3.net/blender/devel/rendering/volumetrics/vol_shad_sharp.png
http://mke3.net/blender/devel/rendering/volumetrics/vol_shad_soft.png
And by popular request the test file:
http://mke3.net/blender/devel/rendering/volumetrics/vol_test_shad_clouds.blend
6 files changed, 87 insertions, 14 deletions
diff --git a/source/blender/render/intern/include/pointdensity.h b/source/blender/render/intern/include/pointdensity.h index 9c21cc0c253..93cdef3b14e 100644 --- a/source/blender/render/intern/include/pointdensity.h +++ b/source/blender/render/intern/include/pointdensity.h @@ -37,6 +37,7 @@ struct Render; struct TexResult; void make_pointdensities(struct Render *re); +void free_pointdensities(struct Render *re); int pointdensitytex(struct Tex *tex, float *texvec, struct TexResult *texres); #endif /* POINTDENSITY_H */ diff --git a/source/blender/render/intern/include/rendercore.h b/source/blender/render/intern/include/rendercore.h index 4b28529a147..972071764d2 100644 --- a/source/blender/render/intern/include/rendercore.h +++ b/source/blender/render/intern/include/rendercore.h @@ -48,6 +48,7 @@ struct RenderPart; struct RenderLayer; struct ObjectRen; struct ListBase; +struct Isect; /* ------------------------------------------------------------------------- */ @@ -98,6 +99,7 @@ extern void makeraytree(Render *re); extern void ray_shadow(ShadeInput *, LampRen *, float *); extern void ray_trace(ShadeInput *, ShadeResult *); +extern void ray_trace_shadow_tra(struct Isect *is, int depth, int traflag); extern void ray_ao(ShadeInput *, float *); extern void init_jitter_plane(LampRen *lar); extern void init_ao_sphere(struct World *wrld); diff --git a/source/blender/render/intern/include/volumetric.h b/source/blender/render/intern/include/volumetric.h index 8db3fa63f98..290be427f01 100644 --- a/source/blender/render/intern/include/volumetric.h +++ b/source/blender/render/intern/include/volumetric.h @@ -26,4 +26,5 @@ * ***** END GPL LICENSE BLOCK ***** */ -void volume_trace(struct ShadeInput *shi, struct ShadeResult *shr);
\ No newline at end of file +void volume_trace(struct ShadeInput *shi, struct ShadeResult *shr); +void volume_trace_shadow(struct ShadeInput *shi, struct ShadeResult *shr, struct Isect *last_is);
\ No newline at end of file diff --git a/source/blender/render/intern/source/convertblender.c b/source/blender/render/intern/source/convertblender.c index 4b663c6caa6..0660d9e0b24 100644 --- a/source/blender/render/intern/source/convertblender.c +++ b/source/blender/render/intern/source/convertblender.c @@ -965,8 +965,6 @@ 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->material_type == MA_VOLUME) re->r.mode |= R_RAYTRACE; - check_material_is_textured(ma); return ma; diff --git a/source/blender/render/intern/source/rayshade.c b/source/blender/render/intern/source/rayshade.c index c431340d770..d06bbcf3300 100644 --- a/source/blender/render/intern/source/rayshade.c +++ b/source/blender/render/intern/source/rayshade.c @@ -54,6 +54,7 @@ #include "pixelshading.h" #include "shading.h" #include "texture.h" +#include "volumetric.h" #include "RE_raytrace.h" @@ -262,21 +263,28 @@ void shade_ray(Isect *is, ShadeInput *shi, ShadeResult *shr) shade_input_set_shade_texco(shi); - if(is->mode==RE_RAY_SHADOW_TRA) + if (shi->mat->material_type == MA_VOLUME) { + if(ELEM(is->mode, RE_RAY_SHADOW, RE_RAY_SHADOW_TRA)) { + volume_trace_shadow(shi, shr, is); + } else { + shade_volume_loop(shi, shr); + } + } + else if(is->mode==RE_RAY_SHADOW_TRA) if(shi->mat->nodetree && shi->mat->use_nodes) { ntreeShaderExecTree(shi->mat->nodetree, shi, shr); shi->mat= vlr->mat; /* shi->mat is being set in nodetree */ } - else + else { shade_color(shi, shr); + } else { if(shi->mat->nodetree && shi->mat->use_nodes) { ntreeShaderExecTree(shi->mat->nodetree, shi, shr); shi->mat= vlr->mat; /* shi->mat is being set in nodetree */ } else { - if (shi->mat->material_type == MA_SOLID) shade_material_loop(shi, shr); - else if (shi->mat->material_type == MA_VOLUME) shade_volume_loop(shi, shr); + shade_material_loop(shi, shr); } /* raytrace likes to separate the spec color */ VECSUB(shr->diff, shr->combined, shr->spec); @@ -1274,7 +1282,7 @@ static void addAlphaLight(float *shadfac, float *col, float alpha, float filter) shadfac[3]= (1.0f-alpha)*shadfac[3]; } -static void ray_trace_shadow_tra(Isect *is, int depth, int traflag) +void ray_trace_shadow_tra(Isect *is, int depth, int traflag) { /* ray to lamp, find first face that intersects, check alpha properties, if it has col[3]>0.0f continue. so exit when alpha is full */ @@ -1303,11 +1311,16 @@ static void ray_trace_shadow_tra(Isect *is, int depth, int traflag) shi.mat_override= NULL;*/ shade_ray(is, &shi, &shr); - if (traflag & RAY_TRA) - d= shade_by_transmission(is, &shi, &shr); - - /* mix colors based on shadfac (rgb + amount of light factor) */ - addAlphaLight(is->col, shr.diff, shr.alpha, d*shi.mat->filter); + if (shi.mat->material_type == MA_SOLID) { + if (traflag & RAY_TRA) + d= shade_by_transmission(is, &shi, &shr); + + /* mix colors based on shadfac (rgb + amount of light factor) */ + addAlphaLight(is->col, shr.diff, shr.alpha, d*shi.mat->filter); + } else { + // MA_VOLUME + addAlphaLight(is->col, shr.combined, shr.alpha, 1.0f); + } if(depth>0 && is->col[3]>0.0f) { diff --git a/source/blender/render/intern/source/volumetric.c b/source/blender/render/intern/source/volumetric.c index e0006a24fba..3b44e1bb87f 100644 --- a/source/blender/render/intern/source/volumetric.c +++ b/source/blender/render/intern/source/volumetric.c @@ -149,6 +149,8 @@ float vol_get_stepsize(struct ShadeInput *shi, int context) else if (context == STEPSIZE_SHADE) return shi->mat->vol_shade_stepsize; } + + return shi->mat->vol_stepsize; } float vol_get_density(struct ShadeInput *shi, float *co) @@ -247,6 +249,8 @@ void vol_get_attenuation(ShadeInput *shi, float *tau, float *co, float *endco, f dist = VecLenf(co, endco); nsteps = (int)ceil(dist / stepsize); + if (density < -0.001f) density = vol_get_density(shi, co); + if (nsteps == 1) { /* homogenous volume within the sampled distance */ tau[0] = tau[1] = tau[2] = dist * density; @@ -485,7 +489,7 @@ static void shade_intersection(ShadeInput *shi, float *col, Isect *is) shi_new.mask= shi->mask; shi_new.osatex= shi->osatex; shi_new.thread= shi->thread; - shi_new.depth= shi->depth; + shi_new.depth= 1; shi_new.volume_depth= shi->volume_depth + 1; shi_new.xs= shi->xs; shi_new.ys= shi->ys; @@ -597,3 +601,57 @@ void volume_trace(struct ShadeInput *shi, struct ShadeResult *shr) shr->combined[3] = shr->alpha = 1.0f; } } + +void volume_trace_shadow(struct ShadeInput *shi, struct ShadeResult *shr, struct Isect *last_is) +{ + float hitco[3], col[4] = {0.f,0.f,0.f,0.f}; + float tr[3] = {1.0,1.0,1.0}; + float tau[3] = {0.0,0.0,0.0}; + Isect is; + float shade_stepsize = vol_get_stepsize(shi, STEPSIZE_SHADE); + + memset(shr, 0, sizeof(ShadeResult)); + + /* if 1st hit normal is facing away from the camera, + * then we're inside the volume already. */ + if (shi->flippednor) { + + vol_get_attenuation(shi, tau, last_is->start, shi->co, -1.0f, shade_stepsize); + tr[0] = exp(-tau[0]); + tr[1] = exp(-tau[1]); + tr[2] = exp(-tau[2]); + + shr->combined[0] = tr[0]; + shr->combined[1] = tr[1]; + shr->combined[2] = tr[2]; + + shr->combined[3] = 1.0f -(tr[0] + tr[1] + tr[2]) * 0.333f; + shr->alpha = shr->combined[3]; + } + /* trace to find a backface, the other side bounds of the volume */ + /* (ray intersect ignores front faces here) */ + else if (vol_get_bounds(shi, shi->co, shi->view, hitco, &is, VOL_BOUNDS_DEPTH, 0)) { + float dist = VecLenf(shi->co, hitco); + + vol_get_attenuation(shi, tau, shi->co, hitco, -1.0f, shade_stepsize); + tr[0] = exp(-tau[0]); + tr[1] = exp(-tau[1]); + tr[2] = exp(-tau[2]); + + shr->combined[0] = tr[0]; + shr->combined[1] = tr[1]; + shr->combined[2] = tr[2]; + + shr->combined[3] = 1.0f -(tr[0] + tr[1] + tr[2]) * 0.333f; + shr->alpha = shr->combined[3]; + + } + else { + shr->combined[0] = 0.0f; + shr->combined[1] = 0.0f; + shr->combined[2] = 0.0f; + shr->combined[3] = shr->alpha = 0.0f; + } + +} + |