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);
