Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatt Ebb <matt@mke3.net>2008-12-31 08:08:04 +0300
committerMatt Ebb <matt@mke3.net>2008-12-31 08:08:04 +0300
commit834fda50d99210a5a69360bbed84f76934792171 (patch)
treeb6130ee3b3d8ba191924ce5198530dd59581f8c3
parentbe1d06a2c544a4ea27139475a72edb75afa37879 (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.h10
-rw-r--r--source/blender/render/intern/source/rayshade.c20
-rw-r--r--source/blender/render/intern/source/shadeinput.c23
-rw-r--r--source/blender/render/intern/source/volumetric.c61
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