Index: source/blender/render/intern/source/rayshade.c =================================================================== --- source/blender/render/intern/source/rayshade.c (revision 13145) +++ source/blender/render/intern/source/rayshade.c (working copy) @@ -1563,12 +1604,29 @@ shadfac[1]+= (1.0f-skyfac)*R.wrld.horg + skyfac*R.wrld.zeng; shadfac[2]+= (1.0f-skyfac)*R.wrld.horb + skyfac*R.wrld.zenb; } - else { /* WO_AOSKYTEX */ + else if (aocolor==WO_AOSKYTEX) { shadeSkyView(skycol, isec.start, view, dxyview); shadfac[0]+= skycol[0]; shadfac[1]+= skycol[1]; shadfac[2]+= skycol[2]; } + else if (aocolor==WO_AODIFFUSESH) { + float dot; + + /* The spherical harmonics are already stored as the result over the whole hemisphere. + * By averaging AO samples, it's averaging a whole series of hemispheres, with the AO + * vector as the up-vector of that hemisphere. This gives an overly smoothed result + * so this simple cosine weighting can help make it look as it should again. --Matt */ + dot = Inpf(dir, shi->vn); + Mat4Mul3Vecfl(R.viewinv, view); + + ibl_diffusesh_getcolor_coeffs(skycol, R.wrld.dsh_coeffs[0], R.wrld.dsh_coeffs[1], R.wrld.dsh_coeffs[2], R.wrld.dsh_coeffs[3], + R.wrld.dsh_coeffs[4], R.wrld.dsh_coeffs[5], R.wrld.dsh_coeffs[6], R.wrld.dsh_coeffs[7], R.wrld.dsh_coeffs[8], view); + + shadfac[0]+= skycol[0]*dot; + shadfac[1]+= skycol[1]*dot; + shadfac[2]+= skycol[2]*dot; + } skyadded++; } Index: source/blender/render/intern/source/shadeinput.c =================================================================== --- source/blender/render/intern/source/shadeinput.c (revision 13145) +++ source/blender/render/intern/source/shadeinput.c (working copy) @@ -765,6 +765,11 @@ else VECCOPY(shi->vn, shi->facenor); + /* normal in worldspace, used in Diffuse SH IBL, and nodes */ + VECCOPY(shi->worldnor, shi->vn); + Mat4Mul3Vecfl(R.viewinv, shi->worldnor); + VecMulf(shi->worldnor, -1.0f); + /* used in nodes */ VECCOPY(shi->vno, shi->vn); Index: source/blender/render/intern/source/shadeoutput.c =================================================================== --- source/blender/render/intern/source/shadeoutput.c (revision 13145) +++ source/blender/render/intern/source/shadeoutput.c (working copy) @@ -1576,6 +1576,10 @@ } } + /* ibl, adds results in diff and shad pass */ + if(R.wrld.mode & WO_IMAGE_BASED_LIGHTING) + image_based_lighting(shi, shr); + /* lighting pass */ if(passflag & (SCE_PASS_COMBINED|SCE_PASS_DIFFUSE|SCE_PASS_SPEC|SCE_PASS_SHADOW)) { GroupObject *go; Index: source/blender/render/intern/source/ibl.c =================================================================== --- source/blender/render/intern/source/ibl.c (revision 0) +++ source/blender/render/intern/source/ibl.c (revision 0) @@ -0,0 +1,284 @@ +/** +* $Id: + * + * ***** 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. + * + * Contributors: Matt Ebb + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#include +#include +#include + +#include "BLI_arithb.h" + +#include "IMB_imbuf_types.h" + +#include "DNA_image_types.h" +#include "DNA_texture_types.h" +#include "DNA_world_types.h" + +#include "BKE_image.h" +#include "BKE_global.h" + +/* local include */ +#include "render_types.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; +/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ + +float sinc(float x) { + if (fabs(x) < 1.0e-4) return 1.0 ; + else return(sin(x)/x) ; +} + + +/* Converts UV coordinates from an environment map to the equivalent 3D vector + * Incoming UV coordinates are considered to be in [-1,1] + * domega = the solid angle that pixel represents in the unit sphere + * returns 1 if the pixel actually represents anything in the env map + * eg. pixels within the unit circle of an angmap */ +static int uv_to_xyz(int mapping, float *uv, float *xyz, float dtheta_dphi, float *domega) +{ + float phi, theta, sinphi, sintheta; + float radius_sq=1.0f; + + float u = uv[0]; + float v = uv[1]; + + switch(mapping) + { + case WO_IBL_MAP_SPHERE: + phi = (v*0.5f+0.5f)*M_PI; // pi < phi < 0 + theta = -u*M_PI; // pi < theta < -pi + + /* transform u,v to cartesian components */ + sinphi = sin(phi); + xyz[0] = -sinphi * sin(theta); + xyz[1] = sinphi * cos(theta); + xyz[2] = -cos(phi); + + /* solid angle */ + *domega = sinphi*dtheta_dphi; + break; + + case WO_IBL_MAP_ANGMAP: + default: + /* for angmap, only consider points inside the unit circle */ + radius_sq = u*u + v*v; + if(radius_sq>1.0f) return 0; + + theta = M_PI*sqrt(radius_sq); + phi = atan2(v,u); + + /* transform u,v to cartesian components */ + sintheta = sin(theta); + xyz[0] = sintheta*cos(phi); + xyz[1] = cos(theta); + xyz[2] = sintheta*sin(phi); + + /* solid angle */ + *domega = sinc(theta)*dtheta_dphi; + break; + } + + return 1; +} + +/* *** Diffuse irradiance: Spherical Harmonics *** */ +/* +* Based on the paper and sample code of: +* "An Efficient Representation for Irradiance Environment Maps" +* by Ravi Ramamoorthi and Pat Hanrahan +* http://graphics.stanford.edu/papers/envmap/ +* +* Also thanks to some example code by Francesco Banterle +* http://www.banterle.com/francesco/ +* +* This calculates RGB values for lighting coefficients L_{lm} with +* 0 <= l <= 2 and -l <= m <= l. There are 9 coefficients in all. +*/ + + +void ibl_diffusesh_prefilter(struct Render *re) +{ + ImBuf *ibuf; + Image *ima; + float uv[2], xyz[3], x, y, z; + float dtheta_dphi, c, domega=0.f; + int w, h, i, j, k; + float *rect_float, pix[3]; + int index, col; + + ima = re->wrld.ibl_image; + if (!ima) return; + ibuf = BKE_image_get_ibuf(ima, NULL); + + w = ibuf->x; + h = ibuf->y; + rect_float = ibuf->rect_float; + if (!rect_float) return; + + dtheta_dphi= (M_PI/(float)h) * (M_PI_2/(float)w); + if (re->wrld.ibl_mapping == WO_IBL_MAP_SPHERE) dtheta_dphi /= 2.0f; + + memset(re->wrld.dsh_coeffs, 0, sizeof(re->wrld.dsh_coeffs)); + + for(j=0;jwrld.ibl_mapping, uv, xyz, dtheta_dphi, &domega); + + x = xyz[0]; y = xyz[1]; z = xyz[2]; + index = j*w+i; + + pix[0] = rect_float[4 * index + 0]; + pix[1] = rect_float[4 * index + 1]; + pix[2] = rect_float[4 * index + 2]; + + /* add the light per pixel to the coefficients per term, + * based on a constant, the differential solid angle and + * cartesian components of surface normal x,y,z */ + for (col = 0 ; col < 3 ; col++) { + + /* L_{00}. Note that Y_{00} = 0.282095 */ + c=0.282095f*domega; + re->wrld.dsh_coeffs[0][col] += pix[col]*c; + + /* L_{1m}. -1 <= m <= 1. The linear terms */ + c=0.488603f*domega; + re->wrld.dsh_coeffs[1][col]+=pix[col]*c*y; + re->wrld.dsh_coeffs[2][col]+=pix[col]*c*z; + re->wrld.dsh_coeffs[3][col]+=pix[col]*c*x; + + /* The Quadratic terms, L_{2m} -2 <= m <= 2 */ + /* First, L_{2-2}, L_{2-1}, L_{21} corresponding to xy,yz,xz */ + c=1.092548f*domega; + re->wrld.dsh_coeffs[4][col]+=pix[col]*c*x*y; + re->wrld.dsh_coeffs[5][col]+=pix[col]*c*y*z; + re->wrld.dsh_coeffs[7][col]+=pix[col]*c*x*z; + + /* L_{20}. Note that Y_{20} = 0.315392 (3z^2 - 1) */ + c=0.315392f*domega*(3.0f*z*z-1.0f); + re->wrld.dsh_coeffs[6][col]+=pix[col]*c; + + c=0.546274f*domega*(x*x-y*y); + re->wrld.dsh_coeffs[8][col]+=pix[col]*c; + } + } + } +}; + + +/* This function is quite ugly, but works ok. + * matrix form (in paper's sample code) would be better if i could get it working... */ +void ibl_diffusesh_getcolor_coeffs( float *col, + float *L00, float *L1_1, float *L10, float *L11, + float *L2_2, float *L2_1, float *L20, float *L21, float *L22, + float *n) +{ + float x2, y2, z2, xy, yz, xz, x, y, z; + const float c1 = 0.429043, c2 = 0.511664, c3 = 0.743125, c4 = 0.886227, c5 = 0.247708; + float a[3], b[3], c[3], d[3], e[3], f[3], g[3], h[3], i[3], j[3]; + float efg[3], hij[3]; + float mycol[3]; + + x = n[0] ; y = n[1] ; z = n[2]; + + x2 = x*x ; y2 = y*y ; z2 = z*z ; + xy = x*y ; yz = y*z ; xz = x*z ; + + + + VECCOPY(a, L22); + VecMulf(a, c1*(x2-y2)); + + VECCOPY(b, L20); + VecMulf(b, c3*(z2)); + + VECCOPY(c, L00); + VecMulf(c, c4); + + VECCOPY(d, L20); + VecMulf(d, c5); + + VECCOPY(e, L2_2); + VecMulf(e, xy); + + VECCOPY(f, L21); + VecMulf(f, xz); + + VECCOPY(g, L2_1); + VecMulf(g, yz); + + VecAddf(efg, e, f); + VecAddf(efg, efg, g); + VecMulf(efg, 2*c1); + + VECCOPY(h, L11); + VecMulf(h, x); + + VECCOPY(i, L1_1); + VecMulf(i, y); + + VECCOPY(j, L10) + VecMulf(j, z); + + VecAddf(hij, h, i); + VecAddf(hij, hij, j); + VecMulf(hij, 2*c2); + + VecAddf(mycol, a, b); + VecAddf(mycol, mycol, c); + VecSubf(mycol, mycol, d); + VecAddf(mycol, mycol, efg); + VecAddf(mycol, mycol, hij); + + VECCOPY(col, mycol); + +/* equation: + col = c1*L22*(x2-y2) + c3*L20*z2 + c4*L00 - c5*L20 + + 2*c1*(L2_2*xy + L21*xz + L2_1*yz) + + 2*c2*(L11*x+L1_1*y+L10*z) ; +*/ +} + + +void image_based_lighting(ShadeInput *shi, ShadeResult *shr) +{ + float iblcol[3], nor[3]; + + VECCOPY(nor, shi->worldnor); + + ibl_diffusesh_getcolor_coeffs(iblcol, R.wrld.dsh_coeffs[0], R.wrld.dsh_coeffs[1], R.wrld.dsh_coeffs[2], R.wrld.dsh_coeffs[3], + R.wrld.dsh_coeffs[4], R.wrld.dsh_coeffs[5], R.wrld.dsh_coeffs[6], R.wrld.dsh_coeffs[7], R.wrld.dsh_coeffs[8], nor); + + VecMulf(iblcol, R.wrld.ibl_multiplier); + + VecAddf(shr->diff, shr->diff, iblcol); + VecAddf(shr->shad, shr->shad, iblcol); +} Property changes on: source/blender/render/intern/source/ibl.c ___________________________________________________________________ Name: svn:executable + * Index: source/blender/render/intern/source/convertblender.c =================================================================== --- source/blender/render/intern/source/convertblender.c (revision 13145) +++ source/blender/render/intern/source/convertblender.c (working copy) @@ -4220,8 +4220,17 @@ init_render_hammersley(re); else if (re->wrld.ao_samp_method == WO_AOSAMP_CONSTANT) init_ao_sphere(&re->wrld); + + if (re->wrld.aocolor == WO_AODIFFUSESH) + ibl_diffusesh_prefilter(re); } + if(re->wrld.mode & WO_IMAGE_BASED_LIGHTING) { + if (re->wrld.ibl_method == WO_IBL_DIFFUSESH) { + ibl_diffusesh_prefilter(re); + } + } + /* still bad... doing all */ init_render_textures(re); init_render_materials(re->r.mode, &re->wrld.ambr); Index: source/blender/render/intern/include/render_types.h =================================================================== --- source/blender/render/intern/include/render_types.h (revision 13145) +++ source/blender/render/intern/include/render_types.h (working copy) @@ -33,6 +33,7 @@ /* ------------------------------------------------------------------------- */ #include "DNA_color_types.h" +#include "DNA_image_types.h" #include "DNA_scene_types.h" #include "DNA_world_types.h" #include "DNA_object_types.h" Index: source/blender/render/intern/include/rendercore.h =================================================================== --- source/blender/render/intern/include/rendercore.h (revision 13145) +++ source/blender/render/intern/include/rendercore.h (working copy) @@ -105,5 +105,14 @@ extern void init_render_hammersley(Render *re); extern void free_render_qmcsampler(Render *re); +/* -------- ibl.c ------- */ + +extern void image_based_lighting(struct ShadeInput *shi, struct ShadeResult *shr); +extern void ibl_diffusesh_prefilter(Render *re); +extern void ibl_diffusesh_getcolor_coeffs( float *col, + float *L00, float *L1_1, float *L10, float *L11, + float *L2_2, float *L2_1, float *L20, float *L21, float *L22, + float *n); + #endif /* RENDER_EXT_H */ Index: source/blender/render/extern/include/RE_shader_ext.h =================================================================== --- source/blender/render/extern/include/RE_shader_ext.h (revision 13145) +++ source/blender/render/extern/include/RE_shader_ext.h (working copy) @@ -133,6 +133,7 @@ float lo[3], gl[3], ref[3], orn[3], winco[3], sticky[3], vcol[4], rad[3]; float refcol[4], displace[3]; float strand, tang[3], stress, winspeed[4]; + float worldnor[3]; ShadeInputUV uv[8]; /* 8 = MAX_MTFACE */ ShadeInputCol col[8]; /* 8 = MAX_MCOL */ Index: source/blender/blenkernel/intern/world.c =================================================================== --- source/blender/blenkernel/intern/world.c (revision 13145) +++ source/blender/blenkernel/intern/world.c (working copy) @@ -37,6 +37,7 @@ #include #include "MEM_guardedalloc.h" +#include "DNA_image_types.h" #include "DNA_world_types.h" #include "DNA_texture_types.h" #include "DNA_scriptlink_types.h" @@ -86,6 +87,7 @@ World *add_world(char *name) { World *wrld; + ImageUser *iuser; wrld= alloc_libblock(&G.main->world, ID_WO, name); @@ -107,6 +109,14 @@ wrld->physicsEngine= WOPHY_BULLET;//WOPHY_SUMO; Bullet by default wrld->preview = NULL; + + iuser = &(wrld->ibl_iuser); + + iuser->sfra= 1; + iuser->fie_ima= 2; + iuser->ok= 1; + + wrld->ibl_multiplier = 1.0; return wrld; } Index: source/blender/python/api2_2x/World.h =================================================================== --- source/blender/python/api2_2x/World.h (revision 13145) +++ source/blender/python/api2_2x/World.h (working copy) @@ -1,5 +1,5 @@ /* - * $Id: World.h 10269 2007-03-15 01:09:14Z campbellbarton $ + * $Id$ * * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** * @@ -34,6 +34,7 @@ #define EXPP_WORLD_H #include +#include "DNA_image_types.h" #include "DNA_world_types.h" #define BPy_World_Check(v) ((v)->ob_type==&World_Type) Index: source/blender/makesdna/DNA_world_types.h =================================================================== --- source/blender/makesdna/DNA_world_types.h (revision 13145) +++ source/blender/makesdna/DNA_world_types.h (working copy) @@ -39,12 +39,18 @@ struct Ipo; struct MTex; +struct Image; +struct ImageUser; #ifndef MAX_MTEX #define MAX_MTEX 10 #endif +typedef struct Ibl { + float dsh_coeffs[9][3]; +} Ibl; + /** * World defines general modeling data such as a background fill, * gravity, color model, stars, etc. It mixes game-data, rendering @@ -110,13 +116,20 @@ float *aosphere, *aotables; + short ibl_method; + short ibl_mapping; + float ibl_multiplier; + struct Image *ibl_image; + struct ImageUser ibl_iuser; struct Ipo *ipo; struct MTex *mtex[10]; /* previews */ struct PreviewImage *preview; - + + float dsh_coeffs[9][3]; + int padblah; ScriptLink scriptlink; } World; @@ -137,6 +150,7 @@ #define WO_DOF 4 #define WO_ACTIVITY_CULLING 8 #define WO_AMB_OCC 16 +#define WO_IMAGE_BASED_LIGHTING 32 /* aomix */ #define WO_AOADD 0 @@ -156,7 +170,15 @@ #define WO_AOPLAIN 0 #define WO_AOSKYCOL 1 #define WO_AOSKYTEX 2 +#define WO_AODIFFUSESH 3 +/* ibl_method */ +#define WO_IBL_DIFFUSESH 0 + +/* ibl_mapping */ +#define WO_IBL_MAP_ANGMAP 0 +#define WO_IBL_MAP_SPHERE 1 + /* texco (also in DNA_material_types.h) */ #define TEXCO_ANGMAP 64 #define TEXCO_H_SPHEREMAP 256 Index: source/blender/src/buttons_shading.c =================================================================== --- source/blender/src/buttons_shading.c (revision 13145) +++ source/blender/src/buttons_shading.c (working copy) @@ -2133,13 +2133,90 @@ } +static void world_panel_ibl(World *wrld) +{ + uiBlock *block; + short yco=PANEL_YMAX; + char *strp; + struct ImageUser *iuser= &(wrld->ibl_iuser); + uiBut *but; + + block= uiNewBlock(&curarea->uiblocks, "world_panel_ibl", UI_EMBOSS, UI_HELV, curarea->win); + uiNewPanelTabbed("Amb Occ", "World"); + if(uiNewPanel(curarea, block, "Image Based Lighting", "World", PANELX, PANELY, PANELW, PANELH)==0) return; + + uiDefButBitS(block, TOG, WO_IMAGE_BASED_LIGHTING, B_REDR, "Image Based Lighting", + X2CLM1, yco-=BUTH, BUTW1, BUTH, &wrld->mode, 0, 0, 0, 0, "Enables lighting from an environment image (light probe)"); + + yco -= YSPACE; + + uiDefButS(block, MENU, B_REDR, "Calculation Method %t|Diffuse Prefiltered %x0", + X2CLM1, yco-=BUTH, BUTW2, BUTH, &wrld->ibl_method, 0, 0, 0, 0, ""); + + yco -= YSPACE; + + /* Browse */ + IMAnames_to_pupstring(&strp, NULL, NULL, &(G.main->image), NULL, &iuser->menunr); + + uiBlockBeginAlign(block); + but= uiDefButS(block, MENU, B_REDR, strp, + X2CLM1, yco-=BUTH, ICONBUTW, BUTH, &iuser->menunr, 0, 0, 0, 0, "Selects an existing Image or Movie"); + uiButSetFunc(but, image_browse_cb, &(wrld->ibl_image), iuser); + + MEM_freeN(strp); + + if (wrld->ibl_image != NULL) { + char str[128]; + + if (wrld->ibl_image->source != IMA_SRC_FILE) { + uiDefBut(block, LABEL, 0, "Still images only", + X2CLM1, yco-=BUTH, BUTW2, BUTH, 0, 0, 0, 0, 0, ""); /* for align in panel */ + return; + } + uiSetButLock(wrld->ibl_image->id.lib!=NULL, ERROR_LIBDATA_MESSAGE); + but= uiDefIconBut(block, BUT, B_REDR, ICON_FILESEL, + X2CLM1+ICONBUTW, yco, X2CLM1+ICONBUTW, BUTH, 0, 0, 0, 0, 0, "Open Fileselect to load new Image"); + uiButSetFunc(but, image_load_fs_cb, &(wrld->ibl_image), iuser); + + but= uiDefBut(block, TEX, B_IDNAME, "IM:", + X2CLM1+2*ICONBUTW, yco, PANEL_XMAX-4*ICONBUTW-BUTW4, BUTH, wrld->ibl_image->id.name+2, 0.0, 21.0, 0, 0, "Current Image Datablock name."); + uiButSetFunc(but, test_idbutton_cb, wrld->ibl_image->id.name, NULL); + + but= uiDefBut(block, BUT, B_REDR, "Reload", + PANEL_XMAX-2*ICONBUTW-BUTW4, yco, BUTW4, BUTH, NULL, 0, 0, 0, 0, "Reloads Image or Movie"); + uiButSetFunc(but, image_reload_cb, &(wrld->ibl_image), iuser); + + but= uiDefIconBut(block, BUT, B_REDR, ICON_X, + PANEL_XMAX-2*ICONBUTW, yco, ICONBUTW, BUTH, 0, 0, 0, 0, 0, "Unlink Image block"); + uiButSetFunc(but, image_unlink_cb, &(wrld->ibl_image), NULL); + + sprintf(str, "%d", wrld->ibl_image->id.us); + uiDefBut(block, BUT, B_NOP, str, + PANEL_XMAX-ICONBUTW, yco, ICONBUTW, BUTH, 0, 0, 0, 0, 0, "Only displays number of users of Image block"); + + } else { + but= uiDefBut(block, BUT, B_REDR, "Load", + X2CLM1+ICONBUTW, yco, BUTW2-ICONBUTW, BUTH, NULL, 0, 0, 0, 0, "Load new Image"); + uiButSetFunc(but, image_load_fs_cb, &(wrld->ibl_image), iuser); + } + + uiBlockEndAlign(block); + + yco-= YSPACE; + + uiDefButF(block, NUM, B_REDR, "Multiplier:", + X2CLM1, yco-=BUTH, BUTW2, BUTH, &wrld->ibl_multiplier, 0.0, 100.0, 1.0, 0, "Multiply the final result to brighten or darken the lighting"); + + uiDefButS(block, MENU, B_REDR, "Image Format %t|Angular Map %x0|Sphere (LatLong) %x1", + X2CLM2, yco, BUTW2, BUTH, &wrld->ibl_mapping, 0, 0, 0, 0, ""); +} + static void world_panel_amb_occ(World *wrld) { uiBlock *block; short yco=PANEL_YMAX; block= uiNewBlock(&curarea->uiblocks, "world_panel_amb_oc", UI_EMBOSS, UI_HELV, curarea->win); - uiNewPanelTabbed("Mist / Stars / Physics", "World"); if(uiNewPanel(curarea, block, "Amb Occ", "World", PANELX, PANELY, PANELW, PANELH)==0) return; uiBlockSetCol(block, TH_BUT_SETTING1); @@ -2205,18 +2282,14 @@ /* color treatment */ uiBlockBeginAlign(block); - uiDefButS(block, ROW, B_REDR, "Plain", - X3CLM1, yco-=BUTH, BUTW3, BUTH, &wrld->aocolor, 2.0, (float)WO_AOPLAIN, 0, 0, "Plain diffuse energy (white)"); - uiDefButS(block, ROW, B_REDR, "Sky Color", - X3CLM2, yco, BUTW3, BUTH, &wrld->aocolor, 2.0, (float)WO_AOSKYCOL, 0, 0, "Use horizon and zenith color for diffuse energy"); - uiDefButS(block, ROW, B_REDR, "Sky Texture", - X3CLM3, yco, BUTW3, BUTH, &wrld->aocolor, 2.0, (float)WO_AOSKYTEX, 0, 0, "Does full Sky texture render for diffuse energy"); + uiDefButS(block, MENU, B_REDR, "Plain %x0|Sky Color %x1|Sky Texture %x2|IBL: Diffuse Prefiltered %x3", + X3CLM1, yco-=BUTH, BUTW2, BUTH, &wrld->aocolor, 0.0, (float)WO_AOPLAIN, 0, 0, ""); uiBlockEndAlign(block); yco -= YSPACE; - uiDefButF(block, NUMSLI, B_REDR, "Energy:", - X2CLM1, yco-=BUTH, BUTW2, BUTH, &wrld->aoenergy, 0.01, 3.0, 100, 0, "Sets global energy scale for AO"); + uiDefButF(block, NUM, B_REDR, "Energy:", + X2CLM1, yco-=BUTH, BUTW2, BUTH, &wrld->aoenergy, 0.01, 10.0, 100, 0, "Sets global energy scale for AO"); } @@ -4238,6 +4311,7 @@ if(wrld) { world_panel_mistaph(wrld); world_panel_amb_occ(wrld); + world_panel_ibl(wrld); world_panel_texture(wrld); world_panel_mapto(wrld); } Index: source/blender/blenloader/intern/readfile.c =================================================================== --- source/blender/blenloader/intern/readfile.c (revision 13145) +++ source/blender/blenloader/intern/readfile.c (working copy) @@ -2083,6 +2083,8 @@ } } + wrld->ibl_image= newlibadr_us(fd, wrld->id.lib, wrld->ibl_image); + lib_link_scriptlink(fd, &wrld->id, &wrld->scriptlink); wrld->id.flag -= LIB_NEEDLINK; @@ -2100,6 +2102,9 @@ for(a=0; amtex[a]= newdataadr(fd, wrld->mtex[a]); } + + wrld->ibl_iuser.ok= 1; + wrld->preview = direct_link_preview_image(fd, wrld->preview); } @@ -7270,6 +7275,8 @@ if ((main->versionfile < 245) || (main->versionfile == 245 && main->subversionfile < 11)) { Object *ob; bActionStrip *strip; + World *wrld; + ImageUser *iuser; /* nla-strips - scale */ for (ob= main->object.first; ob; ob= ob->id.next) { @@ -7289,6 +7296,16 @@ if (strip->scale == 0.0f) strip->scale= 1.0f; } } + + for(wrld=main->world.first; wrld; wrld= wrld->id.next) { + iuser = &(wrld->ibl_iuser); + + iuser->sfra= 1; + iuser->fie_ima= 2; + iuser->ok= 1; + wrld->ibl_multiplier = 1.0; + } + } Index: source/blender/nodes/intern/SHD_util.h =================================================================== --- source/blender/nodes/intern/SHD_util.h (revision 13145) +++ source/blender/nodes/intern/SHD_util.h (working copy) @@ -109,6 +109,7 @@ #define GEOM_OUT_NORMAL 5 #define GEOM_OUT_VCOL 6 #define GEOM_OUT_FRONTBACK 7 +#define GEOM_OUT_WORLDNORMAL 8 /* input socket defines */ Index: source/blender/nodes/intern/SHD_nodes/SHD_geom.c =================================================================== --- source/blender/nodes/intern/SHD_nodes/SHD_geom.c (revision 13145) +++ source/blender/nodes/intern/SHD_nodes/SHD_geom.c (working copy) @@ -39,9 +39,10 @@ { SOCK_VECTOR, 0, "View", 0.0f, 0.0f, 0.0f, 1.0f, -1.0f, 1.0f}, { SOCK_VECTOR, 0, "Orco", 0.0f, 0.0f, 0.0f, 1.0f, -1.0f, 1.0f}, { SOCK_VECTOR, 0, "UV", 0.0f, 0.0f, 0.0f, 1.0f, -1.0f, 1.0f}, - { SOCK_VECTOR, 0, "Normal", 0.0f, 0.0f, 0.0f, 1.0f, -1.0f, 1.0f}, + { SOCK_VECTOR, 0, "View Normal", 0.0f, 0.0f, 0.0f, 1.0f, -1.0f, 1.0f}, { SOCK_RGBA, 0, "Vertex Color", 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f}, { SOCK_VALUE, 0, "Front/Back", 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f}, + { SOCK_VECTOR, 0, "World Normal", 0.0f, 0.0f, 0.0f, 1.0f, -1.0f, 1.0f}, { -1, 0, "" } }; @@ -73,6 +74,7 @@ VECCOPY(out[GEOM_OUT_ORCO]->vec, shi->lo); VECCOPY(out[GEOM_OUT_UV]->vec, suv->uv); VECCOPY(out[GEOM_OUT_NORMAL]->vec, shi->vno); + VECCOPY(out[GEOM_OUT_WORLDNORMAL]->vec, shi->worldnor); if (shi->totcol) { /* find vertex color layer by name */