Index: blenkernel/BKE_blender.h =================================================================== --- blenkernel/BKE_blender.h (revision 11161) +++ 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: blenkernel/intern/material.c =================================================================== --- blenkernel/intern/material.c (revision 11161) +++ blenkernel/intern/material.c (working copy) @@ -139,6 +139,12 @@ 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= 12; + ma->adapt_thresh_mir = ma->adapt_thresh_tra = 0.005; + ma->dist_mir = 0.0; + ma->fadeto_mir = 0; + ma->rampfac_col= 1.0; ma->rampfac_spec= 1.0; ma->pr_lamp= 3; /* two lamps, is bits */ Index: blenkernel/intern/object.c =================================================================== --- blenkernel/intern/object.c (revision 11161) +++ blenkernel/intern/object.c (working copy) @@ -599,6 +599,7 @@ la->area_size=la->area_sizey=la->area_sizez= 1.0; la->buffers= 1; la->buftype= LA_SHADBUF_HALFWAY; + la->adapt_thresh = 0.001; return la; } Index: blenloader/intern/readfile.c =================================================================== --- blenloader/intern/readfile.c (revision 11161) +++ blenloader/intern/readfile.c (working copy) @@ -6480,8 +6480,10 @@ } if(main->versionfile <= 244) { Scene *sce; + Material *ma; bScreen *sc; + if(main->versionfile != 244 || main->subversionfile < 2) { Mesh *me; @@ -6505,7 +6507,7 @@ } } } - + /* correct older action editors - incorrect scrolling */ for(sc= main->screen.first; sc; sc= sc->id.next) { ScrArea *sa; @@ -6528,6 +6530,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= 12; + ma->adapt_thresh_mir = ma->adapt_thresh_tra = 0.005; + ma->dist_mir = 0.0; + ma->fadeto_mir = MA_RAYMIR_FADETOSKY; + } + } } /* WATCH IT!!!: pointers from libdata have not been converted yet here! */ Index: include/BIF_butspace.h =================================================================== --- include/BIF_butspace.h (revision 11161) +++ 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: makesdna/DNA_lamp_types.h =================================================================== --- makesdna/DNA_lamp_types.h (revision 11161) +++ makesdna/DNA_lamp_types.h (working copy) @@ -64,6 +64,8 @@ short ray_samp, ray_sampy, ray_sampz, ray_samp_type; short area_shape; float area_size, area_sizey, area_sizez; + float adapt_thresh; + int pad1; /* texact is for buttons */ short texact, shadhalostep; Index: makesdna/DNA_material_types.h =================================================================== --- makesdna/DNA_material_types.h (revision 11161) +++ makesdna/DNA_material_types.h (working copy) @@ -73,6 +73,13 @@ short har; char seed1, seed2; + float gloss_mir, gloss_tra; + short samp_gloss_mir, samp_gloss_tra; + float adapt_thresh_mir, adapt_thresh_tra; + float dist_mir; + short fadeto_mir; + short pad[3]; + 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; @@ -182,6 +189,10 @@ #define MA_MODE_MASK 0x1fffffff /* all valid mode bits */ +/* ray mirror fadeout */ +#define MA_RAYMIR_FADETOSKY 0 +#define MA_RAYMIR_FADETOMAT 1 + /* diff_shader */ #define MA_DIFF_LAMBERT 0 #define MA_DIFF_ORENNAYAR 1 Index: render/intern/include/render_types.h =================================================================== --- render/intern/include/render_types.h (revision 11161) +++ render/intern/include/render_types.h (working copy) @@ -349,6 +349,7 @@ short ray_samp, ray_sampy, ray_sampz, ray_samp_type, area_shape, ray_totsamp; short xold[BLENDER_MAX_THREADS], yold[BLENDER_MAX_THREADS]; /* last jitter table for area lights */ float area_size, area_sizey, area_sizez; + float adapt_thresh; struct ShadBuf *shb; float *jitter; Index: render/intern/source/convertblender.c =================================================================== --- render/intern/source/convertblender.c (revision 11161) +++ render/intern/source/convertblender.c (working copy) @@ -2243,15 +2243,21 @@ lar->ray_samp= la->ray_samp; lar->ray_sampy= la->ray_sampy; lar->ray_sampz= la->ray_sampz; - + lar->area_size= la->area_size; lar->area_sizey= la->area_sizey; lar->area_sizez= la->area_sizez; lar->area_shape= la->area_shape; lar->ray_samp_type= la->ray_samp_type; - - if(lar->type==LA_AREA) { + + lar->adapt_thresh= la->adapt_thresh; + + if( ELEM(lar->type, LA_SPOT, LA_SUN)) { + lar->ray_totsamp= lar->ray_samp*lar->ray_samp; + lar->area_shape = LA_AREA_SQUARE; + } + else if(lar->type==LA_AREA) { switch(lar->area_shape) { case LA_AREA_SQUARE: lar->ray_totsamp= lar->ray_samp*lar->ray_samp; @@ -3024,8 +3030,11 @@ if(vlr->mat->mode & MA_FULL_OSA) vlr->flag |= R_FULL_OSA; else if(trace) { if(vlr->mat->mode & MA_SHLESS); - else if(vlr->mat->mode & (MA_RAYTRANSP|MA_RAYMIRROR|MA_SHADOW)) - vlr->flag |= R_FULL_OSA; + else if(vlr->mat->mode & (MA_RAYTRANSP|MA_RAYMIRROR)) + /* for blurry reflect/refract, better to take more samples + * inside the raytrace than as OSA samples */ + if ((vlr->mat->gloss_mir == 1.0) && (vlr->mat->gloss_tra == 1.0)) + vlr->flag |= R_FULL_OSA; } } } Index: render/intern/source/ray.c =================================================================== --- render/intern/source/ray.c (revision 11161) +++ render/intern/source/ray.c (working copy) @@ -1584,19 +1584,50 @@ return d; } +static void ray_fadeout(Isect *is, ShadeInput *shi, float *col, float *blendcol, float dist_mir) +{ + /* if fading out, linear blend against fade colour */ + float d, dx, dy, dz; + float blendfac; + + /* get the ray's length - shi.co[] calculated by shade_ray() */ + dx= shi->co[0] - is->start[0]; + dy= shi->co[1] - is->start[1]; + dz= shi->co[2] - is->start[2]; + d= sqrt(dx*dx+dy*dy+dz*dz); + + // /* quadratic blend from ray colour to mat/sky colour */ + // blendfac = (dist_mir - ((d*d)/dist_mir)) / dist_mir; + + /* linear blend from ray colour to mat/sky colour */ + blendfac = 1.0 - d/dist_mir; + + col[0] = col[0]*blendfac + (1.0 - blendfac)*blendcol[0]; + col[1] = col[1]*blendfac + (1.0 - blendfac)*blendcol[1]; + col[2] = col[2]*blendfac + (1.0 - blendfac)*blendcol[2]; +} + /* the main recursive tracer itself */ -static void traceray(ShadeInput *origshi, short depth, float *start, float *vec, float *col, VlakRen *vlr, int traflag) +static void traceray(ShadeInput *origshi, ShadeResult *origshr, short depth, float *start, float *vec, float *col, VlakRen *vlr, int traflag) { ShadeInput shi; ShadeResult shr; Isect isec; float f, f1, fr, fg, fb; float ref[3]; + float dist_mir = origshi->mat->dist_mir; + + VECCOPY(isec.start, start); - VECCOPY(isec.start, start); - isec.end[0]= start[0]+R.oc.ocsize*vec[0]; - isec.end[1]= start[1]+R.oc.ocsize*vec[1]; - isec.end[2]= start[2]+R.oc.ocsize*vec[2]; + if (dist_mir > 0.0) { + isec.end[0]= start[0]+dist_mir*vec[0]; + isec.end[1]= start[1]+dist_mir*vec[1]; + isec.end[2]= start[2]+dist_mir*vec[2]; + } else { + isec.end[0]= start[0]+R.oc.ocsize*vec[0]; + isec.end[1]= start[1]+R.oc.ocsize*vec[1]; + isec.end[2]= start[2]+R.oc.ocsize*vec[2]; + } isec.mode= DDA_MIRROR; isec.vlrorig= vlr; @@ -1620,6 +1651,7 @@ memset(&shr, 0, sizeof(ShadeResult)); shade_ray(&isec, &shi, &shr); + if (traflag & RAY_TRA) d= shade_by_transmission(&isec, &shi, &shr); @@ -1648,10 +1680,10 @@ reflection(refract, shi.vn, shi.view, shi.vn); } traflag |= RAY_TRA; - traceray(origshi, depth-1, shi.co, refract, tracol, shi.vlr, traflag ^ RAY_TRAFLIP); + traceray(origshi, origshr, depth-1, shi.co, refract, tracol, shi.vlr, traflag ^ RAY_TRAFLIP); } else - traceray(origshi, depth-1, shi.co, shi.view, tracol, shi.vlr, 0); + traceray(origshi, origshr, depth-1, shi.co, shi.view, tracol, shi.vlr, 0); f= shr.alpha; f1= 1.0f-f; nf= d * shi.mat->filter; @@ -1681,7 +1713,7 @@ float mircol[4]; reflection(ref, shi.vn, shi.view, NULL); - traceray(origshi, depth-1, shi.co, ref, mircol, shi.vlr, 0); + traceray(origshi, origshr, depth-1, shi.co, ref, mircol, shi.vlr, 0); f1= 1.0f-f; @@ -1703,6 +1735,27 @@ col[0]= shr.diff[0] + shr.spec[0]; col[1]= shr.diff[1] + shr.spec[1]; col[2]= shr.diff[2] + shr.spec[2]; + + if (dist_mir > 0.0) { + float blendcol[3]; + + /* max ray distance set, but found an intersection, so fade this colour + * out towards the sky/material colour for a smooth transition */ + + if (origshi->mat->fadeto_mir == MA_RAYMIR_FADETOMAT) { + /* un-intersected rays take material colour */ + blendcol[0]= origshr->diff[0] + origshr->spec[0]; + blendcol[1]= origshr->diff[1] + origshr->spec[1]; + blendcol[2]= origshr->diff[2] + origshr->spec[2]; + } else if (origshi->mat->fadeto_mir == MA_RAYMIR_FADETOSKY) { + VECCOPY(shi.view, vec); + Normalize(shi.view); + + shadeSkyView(blendcol, isec.start, shi.view, NULL); + } + + ray_fadeout(&isec, &shi, col, blendcol, dist_mir); + } } } else { @@ -1710,13 +1763,21 @@ col[1]= shr.diff[1] + shr.spec[1]; col[2]= shr.diff[2] + shr.spec[2]; } - + } - else { /* sky */ - VECCOPY(shi.view, vec); - Normalize(shi.view); - - shadeSkyView(col, isec.start, shi.view, NULL); + else { + if (origshi->mat->fadeto_mir == MA_RAYMIR_FADETOMAT) { + /* un-intersected rays take material colour */ + col[0]= origshr->diff[0] + origshr->spec[0]; + col[1]= origshr->diff[1] + origshr->spec[1]; + col[2]= origshr->diff[2] + origshr->spec[2]; + } else { + /* un-intersected rays take sky colour */ + VECCOPY(shi.view, vec); + Normalize(shi.view); + + shadeSkyView(col, isec.start, shi.view, NULL); + } } } @@ -1831,15 +1892,295 @@ return lar->jitter; } +/* **************** sampling *************** */ +// floats will result in precision errors, so we use doubles + +static void halton_reset(double *ht_invprimes, double *ht_nums, 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); + + ht_nums[0] = v; + ht_nums[1] = v; + + ht_invprimes[0] = 0.5; + ht_invprimes[1] = 1.0/3.0; +} + +static void halton_sample(double *ht_invprimes, double *ht_nums, float *v) +{ + // incremental halton sequence generator, from: + // "Instant Radiosity", Keller A. + unsigned int i; + + for (i = 0; i < 2; i++) + { + double r = (1.0 - ht_nums[i]) - 1e-10; + + if (ht_invprimes[i] >= r) + { + double lasth; + double h = ht_invprimes[i]; + + do { + lasth = h; + h *= ht_invprimes[i]; + } while (h >= r); + + ht_nums[i] += ((lasth + h) - 1.0); + } + else + ht_nums[i] += ht_invprimes[i]; + + v[i] = (float)ht_nums[i]; + } +} + +static void halton_samplePhong(double *ht_invprimes, double *ht_nums, float *vec, float blur) +{ + float r[2]; + float phi, pz, sqr; + + halton_sample(ht_invprimes, ht_nums, r); + + phi = r[0]*2*M_PI; + pz = pow(r[1], blur*blur); + sqr = sqrt(1.0f-pz*pz); + + vec[0] = cos(phi)*sqr; + vec[1] = sin(phi)*sqr; + vec[2] = 0.0f; +} + +static void halton_sampleDisc(double *ht_invprimes, double *ht_nums, float *vec, float radius) +{ + float r[2]; + float phi, sqr; + + halton_sample(ht_invprimes, ht_nums, r); + + phi = r[0]*2*M_PI; + sqr = r[1]*sqrt(2-r[1]*r[1]); + + vec[0] = cos(phi)*sqr* radius/2.0; + vec[1] = sin(phi)*sqr* radius/2.0; + vec[2] = 0.0f; +} + +/* gives rect of edge lengths sizex, sizey, centred on 0.0,0.0 i.e. ranging from -0.5 to +0.5 */ +static void halton_sampleRect(double *ht_invprimes, double *ht_nums, float *vec, float sizex, float sizey) +{ + float r[2]; + + halton_sample(ht_invprimes, ht_nums, r); + + vec[0] = (r[0] - 0.5) * sizex; + vec[1] = (r[1] - 0.5) * sizey; + vec[2] = 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; +} + +static void orthovec(float *v, float *v1, float *v2) +{ + if (v[0] == 0.0f && v[1] == 0.0f) + { + // degenerate case + v1[0] = 0.0f; v1[1] = 1.0f; v1[2] = 0.0f; + if (v[2] > 0.0f) { + v2[0] = 1.0f; v2[1] = v2[2] = 0.0f; + } + else { + v2[0] = -1.0f; v2[1] = v2[2] = 0.0f; + } + } + else + { + float f = 1.0f/sqrt(v[0]*v[0] + v[1]*v[1]); + v1[0] = v[1]*f; + v1[1] = -v[0]*f; + v1[2] = 0.0f; + + Crossf(v2, v, v1); + } +} + /* ***************** main calls ************** */ +static void trace_refract(float *col, ShadeInput *shi, ShadeResult *shr) +{ + float v_refract[3], v_refract_new[3]; + float sampcol[4], prevcol[4]; + + 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 ht_invprimes[2]; + double ht_nums[2]; + col[0] = col[1] = col[2] = 0.0; + col[3]= shr->alpha; + + if (blur > 0.0) + halton_reset(ht_invprimes, ht_nums, 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(ht_invprimes, ht_nums, v_refract_new, 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, shr, shi->mat->ray_depth_tra, shi->co, v_refract_new, sampcol, shi->vlr, RAY_TRA|RAY_TRAFLIP); + + QUATCOPY(prevcol, col); + col[0] += sampcol[0]; + col[1] += sampcol[1]; + col[2] += sampcol[2]; + col[3] += sampcol[3]; + + samples++; + + /* adaptive sampling */ + if (adapt_thresh < 1.0 && samples > max_samples/2) + { + 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; + col[3] /= (float)samples; +} + +static void trace_reflect(float *col, ShadeInput *shi, ShadeResult *shr, float fresnelfac) +{ + float halton_samp[3]; + float v_nor_new[3], v_reflect[3]; + float orthx[3], orthy[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 ht_invprimes[2]; + double ht_nums[2]; + + col[0] = col[1] = col[2] = 0.0; + + if (blur > 0.0) + halton_reset(ht_invprimes, ht_nums, 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(ht_invprimes, ht_nums, halton_samp, blur); + + /* find the normal's perpendicular plane */ + orthovec(shi->vn, orthx, orthy); + VecMulf(orthx, halton_samp[0]); + VecMulf(orthy, halton_samp[1]); + + /* and perturb the normal in it */ + VecAddf(v_nor_new, shi->vn, orthx); + VecAddf(v_nor_new, v_nor_new, orthy); + + 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, shr, 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 > max_samples/2) + { + 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 +2195,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 +2224,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]; @@ -2293,8 +2625,6 @@ } } - - /* extern call from shade_lamp_loop */ void ray_shadow(ShadeInput *shi, LampRen *lar, float *shadfac) { @@ -2323,8 +2653,99 @@ VECCOPY(lampco, lar->co); } - if(lar->ray_totsamp<2) { + if (G.rt < 100) { + /* halton area shadow */ + int samples=0; + double ht_invprimes[2], ht_invprimes_jit[2]; + double ht_nums[2], ht_nums_jit[2]; + float ht_samp[3]; + float fac=0.0f, vec[3]; + float adapt_thresh = lar->adapt_thresh; + int max_samples; + float pos[3]; + int do_soft=1; + + if(isec.mode==DDA_SHADOW_TRA) { + shadfac[0]= shadfac[1]= shadfac[2]= shadfac[3]= 0.0f; + } + else shadfac[3]= 1.0f; + + halton_reset(ht_invprimes, ht_nums, shi->thread); + halton_reset(ht_invprimes_jit, ht_nums_jit, shi->thread); + VECCOPY(vec, lampco); + + if ((lar->ray_totsamp < 2) || (lar->type == LA_LOCAL)) do_soft = 0; + + /* give sharp shadows R.osa number of samples */ + if (do_soft) max_samples = lar->ray_totsamp; + else max_samples = (R.osa > 4)?R.osa:5; + + + while (samples < max_samples) { + isec.vlrorig= shi->vlr; // ray_trace_shadow_tra changes it + + /* manually jitter the start shading co-ord per sample + * based on the pre-generated OSA texture sampling offsets, + * for anti-aliasing sharp shadow edges. */ + VECCOPY(pos, shi->co); + if (shi->vlr && ((shi->vlr->flag & R_FULL_OSA) == 0)) { + float jit[2]; + + halton_sampleRect(ht_invprimes_jit, ht_nums_jit, jit, 1.0, 1.0); + + pos[0] += shi->dxco[0]*jit[0] + shi->dyco[0]*jit[1]; + pos[1] += shi->dxco[1]*jit[0] + shi->dyco[1]*jit[1]; + pos[2] += shi->dxco[2]*jit[0] + shi->dyco[2]*jit[1]; + } + VECCOPY(isec.start, pos); + + /* for soft shadows, use halton sampling to scatter the end co-ord per sample */ + if (do_soft) { + /* should give rect around origin, -0.5*size to 0.5*size */ + halton_sampleRect(ht_invprimes, ht_nums, ht_samp, lar->area_size, lar->area_sizey); + + /* align halton samples to lamp vector */ + Mat3MulVecfl(lar->mat, ht_samp); + + isec.end[0]= vec[0]+ht_samp[0]; + isec.end[1]= vec[1]+ht_samp[1]; + isec.end[2]= vec[2]+ht_samp[2]; + } else { + VECCOPY(isec.end, vec); + } + + /* the ray trace itself */ + if(isec.mode==DDA_SHADOW_TRA) { + /* isec.col is like shadfac, so defines amount of light (0.0 is full shadow) */ + isec.col[0]= isec.col[1]= isec.col[2]= 1.0f; + isec.col[3]= 1.0f; + + ray_trace_shadow_tra(&isec, DEPTH_SHADOW_TRA, 0); + shadfac[0] += isec.col[0]; + shadfac[1] += isec.col[1]; + shadfac[2] += isec.col[2]; + shadfac[3] += isec.col[3]; + } + else if( d3dda(&isec) ) fac+= 1.0f; + + samples++; + + if ((do_soft) && (adapt_thresh > 0.0)) { + if ( (samples > lar->ray_totsamp/3) && ((fac / samples > (1.0-adapt_thresh)) || (fac / samples < adapt_thresh)) ) break; + } + } + + if(isec.mode==DDA_SHADOW_TRA) { + shadfac[0] /= samples; + shadfac[1] /= samples; + shadfac[2] /= samples; + shadfac[3] /= samples; + } else + shadfac[3]= 1.0f-fac/samples; + } + else if(lar->ray_totsamp<2) { + isec.vlrorig= shi->vlr; shadfac[3]= 1.0f; // 1.0=full light Index: src/buttons_shading.c =================================================================== --- src/buttons_shading.c (revision 11161) +++ src/buttons_shading.c (working copy) @@ -2521,25 +2521,33 @@ } } - else if(la->type==LA_AREA && (la->mode & LA_SHAD_RAY)) { - uiBlockBeginAlign(block); - uiBlockSetCol(block, TH_AUTO); - if(la->area_shape==LA_AREA_SQUARE) - uiDefButS(block, NUM,0,"Samples:", 100,180,200,19, &la->ray_samp, 1.0, 16.0, 100, 0, "Sets the amount of samples taken extra (samp x samp)"); - if(la->area_shape==LA_AREA_CUBE) - uiDefButS(block, NUM,0,"Samples:", 100,160,200,19, &la->ray_samp, 1.0, 16.0, 100, 0, "Sets the amount of samples taken extra (samp x samp x samp)"); + if(ELEM3(la->type, LA_AREA, LA_SPOT, LA_SUN) && (la->mode & LA_SHAD_RAY)) { + + + if (ELEM(la->type, LA_SPOT, LA_SUN)) { + uiDefButS(block, NUM,0,"Samples:", 100,110,200,19, &la->ray_samp, 1.0, 16.0, 100, 0, "Sets the amount of samples taken extra (samp x samp)"); + uiDefButF(block, NUM,B_LAMPREDRAW,"Soft Size", 100,90,200,19, &la->area_size, 0.01, 100.0, 10, 0, "Area light size X, doesn't affect energy amount"); + } + else if (la->type == LA_AREA) { + if(la->area_shape==LA_AREA_SQUARE) + uiDefButS(block, NUM,0,"Samples:", 100,180,200,19, &la->ray_samp, 1.0, 16.0, 100, 0, "Sets the amount of samples taken extra (samp x samp)"); + else if(la->area_shape==LA_AREA_CUBE) + uiDefButS(block, NUM,0,"Samples:", 100,160,200,19, &la->ray_samp, 1.0, 16.0, 100, 0, "Sets the amount of samples taken extra (samp x samp x samp)"); - if (ELEM(la->area_shape, LA_AREA_RECT, LA_AREA_BOX)) { - uiDefButS(block, NUM,0,"SamplesX:", 100,180,200,19, &la->ray_samp, 1.0, 16.0, 100, 0, "Sets the amount of X samples taken extra"); - uiDefButS(block, NUM,0,"SamplesY:", 100,160,200,19, &la->ray_sampy, 1.0, 16.0, 100, 0, "Sets the amount of Y samples taken extra"); - if(la->area_shape==LA_AREA_BOX) - uiDefButS(block, NUM,0,"SamplesZ:", 100,140,200,19, &la->ray_sampz, 1.0, 8.0, 100, 0, "Sets the amount of Z samples taken extra"); + if (ELEM(la->area_shape, LA_AREA_RECT, LA_AREA_BOX)) { + uiDefButS(block, NUM,0,"SamplesX:", 100,180,200,19, &la->ray_samp, 1.0, 16.0, 100, 0, "Sets the amount of X samples taken extra"); + uiDefButS(block, NUM,0,"SamplesY:", 100,160,200,19, &la->ray_sampy, 1.0, 16.0, 100, 0, "Sets the amount of Y samples taken extra"); + if(la->area_shape==LA_AREA_BOX) + uiDefButS(block, NUM,0,"SamplesZ:", 100,140,200,19, &la->ray_sampz, 1.0, 8.0, 100, 0, "Sets the amount of Z samples taken extra"); + } + + uiBlockBeginAlign(block); + uiDefButBitS(block, TOG, LA_SAMP_UMBRA, 0,"Umbra", 100,110,200,19,&la->ray_samp_type, 0, 0, 0, 0, "Emphasis parts that are fully shadowed"); + uiDefButBitS(block, TOG, LA_SAMP_DITHER, 0,"Dither", 100,90,100,19,&la->ray_samp_type, 0, 0, 0, 0, "Use 2x2 dithering for sampling"); + uiDefButBitS(block, TOG, LA_SAMP_JITTER, 0,"Noise", 200,90,100,19,&la->ray_samp_type, 0, 0, 0, 0, "Use noise for sampling"); } + uiDefButF(block, NUM,0,"Threshold:", 100,60,200,19, &la->adapt_thresh, 0.0, 1.0, 100, 0, "Threshold for adaptive sampling"); - uiBlockBeginAlign(block); - uiDefButBitS(block, TOG, LA_SAMP_UMBRA, 0,"Umbra", 100,110,200,19,&la->ray_samp_type, 0, 0, 0, 0, "Emphasis parts that are fully shadowed"); - uiDefButBitS(block, TOG, LA_SAMP_DITHER, 0,"Dither", 100,90,100,19,&la->ray_samp_type, 0, 0, 0, 0, "Use 2x2 dithering for sampling"); - uiDefButBitS(block, TOG, LA_SAMP_JITTER, 0,"Noise", 200,90,100,19,&la->ray_samp_type, 0, 0, 0, 0, "Use noise for sampling"); } else uiDefBut(block, LABEL,0," ", 100,180,200,19,NULL, 0, 0, 0, 0, ""); @@ -3226,41 +3234,99 @@ 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, 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, 512.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); + 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"); + + 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, NUM, B_MATPRV, "Max Dist:", + X2CLM1, yco-=BUTH, BUTW2, BUTH, &(ma->dist_mir), 0.0, 100.0, 100, 0, "Maximum distance of reflected rays. Reflections further than this range fade to sky color"); + uiDefButS(block, MENU, B_MATPRV, "Ray end fade-out: %t|Fade to Sky Color %x0|Fade to Material Color %x1", + X2CLM1, yco-=BUTH, BUTW2, BUTH, &(ma->fadeto_mir), 0, 0, 0, 0, "The color that rays with no intersection within the Max Distance take. Material color can be best for indoor scenes, sky color for outdoor."); + 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=PANEL_YMAX; - 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"); + 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, "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, 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, 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, 512.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"); }