From 2cc124cf3b1281488c726b71090c1d2640e8078d Mon Sep 17 00:00:00 2001 From: Ton Roosendaal Date: Fri, 16 Apr 2004 15:32:49 +0000 Subject: Improved sample pattern for AO. It used to jitter locatations within a UV Sphere which isn't a very uniform distribution on a sphere. Now I itterate a evenly distributed set of points on sphere, and use that by random rotating the entire sphere for each pixel. http://www.blender.org/bf/samp3.jpg http://www.blender.org/bf/samp4.jpg Both pics same rendertime, 36 AO samples. Quite a difference, eh! Will put html page for release up. --- source/blender/render/intern/source/ray.c | 212 ++++++++++++++++++++++-------- 1 file changed, 157 insertions(+), 55 deletions(-) (limited to 'source/blender') diff --git a/source/blender/render/intern/source/ray.c b/source/blender/render/intern/source/ray.c index ca4da031af8..f81c829fa46 100644 --- a/source/blender/render/intern/source/ray.c +++ b/source/blender/render/intern/source/ray.c @@ -1860,18 +1860,147 @@ void RandomSpherical(float *v) else v[2] = 1.f; } +static void DS_energy(float *sphere, int tot, float *vec) +{ + float *fp, fac, force[3], res[3]; + int a; + + res[0]= res[1]= res[2]= 0.0; + + for(a=0, fp=sphere; a16) return sphere; + + tot= 2*resol*resol; + + if (type & WO_AORNDSMP) { + int a; + + /* total random sampling */ + vec= sphere; + for (a=0; aaosamp; - float gdiv = 1.0/grid; - float gdiv2p = gdiv*2.0*M_PI; + float *vec, *nrm, div, sh=0; float maxdist = wrld->aodist; - int x, y; + int tot, actual; int j=0; VECCOPY(isec.start, shi->co); @@ -1890,50 +2019,20 @@ void ray_ao(ShadeInput *shi, World *wrld, float *shadfac) R.wrld.zeng= G.scene->world->zeng; R.wrld.zenb= G.scene->world->zenb; } - - /* calculate the two perpendicular vectors */ - VECCOPY(nrm, shi->vn); - if ((nrm[0]==0.0) && (nrm[1]==0.0)) { - if (nrm[2]<0) ru[0]=-1; else ru[0]=1; - ru[1] = ru[2] = 0; - rv[0] = rv[2] = 0; - rv[1] = 1; - } - else { - ru[0] = nrm[1]; - ru[1] = -nrm[0]; - ru[2] = 0.0; - d = ru[0]*ru[0] + ru[1]*ru[1]; - if (d!=0) { - d = 1.0/sqrt(d); - ru[0] *= d; - ru[1] *= d; - } - Crossf(rv, nrm, ru); - } - - for (x=0;xaomode & WO_AORNDSMP) { - /* total random sampling */ - RandomSpherical(vec); - if ((vec[0]*nrm[0] + vec[1]*nrm[1] + vec[2]*nrm[2]) < 0.0) { - vec[0] = -vec[0]; - vec[1] = -vec[1]; - vec[2] = -vec[2]; - } - } - else { - /* stratified uniform sampling */ - z1 = (x + BLI_frand()) * gdiv; - z2 = (y + BLI_frand()) * gdiv2p; - if ((sqz1 = 1.0-z1*z1)<0) sqz1=0; else sqz1=sqrt(sqz1); - sz2 = sin(z2); - cz2 = cos(z2); - vec[0] = sqz1*(cz2*ru[0] + sz2*rv[0]) + nrm[0]*z1; - vec[1] = sqz1*(cz2*ru[1] + sz2*rv[1]) + nrm[1]*z1; - vec[2] = sqz1*(cz2*ru[2] + sz2*rv[2]) + nrm[2]*z1; - } + + nrm= shi->vlr->n; + vec= sphere_sampler(wrld->aomode, wrld->aosamp, nrm); + + // warning: since we use full sphere now, and dotproduct is below, we do twice as much + tot= 2*wrld->aosamp*wrld->aosamp; + actual= 0; + + while(tot--) { + + if ((vec[0]*nrm[0] + vec[1]*nrm[1] + vec[2]*nrm[2]) > 0.0) { + + actual++; + isec.end[0] = shi->co[0] - maxdist*vec[0]; isec.end[1] = shi->co[1] - maxdist*vec[1]; isec.end[2] = shi->co[2] - maxdist*vec[2]; @@ -1943,6 +2042,7 @@ void ray_ao(ShadeInput *shi, World *wrld, float *shadfac) isec.start[2]= shi->co[2] + (jit[j][0]-0.5)*O.dxco[2] + (jit[j][1]-0.5)*O.dyco[2] ; j = ((j+1) % R.osa); } + /* do the trace */ if (d3dda(&isec)) { if (wrld->aomode & WO_AODIST) sh+=exp(-isec.labda*wrld->aodistfac); else sh+=1.0; @@ -1970,15 +2070,17 @@ void ray_ao(ShadeInput *shi, World *wrld, float *shadfac) } } } + // samples + vec+= 3; } - gdiv= wrld->aoenergy/(float)(wrld->aosamp*wrld->aosamp); - shadfac[3] = wrld->aoenergy - (sh*gdiv); + div= wrld->aoenergy/(float)(actual); + shadfac[3] = wrld->aoenergy - (sh*div); if(wrld->aocolor!=WO_AOPLAIN) { - shadfac[0] *= gdiv; - shadfac[1] *= gdiv; - shadfac[2] *= gdiv; + shadfac[0] *= div; + shadfac[1] *= div; + shadfac[2] *= div; } } -- cgit v1.2.3