From d6808c2b4b9d53f5481e96d4041e67b20f1d56f0 Mon Sep 17 00:00:00 2001 From: Matt Ebb Date: Mon, 13 Oct 2008 05:22:31 +0000 Subject: * 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 --- .../blender/render/intern/include/pointdensity.h | 1 + source/blender/render/intern/include/rendercore.h | 2 + source/blender/render/intern/include/volumetric.h | 3 +- .../blender/render/intern/source/convertblender.c | 2 - source/blender/render/intern/source/rayshade.c | 33 ++++++++---- source/blender/render/intern/source/volumetric.c | 60 +++++++++++++++++++++- 6 files changed, 87 insertions(+), 14 deletions(-) (limited to 'source/blender/render/intern') 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; + } + +} + -- cgit v1.2.3