svn merge -r 16592:16667 https://svn.blender.org/svnroot/bf-blender/trunk/blender
authorDaniel Genrich <daniel.genrich@gmx.net>
Mon, 22 Sep 2008 10:04:45 +0000 (10:04 +0000)
committerDaniel Genrich <daniel.genrich@gmx.net>
Mon, 22 Sep 2008 10:04:45 +0000 (10:04 +0000)
15 files changed:
source/blender/blenkernel/intern/material.c
source/blender/blenlib/BLI_arithb.h
source/blender/blenlib/intern/arithb.c
source/blender/blenloader/intern/readfile.c
source/blender/makesdna/DNA_material_types.h
source/blender/render/intern/include/shading.h
source/blender/render/intern/include/texture.h
source/blender/render/intern/include/volumetric.h [new file with mode: 0644]
source/blender/render/intern/source/convertblender.c
source/blender/render/intern/source/shadeinput.c
source/blender/render/intern/source/shadeoutput.c
source/blender/render/intern/source/texture.c
source/blender/render/intern/source/volumetric.c [new file with mode: 0644]
source/blender/src/buttons_shading.c
source/blender/src/previewrender.c

index f05b84f6e90ddc8727c9af9467fbbd015feb17a5..5c20858ec63763c4854fa3dc449842943d9a56f2 100644 (file)
@@ -166,6 +166,11 @@ void init_material(Material *ma)
        ma->sss_texfac= 0.0f;
        ma->sss_front= 1.0f;
        ma->sss_back= 1.0f;
+       
+       ma->vol_stepsize = 0.2f;
+       ma->vol_shade_stepsize = 0.2f;
+       ma->vol_absorption = 1.0f;
+       ma->vol_scattering = 1.0f;
 
        ma->mode= MA_TRACEBLE|MA_SHADBUF|MA_SHADOW|MA_RADIO|MA_RAYBIAS|MA_TANGENT_STR;
 
index e2e71a2fb1a7e67cde095a0f5886eee2e2f78bd9..bc5306214037ef1f5e98bb724ddf384ac24a1baa 100644 (file)
@@ -251,6 +251,7 @@ void printvec4f(char *str, float v[4]);
 
 void VecAddf(float *v, float *v1, float *v2);
 void VecSubf(float *v, float *v1, float *v2);
+void VecMulVecf(float *v, float *v1, float *v2);
 void VecLerpf(float *target, float *a, float *b, float t);
 void VecMidf(float *v, float *v1, float *v2);
 
index 888a5ab2f6437c3e69e4296aa327972ebd5b72f3..9c3c561ac8484220da946ceead7dcc82a3e885a9 100644 (file)
@@ -2139,6 +2139,13 @@ void VecSubf(float *v, float *v1, float *v2)
        v[2]= v1[2]- v2[2];
 }
 
+void VecMulVecf(float *v, float *v1, float *v2)
+{
+       v[0] = v1[0] * v2[0];
+       v[1] = v1[1] * v2[1];
+       v[2] = v1[2] * v2[2];
+}
+
 void VecLerpf(float *target, float *a, float *b, float t)
 {
        float s = 1.0f-t;
@@ -3282,6 +3289,12 @@ float Normalize2(float *n)
        return d;
 }
 
+float rgb_to_luminance(float r, float g, float b)
+{
+       /* Rec. 709 HDTV */
+       return (0.2126*r + 0.7152*g + 0.0722*b);
+}
+
 void hsv_to_rgb(float h, float s, float v, float *r, float *g, float *b)
 {
        int i;
index 8d9980166675b16d62f53590193d5f94de9b7c87..63f3f88da500dec5be94295fdccf89c85fdbe59b 100644 (file)
@@ -7689,6 +7689,7 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
        if ((main->versionfile < 245) || (main->versionfile == 245 && main->subversionfile < 11)) {
                Object *ob;
                bActionStrip *strip;
+
                
                /* nla-strips - scale */                
                for (ob= main->object.first; ob; ob= ob->id.next) {
@@ -7712,12 +7713,14 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
                                ob->soft->shearstiff = 1.0f; 
                        }
                }
+               
        }
 
        if ((main->versionfile < 245) || (main->versionfile == 245 && main->subversionfile < 14)) {
                Scene *sce= main->scene.first;
                Sequence *seq;
                Editing *ed;
+               Material *ma;
                
                while(sce) {
                        ed= sce->ed;
@@ -7732,6 +7735,13 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
                        
                        sce= sce->id.next;
                }
+               
+               for(ma=main->mat.first; ma; ma= ma->id.next) {
+                       if (ma->vol_shade_stepsize < 0.001f) ma->vol_shade_stepsize = 0.2f;
+                       if (ma->vol_stepsize < 0.001f) ma->vol_stepsize = 0.2f;
+                       if (ma->vol_absorption < 0.001f) ma->vol_absorption = 1.0f;
+                       if (ma->vol_scattering < 0.001f) ma->vol_scattering = 1.0f;
+               }
        }
        
        /*fix broken group lengths in id properties*/
index aa8470505810d694e47165e35c8a69582e26a14f..ee4779779ec7c338d3b9bbb4e0b01f34ab7bf469 100644 (file)
@@ -62,6 +62,16 @@ typedef struct Material {
        float translucency;
        /* end synced with render_types.h */
        
+       short material_type; /* solid, halo, volumetric */
+       short pad5[3];
+       
+       /* volumetrics */
+       float vol_alphathresh;
+       float vol_stepsize, vol_shade_stepsize;
+       float vol_absorption, vol_scattering;
+       short vol_shadeflag;
+       short vpad;
+       
        float fresnel_mir, fresnel_mir_i;
        float fresnel_tra, fresnel_tra_i;
        float filter;           /* filter added, for raytrace transparency and transmissivity */
@@ -154,6 +164,12 @@ typedef struct Material {
                /* for render */
 #define MA_IS_USED             1
 
+/* material_type */
+#define MA_SOLID               0
+#define MA_PTHALO              1
+#define MA_VOLUME              2
+#define MA_VOLUMESOLID 3
+
 /* mode (is int) */
 #define MA_TRACEBLE            1
 #define MA_SHADOW              2
@@ -328,5 +344,10 @@ typedef struct Material {
 /* sss_flag */
 #define MA_DIFF_SSS            1
 
+/* vol_shadeflag */
+#define MA_VOL_SHADED          1
+#define MA_VOL_ATTENUATED      2
+#define MA_VOL_SHADOWED                4
+
 #endif
 
index 6f1cb8dd7a923cab9932a15e00feed0d26a44afb..9229e612337c5d8f85c6bd222523538c4cc5c750 100644 (file)
@@ -52,6 +52,7 @@ typedef struct ShadeSample {
 
        /* also the node shader callback */
 void shade_material_loop(struct ShadeInput *shi, struct ShadeResult *shr);
+void shade_volume_loop(struct ShadeInput *shi, struct ShadeResult *shr);
 
 void shade_input_set_triangle_i(struct ShadeInput *shi, struct ObjectInstanceRen *obi, struct VlakRen *vlr, short i1, short i2, short i3);
 void shade_input_set_triangle(struct ShadeInput *shi, volatile int obi, volatile int facenr, int normal_flip);
@@ -85,6 +86,7 @@ void shade_color(struct ShadeInput *shi, ShadeResult *shr);
 void ambient_occlusion_to_diffuse(struct ShadeInput *shi, float *diff);
 void ambient_occlusion(struct ShadeInput *shi);
 
+ListBase *get_lights(struct ShadeInput *shi);
 float lamp_get_visibility(struct LampRen *lar, float *co, float *lv, float *dist);
 void lamp_get_shadow(struct LampRen *lar, ShadeInput *shi, float inp, float *shadfac, int do_real);
 
index be5471e07c4d451a5b6ce0ce31d34697c0393a8d..64b88c050d2908f12b7f46d972193f7f5aa97f23 100644 (file)
@@ -56,6 +56,7 @@ void do_halo_tex(struct HaloRen *har, float xn, float yn, float *colf);
 void do_sky_tex(float *rco, float *lo, float *dxyview, float *hor, float *zen, float *blend, int skyflag);
 void do_material_tex(struct ShadeInput *shi);
 void do_lamp_tex(LampRen *la, float *lavec, struct ShadeInput *shi, float *colf, int effect);
+void do_volume_tex(ShadeInput *shi, float *xyz, float *col, float *alpha, float *emit);
 
 void init_render_textures(Render *re);
 
diff --git a/source/blender/render/intern/include/volumetric.h b/source/blender/render/intern/include/volumetric.h
new file mode 100644 (file)
index 0000000..8db3fa6
--- /dev/null
@@ -0,0 +1,29 @@
+/**
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): Farsthary (Raul FHernandez), Matt Ebb.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+void volume_trace(struct ShadeInput *shi, struct ShadeResult *shr);
\ No newline at end of file
index 2baa4d274489b549d68707b4a120eea75ace8229..a752561218ca24fff517b989a2b97bf8c65fa1a4 100644 (file)
@@ -941,6 +941,8 @@ 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;
+       
        return ma;
 }
 
index 7397d623264b7d06a2c338412179d1225f37bfab..cd5ecc413dff8b21845b946bb7bf1470b3ed4251 100644 (file)
@@ -135,6 +135,12 @@ void shade_material_loop(ShadeInput *shi, ShadeResult *shr)
        }       
 }
 
+/* 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);
+}
+
 
 /* do a shade, finish up some passes, apply mist */
 void shade_input_do_shade(ShadeInput *shi, ShadeResult *shr)
@@ -151,7 +157,8 @@ void shade_input_do_shade(ShadeInput *shi, ShadeResult *shr)
                memcpy(&shi->r, &shi->mat->r, 23*sizeof(float));
                shi->har= shi->mat->har;
                
-               shade_material_loop(shi, shr);
+               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);
        }
        
        /* copy additional passes */
index 91621c24365810de283276913798737948554f5a..7a2a9ef7b6e0b2330892db368ab04d199739d33f 100644 (file)
@@ -58,7 +58,7 @@
 extern struct Render R;
 /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
 
-static ListBase *get_lights(ShadeInput *shi)
+ListBase *get_lights(ShadeInput *shi)
 {
        
        if(shi->light_override)
index c14425e274fb75871ba115c46bb5c028e82a1cfa..e874f98ede192a6b0daa1eb0287dc47b144b5da1 100644 (file)
@@ -1451,6 +1451,141 @@ float texture_value_blend(float tex, float out, float fact, float facg, int blen
        return in;
 }
 
+void do_volume_tex(ShadeInput *shi, float *xyz, float *col, float *alpha, float *emit)
+{
+       MTex *mtex;
+       Tex *tex;
+       TexResult texres= {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0, NULL};
+       int tex_nr, rgbnor= 0;
+       float co[3], texvec[3];
+       float fact, stencilTin=1.0;
+       
+       if (R.r.scemode & R_NO_TEX) return;
+       /* here: test flag if there's a tex (todo) */
+       
+       for(tex_nr=0; tex_nr<MAX_MTEX; tex_nr++) {
+               /* separate tex switching */
+               if(shi->mat->septex & (1<<tex_nr)) continue;
+               
+               if(shi->mat->mtex[tex_nr]) {
+                       mtex= shi->mat->mtex[tex_nr];
+                       tex= mtex->tex;
+                       if(tex==0) continue;
+                       
+                       /* which coords */
+                       if(mtex->texco==TEXCO_OBJECT) { 
+                               Object *ob= mtex->object;
+                               ob= mtex->object;
+                               if(ob) {                                                
+                                       VECCOPY(co, xyz);       
+                                       if(mtex->texflag & MTEX_OB_DUPLI_ORIG) {
+                                               if(shi->obi && shi->obi->duplitexmat)
+                                                       MTC_Mat4MulVecfl(shi->obi->duplitexmat, co);                                    
+                                       } 
+                                       MTC_Mat4MulVecfl(ob->imat, co);
+                               }
+                       }
+                       else if(mtex->texco==TEXCO_GLOB) {                                                      
+                          VECCOPY(co, xyz);            
+                       }
+                       else continue;  // can happen when texco defines disappear and it renders old files
+
+                       texres.nor= NULL;
+                       
+                       if(tex->type==TEX_IMAGE) {
+                               continue;       /* not supported yet */
+                       }
+                       else {
+                               /* placement */
+                               if(mtex->projx) texvec[0]= mtex->size[0]*(co[mtex->projx-1]+mtex->ofs[0]);
+                               else texvec[0]= mtex->size[0]*(mtex->ofs[0]);
+
+                               if(mtex->projy) texvec[1]= mtex->size[1]*(co[mtex->projy-1]+mtex->ofs[1]);
+                               else texvec[1]= mtex->size[1]*(mtex->ofs[1]);
+
+                               if(mtex->projz) texvec[2]= mtex->size[2]*(co[mtex->projz-1]+mtex->ofs[2]);
+                               else texvec[2]= mtex->size[2]*(mtex->ofs[2]);
+                       }
+                       
+
+                       rgbnor= multitex(tex, co, NULL, NULL, 0, &texres);      /* NULL = dxt/dyt, 0 = shi->osatex - not supported */
+                       
+                       /* texture output */
+
+                       if( (rgbnor & TEX_RGB) && (mtex->texflag & MTEX_RGBTOINT)) {
+                               texres.tin= (0.35*texres.tr+0.45*texres.tg+0.2*texres.tb);
+                               rgbnor-= TEX_RGB;
+                       }
+                       if(mtex->texflag & MTEX_NEGATIVE) {
+                               if(rgbnor & TEX_RGB) {
+                                       texres.tr= 1.0-texres.tr;
+                                       texres.tg= 1.0-texres.tg;
+                                       texres.tb= 1.0-texres.tb;
+                               }
+                               texres.tin= 1.0-texres.tin;
+                       }
+                       if(mtex->texflag & MTEX_STENCIL) {
+                               if(rgbnor & TEX_RGB) {
+                                       fact= texres.ta;
+                                       texres.ta*= stencilTin;
+                                       stencilTin*= fact;
+                               }
+                               else {
+                                       fact= texres.tin;
+                                       texres.tin*= stencilTin;
+                                       stencilTin*= fact;
+                               }
+                       }
+                       
+                       
+                       if(mtex->mapto & (MAP_COL)) {
+                               float tcol[3], colfac;
+                               
+                               /* stencil maps on the texture control slider, not texture intensity value */
+                               colfac= mtex->colfac*stencilTin;
+                               
+                               tcol[0]=texres.tr; tcol[1]=texres.tg; tcol[2]=texres.tb;
+                               
+                               if((rgbnor & TEX_RGB)==0) {
+                                       tcol[0]= mtex->r;
+                                       tcol[1]= mtex->g;
+                                       tcol[2]= mtex->b;
+                               }
+                               else if(mtex->mapto & MAP_ALPHA) {
+                                       texres.tin= stencilTin;
+                               }
+                               else texres.tin= texres.ta;
+                               
+                               if(mtex->mapto & MAP_COL) {
+                                       texture_rgb_blend(col, tcol, col, texres.tin, colfac, mtex->blendtype);
+                               }
+                       }
+                       
+                       if(mtex->mapto & MAP_VARS) {
+                               /* stencil maps on the texture control slider, not texture intensity value */
+                               float varfac= mtex->varfac*stencilTin;
+                               
+                               if(rgbnor & TEX_RGB) {
+                                       if(texres.talpha) texres.tin= texres.ta;
+                                       else texres.tin= (0.35*texres.tr+0.45*texres.tg+0.2*texres.tb);
+                               }
+                               
+                               if(mtex->mapto & MAP_EMIT) {
+                                       int flip= mtex->maptoneg & MAP_EMIT;
+
+                                       *emit = texture_value_blend(mtex->def_var, *emit, texres.tin, varfac, mtex->blendtype, flip);
+                                       if(*emit<0.0) *emit= 0.0;
+                               }
+                               if(mtex->mapto & MAP_ALPHA) {
+                                       int flip= mtex->maptoneg & MAP_ALPHA;
+
+                                       *alpha = texture_value_blend(mtex->def_var, *alpha, texres.tin, varfac, mtex->blendtype, flip);
+                                       CLAMP(*alpha, 0.0, 1.0);
+                               }
+                       }
+               }
+       }
+}
 
 void do_material_tex(ShadeInput *shi)
 {
diff --git a/source/blender/render/intern/source/volumetric.c b/source/blender/render/intern/source/volumetric.c
new file mode 100644 (file)
index 0000000..3ca8c0a
--- /dev/null
@@ -0,0 +1,400 @@
+/**
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): Farsthary (Raul FHernandez), Matt Ebb.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include <math.h>
+#include <string.h>
+#include <stdlib.h>
+#include <float.h>
+
+#include "BLI_blenlib.h"
+#include "BLI_arithb.h"
+#include "BLI_rand.h"
+
+#include "RE_shader_ext.h"
+#include "RE_raytrace.h"
+
+#include "DNA_material_types.h"
+#include "DNA_group_types.h"
+#include "DNA_lamp_types.h"
+
+#include "render_types.h"
+#include "shading.h"
+
+/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
+/* defined in pipeline.c, is hardcopy of active dynamic allocated Render */
+/* only to be used here in this file, it's for speed */
+extern struct Render R;
+/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
+
+static int vol_backface_intersect_check(Isect *is, int ob, RayFace *face)
+{
+       VlakRen *vlr = (VlakRen *)face;
+       
+       /* only consider faces away, so overlapping layers
+        * of foward facing geometry don't cause the ray to stop */
+       return (INPR(is->vec, vlr->n) < 0.0f);
+}
+
+#define VOL_IS_SAMEOBJECT              1
+#define VOL_IS_SAMEMATERIAL            2
+
+int vol_get_bounds(ShadeInput *shi, float *co, float *vec, float *hitco)
+{
+       /* TODO: Box or sphere intersection types could speed things up */
+
+       /* raytrace method */
+       Isect isect;
+       float maxsize = RE_ray_tree_max_size(R.raytree);
+
+       /* TODO: use object's bounding box to calculate max size */
+       VECCOPY(isect.start, co);
+       isect.end[0] = co[0] + vec[0] * maxsize;
+       isect.end[1] = co[1] + vec[1] * maxsize;
+       isect.end[2] = co[2] + vec[2] * maxsize;
+       
+       isect.mode= RE_RAY_MIRROR;
+       isect.faceorig= (RayFace*)shi->vlr;
+       isect.oborig= RAY_OBJECT_SET(&R, shi->obi);
+       isect.face_last= NULL;
+       isect.ob_last= 0;
+       isect.lay= -1;
+       
+       if(RE_ray_tree_intersect(R.raytree, &isect))
+       {
+               float isvec[3];
+
+               VECCOPY(isvec, isect.vec);
+               hitco[0] = isect.start[0] + isect.labda*isvec[0];
+               hitco[1] = isect.start[1] + isect.labda*isvec[1];
+               hitco[2] = isect.start[2] + isect.labda*isvec[2];
+               
+               return 1;
+       } else {
+               return 0;
+       }
+}
+
+float vol_get_density(struct ShadeInput *shi, float *co)
+{
+       float density = shi->mat->alpha;
+       float emit_fac=0.0f;
+       float col[3] = {0.0, 0.0, 0.0};
+       
+       /* do any density gain stuff here */
+       
+       do_volume_tex(shi, co, col, &density, &emit_fac);
+       
+       return density;
+}
+
+
+/* compute emission component, amount of radiance to add per segment
+ * can be textured with 'emit' */
+void vol_get_emission(ShadeInput *shi, float *em, float *co, float *endco, float density)
+{
+       float emission = shi->mat->emit;
+       float col[3] = {0.0, 0.0, 0.0};
+       float dens_dummy = 1.0f;
+       
+       do_volume_tex(shi, co, col, &dens_dummy, &emission);
+       
+       em[0] = em[1] = em[2] = emission;
+}
+
+
+/* Compute attenuation, otherwise known as 'optical thickness', extinction, or tau.
+ * Used in the relationship Transmittance = e^(-attenuation)
+ * can be textured with 'alpha' */
+void vol_get_attenuation(ShadeInput *shi, float *tau, float *co, float *endco, float density, float stepsize)
+{
+       /* input density = density at co */
+
+       float dist;
+       float absorption = shi->mat->vol_absorption;
+       int s, nsteps;
+       float step_vec[3], step_sta[3], step_end[3];
+
+       dist = VecLenf(co, endco);
+
+       nsteps = (int)ceil(dist / stepsize);
+       
+       if (nsteps == 1) {
+               /* homogenous volume within the sampled distance */
+               tau[0] = tau[1] = tau[2] = dist * density;
+               VecMulf(tau, absorption);
+               return;
+       } else {
+               tau[0] = tau[1] = tau[2] = 0.0;
+       }
+       
+       VecSubf(step_vec, endco, co);
+       VecMulf(step_vec, 1.0f / nsteps);
+       
+       VECCOPY(step_sta, co);
+       VecAddf(step_end, step_sta, step_vec);
+       
+       for (s = 0;  s < nsteps; s++) {
+               
+               if (s > 0) density = vol_get_density(shi, step_sta);
+               
+               tau[0] += stepsize * density;
+               tau[1] += stepsize * density;
+               tau[2] += stepsize * density;
+               
+               if (s < nsteps-1) {
+                       VECCOPY(step_sta, step_end);
+                       VecAddf(step_end, step_end, step_vec);
+               }
+       }
+       VecMulf(tau, absorption);       
+}
+
+void vol_shade_one_lamp(struct ShadeInput *shi, float *co, LampRen *lar, float *col, float stepsize, float density)
+{
+       float visifac, lv[3], lampdist;
+       float lacol[3];
+       float tau[3], tr[3]={1.0,1.0,1.0};
+       float hitco[3], *atten_co;
+       
+       if (lar->mode & LA_LAYER) if((lar->lay & shi->obi->lay)==0) return;
+       if ((lar->lay & shi->lay)==0) return;
+       if (lar->energy == 0.0) return;
+       
+       visifac= lamp_get_visibility(lar, co, lv, &lampdist);
+       if(visifac==0.0f) return;
+
+       lacol[0] = lar->r;
+       lacol[1] = lar->g;
+       lacol[2] = lar->b;
+       
+       if(lar->mode & LA_TEXTURE) {
+               shi->osatex= 0;
+               do_lamp_tex(lar, lv, shi, lacol);
+       }
+       
+       VecMulf(lacol, visifac*lar->energy);
+
+       if (shi->mat->vol_shadeflag & MA_VOL_ATTENUATED) {
+               /* find minimum of volume bounds, or lamp coord */
+               
+               if (ELEM(lar->type, LA_SUN, LA_HEMI))
+                       VECCOPY(lv, lar->vec);
+               
+               VecMulf(lv, -1.0f);
+               
+               if (vol_get_bounds(shi, co, lv, hitco)) {
+                       if (ELEM(lar->type, LA_SUN, LA_HEMI))
+                               atten_co = hitco;
+                       else if ( lampdist < VecLenf(co, hitco) )
+                               atten_co = lar->co;
+                       else
+                               atten_co = hitco;
+
+                       atten_co = lar->co;
+
+                       vol_get_attenuation(shi, tau, co, atten_co, density, shi->mat->vol_shade_stepsize);
+                       tr[0] = exp(-tau[0]);
+                       tr[1] = exp(-tau[1]);
+                       tr[2] = exp(-tau[2]);
+                       
+                       VecMulVecf(lacol, lacol, tr);
+               }
+               else {
+                       /* point is on the outside edge of the volume,
+                        * therefore no attenuation, full transmission
+                        * radiance from lamp remains unchanged */
+               }
+       }
+       
+       VecAddf(col, col, lacol);
+}              
+
+/* shadows -> trace a ray to find blocker geometry
+   - if blocker is outside the volume, use standard shadow functions
+   - if blocker is inside the volume, use raytracing
+    -- (deep shadow maps could potentially slot in here too I suppose)
+   - attenuate from current point, to blocked point or volume bounds
+*/
+
+/* single scattering only for now */
+void vol_get_scattering(ShadeInput *shi, float *scatter, float *co, float *endco, float stepsize, float density)
+{
+       GroupObject *go;
+       ListBase *lights;
+       LampRen *lar;
+       float col[3] = {0.f, 0.f, 0.f};
+       
+       lights= get_lights(shi);
+       for(go=lights->first; go; go= go->next)
+       {
+               float lacol[3] = {0.f, 0.f, 0.f};
+       
+               lar= go->lampren;
+               if (lar==NULL) continue;
+               
+               vol_shade_one_lamp(shi, co, lar, lacol, stepsize, density);
+               
+               /* isotropic phase function */
+               VecMulf(lacol, 1.0f / (4.f * M_PI));
+       
+               VecMulf(lacol, density);
+               
+               VecAddf(col, col, lacol);
+       }
+       
+       
+               
+       VECCOPY(scatter, col);
+}
+
+
+
+static void volumeintegrate(struct ShadeInput *shi, float *col, float *co, float *endco)
+{
+       float total_tau;
+       float total_tr[3];
+       float tr[3] = {1.f, 1.f, 1.f};                  /* total transmittance */
+       float radiance[3] = {0.f, 0.f, 0.f}, d_radiance[3] = {0.f, 0.f, 0.f};
+       float stepsize = shi->mat->vol_stepsize;
+       int nsteps;
+       float vec[3], stepvec[3] = {0.0, 0.0, 0.0};
+       float step_tau[3], step_emit[3], step_scatter[3] = {0.0, 0.0, 0.0};
+       int s;
+       float step_sta[3], step_end[3], step_offs[3] = {0.0, 0.0, 0.0};
+       float alpha_fac, emit_fac=0.0f, tex_col[3];
+       
+       /* multiply col_behind with beam transmittance over entire distance */
+/*
+       // get col_behind
+       
+       // get total transmittance
+       vol_get_attenuation(shi, total_tau, start, dist, stepsize);
+       total_tr[0] = exp(-total_tau[0]);
+       total_tr[1] = exp(-total_tau[1]);
+       total_tr[2] = exp(-total_tau[2]);
+       VecMulVecf(radiance, total_tr, col_behind);
+*/     
+       
+       /* ray marching */
+       nsteps = (int)ceil(VecLenf(co, endco) / stepsize);
+       
+       VecSubf(vec, endco, co);
+       VECCOPY(stepvec, vec);
+       VecMulf(stepvec, 1.0f / nsteps);
+       
+       VECCOPY(step_sta, co);
+       VecAddf(step_end, step_sta, stepvec);
+       
+       
+       /* get radiance from all points along the ray due to participating media */
+       for (s = 0; s < nsteps; s++) {
+               float density = vol_get_density(shi, step_sta);
+               
+               /* *** transmittance and emission *** */
+               
+               /* transmittance component (alpha) */
+               vol_get_attenuation(shi, step_tau, step_sta, step_end, density, stepsize);
+               tr[0] *= exp(-step_tau[0]);
+               tr[1] *= exp(-step_tau[1]);
+               tr[2] *= exp(-step_tau[2]);
+               
+               /* Terminate raymarching if transmittance is small */
+               //if (rgb_to_luminance(tr[0], tr[1], tr[2]) < 1e-3) break;
+               
+               /* incoming light via emission or scattering (additive) */
+               vol_get_emission(shi, step_emit, step_sta, step_end, density);
+               vol_get_scattering(shi, step_scatter, step_end, step_end, stepsize, density);
+               
+               VecAddf(d_radiance, step_emit, step_scatter);
+               
+               /*   Lv += Tr * (Lve() + Ld) */
+               VecMulVecf(d_radiance, tr, d_radiance);
+               VecAddf(radiance, radiance, d_radiance);        
+
+               if (s < nsteps-1) {
+                       VECCOPY(step_sta, step_end);
+                       VecAddf(step_end, step_end, stepvec);
+               }
+       }
+       
+       VecMulf(radiance, stepsize);
+       VECCOPY(col, radiance);
+       
+       /*
+       Incoming radiance = 
+                 outgoing radiance from behind surface * beam transmittance/attenuation
+               
+               + added radiance from all points along the ray due to participating media
+                   --> radiance for each segment = 
+                                         radiance added by scattering 
+                                       + radiance added by emission
+                                       * beam transmittance/attenuation
+       
+       
+       -- To find transmittance:
+               compute optical thickness with tau (perhaps involving monte carlo integration)
+               return exp(-tau)
+               
+       -- To find radiance from segments along the way:
+               find radiance for one step:
+                 - loop over lights and weight by phase function
+
+                 - single scattering
+                   : integrate over sphere
+               
+               then multiply each step for final exit radiance
+               */
+}
+
+void volume_trace(struct ShadeInput *shi, struct ShadeResult *shr)
+{
+       Isect isect;
+       float hitco[3], col[3];
+
+       memset(shr, 0, sizeof(ShadeResult));
+
+       if (vol_get_bounds(shi, shi->co, shi->view, hitco)) {
+               
+               volumeintegrate(shi, col, shi->co, hitco);
+               
+               /* hit */
+               shr->alpha = 1.0f;
+               shr->combined[0] = col[0];
+               shr->combined[1] = col[1];
+               shr->combined[2] = col[2];
+               
+               QUATCOPY(shr->diff, shr->combined);
+       }
+       else {
+               /* no hit */
+               shr->combined[0] = 0.0f;
+               shr->combined[1] = 0.0f;
+               shr->combined[2] = 0.0f;
+               shr->combined[3] = shr->alpha =  0.0f;
+       }
+}
\ No newline at end of file
index e58ef3f5b12991bb63b206aa5ed2037d79ef6621..73ff5945d2569fef54e84cf14451df02ded16203 100644 (file)
@@ -3400,6 +3400,10 @@ static void material_panel_map_to(Object *ob, Material *ma, int from_nodes)
                uiDefButBitS(block, TOG, 1, B_MATPRV, "PAttr",          250,160,60,19, &pattr, 0, 0, 0, 0, "Display settings for particle attributes");
                uiBlockSetCol(block, TH_AUTO);
        }
+       else if (ma->material_type == MA_VOLUME) {
+               uiDefButBitS(block, TOG3, MAP_ALPHA, B_MATPRV, "Density",               10,180,60,19, &(mtex->mapto), 0, 0, 0, 0, "Causes the texture to affect the alpha value");
+               uiDefButBitS(block, TOG3, MAP_EMIT, B_MATPRV, "Emit",           70,180,45,19, &(mtex->mapto), 0, 0, 0, 0, "Causes the texture to affect the emit value");
+       }
        else {
                uiDefButBitS(block, TOG, MAP_COL, B_MATPRV, "Col",              10,180,40,19, &(mtex->mapto), 0, 0, 0, 0, "Causes the texture to affect basic color of the material");
                uiDefButBitS(block, TOG3, MAP_NORM, B_MATPRV, "Nor",            50,180,40,19, &(mtex->mapto), 0, 0, 0, 0, "Causes the texture to affect the rendered normal");
@@ -3516,37 +3520,43 @@ static void material_panel_map_input(Object *ob, Material *ma)
        
        /* TEXCO */
        uiBlockBeginAlign(block);
-       uiDefButS(block, ROW, B_MATPRV, "Glob",                 630,180,45,18, &(mtex->texco), 4.0, (float)TEXCO_GLOB, 0, 0, "Uses global coordinates for the texture coordinates");
-       uiDefButS(block, ROW, B_MATPRV, "Object",               675,180,75,18, &(mtex->texco), 4.0, (float)TEXCO_OBJECT, 0, 0, "Uses linked object's coordinates for texture coordinates");
-       if(mtex->texco == TEXCO_UV && !(mtex->texflag & MTEX_DUPLI_MAPTO)) {
-               if(!verify_valid_uv_name(mtex->uvname))
-            uiBlockSetCol(block, TH_REDALERT);
-               but=uiDefBut(block, TEX, B_MATPRV, "UV:", 750,180,158,18, mtex->uvname, 0, 31, 0, 0, "Set name of UV layer to use, default is active UV layer");
-               uiButSetCompleteFunc(but, autocomplete_uv, NULL);
-               uiBlockSetCol(block, TH_AUTO);
-       }
-       else
-               uiDefIDPoinBut(block, test_obpoin_but, ID_OB, B_MATPRV, "Ob:",750,180,158,18, &(mtex->object), "");
-       
-       uiDefButS(block, ROW, B_MATPRV, "UV",                   630,160,40,18, &(mtex->texco), 4.0, (float)TEXCO_UV, 0, 0, "Uses UV coordinates for texture coordinates");
-       uiDefButS(block, ROW, B_MATPRV, "Orco",                 670,160,55,18, &(mtex->texco), 4.0, (float)TEXCO_ORCO, 0, 0, "Uses the original undeformed coordinates of the object");
-       if( ob->particlesystem.first )
-               uiDefButS(block, ROW, B_MATPRV, "Strand",       725,160,50,18, &(mtex->texco), 4.0, (float)TEXCO_STRAND, 0, 0, "Uses normalized strand texture coordinate (1D)");
-       else
-               uiDefButS(block, ROW, B_MATPRV, "Stick",        725,160,50,18, &(mtex->texco), 4.0, (float)TEXCO_STICKY, 0, 0, "Uses mesh's sticky coordinates for the texture coordinates");
-       uiDefButS(block, ROW, B_MATPRV, "Win",                  775,160,45,18, &(mtex->texco), 4.0, (float)TEXCO_WINDOW, 0, 0, "Uses screen coordinates as texture coordinates");
-       uiDefButS(block, ROW, B_MATPRV, "Nor",                  820,160,44,18, &(mtex->texco), 4.0, (float)TEXCO_NORM, 0, 0, "Uses normal vector as texture coordinates");
-       uiDefButS(block, ROW, B_MATPRV, "Refl",                 864,160,44,18, &(mtex->texco), 4.0, (float)TEXCO_REFL, 0, 0, "Uses reflection vector as texture coordinates");
        
-       uiDefButS(block, ROW, B_MATPRV, "Stress",               630,140,70,18, &(mtex->texco), 4.0, (float)TEXCO_STRESS, 0, 0, "Uses the difference of edge lengths compared to original coordinates of the mesh");
-       uiDefButS(block, ROW, B_MATPRV, "Tangent",              700,140,70,18, &(mtex->texco), 4.0, (float)TEXCO_TANGENT, 0, 0, "Uses the optional tangent vector as texture coordinates");
-       uiBlockEndAlign(block);
-
-       if(ELEM(mtex->texco, TEXCO_UV, TEXCO_ORCO))
-               uiDefButBitS(block, TOG, MTEX_DUPLI_MAPTO, B_MATPRV, "From Dupli",      820,140,88,18, &(mtex->texflag), 0, 0, 0, 0, "Dupli's instanced from verts, faces or particles, inherit texture coordinate from their parent");
-       else if(mtex->texco == TEXCO_OBJECT)
-               uiDefButBitS(block, TOG, MTEX_OB_DUPLI_ORIG, B_MATPRV, "From Original", 820,140,88,18, &(mtex->texflag), 0, 0, 0, 0, "Dupli's derive their object coordinates from the original objects transformation");
+       if (ma->material_type == MA_VOLUME) {
+               uiDefButS(block, ROW, B_MATPRV, "Glob",                 630,180,45,18, &(mtex->texco), 4.0, (float)TEXCO_GLOB, 0, 0, "Uses global coordinates for the texture coordinates");
+               uiDefButS(block, ROW, B_MATPRV, "Object",               675,180,75,18, &(mtex->texco), 4.0, (float)TEXCO_OBJECT, 0, 0, "Uses linked object's coordinates for texture coordinates");
+               uiDefIDPoinBut(block, test_obpoin_but, ID_OB, B_MATPRV, "Ob:",750,180,158,18, &(mtex->object), "");
+       } else {
+               uiDefButS(block, ROW, B_MATPRV, "Glob",                 630,180,45,18, &(mtex->texco), 4.0, (float)TEXCO_GLOB, 0, 0, "Uses global coordinates for the texture coordinates");
+               uiDefButS(block, ROW, B_MATPRV, "Object",               675,180,75,18, &(mtex->texco), 4.0, (float)TEXCO_OBJECT, 0, 0, "Uses linked object's coordinates for texture coordinates");
+               if(mtex->texco == TEXCO_UV && !(mtex->texflag & MTEX_DUPLI_MAPTO)) {
+                       if(!verify_valid_uv_name(mtex->uvname))
+                               uiBlockSetCol(block, TH_REDALERT);
+                       but=uiDefBut(block, TEX, B_MATPRV, "UV:", 750,180,158,18, mtex->uvname, 0, 31, 0, 0, "Set name of UV layer to use, default is active UV layer");
+                       uiButSetCompleteFunc(but, autocomplete_uv, NULL);
+                       uiBlockSetCol(block, TH_AUTO);
+               }
+               else
+                       uiDefIDPoinBut(block, test_obpoin_but, ID_OB, B_MATPRV, "Ob:",750,180,158,18, &(mtex->object), "");
+               
+               uiDefButS(block, ROW, B_MATPRV, "UV",                   630,160,40,18, &(mtex->texco), 4.0, (float)TEXCO_UV, 0, 0, "Uses UV coordinates for texture coordinates");
+               uiDefButS(block, ROW, B_MATPRV, "Orco",                 670,160,55,18, &(mtex->texco), 4.0, (float)TEXCO_ORCO, 0, 0, "Uses the original undeformed coordinates of the object");
+               if( ob->particlesystem.first )
+                       uiDefButS(block, ROW, B_MATPRV, "Strand",       725,160,50,18, &(mtex->texco), 4.0, (float)TEXCO_STRAND, 0, 0, "Uses normalized strand texture coordinate (1D)");
+               else
+                       uiDefButS(block, ROW, B_MATPRV, "Stick",        725,160,50,18, &(mtex->texco), 4.0, (float)TEXCO_STICKY, 0, 0, "Uses mesh's sticky coordinates for the texture coordinates");
+               uiDefButS(block, ROW, B_MATPRV, "Win",                  775,160,45,18, &(mtex->texco), 4.0, (float)TEXCO_WINDOW, 0, 0, "Uses screen coordinates as texture coordinates");
+               uiDefButS(block, ROW, B_MATPRV, "Nor",                  820,160,44,18, &(mtex->texco), 4.0, (float)TEXCO_NORM, 0, 0, "Uses normal vector as texture coordinates");
+               uiDefButS(block, ROW, B_MATPRV, "Refl",                 864,160,44,18, &(mtex->texco), 4.0, (float)TEXCO_REFL, 0, 0, "Uses reflection vector as texture coordinates");
+               
+               uiDefButS(block, ROW, B_MATPRV, "Stress",               630,140,70,18, &(mtex->texco), 4.0, (float)TEXCO_STRESS, 0, 0, "Uses the difference of edge lengths compared to original coordinates of the mesh");
+               uiDefButS(block, ROW, B_MATPRV, "Tangent",              700,140,70,18, &(mtex->texco), 4.0, (float)TEXCO_TANGENT, 0, 0, "Uses the optional tangent vector as texture coordinates");
+               uiBlockEndAlign(block);
 
+               if(ELEM(mtex->texco, TEXCO_UV, TEXCO_ORCO))
+                       uiDefButBitS(block, TOG, MTEX_DUPLI_MAPTO, B_MATPRV, "From Dupli",      820,140,88,18, &(mtex->texflag), 0, 0, 0, 0, "Dupli's instanced from verts, faces or particles, inherit texture coordinate from their parent");
+               else if(mtex->texco == TEXCO_OBJECT)
+                       uiDefButBitS(block, TOG, MTEX_OB_DUPLI_ORIG, B_MATPRV, "From Original", 820,140,88,18, &(mtex->texflag), 0, 0, 0, 0, "Dupli's derive their object coordinates from the original objects transformation");
+       }
 
        /* COORDS */
        uiBlockBeginAlign(block);
@@ -4128,7 +4138,7 @@ static uiBlock *strand_menu(void *mat_v)
 }
 
 
-static void material_panel_material(Material *ma)
+static void material_panel_material_solid(Material *ma)
 {
        uiBlock *block;
        float *colpoin = NULL;
@@ -4216,6 +4226,43 @@ static void material_panel_material(Material *ma)
 
 }
 
+static void material_panel_material_volume(Material *ma)
+{
+       uiBlock *block;
+       short yco=PANEL_YMAX;
+       
+       block= uiNewBlock(&curarea->uiblocks, "material_panel_material_volume", UI_EMBOSS, UI_HELV, curarea->win);
+       if(uiNewPanel(curarea, block, "Volume", "Material", PANELX, PANELY, PANELW, PANELH)==0) return;
+       
+       uiSetButLock(ma->id.lib!=NULL, ERROR_LIBDATA_MESSAGE);
+       
+       uiBlockBeginAlign(block);
+       uiDefButF(block, NUM, B_MATPRV, "Step Size: ",
+               X2CLM1, yco-=BUTH, BUTW2, BUTH, &(ma->vol_stepsize), 0.001, 100.0, 10, 2, "Ray marching step size");
+       uiDefButF(block, NUMSLI, B_MATPRV, "Density: ",
+               X2CLM1, yco-=BUTH, BUTW2, BUTH, &(ma->alpha), 0.0, 1.0, 0, 0, "Base opacity value");
+       uiDefButF(block, NUM, B_MATPRV, "Absorption: ",
+               X2CLM1, yco-=BUTH, BUTW2, BUTH, &(ma->vol_absorption), 0.0, 5.0, 0, 0, "Multiplier for absorption");
+       uiBlockEndAlign(block);
+       
+       yco -= YSPACE;
+       
+       uiDefButF(block, NUMSLI, B_MATPRV, "Emit: ",
+               X2CLM1, yco-=BUTH, BUTW2, BUTH, &(ma->emit), 0.0, 2.0, 0, 0, "Emission component");
+       
+       yco -= YSPACE;
+               
+       uiBlockBeginAlign(block);
+       uiDefButBitS(block, TOG, MA_VOL_ATTENUATED, B_MATPRV, "Shading",
+               X2CLM1, yco-=BUTH, BUTW2, BUTH, &(ma->vol_shadeflag), 0, 0, 0, 0, "Uses absorption for light attenuation");
+       uiDefButF(block, NUM, B_MATPRV, "Step Size: ",
+               X2CLM1, yco-=BUTH, BUTW2, BUTH, &(ma->vol_shade_stepsize), 0.001, 100.0, 10, 2, "Step");
+       uiBlockEndAlign(block);
+
+       uiDefBut(block, LABEL, B_DIFF, "",
+               X2CLM2, yco, BUTW2, BUTH, 0, 0, 0, 0, 0, "");
+}
+
 static void material_panel_nodes(Material *ma)
 {
        bNode *node;
@@ -4254,7 +4301,7 @@ static void material_panel_links(Object *ob, Material *ma)
        
        block= uiNewBlock(&curarea->uiblocks, "material_panel_links", UI_EMBOSS, UI_HELV, curarea->win);
        /* 310 makes sorting code to put it right after preview panel */
-       if(uiNewPanel(curarea, block, "Links and Pipeline", "Material", 310, 0, 318, 204)==0) return;
+       if(uiNewPanel(curarea, block, "Links and Pipeline", "Material", 310, 0, 338, 204)==0) return;
 
        /* Links from object to material/nodes */
        uiDefBut(block, ROUNDBOX, 0, "",                                        5, 90, 310, 110, NULL, 7.0, 0.0, 15 , 20, ""); 
@@ -4347,7 +4394,10 @@ static void material_panel_links(Object *ob, Material *ma)
        uiDefButBitI(block, TOG, MA_ONLYCAST, B_MATPRV,"OnlyCast",              85,10,75,19, &(ma->mode), 0, 0, 0, 0, "Makes faces cast shadows only, not rendered");
        uiDefButBitI(block, TOG, MA_TRACEBLE, B_NOP,"Traceable",        160,10,75,19, &(ma->mode), 0, 0, 0, 0, "Makes material detectable by ray tracing");
        uiDefButBitI(block, TOG, MA_SHADBUF, B_MATPRV,  "Shadbuf",              235,10,75,19, &(ma->mode), 0, 0, 0, 0, "Makes material cast shadows from shadow buffer lamps");
-                                 
+       uiBlockEndAlign(block);
+       
+       uiDefButS(block, MENU, B_MATPRV, "Material Type %t|Solid %x0|Halo %x1|Volume %x2",
+               10, -15, 300, 20, &(ma->material_type), 0.0, 0.0, 0, 0, "");
        
 }
 
@@ -4405,21 +4455,26 @@ void material_panels()
                
                ma= editnode_get_active_material(ma);
                if(ma) {
-                       material_panel_material(ma);
-                       material_panel_ramps(ma);
-                       material_panel_shading(ma);
-                       
-                       if (G.scene->r.renderer==R_INTERN)
-                               material_panel_tramir(ma);
-                       else {
-                               if(ma->YF_ar==0.f) {
-                                       ma->YF_ar = ma->YF_ag = ma->YF_ab = 1;
-                                       ma->YF_dscale = 1;
+                       if (ma->material_type == MA_SOLID) {
+                               material_panel_material_solid(ma);
+                               material_panel_ramps(ma);
+                               material_panel_shading(ma);
+                               
+                               if (G.scene->r.renderer==R_INTERN)
+                                       material_panel_tramir(ma);
+                               else {
+                                       if(ma->YF_ar==0.f) {
+                                               ma->YF_ar = ma->YF_ag = ma->YF_ab = 1;
+                                               ma->YF_dscale = 1;
+                                       }
+                                       material_panel_tramir_yafray(ma);
                                }
-                               material_panel_tramir_yafray(ma);
-                       }
 
-                       material_panel_sss(ma);
+                               material_panel_sss(ma);
+                               
+                       } else if (ma->material_type == MA_VOLUME) {
+                               material_panel_material_volume(ma);
+                       }
                        material_panel_texture(ob, ma);
                        
                        mtex= ma->mtex[ ma->texact ];
index 8dfa32d48c8049feaabbab414732d098579eed43..f29cc8e595376e2b728b04bde16110f58ae53ec6 100644 (file)
@@ -324,6 +324,8 @@ static Scene *preview_prepare_scene(RenderInfo *ri, int id_type, ID *id, int pr_
                                /* turn on raytracing if needed */
                                if(mat->mode_l & (MA_RAYTRANSP|MA_RAYMIRROR))
                                        sce->r.mode |= R_RAYTRACE;
+                               if(mat->material_type == MA_VOLUME)
+                                       sce->r.mode |= R_RAYTRACE;
                                if(mat->sss_flag & MA_DIFF_SSS)
                                        sce->r.mode |= R_SSS;