diff options
author | Matt Ebb <matt@mke3.net> | 2008-12-31 08:08:04 +0300 |
---|---|---|
committer | Matt Ebb <matt@mke3.net> | 2008-12-31 08:08:04 +0300 |
commit | 834fda50d99210a5a69360bbed84f76934792171 (patch) | |
tree | b6130ee3b3d8ba191924ce5198530dd59581f8c3 | |
parent | be1d06a2c544a4ea27139475a72edb75afa37879 (diff) |
Volume rendering
* Fixed an old problem where if both the camera and a solid surface were
inside a volume, the volume wouldn't attenuate in front of the surface (was
visible in the blender conference art festival clouds animation:
http://mke3.net/blender/devel/rendering/volumetrics/vol_shade_cam_inside.mov
* Initial support for refracting solids inside volumes. I might be able to
make this work better, but not sure at the moment. It's a bit dodgy,
limited by the code that does the recursive ray shading - it's really not
set up for this kind of thing and could use a refactor very much.
-rw-r--r-- | source/blender/render/intern/include/volumetric.h | 10 | ||||
-rw-r--r-- | source/blender/render/intern/source/rayshade.c | 20 | ||||
-rw-r--r-- | source/blender/render/intern/source/shadeinput.c | 23 | ||||
-rw-r--r-- | source/blender/render/intern/source/volumetric.c | 61 |
4 files changed, 87 insertions, 27 deletions
diff --git a/source/blender/render/intern/include/volumetric.h b/source/blender/render/intern/include/volumetric.h index a69238f54b3..40d79e8d173 100644 --- a/source/blender/render/intern/include/volumetric.h +++ b/source/blender/render/intern/include/volumetric.h @@ -30,8 +30,9 @@ float vol_get_stepsize(struct ShadeInput *shi, int context); float vol_get_density(struct ShadeInput *shi, float *co); void vol_get_scattering(ShadeInput *shi, float *scatter, float *co, float stepsize, float density); -void volume_trace(struct ShadeInput *shi, struct ShadeResult *shr); -void volume_trace_shadow(struct ShadeInput *shi, struct ShadeResult *shr, struct Isect *last_is); +void shade_volume_outside(ShadeInput *shi, ShadeResult *shr); +void shade_volume_inside(ShadeInput *shi, ShadeResult *shr); +void shade_volume_shadow(struct ShadeInput *shi, struct ShadeResult *shr, struct Isect *last_is); #define STEPSIZE_VIEW 0 #define STEPSIZE_SHADE 1 @@ -40,4 +41,7 @@ void volume_trace_shadow(struct ShadeInput *shi, struct ShadeResult *shr, struct #define VOL_IS_SAMEMATERIAL 2 #define VOL_BOUNDS_DEPTH 0 -#define VOL_BOUNDS_SS 1
\ No newline at end of file +#define VOL_BOUNDS_SS 1 + +#define VOL_SHADE_OUTSIDE 0 +#define VOL_SHADE_INSIDE 1
\ No newline at end of file diff --git a/source/blender/render/intern/source/rayshade.c b/source/blender/render/intern/source/rayshade.c index 8bbdb243c8a..d09bd5c707a 100644 --- a/source/blender/render/intern/source/rayshade.c +++ b/source/blender/render/intern/source/rayshade.c @@ -276,9 +276,9 @@ void shade_ray(Isect *is, ShadeInput *shi, ShadeResult *shr) if (shi->mat->material_type == MA_VOLUME) { if(ELEM(is->mode, RE_RAY_SHADOW, RE_RAY_SHADOW_TRA)) { - volume_trace_shadow(shi, shr, is); + shade_volume_shadow(shi, shr, is); } else { - shade_volume_loop(shi, shr); + shade_volume_outside(shi, shr); } } else if(is->mode==RE_RAY_SHADOW_TRA) @@ -295,7 +295,18 @@ void shade_ray(Isect *is, ShadeInput *shi, ShadeResult *shr) shi->mat= vlr->mat; /* shi->mat is being set in nodetree */ } else { - shade_material_loop(shi, shr); + int tempdepth; + /* XXX dodgy business here, set ray depth to -1 + * to ignore raytrace in shade_material_loop() + * this could really use a refactor --Matt */ + if (shi->volume_depth == 0) { + tempdepth = shi->depth; + shi->depth = -1; + shade_material_loop(shi, shr); + shi->depth = tempdepth; + } else { + shade_material_loop(shi, shr); + } } /* raytrace likes to separate the spec color */ VECSUB(shr->diff, shr->combined, shr->spec); @@ -467,7 +478,7 @@ static void traceray(ShadeInput *origshi, ShadeResult *origshr, short depth, flo shi.mask= origshi->mask; shi.osatex= origshi->osatex; - shi.depth= 1; /* only used to indicate tracing */ + shi.depth = origshi->depth + 1; /* only used to indicate tracing */ shi.thread= origshi->thread; //shi.sample= 0; // memset above, so dont need this shi.xs= origshi->xs; @@ -482,6 +493,7 @@ static void traceray(ShadeInput *origshi, ShadeResult *origshr, short depth, flo memset(&shr, 0, sizeof(ShadeResult)); shade_ray(&isec, &shi, &shr); + if (traflag & RAY_TRA) d= shade_by_transmission(&isec, &shi, &shr); diff --git a/source/blender/render/intern/source/shadeinput.c b/source/blender/render/intern/source/shadeinput.c index aa11e3d75dd..5bf2f58ae4e 100644 --- a/source/blender/render/intern/source/shadeinput.c +++ b/source/blender/render/intern/source/shadeinput.c @@ -121,7 +121,7 @@ void shade_material_loop(ShadeInput *shi, ShadeResult *shr) } /* depth >= 1 when ray-shading */ - if(shi->depth==0) { + if(shi->depth >= 0 && (shi->depth < MAX2(shi->mat->ray_depth_tra, shi->mat->ray_depth))) { if(R.r.mode & R_RAYTRACE) { if(shi->ray_mirror!=0.0f || ((shi->mat->mode & MA_RAYTRANSP) && shr->alpha!=1.0f)) { /* ray trace works on combined, but gives pass info */ @@ -132,16 +132,13 @@ void shade_material_loop(ShadeInput *shi, ShadeResult *shr) if(shi->mat->mode & MA_RAYTRANSP) if((shi->layflag & SCE_LAY_SKY) && (R.r.alphamode==R_ADDSKY)) shr->alpha= 1.0f; - } -} - -/* delivers a fully filled in ShadeResult, for all passes */ -void shade_volume_loop(ShadeInput *shi, ShadeResult *shr) -{ - if(R.r.mode & R_RAYTRACE) volume_trace(shi, shr); + } + + if(R.r.mode & R_RAYTRACE) { + shade_volume_inside(shi, shr); + } } - /* do a shade, finish up some passes, apply mist */ void shade_input_do_shade(ShadeInput *shi, ShadeResult *shr) { @@ -157,8 +154,12 @@ void shade_input_do_shade(ShadeInput *shi, ShadeResult *shr) memcpy(&shi->r, &shi->mat->r, 23*sizeof(float)); shi->har= shi->mat->har; - 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); + if (shi->mat->material_type == MA_SOLID) { + shade_material_loop(shi, shr); + } else if (shi->mat->material_type == MA_VOLUME) { + if(R.r.mode & R_RAYTRACE) + shade_volume_outside(shi, shr); + } } /* copy additional passes */ diff --git a/source/blender/render/intern/source/volumetric.c b/source/blender/render/intern/source/volumetric.c index 3206989d1d7..10a3f83758c 100644 --- a/source/blender/render/intern/source/volumetric.c +++ b/source/blender/render/intern/source/volumetric.c @@ -548,7 +548,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= 1; + shi_new.depth = shi->depth + 1; shi_new.volume_depth= shi->volume_depth + 1; shi_new.xs= shi->xs; shi_new.ys= shi->ys; @@ -601,18 +601,31 @@ static void vol_trace_behind(ShadeInput *shi, VlakRen *vlr, float *co, float *co } /* the main entry point for volume shading */ -void volume_trace(struct ShadeInput *shi, struct ShadeResult *shr) +static void volume_trace(struct ShadeInput *shi, struct ShadeResult *shr, int inside_volume) { float hitco[3], col[4] = {0.f,0.f,0.f,0.f}; + int trace_behind = 1; Isect is; - memset(shr, 0, sizeof(ShadeResult)); + /* check for shading an internal face a volume object directly */ + if (inside_volume == VOL_SHADE_INSIDE) { + trace_behind = 0; + } + if (inside_volume == VOL_SHADE_OUTSIDE) { + if (shi->flippednor) + inside_volume = VOL_SHADE_INSIDE; + } - /* if 1st hit normal is facing away from the camera, - * then we're inside the volume already. */ - if (shi->flippednor) { - /* trace behind the 1st hit point */ - vol_trace_behind(shi, shi->vlr, shi->co, col); + if (inside_volume == VOL_SHADE_INSIDE) { + + if (trace_behind) { + /* trace behind the volume object */ + vol_trace_behind(shi, shi->vlr, shi->co, col); + } else { + /* we're tracing through the volume between the camera + * and a solid surface, so use that pre-shaded radiance */ + QUATCOPY(col, shr->combined); + } /* shade volume from 'camera' to 1st hit point */ volumeintegrate(shi, col, shi->camera_co, shi->co); @@ -673,7 +686,7 @@ void volume_trace(struct ShadeInput *shi, struct ShadeResult *shr) /* Traces a shadow through the object, * pretty much gets the transmission over a ray path */ -void volume_trace_shadow(struct ShadeInput *shi, struct ShadeResult *shr, struct Isect *last_is) +void shade_volume_shadow(struct ShadeInput *shi, struct ShadeResult *shr, struct Isect *last_is) { float hitco[3]; float tr[3] = {1.0,1.0,1.0}; @@ -724,3 +737,33 @@ void volume_trace_shadow(struct ShadeInput *shi, struct ShadeResult *shr, struct } } + +/* delivers a fully filled in ShadeResult, for all passes */ +void shade_volume_outside(ShadeInput *shi, ShadeResult *shr) +{ + memset(shr, 0, sizeof(ShadeResult)); + + volume_trace(shi, shr, VOL_SHADE_OUTSIDE); +} + + +void shade_volume_inside(ShadeInput *shi, ShadeResult *shr) +{ + MatInside *m; + Material *mat_backup; + + if (BLI_countlist(&R.render_volumes_inside) == 0) return; + + mat_backup = shi->mat; + +// for (m=R.render_volumes_inside.first; m; m=m->next) { +// printf("matinside: ma: %s \n", m->ma->id.name+2); +// } + + m = R.render_volumes_inside.first; + shi->mat = m->ma; + + volume_trace(shi, shr, VOL_SHADE_INSIDE); + + shi->mat = mat_backup; +}
\ No newline at end of file |