Index: source/blender/render/intern/source/convertblender.c =================================================================== --- source/blender/render/intern/source/convertblender.c (revision 12896) +++ source/blender/render/intern/source/convertblender.c (working copy) @@ -3596,7 +3596,11 @@ for(a=0; awrld.mtex[a] && re->wrld.mtex[a]->tex) re->wrld.skytype |= WO_SKYTEX; - + + // Sky shaders are handled as a special case of (procedural) textures + // so also set the WO_SKYTEX flag + if (re->wrld.skytype & WO_SKYSKY) re->wrld.skytype |= WO_SKYTEX; + /* AO samples should be OSA minimum */ if(re->osa) while(re->wrld.aosamp*re->wrld.aosamp < re->osa) Index: source/blender/render/intern/source/pixelshading.c =================================================================== --- source/blender/render/intern/source/pixelshading.c (revision 12896) +++ source/blender/render/intern/source/pixelshading.c (working copy) @@ -55,6 +55,7 @@ #include "rendercore.h" #include "shadbuf.h" #include "pixelshading.h" +#include "skylight.h" /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ /* defined in pipeline.c, is hardcopy of active dynamic allocated Render */ @@ -453,62 +454,132 @@ } } -/* Only view vector is important here. Result goes to colf[3] */ +/** + * Called to get sky (background) color. + * @param colf Place to put the result color (float[3]). + * Place the RGB color of the background at direction "view" here. + * @param rco ??? + * @param view The view vector (float[3]). + * 3 komponent vector indicating the view ray direction. + * This vector vector is in camera space. + * If you want view vector in world space multibly it with R.imat. + * @param dxyview ??? + */ void shadeSkyView(float *colf, float *rco, float *view, float *dxyview) { float lo[3], zen[3], hor[3], blend, blendm; int skyflag; + float sun[3], direction[3], d; + + // todo: move these somewhere where they are initialized only ones per frame + Skylight sky; + ToneReproducer tone; + + + // Using physically generated sky color overwrites other options, + // but can be used only with real horizon + if ((R.wrld.skytype & WO_SKYREAL) && (R.wrld.skytype & WO_SKYSKY)) + { + // If there is a control object for sun direction then use it's + // z-axis as sun direction + if (R.wrld.sun_object) + { + sun[0] = R.wrld.sun_object->obmat[2][0]; + sun[1] = R.wrld.sun_object->obmat[2][1]; + sun[2] = R.wrld.sun_object->obmat[2][2]; + } + else // Otherwise calculate sun direction from the given angles + { + sun[0] = sin(R.wrld.sun_z_angle)*cos(R.wrld.sun_x_angle); + sun[1] = sin(R.wrld.sun_z_angle)*sin(R.wrld.sun_x_angle); + sun[2] = cos(R.wrld.sun_z_angle); + } + + // todo: don't call these for every pixel + ToneReproducer_set_params(&tone, R.wrld.display_adaptation, R.wrld.world_adaptation); + Skylight_set_params(&sky, sun, R.wrld.turbidity); + + // Transform view vector from camera-space to world-space + d = 1.0f/sqrt(view[0]*view[0]+view[1]*view[1]+view[2]*view[2]); + direction[0] = d*view[0]; + direction[1] = d*view[1]; + direction[2] = d*view[2]; + MTC_Mat3MulVecfl(R.imat, direction); + + // If the pixel is below horizon check what to do + if (direction[2]<0) + { + if (R.wrld.skyshader_flags & WOSKYSHADER_BELOWHORIZON) + { + if (R.wrld.skyshader_flags & WOSKYSHADER_MIRRORHORIZON) + direction[2] = -direction[2]; + } + else + { + colf[0] = 0; + colf[1] = 0; + colf[2] = 0; + return; + } + } + + // Get the sky color and convert it to RGB + Skylight_get_xyY_value(&sky, direction, colf); + ToneReproducer_xyY_to_RGB(&tone, colf); + } + else // No physically generated sky use other options instead + { + // flag indicating if we render the top hemisphere + skyflag = WO_ZENUP; - /* flag indicating if we render the top hemisphere */ - skyflag = WO_ZENUP; - - /* Some view vector stuff. */ - if(R.wrld.skytype & WO_SKYREAL) { + // Some view vector stuff. + if(R.wrld.skytype & WO_SKYREAL) { + + blend= view[0]*R.grvec[0]+ view[1]*R.grvec[1]+ view[2]*R.grvec[2]; - blend= view[0]*R.grvec[0]+ view[1]*R.grvec[1]+ view[2]*R.grvec[2]; + if(blend<0.0) skyflag= 0; - if(blend<0.0) skyflag= 0; - - blend= fabs(blend); - } - else if(R.wrld.skytype & WO_SKYPAPER) { - blend= 0.5+ 0.5*view[1]; - } - else { - /* the fraction of how far we are above the bottom of the screen */ - blend= fabs(0.5+ view[1]); - } + blend= fabs(blend); + } + else if(R.wrld.skytype & WO_SKYPAPER) { + blend= 0.5+ 0.5*view[1]; + } + else { + // the fraction of how far we are above the bottom of the screen + blend= fabs(0.5+ view[1]); + } - hor[0]= R.wrld.horr; hor[1]= R.wrld.horg; hor[2]= R.wrld.horb; - zen[0]= R.wrld.zenr; zen[1]= R.wrld.zeng; zen[2]= R.wrld.zenb; + hor[0]= R.wrld.horr; hor[1]= R.wrld.horg; hor[2]= R.wrld.horb; + zen[0]= R.wrld.zenr; zen[1]= R.wrld.zeng; zen[2]= R.wrld.zenb; - /* Careful: SKYTEX and SKYBLEND are NOT mutually exclusive! If */ - /* SKYBLEND is active, the texture and color blend are added. */ - if(R.wrld.skytype & WO_SKYTEX) { - VECCOPY(lo, view); - if(R.wrld.skytype & WO_SKYREAL) { + // Careful: SKYTEX and SKYBLEND are NOT mutually exclusive! If + // SKYBLEND is active, the texture and color blend are added. + if(R.wrld.skytype & WO_SKYTEX) { + VECCOPY(lo, view); + if(R.wrld.skytype & WO_SKYREAL) { + + MTC_Mat3MulVecfl(R.imat, lo); - MTC_Mat3MulVecfl(R.imat, lo); + SWAP(float, lo[1], lo[2]); - SWAP(float, lo[1], lo[2]); - + } + do_sky_tex(rco, lo, dxyview, hor, zen, &blend, skyflag); } - do_sky_tex(rco, lo, dxyview, hor, zen, &blend, skyflag); - } - if(blend>1.0) blend= 1.0; - blendm= 1.0-blend; + if(blend>1.0) blend= 1.0; + blendm= 1.0-blend; - /* No clipping, no conversion! */ - if(R.wrld.skytype & WO_SKYBLEND) { - colf[0] = (blendm*hor[0] + blend*zen[0]); - colf[1] = (blendm*hor[1] + blend*zen[1]); - colf[2] = (blendm*hor[2] + blend*zen[2]); - } else { - /* Done when a texture was grabbed. */ - colf[0]= hor[0]; - colf[1]= hor[1]; - colf[2]= hor[2]; + // No clipping, no conversion! + if(R.wrld.skytype & WO_SKYBLEND) { + colf[0] = (blendm*hor[0] + blend*zen[0]); + colf[1] = (blendm*hor[1] + blend*zen[1]); + colf[2] = (blendm*hor[2] + blend*zen[2]); + } else { + // Done when a texture was grabbed. + colf[0]= hor[0]; + colf[1]= hor[1]; + colf[2]= hor[2]; + } } } @@ -569,3 +640,4 @@ /* eof */ + Index: source/blender/blenkernel/intern/world.c =================================================================== --- source/blender/blenkernel/intern/world.c (revision 12896) +++ source/blender/blenkernel/intern/world.c (working copy) @@ -108,6 +108,16 @@ wrld->physicsEngine= WOPHY_BULLET;//WOPHY_SUMO; Bullet by default wrld->preview = NULL; + // Init sky shader attributes + wrld->sun_x_angle = 1.57; + wrld->sun_z_angle = 0.8; + wrld->sun_object = 0; + wrld->skyshader = 0; + wrld->skyshader_flags = 0; + wrld->turbidity = 4; + wrld->world_adaptation = 40000.0f; + wrld->display_adaptation = 50.0f; + return wrld; } Index: source/blender/makesdna/DNA_world_types.h =================================================================== --- source/blender/makesdna/DNA_world_types.h (revision 12896) +++ source/blender/makesdna/DNA_world_types.h (working copy) @@ -119,6 +119,16 @@ ScriptLink scriptlink; + // For sky color calculation + float sun_x_angle; // Sun angle from x axis 0-2pi + float sun_z_angle; // Sun angle from z-axis (zenith) 0-pi + struct Object *sun_object; // Sun control object + short skyshader; // reserved for future to choose sky shader if more are added + short skyshader_flags; // flags + float turbidity; // 2 (clear) - 25 (haze) + float world_adaptation; + float display_adaptation; + } World; /* **************** WORLD ********************* */ @@ -127,6 +137,7 @@ #define WO_SKYBLEND 1 #define WO_SKYREAL 2 #define WO_SKYPAPER 4 +#define WO_SKYSKY 32 /* while render: */ #define WO_SKYTEX 8 #define WO_ZENUP 16 @@ -177,5 +188,9 @@ #define WOPHY_ODE 4 #define WOPHY_BULLET 5 +/* Sky shader flags */ +#define WOSKYSHADER_BELOWHORIZON 1 +#define WOSKYSHADER_MIRRORHORIZON 2 + #endif Index: source/blender/src/buttons_shading.c =================================================================== --- source/blender/src/buttons_shading.c (revision 12896) +++ source/blender/src/buttons_shading.c (working copy) @@ -1943,6 +1943,38 @@ } } + +/** + * Creates the options panel for sky color generation controls. + * @param wrld Pointer to the World-struct + */ +static void world_panel_sky(World *wrld) +{ + // Add the panel as a tab to the preview panel + uiBlock *block; + block= uiNewBlock(&curarea->uiblocks, "world_panel_sky", UI_EMBOSS, UI_HELV, curarea->win); + uiNewPanelTabbed("Preview", "World"); + if(uiNewPanel(curarea, block, "Sky", "World", 320, 0, 318, 204)==0) return; + uiSetButLock(wrld->id.lib!=0, ERROR_LIBDATA_MESSAGE); + + // Eye luminance adaptation values + uiDefButF(block, NUM, B_WORLDPRV, "World adaptation:",10,230,220,19, &wrld->world_adaptation, 0.001f, 100000.0f, 1, 0, "Set eye world adaptation luminance"); + uiDefButF(block, NUM, B_WORLDPRV, "Display adaptation:",10,250,220,19, &wrld->display_adaptation, 1.0f, 100.0f, 1, 0, "Set eye display adaptation luminance"); + + // Air tubidity control 2-25 + uiDefButF(block, NUM, B_WORLDPRV, "Turbidity:",10,210,220,19, &wrld->turbidity, 2.0f, 25.0, 1, 0, "Set turbidity 2 (clear) - 25 (haze)"); + + // Sun direction controls angles and control object + uiDefButF(block, NUM, B_WORLDPRV, "Sun x angle:", 10,150,220,19, &(wrld->sun_x_angle), 0.0, 6.28, 0, 0, "Angle between the sun direction and x-axis"); + uiDefButF(block, NUM, B_WORLDPRV, "Sun z angle:", 10,170,220,19, &(wrld->sun_z_angle), 0.0, 3.14, 0, 0, "Angle between the sun direction and z-axis (zenith)"); + uiDefIDPoinBut(block, test_obpoin_but, ID_OB, B_WORLDPRV, "Ob:", 10,190,220,19, &(wrld->sun_object), "Object to use as sun direction"); + + // Flags about how to render below horizon + uiDefButBitS(block, TOG, WOSKYSHADER_BELOWHORIZON, B_WORLDPRV, "Below horizon", 10, 270,110,19, &(wrld->skyshader_flags), 0, 0, 0, 0, "Also shade below horizon"); + uiDefButBitS(block, TOG, WOSKYSHADER_MIRRORHORIZON, B_WORLDPRV, "Mirror horizon", 120,270,110,19, &(wrld->skyshader_flags), 0, 0, 0, 0, "Shade below horizon by mirroring values above it"); +} + + static void world_panel_mapto(World *wrld) { uiBlock *block; @@ -2277,9 +2309,10 @@ uiDefBut(block, LABEL, 0, " ", 20,20,10,10, 0, 0, 0, 0, 0, ""); uiBlockBeginAlign(block); - uiDefButBitS(block, TOG, WO_SKYREAL, B_WORLDPRV,"Real", 200,175,80,25, &wrld->skytype, 0, 0, 0, 0, "Renders background with a real horizon"); - uiDefButBitS(block, TOG, WO_SKYBLEND, B_WORLDPRV,"Blend",200,150,80,25, &wrld->skytype, 0, 0, 0, 0, "Renders background with natural progression from horizon to zenith"); - uiDefButBitS(block, TOG,WO_SKYPAPER, B_WORLDPRV,"Paper",200,125,80,25, &wrld->skytype, 0, 0, 0, 0, "Flattens blend or texture coordinates"); + uiDefButBitS(block, TOG, WO_SKYREAL, B_WORLDPRV, "Real", 200,175,80,25, &wrld->skytype, 0, 0, 0, 0, "Renders background with a real horizon"); + uiDefButBitS(block, TOG, WO_SKYBLEND, B_WORLDPRV, "Blend", 200,150,80,25, &wrld->skytype, 0, 0, 0, 0, "Renders background with natural progression from horizon to zenith"); + uiDefButBitS(block, TOG, WO_SKYPAPER, B_WORLDPRV, "Paper", 200,125,80,25, &wrld->skytype, 0, 0, 0, 0, "Flattens blend or texture coordinates"); + uiDefButBitS(block, TOG, WO_SKYSKY, B_WORLDPRV, "Sky", 200,100,80,25, &wrld->skytype, 0, 0, 0, 0, "Use physically based sky model to calculate color (overwrites blend and texture color)"); uiBlockEndAlign(block); } @@ -4231,6 +4264,7 @@ world_panel_amb_occ(wrld); world_panel_texture(wrld); world_panel_mapto(wrld); + world_panel_sky(wrld); } } Index: source/blender/blenloader/intern/readfile.c =================================================================== --- source/blender/blenloader/intern/readfile.c (revision 12896) +++ source/blender/blenloader/intern/readfile.c (working copy) @@ -6673,6 +6673,21 @@ Lamp *la; Material *ma; ParticleSettings *part; + World *wo; + + // Set sky shader default settings + if (main->subversionfile==0) { + for (wo = main->world.first; wo; wo= wo->id.next) { + wo->sun_x_angle = 1.57; + wo->sun_z_angle = 0.8; + wo->sun_object = 0; + wo->skyshader = 0; + wo->skyshader_flags = 0; + wo->turbidity = 4; + wo->world_adaptation = 40000; + wo->display_adaptation = 50; + } + } /* unless the file was created 2.44.3 but not 2.45, update the constraints */ if ( !(main->versionfile==244 && main->subversionfile==3) &&