Index: source/blender/render/intern/source/rayshade.c =================================================================== --- source/blender/render/intern/source/rayshade.c (revision 12223) +++ source/blender/render/intern/source/rayshade.c (working copy) @@ -1397,6 +1397,66 @@ } } +/* Fill isec but also provide the dir used as separate param, + to avoid substraction ops + Results accumulated in fac, shadfac and skyadded +*/ +void ao_single_sample(int aotype, Isect *isec, float *dir, float *dxyview, float *fac, float *shadfac, int *skyadded) { + + if(RE_ray_tree_intersect(R.raytree, isec)) { + float falloff; + + if (R.wrld.aomode & WO_AODIST) falloff = exp(-isec->labda*R.wrld.aodistfac); + else falloff = 1.0f; + *fac += falloff; + if (aotype == WO_AOOBJSHADED) { + ShadeInput shi; + ShadeResult shr; + short prevmode = isec->mode; + + memset(&shr, 0, sizeof(ShadeResult)); + memset(&shi, 0, sizeof(ShadeInput)); + //shi.vlr = (VlakRen*)isec->face; shade_ray does already + //shi.mat = shi.vlr->mat; shade_ray does already + //shi.mask = no idea + shi.osatex = 0; // do not to use dx[] and dy[] texture AA vectors + shi.depth = -1; // no more tracing, 0 crashes (see shade_material_loop), and >0 did too + shi.lay = G.scene->lay; // it works, but does it help? + //memcpy(&(shi.r), &(shi.mat)->r, 23*sizeof(float)); // note, keep this synced with render_types.h shade_ray does already + shi.passflag = SCE_PASS_RGBA|SCE_PASS_DIFFUSE|SCE_PASS_SPEC|SCE_PASS_SHADOW; // RGBA instead of COMBINED, to get textures + isec->mode = RE_RAY_MIRROR; + shade_ray(isec, &shi, &shr); + isec->mode = prevmode; + shadfac[0] += falloff * shr.shad[0] * (shr.diff[0] + shr.spec[0]); + shadfac[1] += falloff * shr.shad[1] * (shr.diff[1] + shr.spec[1]); + shadfac[2] += falloff * shr.shad[2] * (shr.diff[2] + shr.spec[2]); + } + } + else if(aotype!=WO_AOPLAIN) { + float skycol[4]; + float skyfac, view[3]; + + view[0]= -dir[0]; + view[1]= -dir[1]; + view[2]= -dir[2]; + Normalize(view); + + if(aotype==WO_AOSKYCOL) { + skyfac= 0.5*(1.0f+view[0]*R.grvec[0]+ view[1]*R.grvec[1]+ view[2]*R.grvec[2]); + shadfac[0]+= (1.0f-skyfac)*R.wrld.horr + skyfac*R.wrld.zenr; + 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 or WO_AOOBJSHADED */ + shadeSkyView(skycol, isec->start, view, dxyview); + shadfac[0]+= skycol[0]; + shadfac[1]+= skycol[1]; + shadfac[2]+= skycol[2]; + } + (*skyadded)++; + } +} + void ray_ao_qmc(ShadeInput *shi, float *shadfac) { Isect isec; @@ -1412,8 +1472,8 @@ int samples=0; int max_samples = R.wrld.aosamp*R.wrld.aosamp; - float dxyview[3], skyadded=0, div; - int aocolor; + float dxyview[3], div; + int aocolor, skyadded=0; isec.faceorig= (RayFace*)shi->vlr; isec.face_last= NULL; @@ -1470,35 +1530,9 @@ isec.end[2] = shi->co[2] - maxdist*dir[2]; prev = fac; + + ao_single_sample(aocolor, &isec, dir, dxyview, &fac, shadfac, &skyadded); - if(RE_ray_tree_intersect(R.raytree, &isec)) { - if (R.wrld.aomode & WO_AODIST) fac+= exp(-isec.labda*R.wrld.aodistfac); - else fac+= 1.0f; - } - else if(aocolor!=WO_AOPLAIN) { - float skycol[4]; - float skyfac, view[3]; - - view[0]= -dir[0]; - view[1]= -dir[1]; - view[2]= -dir[2]; - Normalize(view); - - if(aocolor==WO_AOSKYCOL) { - skyfac= 0.5*(1.0f+view[0]*R.grvec[0]+ view[1]*R.grvec[1]+ view[2]*R.grvec[2]); - shadfac[0]+= (1.0f-skyfac)*R.wrld.horr + skyfac*R.wrld.zenr; - 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 */ - shadeSkyView(skycol, isec.start, view, dxyview); - shadfac[0]+= skycol[0]; - shadfac[1]+= skycol[1]; - shadfac[2]+= skycol[2]; - } - skyadded++; - } - samples++; if (qsa->type == SAMP_TYPE_HALTON) { @@ -1511,15 +1545,23 @@ } } } + + fac = 1.0f - fac/(float)samples; - if(aocolor!=WO_AOPLAIN && skyadded) { - div= (1.0f - fac/(float)samples)/((float)skyadded); + if (aocolor==WO_AOOBJSHADED) { + div = 1.0f / (float)samples; + + shadfac[0]*= div; // All samples were coloured + shadfac[1]*= div; // and those where distance attenuation was used + shadfac[2]*= div; // contribute "black", not sky + } else if(aocolor!=WO_AOPLAIN && skyadded) { + div= fac/(float)skyadded; shadfac[0]*= div; // average color times distances/hits formula shadfac[1]*= div; // average color times distances/hits formula shadfac[2]*= div; // average color times distances/hits formula } else { - shadfac[0]= shadfac[1]= shadfac[2]= 1.0f - fac/(float)samples; + shadfac[0]= shadfac[1]= shadfac[2]= fac; } if ((qsa) && (qsa->type == SAMP_TYPE_HALTON)) QMC_freeSampler(qsa); @@ -1529,7 +1571,7 @@ void ray_ao_spheresamp(ShadeInput *shi, float *shadfac) { Isect isec; - float *vec, *nrm, div, bias, sh=0.0f; + float *vec, *nrm, div, bias, fac=0.0f; float maxdist = R.wrld.aodist; float dxyview[3]; int j= -1, tot, actual=0, skyadded=0, aocolor; @@ -1590,50 +1632,30 @@ isec.end[2] = shi->co[2] - maxdist*vec[2]; /* do the trace */ - if(RE_ray_tree_intersect(R.raytree, &isec)) { - if (R.wrld.aomode & WO_AODIST) sh+= exp(-isec.labda*R.wrld.aodistfac); - else sh+= 1.0f; - } - else if(aocolor!=WO_AOPLAIN) { - float skycol[4]; - float fac, view[3]; - - view[0]= -vec[0]; - view[1]= -vec[1]; - view[2]= -vec[2]; - Normalize(view); - - if(aocolor==WO_AOSKYCOL) { - fac= 0.5*(1.0f+view[0]*R.grvec[0]+ view[1]*R.grvec[1]+ view[2]*R.grvec[2]); - shadfac[0]+= (1.0f-fac)*R.wrld.horr + fac*R.wrld.zenr; - shadfac[1]+= (1.0f-fac)*R.wrld.horg + fac*R.wrld.zeng; - shadfac[2]+= (1.0f-fac)*R.wrld.horb + fac*R.wrld.zenb; - } - else { /* WO_AOSKYTEX */ - shadeSkyView(skycol, isec.start, view, dxyview); - shadfac[0]+= skycol[0]; - shadfac[1]+= skycol[1]; - shadfac[2]+= skycol[2]; - } - skyadded++; - } + ao_single_sample(aocolor, &isec, vec, dxyview, &fac, shadfac, &skyadded); } // samples vec+= 3; } - if(actual==0) sh= 1.0f; - else sh = 1.0f - sh/((float)actual); + if(actual==0) fac= 1.0f; + else fac = 1.0f - fac/((float)actual); - if(aocolor!=WO_AOPLAIN && skyadded) { - div= sh/((float)skyadded); + if (aocolor==WO_AOOBJSHADED) { + div = 1.0f / (float)actual; + + shadfac[0]*= div; // All samples were coloured + shadfac[1]*= div; // and those where distance attenuation was used + shadfac[2]*= div; // contribute "black", not sky + } else if(aocolor!=WO_AOPLAIN && skyadded) { + div= fac/((float)skyadded); shadfac[0]*= div; // average color times distances/hits formula shadfac[1]*= div; // average color times distances/hits formula shadfac[2]*= div; // average color times distances/hits formula } else { - shadfac[0]= shadfac[1]= shadfac[2]= sh; + shadfac[0]= shadfac[1]= shadfac[2]= fac; } } Index: source/blender/makesdna/DNA_world_types.h =================================================================== --- source/blender/makesdna/DNA_world_types.h (revision 12223) +++ source/blender/makesdna/DNA_world_types.h (working copy) @@ -156,6 +156,7 @@ #define WO_AOPLAIN 0 #define WO_AOSKYCOL 1 #define WO_AOSKYTEX 2 +#define WO_AOOBJSHADED 3 /* texco (also in DNA_material_types.h) */ #define TEXCO_ANGMAP 64 Index: source/blender/src/buttons_shading.c =================================================================== --- source/blender/src/buttons_shading.c (revision 12223) +++ source/blender/src/buttons_shading.c (working copy) @@ -1924,10 +1924,12 @@ } break; case B_AO_DISTANCES: + // Comented out, as code does not care and we can test what really happens with such option on + // Redraw still required to show/hide the slider, though /* distances option only supports plain */ - wrld= G.buts->lockpoin; - if(wrld) - wrld->aocolor= WO_AOPLAIN; + //wrld= G.buts->lockpoin; + //if(wrld) + // wrld->aocolor= WO_AOPLAIN; scrarea_queue_winredraw(curarea); break; } @@ -2149,10 +2151,10 @@ 165, 95, 145, 19, &wrld->aodist, 0.001, 5000.0, 100, 0, "Sets length of AO rays, defines how far away other faces give occlusion effect"); uiBlockBeginAlign(block); - uiDefButBitS(block, TOG, WO_AODIST, B_AO_DISTANCES, "Use Distances", 10, 70, 150, 19, &wrld->aomode, 0, 0, 0, 0, "When enabled, distances to objects will be used to attenuate shadows. Only for Plain AO."); + uiDefButBitS(block, TOG, WO_AODIST, B_AO_DISTANCES, "Falloff", 10, 70, 150, 19, &wrld->aomode, 0, 0, 0, 0, "When enabled, distances to objects will be used to attenuate shadows."); /* distance attenuation factor */ if (wrld->aomode & WO_AODIST) - uiDefButF(block, NUM, B_REDR, "DistF:", 160, 70, 150, 19, &wrld->aodistfac, 0.00001, 10.0, 100, 0, "Distance factor, the higher, the 'shorter' the shadows"); + uiDefButF(block, NUM, B_REDR, "FallPow:", 160, 70, 150, 19, &wrld->aodistfac, 0.00001, 10.0, 100, 0, "Attenuation falloff power, the higher, the 'shorter' the shadows. Only nearest surfaces will have visible contribution."); /* result mix modes */ uiBlockBeginAlign(block); @@ -2162,12 +2164,13 @@ /* color treatment */ uiBlockBeginAlign(block); - uiDefButS(block, ROW, B_REDR, "Plain", 10, 25, 100, 20, &wrld->aocolor, 2.0, (float)WO_AOPLAIN, 0, 0, "Plain diffuse energy (white)"); - uiDefButS(block, ROW, B_REDR, "Sky Color", 110, 25, 100, 20, &wrld->aocolor, 2.0, (float)WO_AOSKYCOL, 0, 0, "Use horizon and zenith color for diffuse energy"); - uiDefButS(block, ROW, B_REDR, "Sky Texture", 210, 25, 100, 20, &wrld->aocolor, 2.0, (float)WO_AOSKYTEX, 0, 0, "Does full Sky texture render for diffuse energy"); + uiDefButS(block, ROW, B_REDR, "Plain", 10, 25, 75, 20, &wrld->aocolor, 2.0, (float)WO_AOPLAIN, 0, 0, "Plain diffuse energy (white)"); + uiDefButS(block, ROW, B_REDR, "Sky Color", 85, 25, 75, 20, &wrld->aocolor, 2.0, (float)WO_AOSKYCOL, 0, 0, "Use horizon and zenith color for diffuse energy"); + uiDefButS(block, ROW, B_REDR, "Sky Texture", 160, 25, 75, 20, &wrld->aocolor, 2.0, (float)WO_AOSKYTEX, 0, 0, "Does full Sky texture render for diffuse energy"); + uiDefButS(block, ROW, B_REDR, "Objects", 235, 25, 75, 20, &wrld->aocolor, 2.0, (float)WO_AOOBJSHADED, 0, 0, "Picks up colour from objects and sky"); // why a 2.0 there? uiBlockBeginAlign(block); - uiDefButF(block, NUMSLI, B_REDR, "Energy:", 10, 0, 150, 19, &wrld->aoenergy, 0.01, 3.0, 100, 0, "Sets global energy scale for AO"); + uiDefButF(block, NUMSLI, B_REDR, "Energy:", 10, 0, 150, 19, &wrld->aoenergy, 0.01, 10.0, 100, 0, "Sets global energy scale for AO"); if (wrld->ao_samp_method == WO_AOSAMP_CONSTANT) uiDefButF(block, NUMSLI, B_REDR, "Bias:", 160, 0, 150, 19, &wrld->aobias, 0.0, 0.5, 10, 0, "Sets bias to prevent smoothed faces to show banding (in radians)"); } @@ -3350,7 +3353,7 @@ uiBlockBeginAlign(block); uiDefButF(block, NUMSLI, B_MATPRV, "IOR: ", - X2CLM2, yco-=BUTH, BUTW2, BUTH, &(ma->ang), 1.0, 3.0, 100, 2, "Sets angular index of refraction for raytraced refraction"); + X2CLM2, yco-=BUTH, BUTW2, BUTH, &(ma->ang), 0.333, 3.0, 100, 2, "Sets angular index of refraction for raytraced refraction"); uiDefButF(block, NUMSLI, B_MATPRV, "Fresnel: ", X2CLM2, yco-=BUTH, BUTW2, BUTH, &(ma->fresnel_tra), 0.0, 5.0, 10, 2, "Power of Fresnel for mirror reflection"); uiDefButF(block, NUMSLI, B_MATPRV, "Fac: ", @@ -3628,7 +3631,7 @@ uiDefButF(block, NUMSLI, B_MATPRV, "Tralu ", 9,30,150,19, &(ma->translucency), 0.0, 1.0, 100, 2, "Translucency, amount of diffuse shading of the back side"); uiDefButF(block, NUMSLI, B_MATPRV, "SBias ", 159,30,151,19, &(ma->sbias), 0.0, 0.25, 10, 2, "Shadow bias, to prevent terminator problems on shadow boundary"); uiDefButF(block, NUMSLI, B_MATPRV, "Amb ", 9,10,150,19, &(ma->amb), 0.0, 1.0, 0, 0, "Sets the amount of global ambient color the material receives"); - uiDefButF(block, NUMSLI, B_MATPRV, "Emit ", 159,10,151,19, &(ma->emit), 0.0, 2.0, 0, 0, "Sets the amount of light the material emits"); + uiDefButF(block, NUMSLI, B_MATPRV, "Emit ", 159,10,151,19, &(ma->emit), 0.0, 10.0, 0, 0, "Sets the amount of light the material emits"); uiBlockEndAlign(block); uiBlockSetCol(block, TH_BUT_SETTING1);