- Recursive environment map render
authorTon Roosendaal <ton@blender.org>
Tue, 23 Sep 2003 21:05:51 +0000 (21:05 +0000)
committerTon Roosendaal <ton@blender.org>
Tue, 23 Sep 2003 21:05:51 +0000 (21:05 +0000)
Multiple environments now can be rendered in one pass. Previously the other objects with environment maps didn't show up in a reflection. Like this:
http://www.blender.org/bf/dep.jpg

By default, Blender renders now this result:
http://www.blender.org/bf/dep0.jpg

For a further 'recursive ray-tracing effect' you can give each EnvMap texture a higher "Depth" value. Here is a result with depth set at '2':
http://www.blender.org/bf/dep2.jpg

Related new options:
- in (F10) DisplayButtons, environment map rendering can be turned on and off.
- in EnvMap texture buttons you can free all environment maps
- Environment map sizes are also reduced with the (F10) 'percentage' option.

Tech note: with this commit the VlakRen struct has on *ob pointer!

source/blender/blenkernel/intern/texture.c
source/blender/blenloader/intern/readfile.c
source/blender/makesdna/DNA_scene_types.h
source/blender/makesdna/DNA_texture_types.h
source/blender/render/extern/include/render_types.h
source/blender/render/intern/source/envmap.c
source/blender/renderconverter/intern/convertBlenderScene.c
source/blender/src/buttons.c

index 7bb863d8c37c2e3c77c95d2052c8a6b35efa949f..5f73bc10ef63cbf7aec6b90c359c2a09d1f3b3b0 100644 (file)
@@ -629,10 +629,6 @@ void init_render_texture(Tex *tex)
                tex->extend= TEX_CLIP;
                
                if(tex->env) {
-                       /* temporal solution: layer 21 is to indicate an anvmap object */
-                       tex->env->notlay |= (1<<20);
-                       if(tex->env->object) tex->env->object->lay |= (1<<20);
-                       
                        if(R.flag & R_RENDERING) {
                                if(tex->env->stype==ENV_ANIM) RE_free_envmapdata(tex->env);
                        }
index 1bd41a82428a5e738c08e6f1395d0bee680373b5..f33dc4982278f5c08b945660d7ef144b04b23646 100644 (file)
@@ -3703,6 +3703,7 @@ static void do_versions(Main *main)
                for (sce= main->scene.first; sce; sce= sce->id.next) {
                        sce->audio.mixrate = 44100;
                        sce->audio.flag |= AUDIO_SCRUB;
+                       sce->r.mode |= R_ENVMAP;
                }
                // init new shader vars
                for (ma= main->mat.first; ma; ma= ma->id.next) {
index a6241f8d607cb0ff6545363dcf73141162fd994a..ca4828009170cd8e226e69f65da2e9df9c2a7145 100644 (file)
@@ -166,7 +166,7 @@ typedef struct RenderData {
         * 1: do shadows                                                         
         * 2: do gamma correction                                                
         * 3: ortho (not used?)                                                  
-        * 4: trace (not used?)                                                  
+        * 4: do envmap                                                 
         * 5: edge shading                                                       
         * 6: field rendering                                                    
         * 7: Disables time difference in field calculations                     
@@ -268,7 +268,7 @@ typedef struct Scene {
 #define R_SHADOW               0x0002  
 #define R_GAMMA                        0x0004
 #define R_ORTHO                        0x0008
-#define R_TRACE                        0x0010
+#define R_ENVMAP               0x0010
 #define R_EDGE                 0x0020
 #define R_FIELDS               0x0040
 #define R_FIELDSTILL   0x0080
index 32559fe7d80e01f7669bb9d39ff64e274190504c..7872e384079b0d994b50762236c98a25d81e80f9 100644 (file)
@@ -113,8 +113,10 @@ typedef struct EnvMap {
        short type, stype;
        float clipsta, clipend;
        unsigned int notlay;
-       int cuberes;
+       short cuberes, depth;
        short ok, lastframe;
+       short recalc, lastsize;
+       int pad1;
 } EnvMap;
 
 typedef struct Tex {
index 6b790c6693670432f41e53846535943210ca66ef..9777393685c09941d5bdadbf846ba1fa470a5f40 100644 (file)
@@ -35,6 +35,7 @@
 
 #include "DNA_scene_types.h"
 #include "DNA_world_types.h"
+#include "DNA_object_types.h"
 
 /* Definitely weird: this equals 1<<21... so wtf?*/
 #define MAXVERT (2<<20)
@@ -190,6 +191,7 @@ typedef struct VlakRen
        char flag, ec;
        unsigned int lay;
        RadFace *radface;
+       Object *ob;
 } VlakRen;
 
 
index 58d6fcce56c75ff37e45ae75e1b9a1ab22d106a7..be52592aa873fc5331bf51c2cd63d328aa3b510c 100644 (file)
@@ -203,13 +203,16 @@ void envmap_renderdata(EnvMap *env)
 {
        static RE_Render envR;
        static Object *camera;
+       int cuberes;
        
        if(env) {
                envR= R;
                camera= G.scene->camera;
                
-               env->cuberes &= 0xFFFC;
-               R.rectx= R.r.xsch= R.recty= R.r.ysch= env->cuberes;
+               cuberes = (env->cuberes * R.r.size) / 100;
+               cuberes &= 0xFFFC;
+               env->lastsize= R.r.size;
+               R.rectx= R.r.xsch= R.recty= R.r.ysch= cuberes;
                R.afmx= R.afmy= R.r.xsch/2;
                R.xstart= R.ystart= -R.afmx;
                R.xend= R.yend= R.xstart+R.rectx-1;
@@ -381,6 +384,18 @@ void env_layerflags(unsigned int notlay)
        }
 }
 
+void env_hideobject(Object *ob)
+{
+       VlakRen *vlr = NULL;
+       int a;
+       
+       for(a=0; a<R.totvlak; a++) {
+               if((a & 255)==0) vlr= R.blovl[a>>8];
+               else vlr++;
+               if(vlr->ob == ob) vlr->flag &= ~R_VISIBLE;
+       }
+}
+
 /* ------------------------------------------------------------------------- */
 
 void env_set_imats()
@@ -443,6 +458,7 @@ void render_envmap(EnvMap *env)
                init_render_world();
                setzbufvlaggen(RE_projectverto);
                env_layerflags(env->notlay);
+               env_hideobject(env->object);
                env_set_imats();
                                
                if(RE_local_test_break()==0) {
@@ -492,29 +508,53 @@ void render_envmap(EnvMap *env)
 void make_envmaps()
 {
        Tex *tex;
-       int do_init= 0;
-       
-       tex= G.main->tex.first;
-       while(tex) {
-               if(tex->id.us && tex->type==TEX_ENVMAP) {
-                       if(tex->env && tex->env->object) {
-                               if(tex->env->object->lay & G.scene->lay) {
-                                       if(tex->env->stype!=ENV_LOAD) {
-                                               
-                                               if(tex->env->ok==0) {
-                                                       do_init= 1;
-                                                       render_envmap(tex->env);
-                                               }
-                                               else if((R.r.mode & R_OSA) && tex->env->ok==ENV_NORMAL) {
-                                                       do_init= 1;
-                                                       RE_free_envmapdata(tex->env);
-                                                       render_envmap(tex->env);
+       int do_init= 0, depth= 0;
+       
+       if (!(R.r.mode & R_ENVMAP)) return;
+
+
+       /* 5 = hardcoded max recursion level */
+       while(depth<5) {
+               tex= G.main->tex.first;
+               while(tex) {
+                       if(tex->id.us && tex->type==TEX_ENVMAP) {
+                               if(tex->env && tex->env->object) {
+                                       if(tex->env->object->lay & G.scene->lay) {
+                                               if(tex->env->stype!=ENV_LOAD) {
+                                                       
+                                                       /* decide if to render an envmap (again) */
+                                                       if(tex->env->depth >= depth) {
+                                                               
+                                                               /* set 'recalc' to make sure it does an entire loop of recalcs */
+                                                               
+                                                               if(tex->env->ok) {
+                                                                               /* free when OSA, and old one isn't OSA */
+                                                                       if((R.r.mode & R_OSA) && tex->env->ok==ENV_NORMAL) 
+                                                                               RE_free_envmapdata(tex->env);
+                                                                               /* free when size larger */
+                                                                       else if(tex->env->lastsize < R.r.size) 
+                                                                               RE_free_envmapdata(tex->env);
+                                                                               /* free when env is in recalcmode */
+                                                                       else if(tex->env->recalc)
+                                                                               RE_free_envmapdata(tex->env);
+                                                               }
+                                                               
+                                                               if(tex->env->ok==0 && depth==0) tex->env->recalc= 1;
+                                                               
+                                                               if(tex->env->ok==0) {
+                                                                       do_init= 1;
+                                                                       render_envmap(tex->env);
+                                                                       
+                                                                       if(depth==tex->env->depth) tex->env->recalc= 0;
+                                                               }
+                                                       }
                                                }
                                        }
                                }
                        }
+                       tex= tex->id.next;
                }
-               tex= tex->id.next;
+               depth++;
        }
 
        if(do_init) {
index 074d13321a5e8f54b0f0b9bb0f74513096e77cd1..f2d1e73807304d8820a84c51a89a940a121c9c7f 100644 (file)
@@ -1194,6 +1194,7 @@ static void init_render_displist_mesh(Object *ob)
                                        flen= CalcNormFloat4(v1->co, v3->co, v4->co, v2->co, n1);
                                        if(flen!=0.0) {
                                                vlr= RE_findOrAddVlak(R.totvlak++);
+                                               vlr->ob= ob;
                                                vlr->v1= v1;
                                                vlr->v2= v3;
                                                vlr->v3= v4;
@@ -1272,6 +1273,7 @@ static void init_render_displist_mesh(Object *ob)
 
                                if(flen!=0.0) {
                                        vlr= RE_findOrAddVlak(R.totvlak++);
+                                       vlr->ob= ob;
                                        vlr->v1= v1;
                                        vlr->v2= v2;
                                        vlr->v3= v3;
@@ -1445,6 +1447,7 @@ static void init_render_mball(Object *ob)
        for(a=0; a<dl->parts; a++, index+=4) {
 
                vlr= RE_findOrAddVlak(R.totvlak++);
+               vlr->ob= ob;
                vlr->v1= RE_findOrAddVert(startvert+index[0]);
                vlr->v2= RE_findOrAddVert(startvert+index[1]);
                vlr->v3= RE_findOrAddVert(startvert+index[2]);
@@ -1648,6 +1651,7 @@ static void init_render_mesh(Object *ob)
                                                if(mface->v3) {
 
                                                        vlr= RE_findOrAddVlak(R.totvlak++);
+                                                       vlr->ob= ob;
                                                        vlr->v1= RE_findOrAddVert(vertofs+mface->v1);
                                                        vlr->v2= RE_findOrAddVert(vertofs+mface->v2);
                                                        vlr->v3= RE_findOrAddVert(vertofs+mface->v3);
@@ -1727,6 +1731,7 @@ static void init_render_mesh(Object *ob)
                                                }
                                                else if(mface->v2 && (ma->mode & MA_WIRE)) {
                                                        vlr= RE_findOrAddVlak(R.totvlak++);
+                                                       vlr->ob= ob;
                                                        vlr->v1= RE_findOrAddVert(vertofs+mface->v1);
                                                        vlr->v2= RE_findOrAddVert(vertofs+mface->v2);
                                                        vlr->v3= vlr->v2;
@@ -2119,6 +2124,7 @@ static void init_render_surf(Object *ob)
 
 //                                     if(flen!=0.0) {
                                                vlr= RE_findOrAddVlak(R.totvlak++);
+                                               vlr->ob= ob;
                                                vlr->v1= v1; vlr->v2= v2; vlr->v3= v3; vlr->v4= v4;
                                                VECCOPY(vlr->n, n1);
                                                vlr->len= flen;
@@ -2255,6 +2261,7 @@ static void init_render_surf(Object *ob)
                                        flen= CalcNormFloat4(v1->co, v3->co, v4->co, v2->co, n1);
                                        if(flen!=0.0) {
                                                vlr= RE_findOrAddVlak(R.totvlak++);
+                                               vlr->ob= ob;
                                                vlr->v1= v1;
                                                vlr->v2= v3;
                                                vlr->v3= v4;
@@ -2492,6 +2499,7 @@ static void init_render_curve(Object *ob)
                                        for(; b<bl->nr; b++) {
 
                                                vlr= RE_findOrAddVlak(R.totvlak++);
+                                               vlr->ob= ob;
                                                vlr->v1= RE_findOrAddVert(p2);
                                                vlr->v2= RE_findOrAddVert(p1);
                                                vlr->v3= RE_findOrAddVert(p3);
index d7071430846279b9bab5ca51ea2e716bbcbfd2b6..b5f1e8d3fbd1c7b6bff9d509e4d4db76cc52dcfe 100644 (file)
@@ -272,6 +272,8 @@ char texstr[15][8]= {"None"  , "Clouds" , "Wood",
 #define B_PACKIMA              1355
 #define B_TEXSETFRAMES 1356
 
+#define B_ENV_FREE_ALL 1357
+
 /* *********************** */
 #define B_ANIMBUTS             1500
 
@@ -3560,6 +3562,19 @@ void do_texbuts(unsigned short event)
                        BIF_preview_changed(G.buts);
                }
                break;
+       case B_ENV_FREE_ALL:
+               tex= G.main->tex.first;
+               while(tex) {
+                       if(tex->id.us && tex->type==TEX_ENVMAP) {
+                               if(tex->env) {
+                                       if(tex->env->stype!=ENV_LOAD) RE_free_envmapdata(tex->env);
+                               }
+                       }
+                       tex= tex->id.next;
+               }
+               allqueue(REDRAWBUTSTEX, 0);
+               BIF_preview_changed(G.buts);
+               break;
        case B_ENV_SAVE:
                if(tex->env && tex->env->ok) {
                        sa= closest_bigger_area();
@@ -3917,8 +3932,10 @@ void texbuts(void)
                }
                else if(tex->type==TEX_ENVMAP) {
                        
-                       if(tex->env==0) tex->env= RE_add_envmap();
-                               
+                       if(tex->env==0) {
+                               tex->env= RE_add_envmap();
+                               tex->env->object= OBACT;
+                       }
                        if(tex->env) {
                                env= tex->env;
                                
@@ -3957,15 +3974,17 @@ void texbuts(void)
                                        uiDefBut(block, BUT, B_ENV_FREE, "Free Data", 350,137,107,24, 0, 0, 0, 0, 0, "Release all images associated with environment map");
                                        uiBlockSetCol(block, BUTGREY);
                                        uiDefBut(block, BUT, B_ENV_SAVE, "Save EnvMap", 461,137,115,24, 0, 0, 0, 0, 0, "Save environment map");
+                                       uiBlockSetCol(block, BUTSALMON);
+                                       uiDefBut(block, BUT, B_ENV_FREE_ALL, "Free all EnvMaps", 600,137,160,24, 0, 0, 0, 0, 0, "Frees all rendered environment maps");
                                }
                                uiBlockSetCol(block, BUTGREY);
-                               uiDefIDPoinBut(block, test_obpoin_but, B_ENV_OB, "Ob:",   350,95,206,24, &(env->object), "Object name");
-                               uiBlockSetCol(block, BUTGREY);
-                               uiDefButF(block, NUM, REDRAWVIEW3D,     "ClipSta", 350,68,122,24, &env->clipsta, 0.01, 50.0, 100, 0, "Set start value for clipping");
-                               uiDefButF(block, NUM, 0,        "ClipEnd", 475,68,142,24, &env->clipend, 0.1, 5000.0, 1000, 0, "Set end value for clipping");
-                               if(env->stype!=ENV_LOAD) uiDefButI(block, NUM, B_ENV_FREE,      "CubeRes", 620,68,140,24, &env->cuberes, 50, 1000.0, 0, 0, "Set the resolution in pixels");
-       
-                               uiDefButF(block, NUM, B_MATPRV, "Filter :",     558,95,201,24, &tex->filtersize, 0.1, 25.0, 0, 0, "Adjust sharpness or blurriness of the reflection"),
+                               uiDefIDPoinBut(block, test_obpoin_but, B_ENV_OB, "Ob:",   350,95,166,24, &(env->object), "Object name");
+                               uiDefButF(block, NUM, B_MATPRV, "Filter :",                               518,95,121,24, &tex->filtersize, 0.1, 25.0, 0, 0, "Adjust sharpness or blurriness of the reflection"),
+                               uiDefButS(block, NUM, B_ENV_FREE, "Depth:",                               639,95,120,24, &env->depth, 0, 5.0, 0, 0, "Number of times a map gets rendered again, for recursive mirror effect"),
+
+                               uiDefButF(block, NUM, REDRAWVIEW3D,     "ClipSta",              350,68,122,24, &env->clipsta, 0.01, 50.0, 100, 0, "Set start value for clipping");
+                               uiDefButF(block, NUM, 0,        "ClipEnd",                                      475,68,142,24, &env->clipend, 0.1, 5000.0, 1000, 0, "Set end value for clipping");
+                               if(env->stype!=ENV_LOAD) uiDefButS(block, NUM, B_ENV_FREE,      "CubeRes", 620,68,140,24, &env->cuberes, 50, 2048.0, 0, 0, "Set the resolution in pixels");
        
                                uiDefBut(block, LABEL, 0, "Don't render layer:",                772,100,140,22, 0, 0.0, 0.0, 0, 0, ""); 
                                xco= 772;
@@ -6628,9 +6647,10 @@ void renderbuts(void)
        uiDefBut(block, BUT,B_DORENDER,"RENDER",        369,142,192,47, 0, 0, 0, 0, 0, "Start the rendering");
        
        uiBlockSetCol(block, BUTGREY);
-       uiDefButS(block, TOG|BIT|1,0,"Shadows", 565,167,122,22, &G.scene->r.mode, 0, 0, 0, 0, "Enable shadow calculation");
-       uiDefButS(block, TOG|BIT|10,0,"Pano",565,142,61,22, &G.scene->r.mode, 0, 0, 0, 0, "Enable panorama rendering (output width is multiplied by Xparts)");
-       uiDefButS(block, TOG|BIT|8,0,"Radio",626,142,61,22, &G.scene->r.mode, 0, 0, 0, 0, "Enable radiosity rendering");
+       uiDefButS(block, TOG|BIT|1,0,"Shadow",  565,167,61,22, &G.scene->r.mode, 0, 0, 0, 0, "Enable shadow calculation");
+       uiDefButS(block, TOG|BIT|4,0,"EnvMap",  626,167,61,22, &G.scene->r.mode, 0, 0, 0, 0, "Enable shadow calculation");
+       uiDefButS(block, TOG|BIT|10,0,"Pano",   565,142,61,22, &G.scene->r.mode, 0, 0, 0, 0, "Enable panorama rendering (output width is multiplied by Xparts)");
+       uiDefButS(block, TOG|BIT|8,0,"Radio",   626,142,61,22, &G.scene->r.mode, 0, 0, 0, 0, "Enable radiosity rendering");
        
        uiDefButS(block, ROW,B_DIFF,"100%",                     565,114,121,20,&G.scene->r.size,1.0,100.0, 0, 0, "Set render size to defined size");
        uiDefButS(block, ROW,B_DIFF,"75%",                      565,90,36,20,&G.scene->r.size,1.0,75.0, 0, 0, "Set render size to 3/4 of defined size");