3D Viewport rendering (Blender Internal)
authorTon Roosendaal <ton@blender.org>
Fri, 17 May 2013 11:13:46 +0000 (11:13 +0000)
committerTon Roosendaal <ton@blender.org>
Fri, 17 May 2013 11:13:46 +0000 (11:13 +0000)
Added incremental re-render on view changes. That means all data preprocessing
only needs to be done once on view changes, quite faster that way.

Also fixed a bug in raytracing strands with soft shadows, was wrongly changing
coordinates in a static array.

Note: proper signals for re-renders is still on the todo. Many button options
don't signal a re-render yet. Work around: press G+ESC for quick full renders.

source/blender/editors/render/render_internal.c
source/blender/render/intern/include/envmap.h
source/blender/render/intern/include/rayintersection.h
source/blender/render/intern/include/renderdatabase.h
source/blender/render/intern/source/convertblender.c
source/blender/render/intern/source/envmap.c
source/blender/render/intern/source/rayshade.c

index a172287113f3bfdbb3919cc04b7e6a0c3b7f32b5..954fff42a370df20ade9c7fc6b92e529c64f37b4 100644 (file)
@@ -718,6 +718,8 @@ typedef struct RenderPreview {
        Main *bmain;
        RenderEngine *engine;
        
+       float viewmat[4][4];
+       
        int keep_data;
 } RenderPreview;
 
@@ -828,7 +830,7 @@ static void render_view3d_startjob(void *customdata, short *stop, short *do_upda
        rp->stop = stop;
        rp->do_update = do_update;
 
-//     printf("Enter previewrender\n");
+       // printf("Enter previewrender\n");
        
        /* ok, are we rendering all over? */
        sprintf(name, "View3dPreview %p", (void *)rp->ar);
@@ -884,14 +886,14 @@ static void render_view3d_startjob(void *customdata, short *stop, short *do_upda
                        lay |= rp->v3d->lay;
                else lay = rp->v3d->lay;
                
-               RE_SetView(re, rp->rv3d->viewmat);
+               RE_SetView(re, rp->viewmat);
                
                RE_Database_FromScene(re, rp->bmain, rp->scene, lay, 0);                // 0= dont use camera view
-//             printf("dbase update\n");
+               // printf("dbase update\n");
        }
        else {
-//             printf("dbase rotate\n");
-               RE_DataBase_IncrementalView(re, rp->rv3d->viewmat, 0);
+               // printf("dbase rotate\n");
+               RE_DataBase_IncrementalView(re, rp->viewmat, 0);
                restore = 1;
        }
 
@@ -900,15 +902,13 @@ static void render_view3d_startjob(void *customdata, short *stop, short *do_upda
        /* OK, can we enter render code? */
        if (rstats->convertdone) {
                RE_TileProcessor(re);
-//             printf("tile processor\n");
                
+               /* always rotate back */
                if (restore)
-                       RE_DataBase_IncrementalView(re, rp->rv3d->viewmat, 1);
-               
+                       RE_DataBase_IncrementalView(re, rp->viewmat, 1);
+
                rp->engine->flag &= ~RE_ENGINE_DO_UPDATE;
        }
-
-//     printf("done\n\n");
 }
 
 static void render_view3d_free(void *customdata)
@@ -943,6 +943,7 @@ static void render_view3d_do(RenderEngine *engine, const bContext *C, int keep_d
        rp->rv3d = CTX_wm_region_view3d(C);
        rp->bmain = CTX_data_main(C);
        rp->keep_data = keep_data;
+       copy_m4_m4(rp->viewmat, rp->rv3d->viewmat);
        
        /* dont alloc in threads */
        if (engine->text == NULL)
@@ -992,13 +993,9 @@ static int render_view3d_changed(RenderEngine *engine, const bContext *C)
                if (engine->resolution_x != ar->winx || engine->resolution_y != ar->winy)
                        update |= PR_UPDATE_RENDERSIZE;
 
-               /* view updating fails on raytrace */
                RE_GetView(re, mat);
                if (compare_m4m4(mat, rv3d->viewmat, 0.00001f) == 0) {
-                       if ((scene->r.mode & R_RAYTRACE) == 0)
-                               update |= PR_UPDATE_VIEW;
-                       else
-                               engine->flag |= RE_ENGINE_DO_UPDATE;
+                       update |= PR_UPDATE_VIEW;
                }
                
                render_view3d_get_rects(ar, v3d, rv3d, &viewplane, engine, &clipsta, &clipend, &orth);
@@ -1013,8 +1010,8 @@ static int render_view3d_changed(RenderEngine *engine, const bContext *C)
                
                if (update)
                        engine->flag |= RE_ENGINE_DO_UPDATE;
-//             if (update)
-//                     printf("changed ma %d res %d view %d\n", update & PR_UPDATE_MATERIAL, update & PR_UPDATE_RENDERSIZE, update & PR_UPDATE_VIEW);
+               //if (update)
+               //      printf("changed ma %d res %d view %d\n", update & PR_UPDATE_MATERIAL, update & PR_UPDATE_RENDERSIZE, update & PR_UPDATE_VIEW);
        }
        
        return update;
index 79233a5d6256e0a6b2ce3a8413cbcb2862c108e4..c813e88c656fe353ad470fd963437288e2fbb590 100644 (file)
@@ -48,7 +48,7 @@ struct ImagePool;
 
 void make_envmaps(struct Render *re);
 int envmaptex(struct Tex *tex, const float texvec[3], float dxt[3], float dyt[3], int osatex, struct TexResult *texres, struct ImagePool *pool);
-void env_rotate_scene(struct Render *re, float mat[4][4], int mode);
+void env_rotate_scene(struct Render *re, float mat[4][4], int do_rotate);
 
 #endif /* __ENVMAP_H__ */
 
index 4dceae56a4c9947ebfb3cd7b3be916a089d34778..3607e66a237c9285936b014ee2d276062146d3e0 100644 (file)
@@ -64,6 +64,10 @@ typedef struct Isect {
        float dir[3];
        float dist;
 
+       /* for envmap and incremental view update renders */
+       float origstart[3];
+       float origdir[3];
+       
        /* precomputed values to accelerate bounding box intersection */
        int bv_index[6];
        float idot_axis[3];
index 1e81ca20d030b1d0e2d9c9484660e5fdd56843f2..9e48299ed9a539b6e98dbc9971b382bf8b9b9309 100644 (file)
@@ -140,6 +140,9 @@ struct VlakRen *RE_vlakren_copy(struct ObjectRen *obr, struct VlakRen *vlr);
 
 void RE_set_customdata_names(struct ObjectRen *obr, struct CustomData *data);
 
+void area_lamp_vectors(struct LampRen *lar);
+
+
 /* haloren->type: flags */
 #define HA_ONLYSKY             1
 #define HA_VECT                        2
index 976be755532f40ebbe6ea58e372be8badf157cc0..2be3c118ec82483900ae00e61e7d02f8ea91f691 100644 (file)
@@ -3765,7 +3765,7 @@ static void initshadowbuf(Render *re, LampRen *lar, float mat[4][4])
        shb->compressthresh= lar->compressthresh;
 }
 
-static void area_lamp_vectors(LampRen *lar)
+void area_lamp_vectors(LampRen *lar)
 {
        float xsize= 0.5f*lar->area_size, ysize= 0.5f*lar->area_sizey, multifac;
 
index 6423bfa94866cf9e3f74b2a03416fe93ffd30907..419c3d8ee23c85c994d41529f84fd42afd9ea697 100644 (file)
@@ -45,6 +45,7 @@
 
 #include "DNA_group_types.h"
 #include "DNA_image_types.h"
+#include "DNA_lamp_types.h"
 #include "DNA_object_types.h"
 #include "DNA_scene_types.h"
 #include "DNA_texture_types.h"
@@ -163,6 +164,7 @@ static Render *envmap_render_copy(Render *re, EnvMap *env)
        /* view stuff in env render */
        viewscale = (env->type == ENV_PLANE) ? env->viewscale : 1.0f;
        RE_SetEnvmapCamera(envre, env->object, viewscale, env->clipsta, env->clipend);
+       copy_m4_m4(envre->viewmat_orig, re->viewmat_orig);
        
        /* callbacks */
        envre->display_draw = re->display_draw;
@@ -265,23 +267,27 @@ static void env_set_imats(Render *re)
 
 /* ------------------------------------------------------------------------- */
 
-void env_rotate_scene(Render *re, float mat[4][4], int mode)
+void env_rotate_scene(Render *re, float mat[4][4], int do_rotate)
 {
        GroupObject *go;
        ObjectRen *obr;
        ObjectInstanceRen *obi;
        LampRen *lar = NULL;
        HaloRen *har = NULL;
-       float imat[3][3], pmat[4][4], smat[4][4], tmat[4][4], cmat[3][3], tmpmat[4][4];
+       float imat[3][3], mat_inverse[4][4], smat[4][4], tmat[4][4], cmat[3][3], tmpmat[4][4];
        int a;
        
-       if (mode == 0) {
+       if (do_rotate == 0) {
                invert_m4_m4(tmat, mat);
                copy_m3_m4(imat, tmat);
+               
+               copy_m4_m4(mat_inverse, mat);
        }
        else {
                copy_m4_m4(tmat, mat);
                copy_m3_m4(imat, mat);
+               
+               invert_m4_m4(mat_inverse, tmat);
        }
 
        for (obi = re->instancetable.first; obi; obi = obi->next) {
@@ -290,7 +296,7 @@ void env_rotate_scene(Render *re, float mat[4][4], int mode)
                        copy_m4_m4(tmpmat, obi->mat);
                        mult_m4_m4m4(obi->mat, tmat, tmpmat);
                }
-               else if (mode == 1)
+               else if (do_rotate == 1)
                        copy_m4_m4(obi->mat, tmat);
                else
                        unit_m4(obi->mat);
@@ -300,10 +306,12 @@ void env_rotate_scene(Render *re, float mat[4][4], int mode)
                transpose_m3(obi->nmat);
 
                /* indicate the renderer has to use transform matrices */
-               if (mode == 0)
+               if (do_rotate == 0)
                        obi->flag &= ~R_ENV_TRANSFORMED;
-               else
+               else {
                        obi->flag |= R_ENV_TRANSFORMED;
+                       copy_m4_m4(obi->imat, mat_inverse);
+               }
        }
        
 
@@ -319,32 +327,50 @@ void env_rotate_scene(Render *re, float mat[4][4], int mode)
        for (go = re->lights.first; go; go = go->next) {
                lar = go->lampren;
                
-               /* removed here some horrible code of someone in NaN who tried to fix
-                * prototypes... just solved by introducing a correct cmat[3][3] instead
-                * of using smat. this works, check square spots in reflections  (ton) */
-               copy_m3_m3(cmat, lar->imat); 
-               mul_m3_m3m3(lar->imat, cmat, imat); 
-
-               mul_m3_v3(imat, lar->vec);
-               mul_m4_v3(tmat, lar->co);
-
-               lar->sh_invcampos[0] = -lar->co[0];
-               lar->sh_invcampos[1] = -lar->co[1];
-               lar->sh_invcampos[2] = -lar->co[2];
-               mul_m3_v3(lar->imat, lar->sh_invcampos);
-               lar->sh_invcampos[2] *= lar->sh_zfac;
+               /* copy from add_render_lamp */
+               if (do_rotate == 1)
+                       mult_m4_m4m4(tmpmat, re->viewmat, go->ob->obmat);
+               else
+                       mult_m4_m4m4(tmpmat, re->viewmat_orig, go->ob->obmat);
+               invert_m4_m4(go->ob->imat, tmpmat);
                
-               if (lar->shb) {
-                       if (mode == 1) {
-                               invert_m4_m4(pmat, mat);
-                               mult_m4_m4m4(smat, lar->shb->viewmat, pmat);
-                               mult_m4_m4m4(lar->shb->persmat, lar->shb->winmat, smat);
+               copy_m3_m4(lar->mat, tmpmat);
+               
+               copy_m3_m4(lar->imat, go->ob->imat);
+
+               lar->vec[0]= -tmpmat[2][0];
+               lar->vec[1]= -tmpmat[2][1];
+               lar->vec[2]= -tmpmat[2][2];
+               normalize_v3(lar->vec);
+               lar->co[0]= tmpmat[3][0];
+               lar->co[1]= tmpmat[3][1];
+               lar->co[2]= tmpmat[3][2];
+
+               if (lar->type == LA_AREA) {
+                       area_lamp_vectors(lar);
+               }
+               else if (lar->type == LA_SPOT) {
+                       normalize_v3(lar->imat[0]);
+                       normalize_v3(lar->imat[1]);
+                       normalize_v3(lar->imat[2]);
+               
+                       lar->sh_invcampos[0] = -lar->co[0];
+                       lar->sh_invcampos[1] = -lar->co[1];
+                       lar->sh_invcampos[2] = -lar->co[2];
+                       mul_m3_v3(lar->imat, lar->sh_invcampos);
+                       lar->sh_invcampos[2] *= lar->sh_zfac;
+               
+                       if (lar->shb) {
+                               if (do_rotate == 1) {
+                                       mult_m4_m4m4(smat, lar->shb->viewmat, mat_inverse);
+                                       mult_m4_m4m4(lar->shb->persmat, lar->shb->winmat, smat);
+                               }
+                               else mult_m4_m4m4(lar->shb->persmat, lar->shb->winmat, lar->shb->viewmat);
                        }
-                       else mult_m4_m4m4(lar->shb->persmat, lar->shb->winmat, lar->shb->viewmat);
                }
        }
        
-       if (mode) {
+       if (do_rotate) {
                init_render_world(re);
                env_set_imats(re);
        }
index 387004527c094ba4035e2cbcc5006567fa2d7219..e77920dde264ba07689a24e6c5972d18476a9154 100644 (file)
@@ -499,7 +499,37 @@ static void shade_ray_set_derivative(ShadeInput *shi)
        
 }
 
+/* four functions to facilitate envmap rotation for raytrace */
+static void ray_env_rotate_start(Isect *is, float imat[4][4])
+{
+       copy_v3_v3(is->origstart, is->start);
+       mul_m4_v3(imat, is->start);
+}
+
+static void ray_env_rotate_dir(Isect *is, float imat[4][4])
+{
+       float end[3];
+       
+       copy_v3_v3(is->origdir, is->dir);
+       add_v3_v3v3(end, is->origstart, is->dir);
+       
+       mul_m4_v3(imat, end);
+       sub_v3_v3v3(is->dir, end, is->start);
+}
+
+static void ray_env_rotate(Isect *is, float imat[4][4])
+{
+       ray_env_rotate_start(is, imat);
+       ray_env_rotate_dir(is, imat);
+}
 
+static void ray_env_rotate_restore(Isect *is)
+{
+       copy_v3_v3(is->start, is->origstart);
+       copy_v3_v3(is->dir, is->origdir);
+}
+
+/* main ray shader */
 void shade_ray(Isect *is, ShadeInput *shi, ShadeResult *shr)
 {
        ObjectInstanceRen *obi = (ObjectInstanceRen *)is->hit.ob;
@@ -716,11 +746,18 @@ static void traceray(ShadeInput *origshi, ShadeResult *origshr, short depth, con
        isec.orig.ob   = obi;
        isec.orig.face = vlr;
        RE_RC_INIT(isec, shi);
+       
+       /* database is in original view, obi->imat transforms current position back to original */
+       if (origshi->obi->flag & R_ENV_TRANSFORMED)
+               ray_env_rotate(&isec, origshi->obi->imat);
 
        if (RE_rayobject_raycast(R.raytree, &isec)) {
                ShadeResult shr= {{0}};
                float d= 1.0f;
 
+               if (origshi->obi->flag & R_ENV_TRANSFORMED)
+                       ray_env_rotate_restore(&isec);
+               
                /* for as long we don't have proper dx/dy transform for rays we copy over original */
                copy_v3_v3(shi.dxco, origshi->dxco);
                copy_v3_v3(shi.dyco, origshi->dyco);
@@ -1621,6 +1658,9 @@ static void ray_trace_shadow_tra(Isect *is, ShadeInput *origshi, int depth, int
                shi.lay= origshi->lay;
                shi.nodes= origshi->nodes;
                
+               if (origshi->obi->flag & R_ENV_TRANSFORMED)
+                       ray_env_rotate_restore(is);
+
                shade_ray(is, &shi, &shr);
                if (shi.mat->material_type == MA_TYPE_SURFACE) {
                        const float d= (traflag & RAY_TRA) ?
@@ -1654,78 +1694,6 @@ static void ray_trace_shadow_tra(Isect *is, ShadeInput *origshi, int depth, int
        }
 }
 
-/* not used, test function for ambient occlusion (yaf: pathlight) */
-/* main problem; has to be called within shading loop, giving unwanted recursion */
-static int UNUSED_FUNCTION(ray_trace_shadow_rad)(ShadeInput *ship, ShadeResult *shr)
-{
-       static int counter=0, only_one= 0;
-       extern float hashvectf[];
-       Isect isec;
-       ShadeInput shi;
-       ShadeResult shr_t;
-       float vec[3], accum[3], div= 0.0f;
-       int a;
-       
-       assert(0);
-       
-       if (only_one) {
-               return 0;
-       }
-       only_one= 1;
-       
-       accum[0]= accum[1]= accum[2]= 0.0f;
-       isec.mode= RE_RAY_MIRROR;
-       isec.orig.ob   = ship->obi;
-       isec.orig.face = ship->vlr;
-       isec.hint = 0;
-
-       copy_v3_v3(isec.start, ship->co);
-       
-       RE_RC_INIT(isec, shi);
-       
-       for (a=0; a<8*8; a++) {
-               
-               counter+=3;
-               counter %= 768;
-               copy_v3_v3(vec, hashvectf+counter);
-               if (dot_v3v3(ship->vn, vec) > 0.0f) {
-                       vec[0]-= vec[0];
-                       vec[1]-= vec[1];
-                       vec[2]-= vec[2];
-               }
-
-               copy_v3_v3(isec.dir, vec);
-               isec.dist = RE_RAYTRACE_MAXDIST;
-
-               if (RE_rayobject_raycast(R.raytree, &isec)) {
-                       float fac;
-                       
-                       /* Warning, This is not that nice, and possibly a bit slow for every ray,
-                        * however some variables were not initialized properly in, unless using shade_input_initialize(...), we need to do a memset */
-                       memset(&shi, 0, sizeof(ShadeInput)); 
-                       /* end warning! - Campbell */
-                       
-                       shade_ray(&isec, &shi, &shr_t);
-                       /* fac= isec.dist*isec.dist; */
-                       fac= 1.0f;
-                       accum[0]+= fac*(shr_t.diff[0]+shr_t.spec[0]);
-                       accum[1]+= fac*(shr_t.diff[1]+shr_t.spec[1]);
-                       accum[2]+= fac*(shr_t.diff[2]+shr_t.spec[2]);
-                       div+= fac;
-               }
-               else div+= 1.0f;
-       }
-       
-       if (div!=0.0f) {
-               shr->diff[0]+= accum[0]/div;
-               shr->diff[1]+= accum[1]/div;
-               shr->diff[2]+= accum[2]/div;
-       }
-       shr->alpha= 1.0f;
-       
-       only_one= 0;
-       return 1;
-}
 
 /* aolight: function to create random unit sphere vectors for total random sampling */
 static void RandomSpherical(RNG *rng, float v[3])
@@ -1909,6 +1877,10 @@ static void ray_ao_qmc(ShadeInput *shi, float ao[3], float env[3])
        isec.lay= -1;
        
        copy_v3_v3(isec.start, shi->co);
+       
+       if (shi->obi->flag & R_ENV_TRANSFORMED)
+               ray_env_rotate_start(&isec, shi->obi->imat);
+       
        RE_rayobject_hint_bb(R.raytree, &point_hint, isec.start, isec.start);
        isec.hint = &point_hint;
 
@@ -1961,12 +1933,15 @@ static void ray_ao_qmc(ShadeInput *shi, float ao[3], float env[3])
                dir[2] = (samp3d[0]*up[2] + samp3d[1]*side[2] + samp3d[2]*nrm[2]);
                
                normalize_v3(dir);
-                       
+               
                isec.dir[0] = -dir[0];
                isec.dir[1] = -dir[1];
                isec.dir[2] = -dir[2];
                isec.dist = maxdist;
                
+               if (shi->obi->flag & R_ENV_TRANSFORMED)
+                       ray_env_rotate_dir(&isec, shi->obi->imat);
+               
                prev = fac;
                
                if (RE_rayobject_raycast(R.raytree, &isec)) {
@@ -2049,6 +2024,9 @@ static void ray_ao_spheresamp(ShadeInput *shi, float ao[3], float env[3])
        isec.lay= -1;
 
        copy_v3_v3(isec.start, shi->co);
+       if (shi->obi->flag & R_ENV_TRANSFORMED)
+               ray_env_rotate_start(&isec, shi->obi->imat);
+
        RE_rayobject_hint_bb(R.raytree, &point_hint, isec.start, isec.start);
        isec.hint = &point_hint;
 
@@ -2106,6 +2084,9 @@ static void ray_ao_spheresamp(ShadeInput *shi, float ao[3], float env[3])
                        isec.dir[2] = -vec[2];
                        isec.dist = maxdist;
                        
+                       if (shi->obi->flag & R_ENV_TRANSFORMED)
+                               ray_env_rotate_dir(&isec, shi->obi->imat);
+
                        /* do the trace */
                        if (RE_rayobject_raycast(R.raytree, &isec)) {
                                if (R.wrld.aomode & WO_AODIST) sh+= expf(-isec.dist*R.wrld.aodistfac);
@@ -2214,7 +2195,7 @@ static void ray_shadow_qmc(ShadeInput *shi, LampRen *lar, const float lampco[3],
        float colsq[4];
        float adapt_thresh = lar->adapt_thresh;
        int min_adapt_samples=4, max_samples = lar->ray_totsamp;
-       float *co;
+       float start[3];
        int do_soft = TRUE, full_osa = FALSE, i;
 
        float min[3], max[3];
@@ -2257,6 +2238,10 @@ static void ray_shadow_qmc(ShadeInput *shi, LampRen *lar, const float lampco[3],
        for (i = 0; i < totjitco; i++) {
                minmax_v3v3_v3(min, max, jitco[i]);
        }
+       if (shi->obi->flag & R_ENV_TRANSFORMED) {
+               mul_m4_v3(shi->obi->imat, min);
+               mul_m4_v3(shi->obi->imat, max);
+       }
        RE_rayobject_hint_bb(R.raytree, &bb_hint, min, max);
        
        isec->hint = &bb_hint;
@@ -2272,7 +2257,7 @@ static void ray_shadow_qmc(ShadeInput *shi, LampRen *lar, const float lampco[3],
                /* manually jitter the start shading co-ord per sample
                 * based on the pre-generated OSA texture sampling offsets, 
                 * for anti-aliasing sharp shadow edges. */
-               co = jitco[samples % totjitco];
+               copy_v3_v3(start, jitco[samples % totjitco]);
 
                if (do_soft) {
                        /* sphere shadow source */
@@ -2280,7 +2265,7 @@ static void ray_shadow_qmc(ShadeInput *shi, LampRen *lar, const float lampco[3],
                                float ru[3], rv[3], v[3], s[3];
                                
                                /* calc tangent plane vectors */
-                               sub_v3_v3v3(v, co, lampco);
+                               sub_v3_v3v3(v, start, lampco);
                                normalize_v3(v);
                                ortho_basis_v3v3_v3(ru, rv, v);
                                
@@ -2314,20 +2299,23 @@ static void ray_shadow_qmc(ShadeInput *shi, LampRen *lar, const float lampco[3],
                        float jitbias= 0.5f*(len_v3(shi->dxco) + len_v3(shi->dyco));
                        float v[3];
 
-                       sub_v3_v3v3(v, co, end);
+                       sub_v3_v3v3(v, start, end);
                        normalize_v3(v);
 
-                       co[0] -= jitbias*v[0];
-                       co[1] -= jitbias*v[1];
-                       co[2] -= jitbias*v[2];
+                       start[0] -= jitbias*v[0];
+                       start[1] -= jitbias*v[1];
+                       start[2] -= jitbias*v[2];
                }
-
-               copy_v3_v3(isec->start, co);
+               
+               copy_v3_v3(isec->start, start);
                isec->dir[0] = end[0]-isec->start[0];
                isec->dir[1] = end[1]-isec->start[1];
                isec->dir[2] = end[2]-isec->start[2];
                isec->dist = normalize_v3(isec->dir);
                
+               if (shi->obi->flag & R_ENV_TRANSFORMED)
+                       ray_env_rotate(isec, shi->obi->imat);
+
                /* trace the ray */
                if (isec->mode==RE_RAY_SHADOW_TRA) {
                        float col[4] = {1.0f, 1.0f, 1.0f, 1.0f};
@@ -2404,6 +2392,9 @@ static void ray_shadow_jitter(ShadeInput *shi, LampRen *lar, const float lampco[
        else if (a==9) mask |= (mask>>9);
        
        copy_v3_v3(isec->start, shi->co);
+       if (shi->obi->flag & R_ENV_TRANSFORMED)
+               ray_env_rotate_start(isec, shi->obi->imat);
+       
        isec->orig.ob   = shi->obi;
        isec->orig.face = shi->vlr;
        RE_rayobject_hint_bb(R.raytree, &point_hint, isec->start, isec->start);
@@ -2429,6 +2420,10 @@ static void ray_shadow_jitter(ShadeInput *shi, LampRen *lar, const float lampco[
                isec->dir[0] = vec[0]+lampco[0]-isec->start[0];
                isec->dir[1] = vec[1]+lampco[1]-isec->start[1];
                isec->dir[2] = vec[2]+lampco[2]-isec->start[2];
+               
+               if (shi->obi->flag & R_ENV_TRANSFORMED)
+                       ray_env_rotate_dir(isec, shi->obi->imat);
+               
                isec->dist = 1.0f;
                isec->check = RE_CHECK_VLR_RENDER;
                isec->skip = RE_SKIP_VLR_NEIGHBOUR;
@@ -2528,6 +2523,9 @@ void ray_shadow(ShadeInput *shi, LampRen *lar, float shadfac[4])
                        sub_v3_v3v3(isec.dir, lampco, isec.start);
                        isec.dist = normalize_v3(isec.dir);
 
+                       if (shi->obi->flag & R_ENV_TRANSFORMED)
+                               ray_env_rotate(&isec, shi->obi->imat);
+
                        if (isec.mode==RE_RAY_SHADOW_TRA) {
                                /* isec.col is like shadfac, so defines amount of light (0.0 is full shadow) */
                                float col[4] = {1.0f, 1.0f, 1.0f, 1.0f};
@@ -2550,51 +2548,3 @@ void ray_shadow(ShadeInput *shi, LampRen *lar, float shadfac[4])
 
 }
 
-#if 0
-/* only when face points away from lamp, in direction of lamp, trace ray and find first exit point */
-static void ray_translucent(ShadeInput *shi, LampRen *lar, float *distfac, float co[3])
-{
-       Isect isec;
-       float lampco[3];
-       
-       assert(0);
-       
-       /* setup isec */
-       RE_RC_INIT(isec, *shi);
-       isec.mode= RE_RAY_SHADOW_TRA;
-       isec.hint = 0;
-       
-       if (lar->mode & LA_LAYER) isec.lay= lar->lay; else isec.lay= -1;
-       
-       if (lar->type==LA_SUN || lar->type==LA_HEMI) {
-               lampco[0]= shi->co[0] - RE_RAYTRACE_MAXDIST*lar->vec[0];
-               lampco[1]= shi->co[1] - RE_RAYTRACE_MAXDIST*lar->vec[1];
-               lampco[2]= shi->co[2] - RE_RAYTRACE_MAXDIST*lar->vec[2];
-       }
-       else {
-               copy_v3_v3(lampco, lar->co);
-       }
-       
-       isec.orig.ob   = shi->obi;
-       isec.orig.face = shi->vlr;
-       
-       /* set up isec.dir */
-       copy_v3_v3(isec.start, shi->co);
-       copy_v3_v3(isec.end, lampco);
-       
-       if (RE_rayobject_raycast(R.raytree, &isec)) {
-               /* we got a face */
-               
-               /* render co */
-               co[0]= isec.start[0]+isec.dist*(isec.dir[0]);
-               co[1]= isec.start[1]+isec.dist*(isec.dir[1]);
-               co[2]= isec.start[2]+isec.dist*(isec.dir[2]);
-               
-               *distfac= len_v3(isec.dir);
-       }
-       else
-               *distfac= 0.0f;
-}
-
-#endif
-