63c4e97f86ee2e0e09c663ee3c6fd95771ff9f87
[blender.git] / source / blender / render / intern / source / volumetric.c
1 /**
2  *
3  * ***** BEGIN GPL LICENSE BLOCK *****
4  *
5  * This program is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU General Public License
7  * as published by the Free Software Foundation; either version 2
8  * of the License, or (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software Foundation,
17  * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18  *
19  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
20  * All rights reserved.
21  *
22  * The Original Code is: all of this file.
23  *
24  * Contributor(s): Matt Ebb, Raul Fernandez Hernandez (Farsthary)
25  *
26  * ***** END GPL LICENSE BLOCK *****
27  */
28
29 #include <math.h>
30 #include <stdlib.h>
31 #include <string.h>
32 #include <float.h>
33
34 #include "MEM_guardedalloc.h"
35
36 #include "BLI_blenlib.h"
37 #include "BLI_arithb.h"
38 #include "BLI_rand.h"
39 #include "BLI_voxel.h"
40
41 #include "RE_shader_ext.h"
42 #include "RE_raytrace.h"
43
44 #include "DNA_material_types.h"
45 #include "DNA_group_types.h"
46 #include "DNA_lamp_types.h"
47
48 #include "BKE_global.h"
49
50 #include "render_types.h"
51 #include "pixelshading.h"
52 #include "shading.h"
53 #include "texture.h"
54 #include "volumetric.h"
55
56 #if defined( _MSC_VER ) && !defined( __cplusplus )
57 # define inline __inline
58 #endif // defined( _MSC_VER ) && !defined( __cplusplus )
59
60 /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
61 /* defined in pipeline.c, is hardcopy of active dynamic allocated Render */
62 /* only to be used here in this file, it's for speed */
63 extern struct Render R;
64 /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
65
66 static int vol_backface_intersect_check(Isect *is, int ob, RayFace *face)
67 {
68         VlakRen *vlr = (VlakRen *)face;
69         
70         /* only consider faces away, so overlapping layers
71          * of foward facing geometry don't cause the ray to stop */
72         return (INPR(is->vec, vlr->n) < 0.0f);
73 }
74
75 /* TODO: Box or sphere intersection types could speed things up */
76 static int vol_get_bounds(ShadeInput *shi, float *co, float *vec, float *hitco, Isect *isect, int intersect_type, int checkfunc)
77 {
78         float maxsize = RE_ray_tree_max_size(R.raytree);
79         int intersected=0;
80
81         /* TODO: use object's bounding box to calculate max size */
82         VECCOPY(isect->start, co);
83         isect->end[0] = co[0] + vec[0] * maxsize;
84         isect->end[1] = co[1] + vec[1] * maxsize;
85         isect->end[2] = co[2] + vec[2] * maxsize;
86         
87         isect->mode= RE_RAY_MIRROR;
88         isect->oborig= RAY_OBJECT_SET(&R, shi->obi);
89         isect->face_last= NULL;
90         isect->ob_last= 0;
91         isect->lay= -1;
92         
93         if (intersect_type == VOL_BOUNDS_DEPTH) isect->faceorig= (RayFace*)shi->vlr;
94         else if (intersect_type == VOL_BOUNDS_SS) isect->faceorig= NULL;
95         
96         if (checkfunc==VOL_IS_BACKFACE)
97                 intersected = RE_ray_tree_intersect_check(R.raytree, isect, vol_backface_intersect_check);
98         else
99                 intersected = RE_ray_tree_intersect(R.raytree, isect);
100         
101         if(intersected)
102         {
103                 float isvec[3];
104
105                 VECCOPY(isvec, isect->vec);
106                 hitco[0] = isect->start[0] + isect->labda*isvec[0];
107                 hitco[1] = isect->start[1] + isect->labda*isvec[1];
108                 hitco[2] = isect->start[2] + isect->labda*isvec[2];
109                 
110                 return 1;
111         } else {
112                 return 0;
113         }
114 }
115
116 float vol_get_stepsize(struct ShadeInput *shi, int context)
117 {
118         if (shi->mat->vol.stepsize_type == MA_VOL_STEP_RANDOMIZED) {
119                 /* range between 0.75 and 1.25 */
120                 const float rnd = 0.5f * BLI_thread_frand(shi->thread) + 0.75f;
121         
122                 if (context == STEPSIZE_VIEW)
123                         return shi->mat->vol.stepsize * rnd;
124                 else if (context == STEPSIZE_SHADE)
125                         return shi->mat->vol.shade_stepsize * rnd;
126         }
127         else {  // MA_VOL_STEP_CONSTANT
128                 
129                 if (context == STEPSIZE_VIEW)
130                         return shi->mat->vol.stepsize;
131                 else if (context == STEPSIZE_SHADE)
132                         return shi->mat->vol.shade_stepsize;
133         }
134         
135         return shi->mat->vol.stepsize;
136 }
137
138 static float vol_get_depth_cutoff(struct ShadeInput *shi)
139 {
140         return shi->mat->vol.depth_cutoff;
141 }
142
143 /* trilinear interpolation */
144 static void vol_get_precached_scattering(ShadeInput *shi, float *scatter_col, float *co)
145 {
146         VolumePrecache *vp = shi->obi->volume_precache;
147         float bbmin[3], bbmax[3], dim[3];
148         float sample_co[3];
149         
150         if (!vp) return;
151         
152         /* convert input coords to 0.0, 1.0 */
153         VECCOPY(bbmin, shi->obi->obr->boundbox[0]);
154         VECCOPY(bbmax, shi->obi->obr->boundbox[1]);
155         VecSubf(dim, bbmax, bbmin);
156
157         sample_co[0] = ((co[0] - bbmin[0]) / dim[0]);
158         sample_co[1] = ((co[1] - bbmin[1]) / dim[1]);
159         sample_co[2] = ((co[2] - bbmin[2]) / dim[2]);
160
161         scatter_col[0] = voxel_sample_trilinear(vp->data_r, vp->res, sample_co);
162         scatter_col[1] = voxel_sample_trilinear(vp->data_g, vp->res, sample_co);
163         scatter_col[2] = voxel_sample_trilinear(vp->data_b, vp->res, sample_co);
164 }
165
166 float vol_get_density(struct ShadeInput *shi, float *co)
167 {
168         float density = shi->mat->vol.density;
169         float density_scale = shi->mat->vol.density_scale;
170         float col[3] = {0.0, 0.0, 0.0};
171         
172         do_volume_tex(shi, co, MAP_DENSITY, col, &density);
173         
174         return density * density_scale;
175 }
176
177 /* scattering multiplier, values above 1.0 are non-physical, 
178  * but can be useful to tweak lighting */
179 float vol_get_scattering_fac(ShadeInput *shi, float *co)
180 {
181         float scatter = shi->mat->vol.scattering;
182         float col[3] = {0.0, 0.0, 0.0};
183         
184         do_volume_tex(shi, co, MAP_SCATTERING, col, &scatter);
185         
186         return scatter;
187 }
188
189 /* compute emission component, amount of radiance to add per segment
190  * can be textured with 'emit' */
191 void vol_get_emission(ShadeInput *shi, float *emission_col, float *co, float density)
192 {
193         float emission = shi->mat->vol.emission;
194         VECCOPY(emission_col, shi->mat->vol.emission_col);
195         
196         do_volume_tex(shi, co, MAP_EMISSION+MAP_EMISSION_COL, emission_col, &emission);
197         
198         emission_col[0] = emission_col[0] * emission * density;
199         emission_col[1] = emission_col[1] * emission * density;
200         emission_col[2] = emission_col[2] * emission * density;
201 }
202
203 void vol_get_absorption(ShadeInput *shi, float *absorb_col, float *co)
204 {
205         float absorption = shi->mat->vol.absorption;
206         VECCOPY(absorb_col, shi->mat->vol.absorption_col);
207         
208         do_volume_tex(shi, co, MAP_ABSORPTION+MAP_ABSORPTION_COL, absorb_col, &absorption);
209         
210         absorb_col[0] = (1.0f - absorb_col[0]) * absorption;
211         absorb_col[1] = (1.0f - absorb_col[1]) * absorption;
212         absorb_col[2] = (1.0f - absorb_col[2]) * absorption;
213 }
214
215
216 /* phase function - determines in which directions the light 
217  * is scattered in the volume relative to incoming direction 
218  * and view direction */
219 float vol_get_phasefunc(ShadeInput *shi, short phasefunc_type, float g, float *w, float *wp)
220 {
221         const float costheta = Inpf(w, wp);
222         const float scale = M_PI;
223         
224         /*
225          * Scale constant is required, since Blender's shading system doesn't normalise for
226          * energy conservation - eg. scaling by 1/pi for a lambert shader.
227          * This makes volumes darker than other solid objects, for the same lighting intensity.
228          * To correct this, scale up the phase function values
229          * until Blender's shading system supports this better. --matt
230          */
231         
232         switch (phasefunc_type) {
233                 case MA_VOL_PH_MIEHAZY:
234                         return scale * (0.5f + 4.5f * powf(0.5 * (1.f + costheta), 8.f)) / (4.f*M_PI);
235                 case MA_VOL_PH_MIEMURKY:
236                         return scale * (0.5f + 16.5f * powf(0.5 * (1.f + costheta), 32.f)) / (4.f*M_PI);
237                 case MA_VOL_PH_RAYLEIGH:
238                         return scale * 3.f/(16.f*M_PI) * (1 + costheta * costheta);
239                 case MA_VOL_PH_HG:
240                         return scale * (1.f / (4.f * M_PI) * (1.f - g*g) / powf(1.f + g*g - 2.f * g * costheta, 1.5f));
241                 case MA_VOL_PH_SCHLICK:
242                 {
243                         const float k = 1.55f * g - .55f * g * g * g;
244                         const float kcostheta = k * costheta;
245                         return scale * (1.f / (4.f * M_PI) * (1.f - k*k) / ((1.f - kcostheta) * (1.f - kcostheta)));
246                 }
247                 case MA_VOL_PH_ISOTROPIC:
248                 default:
249                         return scale * (1.f / (4.f * M_PI));
250         }
251 }
252
253 /* Compute attenuation, otherwise known as 'optical thickness', extinction, or tau.
254  * Used in the relationship Transmittance = e^(-attenuation)
255  */
256 void vol_get_attenuation(ShadeInput *shi, float *tau, float *co, float *endco, float density, float stepsize)
257 {
258         /* input density = density at co */
259         float absorb_col[3];
260         int s, nsteps;
261         float step_vec[3], step_sta[3], step_end[3];
262         const float dist = VecLenf(co, endco);
263
264         vol_get_absorption(shi, absorb_col, co);
265
266         nsteps = (int)((dist / stepsize) + 0.5);
267         
268         /* trigger for recalculating density */
269         if (density < -0.001f) density = vol_get_density(shi, co);
270         
271         if (nsteps == 1) {
272                 /* homogenous volume within the sampled distance */
273                 tau[0] = tau[1] = tau[2] = dist * density;
274                 
275                 VecMulVecf(tau, tau, absorb_col);
276                 return;
277         } else {
278                 tau[0] = tau[1] = tau[2] = 0.0;
279         }
280         
281         VecSubf(step_vec, endco, co);
282         VecMulf(step_vec, 1.0f / nsteps);
283         
284         VecCopyf(step_sta, co);
285         VecAddf(step_end, step_sta, step_vec);
286         
287         for (s = 0;  s < nsteps; s++) {
288                 if (s > 0)
289                         density = vol_get_density(shi, step_sta);
290                 
291                 tau[0] += stepsize * density;
292                 tau[1] += stepsize * density;
293                 tau[2] += stepsize * density;
294                 
295                 if (s < nsteps-1) {
296                         VECCOPY(step_sta, step_end);
297                         VecAddf(step_end, step_end, step_vec);
298                 }
299         }
300         VecMulVecf(tau, tau, absorb_col);
301 }
302
303 void vol_shade_one_lamp(struct ShadeInput *shi, float *co, LampRen *lar, float *lacol, float stepsize, float density)
304 {
305         float visifac, lv[3], lampdist;
306         float tau[3], tr[3]={1.0,1.0,1.0};
307         float hitco[3], *atten_co;
308         float p;
309         float scatter_fac;
310         float shade_stepsize = vol_get_stepsize(shi, STEPSIZE_SHADE);
311         
312         if (lar->mode & LA_LAYER) if((lar->lay & shi->obi->lay)==0) return;
313         if ((lar->lay & shi->lay)==0) return;
314         if (lar->energy == 0.0) return;
315         
316         visifac= lamp_get_visibility(lar, co, lv, &lampdist);
317         if(visifac==0.0f) return;
318
319         lacol[0] = lar->r;
320         lacol[1] = lar->g;
321         lacol[2] = lar->b;
322         
323         if(lar->mode & LA_TEXTURE) {
324                 shi->osatex= 0;
325                 do_lamp_tex(lar, lv, shi, lacol, LA_TEXTURE);
326         }
327
328         VecMulf(lacol, visifac*lar->energy);
329
330         if (ELEM(lar->type, LA_SUN, LA_HEMI))
331                 VECCOPY(lv, lar->vec);
332         VecMulf(lv, -1.0f);
333         
334         p = vol_get_phasefunc(shi, shi->mat->vol.phasefunc_type, shi->mat->vol.phasefunc_g, shi->view, lv);
335         VecMulf(lacol, p);
336         
337         if (shi->mat->vol.shade_type != MA_VOL_SHADE_NONE) {
338                 Isect is;
339                 
340                 /* find minimum of volume bounds, or lamp coord */
341                 if (vol_get_bounds(shi, co, lv, hitco, &is, VOL_BOUNDS_SS, 0)) {
342                         float dist = VecLenf(co, hitco);
343                         VlakRen *vlr = (VlakRen *)is.face;
344                         
345                         /* simple internal shadowing */
346                         if (vlr->mat->material_type == MA_TYPE_SURFACE) {
347                                 lacol[0] = lacol[1] = lacol[2] = 0.0f;
348                                 return;
349                         }
350
351                         if (ELEM(lar->type, LA_SUN, LA_HEMI))
352                                 atten_co = hitco;
353                         else if ( lampdist < dist ) {
354                                 atten_co = lar->co;
355                         } else
356                                 atten_co = hitco;
357                         
358                         vol_get_attenuation(shi, tau, co, atten_co, density, shade_stepsize);
359                         tr[0] = exp(-tau[0]);
360                         tr[1] = exp(-tau[1]);
361                         tr[2] = exp(-tau[2]);
362                         
363                         VecMulVecf(lacol, lacol, tr);
364                 }
365                 else {
366                         /* Point is on the outside edge of the volume,
367                          * therefore no attenuation, full transmission.
368                          * Radiance from lamp remains unchanged */
369                 }
370         }
371         
372         scatter_fac = vol_get_scattering_fac(shi, co);
373         VecMulf(lacol, scatter_fac);
374 }
375
376 /* single scattering only for now */
377 void vol_get_scattering(ShadeInput *shi, float *scatter, float *co, float stepsize, float density)
378 {
379         ListBase *lights;
380         GroupObject *go;
381         LampRen *lar;
382         float col[3] = {0.f, 0.f, 0.f};
383         
384         lights= get_lights(shi);
385         for(go=lights->first; go; go= go->next)
386         {
387                 float lacol[3] = {0.f, 0.f, 0.f};
388                 lar= go->lampren;
389                 
390                 if (lar) {
391                         vol_shade_one_lamp(shi, co, lar, lacol, stepsize, density);
392                         VecAddf(col, col, lacol);
393                 }
394         }
395         
396         VECCOPY(scatter, col);
397 }
398
399         
400 /*
401 The main volumetric integrator, using an emission/absorption/scattering model.
402
403 Incoming radiance = 
404
405 outgoing radiance from behind surface * beam transmittance/attenuation
406 + added radiance from all points along the ray due to participating media
407         --> radiance for each segment = 
408                 (radiance added by scattering + radiance added by emission) * beam transmittance/attenuation
409
410 -- To find transmittance:
411         compute optical thickness with tau (perhaps involving monte carlo integration)
412         transmittance = exp(-tau)
413         
414 -- To find radiance from segments along the way:
415         find radiance for one step: 
416         - loop over lights and weight by phase function
417 */
418 static void volumeintegrate(struct ShadeInput *shi, float *col, float *co, float *endco)
419 {
420         float tr[3] = {1.0f, 1.0f, 1.0f};
421         float radiance[3] = {0.f, 0.f, 0.f}, d_radiance[3] = {0.f, 0.f, 0.f};
422         float stepsize = vol_get_stepsize(shi, STEPSIZE_VIEW);
423         int nsteps, s;
424         float tau[3], emit_col[3], scatter_col[3] = {0.0, 0.0, 0.0};
425         float stepvec[3], step_sta[3], step_end[3], step_mid[3];
426         float density = vol_get_density(shi, co);
427         const float depth_cutoff = vol_get_depth_cutoff(shi);
428         
429         /* multiply col_behind with beam transmittance over entire distance */
430         vol_get_attenuation(shi, tau, co, endco, density, stepsize);
431         tr[0] *= exp(-tau[0]);
432         tr[1] *= exp(-tau[1]);
433         tr[2] *= exp(-tau[2]);
434         VecMulVecf(radiance, tr, col);  
435         tr[0] = tr[1] = tr[2] = 1.0f;
436         
437         /* ray marching */
438         nsteps = (int)((VecLenf(co, endco) / stepsize) + 0.5);
439         
440         VecSubf(stepvec, endco, co);
441         VecMulf(stepvec, 1.0f / nsteps);
442         VecCopyf(step_sta, co);
443         VecAddf(step_end, step_sta, stepvec);
444         
445         /* get radiance from all points along the ray due to participating media */
446         for (s = 0; s < nsteps; s++) {
447
448                 if (s > 0) density = vol_get_density(shi, step_sta);
449                 
450                 /* there's only any use in shading here if there's actually some density to shade! */
451                 if (density > 0.01f) {
452                 
453                         /* transmittance component (alpha) */
454                         vol_get_attenuation(shi, tau, step_sta, step_end, density, stepsize);
455                         tr[0] *= exp(-tau[0]);
456                         tr[1] *= exp(-tau[1]);
457                         tr[2] *= exp(-tau[2]);
458                         
459                         step_mid[0] = step_sta[0] + (stepvec[0] * 0.5);
460                         step_mid[1] = step_sta[1] + (stepvec[1] * 0.5);
461                         step_mid[2] = step_sta[2] + (stepvec[2] * 0.5);
462                 
463                         /* incoming light via emission or scattering (additive) */
464                         vol_get_emission(shi, emit_col, step_mid, density);
465                         
466                         if (using_lightcache(shi->mat)) {
467                                 vol_get_precached_scattering(shi, scatter_col, step_mid);
468                         } else
469                                 vol_get_scattering(shi, scatter_col, step_mid, stepsize, density);
470                                                 
471                         VecMulf(scatter_col, density);
472                         VecAddf(d_radiance, emit_col, scatter_col);
473                         
474                         /*   Lv += Tr * (Lve() + Ld) */
475                         VecMulVecf(d_radiance, tr, d_radiance);
476                         VecMulf(d_radiance, stepsize);
477                         
478                         VecAddf(radiance, radiance, d_radiance);        
479                 }
480
481                 VecCopyf(step_sta, step_end);
482                 VecAddf(step_end, step_end, stepvec);
483                 
484                 /* luminance rec. 709 */
485                 if ((0.2126*tr[0] + 0.7152*tr[1] + 0.0722*tr[2]) < depth_cutoff) break; 
486         }
487         
488         VecCopyf(col, radiance);
489         col[3] = 1.0f -(tr[0] + tr[1] + tr[2]) * 0.333f;
490 }
491
492 static void shade_intersection(ShadeInput *shi, float *col, Isect *is)
493 {
494         ShadeInput shi_new;
495         ShadeResult shr_new;
496         
497         memset(&shi_new, 0, sizeof(ShadeInput)); 
498         
499         shi_new.mask= shi->mask;
500         shi_new.osatex= shi->osatex;
501         shi_new.thread= shi->thread;
502         shi_new.depth = shi->depth + 1;
503         shi_new.volume_depth= shi->volume_depth + 1;
504         shi_new.xs= shi->xs;
505         shi_new.ys= shi->ys;
506         shi_new.lay= shi->lay;
507         shi_new.passflag= SCE_PASS_COMBINED; /* result of tracing needs no pass info */
508         shi_new.combinedflag= 0xFFFFFF;          /* ray trace does all options */
509         shi_new.light_override= shi->light_override;
510         shi_new.mat_override= shi->mat_override;
511         
512         VECCOPY(shi_new.camera_co, is->start);
513         
514         memset(&shr_new, 0, sizeof(ShadeResult));
515
516         /* hardcoded limit of 100 for now - prevents problems in weird geometry */
517         if (shi->volume_depth < 100) {
518                 shade_ray(is, &shi_new, &shr_new);
519         }
520         
521         col[0] = shr_new.combined[0];
522         col[1] = shr_new.combined[1];
523         col[2] = shr_new.combined[2];
524         col[3] = shr_new.alpha;
525 }
526
527 static void vol_trace_behind(ShadeInput *shi, VlakRen *vlr, float *co, float *col)
528 {
529         Isect isect;
530         float maxsize = RE_ray_tree_max_size(R.raytree);
531
532         VECCOPY(isect.start, co);
533         isect.end[0] = isect.start[0] + shi->view[0] * maxsize;
534         isect.end[1] = isect.start[1] + shi->view[1] * maxsize;
535         isect.end[2] = isect.start[2] + shi->view[2] * maxsize;
536
537         isect.faceorig= (RayFace *)vlr;
538         
539         isect.mode= RE_RAY_MIRROR;
540         isect.oborig= RAY_OBJECT_SET(&R, shi->obi);
541         isect.face_last= NULL;
542         isect.ob_last= 0;
543         isect.lay= -1;
544         
545         /* check to see if there's anything behind the volume, otherwise shade the sky */
546         if(RE_ray_tree_intersect(R.raytree, &isect)) {
547                 shade_intersection(shi, col, &isect);
548         } else {
549                 shadeSkyView(col, co, shi->view, NULL, shi->thread);
550                 shadeSunView(col, shi->view);
551         }
552 }
553
554 /* the main entry point for volume shading */
555 static void volume_trace(struct ShadeInput *shi, struct ShadeResult *shr, int inside_volume)
556 {
557         float hitco[3], col[4] = {0.f,0.f,0.f,0.f};
558         int trace_behind = 1;
559         Isect is;
560
561         /* check for shading an internal face a volume object directly */
562         if (inside_volume == VOL_SHADE_INSIDE) {
563                 trace_behind = 0;
564         }
565         if (inside_volume == VOL_SHADE_OUTSIDE) {
566                 if (shi->flippednor)
567                         inside_volume = VOL_SHADE_INSIDE;
568         }
569
570         if (inside_volume == VOL_SHADE_INSIDE) {
571                 
572                 if (trace_behind) {
573                         /* trace behind the volume object */
574                         vol_trace_behind(shi, shi->vlr, shi->co, col);
575                 } else {
576                         /* we're tracing through the volume between the camera 
577                          * and a solid surface, so use that pre-shaded radiance */
578                         QUATCOPY(col, shr->combined);
579                 }
580                 
581                 /* shade volume from 'camera' to 1st hit point */
582                 volumeintegrate(shi, col, shi->camera_co, shi->co);
583                 
584                 VecCopyf(shr->combined, col);
585                 
586                 if (shi->mat->vol.shadeflag & MA_VOL_USEALPHA) {
587                         if (col[3] > 1.0f)
588                                 col[3] = 1.0f;
589                 }
590                 else
591                         col[3] = 1.0f;
592                 shr->combined[3] = col[3];
593                 shr->alpha = col[3];
594                 
595                 VECCOPY(shr->diff, shr->combined);
596         }
597         /* trace to find a backface, the other side bounds of the volume */
598         /* (ray intersect ignores front faces here) */
599         else if (vol_get_bounds(shi, shi->co, shi->view, hitco, &is, VOL_BOUNDS_DEPTH, 0)) {
600                 VlakRen *vlr = (VlakRen *)is.face;
601                 
602                 /* if it's another face in the same material */
603                 if (vlr->mat == shi->mat) {
604                         /* trace behind the 2nd (raytrace) hit point */
605                         vol_trace_behind(shi, (VlakRen *)is.face, hitco, col);
606                 } else {
607                         shade_intersection(shi, col, &is);
608                 }
609         
610                 /* shade volume from 1st hit point to 2nd hit point */
611                 volumeintegrate(shi, col, shi->co, hitco);
612                 
613                 VecCopyf(shr->combined, col);
614                 
615                 if (shi->mat->vol.shadeflag & MA_VOL_USEALPHA) {
616                         if (col[3] > 1.0f)
617                                 col[3] = 1.0f;
618                 }
619                 else
620                         col[3] = 1.0f;
621                 shr->combined[3] = col[3];
622                 shr->alpha = col[3];
623                 
624                 VECCOPY(shr->diff, shr->combined);
625         }
626         else {
627                 shr->combined[0] = 0.0f;
628                 shr->combined[1] = 0.0f;
629                 shr->combined[2] = 0.0f;
630                 shr->combined[3] = shr->alpha =  1.0f;
631         }
632 }
633
634 /* Traces a shadow through the object, 
635  * pretty much gets the transmission over a ray path */
636 void shade_volume_shadow(struct ShadeInput *shi, struct ShadeResult *shr, struct Isect *last_is)
637 {
638         float hitco[3];
639         float tr[3] = {1.0,1.0,1.0};
640         float tau[3] = {0.0,0.0,0.0};
641         Isect is;
642         float shade_stepsize = vol_get_stepsize(shi, STEPSIZE_SHADE);
643
644         memset(shr, 0, sizeof(ShadeResult));
645         
646         /* if 1st hit normal is facing away from the camera, 
647          * then we're inside the volume already. */
648         if (shi->flippednor) {
649         
650                 vol_get_attenuation(shi, tau, last_is->start, shi->co, -1.0f, shade_stepsize);
651                 tr[0] = exp(-tau[0]);
652                 tr[1] = exp(-tau[1]);
653                 tr[2] = exp(-tau[2]);
654                 
655                 
656                 VecCopyf(shr->combined, tr);
657                 
658                 shr->combined[3] = 1.0f -(tr[0] + tr[1] + tr[2]) * 0.333f;
659                 shr->alpha = shr->combined[3];
660         }
661         /* trace to find a backface, the other side bounds of the volume */
662         /* (ray intersect ignores front faces here) */
663         else if (vol_get_bounds(shi, shi->co, shi->view, hitco, &is, VOL_BOUNDS_DEPTH, 0)) {
664                 
665                 vol_get_attenuation(shi, tau, shi->co, hitco, -1.0f, shade_stepsize);
666                 tr[0] = exp(-tau[0]);
667                 tr[1] = exp(-tau[1]);
668                 tr[2] = exp(-tau[2]);
669                 
670                 VecCopyf(shr->combined, tr);
671                 
672                 shr->combined[3] = 1.0f -(tr[0] + tr[1] + tr[2]) * 0.333f;
673                 shr->alpha = shr->combined[3];
674
675         }
676         else {
677                 shr->combined[0] = 0.0f;
678                 shr->combined[1] = 0.0f;
679                 shr->combined[2] = 0.0f;
680                 shr->combined[3] = shr->alpha =  0.0f;
681         }
682 }
683
684
685 /* delivers a fully filled in ShadeResult, for all passes */
686 void shade_volume_outside(ShadeInput *shi, ShadeResult *shr)
687 {
688         memset(shr, 0, sizeof(ShadeResult));
689         
690         volume_trace(shi, shr, VOL_SHADE_OUTSIDE);
691 }
692
693
694 void shade_volume_inside(ShadeInput *shi, ShadeResult *shr)
695 {
696         MatInside *m;
697         Material *mat_backup;
698         
699         if (BLI_countlist(&R.render_volumes_inside) == 0) return;
700         
701         mat_backup = shi->mat;
702         
703 //      for (m=R.render_volumes_inside.first; m; m=m->next) {
704 //              printf("matinside: ma: %s \n", m->ma->id.name+2);
705 //      }
706
707         m = R.render_volumes_inside.first;
708         shi->mat = m->ma;
709         
710         volume_trace(shi, shr, VOL_SHADE_INSIDE);
711
712         shi->mat = mat_backup;
713 }