Index: ray.c =================================================================== --- ray.c (revision 10746) +++ ray.c (working copy) @@ -1682,7 +1682,7 @@ reflection(ref, shi.vn, shi.view, NULL); traceray(origshi, depth-1, shi.co, ref, mircol, shi.vlr, 0); - + f1= 1.0f-f; /* combine */ @@ -1831,7 +1831,81 @@ return lar->jitter; } +/* **************** sampling *************** */ +double random_float() +{ + return (double)rand()/(double)(RAND_MAX); +} + +static void halton_reset(double *m_numbers, double *m_invPrimes) +{ + // using the same sequence across pixels seems to give ugly structures + // so we reset it every time we sample some area, not sure if that's + // how it supposed to be, or if we are doing something wrong .. + double v = random_float(); + + m_numbers[0] = v; + m_numbers[1] = v; + + m_invPrimes[0] = 0.5; + m_invPrimes[1] = 1.0/3.0; +} + +static void halton_sample(float *v, double *m_numbers, double *m_invPrimes) +{ + // incremental halton sequence generator, from: + // "Instant Radiosity", Keller A. + unsigned int i; + + for (i = 0; i < 2; i++) + { + double r = (1.0 - m_numbers[i]) - 1e-10; + + if (m_invPrimes[i] >= r) + { + double lasth; + double h = m_invPrimes[i]; + + do { + lasth = h; + h *= m_invPrimes[i]; + } while (h >= r); + + m_numbers[i] += ((lasth + h) - 1.0); + } + else + m_numbers[i] += m_invPrimes[i]; + + v[i] = (float)m_numbers[i]; + } +} + +static void halton_sampleCone(double *m_numbers, double *m_invPrimes, float *x, float *y, float *z, float blur) +{ + float r[2]; + + halton_sample(r, m_numbers, m_invPrimes); + + { + float phi = r[0]*2*M_PI; + float sqr = r[1]*sqrt(2-r[1]*r[1]); + *x = cos(phi)*sqr*blur; + *y = sin(phi)*sqr*blur; + *z = 0.0f; + + } + +} + +static void getRandomVec (float *vec, float max) +{ + vec[0] = (float) (rand() * (max*2))-max; + vec[1] = (float) (rand() * (max*2))-max; + vec[2] = (float) (rand() * (max*2))-max; + +} + /* ***************** main calls ************** */ @@ -1887,18 +1961,48 @@ i= shi->ray_mirror*fresnel_fac(shi->view, shi->vn, shi->mat->fresnel_mir_i, shi->mat->fresnel_mir); if(i!=0.0f) { + float mycol[4]; + int j; + float hvec[3]; + float blur = shi->mat->blur_mir; + char samples = shi->mat->samp_blur_mir; + // floats will result in precision errors, so we use doubles + double m_invPrimes[2]; + double m_numbers[2]; + mircol[0] = mircol[1] = mircol[2] = mircol[3] = 0.0; + + if (blur > 0.0) + halton_reset(m_numbers, m_invPrimes); + else + samples = 1; + + for (j=0;j< samples; j++) { + if (samples > 1) { + if (G.rt == 0) halton_sampleCone(m_numbers, m_invPrimes, hvec, hvec+1, hvec+2, blur); + else getRandomVec(hvec, blur); + VECADD(hvec,hvec,shi->vn); + Normalize(hvec); + } else { + VECCOPY(hvec, shi->vn); + } + + if(vlr->flag & R_SMOOTH) + reflection(vec, hvec, shi->view, shi->facenor); + else + reflection(vec, hvec, shi->view, NULL); + + traceray(shi, shi->mat->ray_depth, shi->co, vec, mycol, shi->vlr, 0); + + mircol[0] += mycol[0] / (float)samples; + mircol[1] += mycol[1] / (float)samples; + mircol[2] += mycol[2] / (float)samples; + } + fr= i*shi->mirr; fg= i*shi->mirg; fb= i*shi->mirb; - if(vlr->flag & R_SMOOTH) - reflection(vec, shi->vn, shi->view, shi->facenor); - else - reflection(vec, shi->vn, shi->view, NULL); - - traceray(shi, shi->mat->ray_depth, shi->co, vec, mircol, shi->vlr, 0); - if(shi->passflag & SCE_PASS_REFLECT) { /* mirror pass is not blocked out with spec */ shr->refl[0]= fr*mircol[0] - fr*diff[0];