Index: source/blender/render/intern/source/ray.c =================================================================== --- source/blender/render/intern/source/ray.c (revision 10899) +++ source/blender/render/intern/source/ray.c (working copy) @@ -1831,15 +1831,230 @@ return lar->jitter; } +/* **************** sampling *************** */ +// floats will result in precision errors, so we use doubles + +static void halton_reset(double *m_invPrimes, double *m_numbers, int thread) +{ + // 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 = BLI_thread_frand(thread); + + m_numbers[0] = v; + m_numbers[1] = v; + + m_invPrimes[0] = 0.5; + m_invPrimes[1] = 1.0/3.0; +} + +static void halton_sample(double *m_invPrimes, double *m_numbers, float *v) +{ + // 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_samplePhong(double *m_invPrimes, double *m_numbers, float *x, float *y, float *z, float blur) +{ + float r[2]; + + halton_sample(m_invPrimes, m_numbers, r); + + { + float phi = r[0]*2*M_PI; + float pz = pow(r[1], blur*blur); + float sqr = sqrt(1.0f-pz*pz); + *x = cos(phi)*sqr; + *y = sin(phi)*sqr; + *z = 0.0f; + } + +} + +static int adaptive_sample_contrast(int samples, float *prevcol, float *curcol, float thresh) +{ + /* if the last sample's contribution to the total raytraced colour was below a small threshold + * (i.e. the samples taken are very similar), then taking more samples that are probably + * going to be the same is wasting effort */ + if ( (fabs( prevcol[0]/(float)(samples-1) - curcol[0]/(float)(samples) ) < thresh) && + (fabs( prevcol[1]/(float)(samples-1) - curcol[1]/(float)(samples) ) < thresh) && + (fabs( prevcol[2]/(float)(samples-1) - curcol[2]/(float)(samples) ) < thresh) ) + { + return 1; + } + else + return 0; +} + /* ***************** main calls ************** */ +static void trace_refract(float *col, ShadeInput *shi, ShadeResult *shr) +{ + float v_refract[3], v_refract_new[3]; + float sampcol[3], prevcol[3]; + + float blur = 1.0 - shi->mat->gloss_tra; + short max_samples = shi->mat->samp_gloss_tra; + float adapt_thresh = shi->mat->adapt_thresh_tra; + + int samples=0; + double m_invPrimes[2]; + double m_numbers[2]; + col[0] = col[1] = col[2] = 0.0; + col[3]= shr->alpha; + + if (blur > 0.0) + halton_reset(m_invPrimes, m_numbers, shi->thread); + else + max_samples = 1; + + while (samples < max_samples) { + refraction(v_refract, shi->vn, shi->view, shi->ang); + + if (max_samples > 1) { + /* get a quasi-random vector from a phong-weighted disc */ + halton_samplePhong(m_invPrimes, m_numbers, v_refract_new, v_refract_new+1, v_refract_new+2, blur/5.0); + + /* modify the refraction vector with it */ + VECADD(v_refract_new, v_refract_new, v_refract); + Normalize(v_refract_new); + } else { + /* no blurriness, use the original normal */ + VECCOPY(v_refract_new, v_refract); + } + + traceray(shi, shi->mat->ray_depth_tra, shi->co, v_refract_new, sampcol, shi->vlr, RAY_TRA|RAY_TRAFLIP); + + VECCOPY(prevcol, col); + col[0] += sampcol[0]; + col[1] += sampcol[1]; + col[2] += sampcol[2]; + + samples++; + + /* adaptive sampling */ + if (adapt_thresh < 1.0 && samples > shi->mat->ray_depth_tra) + { + if (adaptive_sample_contrast(samples, prevcol, col, adapt_thresh)) + break; + + /* if the pixel so far is very dark, we can get away with less samples */ + if ( (col[0] + col[1] + col[2])/3.0/(float)samples < 0.01 ) + max_samples--; + } + } + + col[0] /= (float)samples; + col[1] /= (float)samples; + col[2] /= (float)samples; +} + +static void trace_reflect(float *col, ShadeInput *shi, ShadeResult *shr, float fresnelfac) +{ + float v_nor[3], v_nor_new[3], v_reflect[3]; + float sampcol[4], prevcol[4]; + + float blur = 1.0 - shi->mat->gloss_mir; + short max_samples = shi->mat->samp_gloss_mir; + float adapt_thresh = shi->mat->adapt_thresh_mir; + + int samples=0; + double m_invPrimes[2]; + double m_numbers[2]; + + col[0] = col[1] = col[2] = 0.0; + + if (blur > 0.0) + halton_reset(m_invPrimes, m_numbers, shi->thread); + else + max_samples = 1; + + while (samples < max_samples) { + if (max_samples > 1) { + /* get a quasi-random vector from a phong-weighted disc */ + halton_samplePhong(m_invPrimes, m_numbers, v_nor_new, v_nor_new+1, v_nor_new+2, blur); + + /* perturb the normal with it */ + VECADD(v_nor_new, v_nor_new, shi->vn); + Normalize(v_nor_new); + } else { + /* no blurriness, use the original normal */ + VECCOPY(v_nor_new, shi->vn); + } + + if(shi->vlr->flag & R_SMOOTH) + reflection(v_reflect, v_nor_new, shi->view, shi->facenor); + else + reflection(v_reflect, v_nor_new, shi->view, NULL); + + traceray(shi, shi->mat->ray_depth, shi->co, v_reflect, sampcol, shi->vlr, 0); + + VECCOPY(prevcol, col); + col[0] += sampcol[0]; + col[1] += sampcol[1]; + col[2] += sampcol[2]; + + samples++; + + /* adaptive sampling */ + if (adapt_thresh < 1.0 && samples > shi->mat->ray_depth_tra) + { + if (adaptive_sample_contrast(samples, prevcol, col, adapt_thresh)) + break; + + /* if the pixel so far is very dark, we can get away with less samples */ + if ( (col[0] + col[1] + col[2])/3.0/(float)samples < 0.01 ) + max_samples--; + + /* reduce samples when reflection is dim due to low ray mirror blend value or fresnel factor + * and when reflection is blurry */ + if (fresnelfac < 0.1 * (blur+1)) { + max_samples--; + + /* even more for very dim */ + if (fresnelfac < 0.05 * (blur+1)) + max_samples--; + } + } + } + + col[0] /= (float)samples; + col[1] /= (float)samples; + col[2] /= (float)samples; + +} + /* extern call from render loop */ void ray_trace(ShadeInput *shi, ShadeResult *shr) { VlakRen *vlr; - float i, f, f1, fr, fg, fb, vec[3], mircol[4], tracol[4]; + float i, f, f1, fr, fg, fb, vec[3]; + float mircol[4], tracol[4]; float diff[3]; int do_tra, do_mir; @@ -1854,14 +2069,10 @@ VECCOPY(diff, shr->combined); if(do_tra) { - float refract[3]; float olddiff[3]; - tracol[3]= shr->alpha; + trace_refract(tracol, shi, shr); - refraction(refract, shi->vn, shi->view, shi->ang); - traceray(shi, shi->mat->ray_depth_tra, shi->co, refract, tracol, shi->vlr, RAY_TRA|RAY_TRAFLIP); - f= shr->alpha; f1= 1.0f-f; fr= 1.0f+ shi->mat->filter*(shi->r-1.0f); fg= 1.0f+ shi->mat->filter*(shi->g-1.0f); @@ -1887,18 +2098,13 @@ i= shi->ray_mirror*fresnel_fac(shi->view, shi->vn, shi->mat->fresnel_mir_i, shi->mat->fresnel_mir); if(i!=0.0f) { + + trace_reflect(mircol, shi, shr, i); 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]; Index: source/blender/blenkernel/BKE_blender.h =================================================================== --- source/blender/blenkernel/BKE_blender.h (revision 10899) +++ source/blender/blenkernel/BKE_blender.h (working copy) @@ -44,7 +44,7 @@ struct MemFile; #define BLENDER_VERSION 244 -#define BLENDER_SUBVERSION 2 +#define BLENDER_SUBVERSION 3 #define BLENDER_MINVERSION 240 #define BLENDER_MINSUBVERSION 0 Index: source/blender/blenkernel/intern/material.c =================================================================== --- source/blender/blenkernel/intern/material.c (revision 10899) +++ source/blender/blenkernel/intern/material.c (working copy) @@ -139,6 +139,10 @@ ma->tx_falloff= 1.0; ma->shad_alpha= 1.0f; + ma->gloss_mir = ma->gloss_tra= 1.0; + ma->samp_gloss_mir = ma->samp_gloss_tra= 8; + ma->adapt_thresh_mir = ma->adapt_thresh_tra = 0.0001; + ma->rampfac_col= 1.0; ma->rampfac_spec= 1.0; ma->pr_lamp= 3; /* two lamps, is bits */ Index: source/blender/include/BIF_butspace.h =================================================================== --- source/blender/include/BIF_butspace.h (revision 10899) +++ source/blender/include/BIF_butspace.h (working copy) @@ -102,6 +102,37 @@ #define BUTS_ACT_LINK 256 +/* buttons grid */ +#define PANELX 320 +#define PANELY 0 +#define PANELW 318 +#define PANELH 204 +#define BUTW1 300 +#define BUTW2 145 +#define BUTW3 93 +#define BUTW4 67 +#define ICONBUTW 20 +#define BUTH 22 + +#define YSPACE 6 +#define XSPACE 10 +#define PANEL_YMAX 210 +#define PANEL_XMAX 310 + +#define X1CLM 10 + +#define X2CLM1 X1CLM +#define X2CLM2 165 + +#define X3CLM1 X1CLM +#define X3CLM2 113 +#define X3CLM3 217 + +#define X4CLM1 X1CLM +#define X4CLM2 77 +#define X4CLM3 165 +#define X4CLM4 232 + #endif Index: source/blender/makesdna/DNA_material_types.h =================================================================== --- source/blender/makesdna/DNA_material_types.h (revision 10899) +++ source/blender/makesdna/DNA_material_types.h (working copy) @@ -73,6 +73,11 @@ short har; char seed1, seed2; + float gloss_mir, gloss_tra; + short samp_gloss_mir, samp_gloss_tra; + float adapt_thresh_mir, adapt_thresh_tra; + char pad[4]; + int mode, mode_l; /* mode_l is the or-ed result of all layer modes */ short flarec, starc, linec, ringc; float hasize, flaresize, subsize, flareboost; Index: source/blender/src/buttons_shading.c =================================================================== --- source/blender/src/buttons_shading.c (revision 10899) +++ source/blender/src/buttons_shading.c (working copy) @@ -3226,41 +3226,92 @@ static void material_panel_tramir(Material *ma) { uiBlock *block; + short yco=PANEL_YMAX; block= uiNewBlock(&curarea->uiblocks, "material_panel_tramir", UI_EMBOSS, UI_HELV, curarea->win); uiNewPanelTabbed("Shaders", "Material"); - if(uiNewPanel(curarea, block, "Mirror Transp", "Material", 640, 0, 318, 204)==0) return; + if(uiNewPanel(curarea, block, "Mirror Transp", "Material", PANELX, PANELY, PANELW, PANELH+80)==0) return; uiSetButLock(ma->id.lib!=NULL, ERROR_LIBDATA_MESSAGE); - uiDefButBitI(block, TOG, MA_RAYMIRROR, B_MATPRV,"Ray Mirror",210,180,100,20, &(ma->mode), 0, 0, 0, 0, "Enables raytracing for mirror reflection rendering"); + uiDefButBitI(block, TOG, MA_RAYMIRROR, B_MATPRV, "Ray Mirror", + X2CLM1, yco-=BUTH, BUTW2, BUTH, &(ma->mode), 0, 0, 0, 0, "Enables raytracing for mirror reflection rendering"); + yco -= YSPACE; + uiBlockBeginAlign(block); - uiDefButF(block, NUMSLI, B_MATPRV, "RayMir ", 10,160,200,20, &(ma->ray_mirror), 0.0, 1.0, 100, 2, "Sets the amount mirror reflection for raytrace"); - uiDefButS(block, NUM, B_MATPRV, "Depth:", 210,160,100,20, &(ma->ray_depth), 0.0, 10.0, 100, 0, "Amount of inter-reflections calculated maximal "); + uiDefButF(block, NUMSLI, B_MATPRV, "RayMir: ", + X2CLM1, yco-=BUTH, BUTW2, BUTH, &(ma->ray_mirror), 0.0, 1.0, 100, 2, "Sets the amount mirror reflection for raytrace"); + uiDefButF(block, NUMSLI, B_MATPRV, "Fresnel: ", + X2CLM1, yco-=BUTH, BUTW2, BUTH, &(ma->fresnel_mir), 0.0, 5.0, 10, 2, "Power of Fresnel for mirror reflection"); + uiDefButF(block, NUMSLI, B_MATPRV, "Fac: ", + X2CLM1, yco-=BUTH, BUTW2, BUTH, &(ma->fresnel_mir_i), 1.0, 5.0, 10, 2, "Blending factor for Fresnel"); + uiBlockEndAlign(block); - uiDefButF(block, NUMSLI, B_MATPRV, "Fresnel ", 10,140,160,20, &(ma->fresnel_mir), 0.0, 5.0, 10, 2, "Power of Fresnel for mirror reflection"); - uiDefButF(block, NUMSLI, B_MATPRV, "Fac ", 170,140,140,20, &(ma->fresnel_mir_i), 1.0, 5.0, 10, 2, "Blending factor for Fresnel"); - + yco -= YSPACE; + uiBlockBeginAlign(block); - uiDefButF(block, NUM, B_MATPRV, "Filt:", 10,110,150,20, &(ma->filter), 0.0, 1.0, 10, 0, "Amount of filtering for transparent raytrace"); - uiDefButBitI(block, TOG, MA_RAYTRANSP, B_MATRAYTRANSP,"Ray Transp",160,110,150,20, &(ma->mode), 0, 0, 0, 0, "Enables raytracing for transparency rendering"); + uiDefButF(block, NUMSLI, B_MATPRV, "Gloss: ", + X2CLM1, yco-=BUTH, BUTW2, BUTH, &(ma->gloss_mir), 0.0, 1.0, 100, 0, "The shininess of the reflection. Values < 1.0 give diffuse, blurry reflections "); + uiDefButS(block, NUM, B_MATPRV, "Samples:", + X2CLM1, yco-=BUTH, BUTW2, BUTH, &(ma->samp_gloss_mir), 0.0, 10.0, 100, 0, "Number of cone samples averaged for blurry reflections"); + uiDefButF(block, NUMSLI, B_MATPRV, "Thresh: ", + X2CLM1, yco-=BUTH, BUTW2, BUTH, &(ma->adapt_thresh_mir), 0.0, 1.0, 100, 0, "Threshold for adaptive sampling. If a sample contributes less than this amount (as a percentage), sampling is stopped"); + uiBlockEndAlign(block); - /* uiBlockBeginAlign(block); */ - uiDefButF(block, NUMSLI, B_MATPRV, "IOR ", 10,90,200,20, &(ma->ang), 1.0, 3.0, 100, 2, "Sets the angular index of refraction for raytrace"); - uiDefButS(block, NUM, B_MATPRV, "Depth:", 210,90,100,20, &(ma->ray_depth_tra), 0.0, 10.0, 100, 0, "Amount of refractions calculated maximal "); + yco -= YSPACE; + uiDefButS(block, NUM, B_MATPRV, "Depth:", + X2CLM1, yco-=BUTH, BUTW2, BUTH, &(ma->ray_depth), 0.0, 10.0, 100, 0, "Maximum allowed number of light inter-reflections"); - uiDefButF(block, NUMSLI, B_MATPRV, "Limit ", 10,70,160,20, &(ma->tx_limit), 0.0, 100.0, 10, 2, "Depth limit for transmissivity (0.0 is disabled)"); - uiDefButF(block, NUMSLI, B_MATPRV, "Falloff ", 170,70,140,20, &(ma->tx_falloff), 0.1, 10.0, 10, 2, "Falloff power for transmissivity (1.0 is linear)"); - uiDefButF(block, NUMSLI, B_MATPRV, "Fresnel ", 10,50,160,20, &(ma->fresnel_tra), 0.0, 5.0, 10, 2, "Power of Fresnel for transparency"); - uiDefButF(block, NUMSLI, B_MATPRV, "Fac ", 170,50,140,20, &(ma->fresnel_tra_i), 1.0, 5.0, 10, 2, "Blending factor for Fresnel"); + yco=PANEL_YMAX; + + uiDefButBitI(block, TOG, MA_RAYTRANSP, B_MATRAYTRANSP,"Ray Transp", + X2CLM2, yco-=BUTH, BUTW2, BUTH, &(ma->mode), 0, 0, 0, 0, "Enables raytracing for transparent refraction rendering"); + + yco -= YSPACE; + uiBlockBeginAlign(block); - uiDefButF(block, NUMSLI, B_MATPRV, "SpecTra ", 10,20,150,20, &(ma->spectra), 0.0, 1.0, 0, 0, "Makes specular areas opaque on transparent materials"); -// uiDefButF(block, NUMSLI, B_MATPRV, "Add ", 160,20,150,20, &(ma->add), 0.0, 1.0, 0, 0, "Uses additive blending for Z-transparant materials"); + 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"); + 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: ", + X2CLM2, yco-=BUTH, BUTW2, BUTH, &(ma->fresnel_tra_i), 1.0, 5.0, 10, 2, "Blending factor for Fresnel"); + uiBlockEndAlign(block); + yco -= YSPACE; + + uiBlockBeginAlign(block); + uiDefButF(block, NUM, B_MATPRV, "Filter:", + X2CLM2, yco-=BUTH, BUTW2, BUTH, &(ma->filter), 0.0, 1.0, 10, 0, "Amount to blend in the material's diffuse colour in raytraced transparency (simulating absorption)"); + uiDefButF(block, NUMSLI, B_MATPRV, "Limit: ", + X2CLM2, yco-=BUTH, BUTW2, BUTH, &(ma->tx_limit), 0.0, 100.0, 10, 2, "Maximum depth for light to travel through the transparent material before becoming fully filtered (0.0 is disabled)"); + uiDefButF(block, NUMSLI, B_MATPRV, "Falloff: ", + X2CLM2, yco-=BUTH, BUTW2, BUTH, &(ma->tx_falloff), 0.1, 10.0, 10, 2, "Falloff power for transmissivity filter effect (1.0 is linear)"); uiBlockEndAlign(block); + + yco -= YSPACE; + + uiBlockBeginAlign(block); + uiDefButF(block, NUMSLI, B_MATPRV, "Gloss: ", + X2CLM2, yco-=BUTH, BUTW2, BUTH, &(ma->gloss_tra), 0.0, 1.0, 100, 0, "The clarity of the refraction. Values < 1.0 give diffuse, blurry reflections "); + uiDefButS(block, NUM, B_MATPRV, "Samples:", + X2CLM2, yco-=BUTH, BUTW2, BUTH, &(ma->samp_gloss_tra), 0.0, 10.0, 100, 0, "Number of cone samples averaged for blurry refractions"); + uiDefButF(block, NUMSLI, B_MATPRV, "Thresh: ", + X2CLM2, yco-=BUTH, BUTW2, BUTH, &(ma->adapt_thresh_tra), 0.0, 1.0, 100, 0, "Threshold for adaptive sampling. If a sample contributes less than this amount (as a percentage), sampling is stopped"); + uiBlockEndAlign(block); + + yco -= YSPACE; + + uiDefButS(block, NUM, B_MATPRV, "Depth:", + X2CLM2, yco-=BUTH, BUTW2, BUTH, &(ma->ray_depth_tra), 0.0, 10.0, 100, 0, "Maximum allowed number of light inter-refractions"); + + yco -= YSPACE; + + uiDefButF(block, NUMSLI, B_MATPRV, "SpecTra: ", + X2CLM2, yco-=BUTH, BUTW2, BUTH, &(ma->spectra), 0.0, 1.0, 0, 0, "Makes specular areas opaque on transparent materials"); } Index: source/blender/blenloader/intern/readfile.c =================================================================== --- source/blender/blenloader/intern/readfile.c (revision 10899) +++ source/blender/blenloader/intern/readfile.c (working copy) @@ -6466,6 +6466,7 @@ } if(main->versionfile <= 244) { Scene *sce; + Material *ma; if(main->versionfile != 244 || main->subversionfile < 2) { Mesh *me; @@ -6489,7 +6490,16 @@ } } } + + } + if(main->versionfile != 244 || main->subversionfile < 3) { + for(ma=main->mat.first; ma; ma= ma->id.next) { + ma->gloss_mir = ma->gloss_tra= 1.0; + ma->samp_gloss_mir = ma->samp_gloss_tra= 8; + ma->adapt_thresh_mir = ma->adapt_thresh_tra = 0.001; + } + } } /* WATCH IT!!!: pointers from libdata have not been converted yet here! */