diff --git a/source/blender/blenkernel/BKE_osa_types.h b/source/blender/blenkernel/BKE_osa_types.h index 32f91dd3ff7..28d4147c11b 100644 --- a/source/blender/blenkernel/BKE_osa_types.h +++ b/source/blender/blenkernel/BKE_osa_types.h @@ -44,6 +44,7 @@ typedef struct RE_Osa float dxlv[3], dylv[3]; float dxwin[3], dywin[3]; float dxsticky[3], dysticky[3]; + float dxrefract[3], dyrefract[3]; } Osa; /* extern Osa O; */ diff --git a/source/blender/blenkernel/intern/material.c b/source/blender/blenkernel/intern/material.c index 28d47d4d90e..16ed3f00355 100644 --- a/source/blender/blenkernel/intern/material.c +++ b/source/blender/blenkernel/intern/material.c @@ -86,6 +86,7 @@ void init_material(Material *ma) ma->r= ma->g= ma->b= ma->ref= 0.8; ma->specr= ma->specg= ma->specb= 1.0; ma->mirr= ma->mirg= ma->mirb= 1.0; + ma->spectra= 1.0; ma->amb= 0.5; ma->alpha= 1.0; ma->spec= ma->hasize= 0.5; @@ -104,6 +105,11 @@ void init_material(Material *ma) ma->param[2]= 0.5; ma->param[3]= 0.1; + ma->ang= 1.0; + ma->ray_depth= 2; + ma->ray_depth_tra= 2; + ma->falloff_mir= 1.0; + ma->falloff_tra= 1.0; ma->mode= MA_TRACEBLE+MA_SHADOW+MA_RADIO; } @@ -577,14 +583,14 @@ void init_render_material(Material *ma) } if(needuv) ma->texco |= NEED_UV; - if(R.r.mode & R_RAYTRACE) { - if(ma->ray_mirror!=0.0) { - ma->texco |= NEED_UV|TEXCO_REFL; - if(R.osa) ma->texco |= TEXCO_OSA; - } + if(ma->mode & MA_RAYMIRROR) { + ma->texco |= NEED_UV|TEXCO_REFL; + if(R.osa) ma->texco |= TEXCO_OSA; + } + if(ma->mode & MA_RAYTRANSP) { + ma->texco |= NEED_UV; + if(R.osa) ma->texco |= TEXCO_OSA; } - - ma->ambr= ma->amb*R.wrld.ambr; ma->ambg= ma->amb*R.wrld.ambg; diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index f57961e8482..a94c8e79dd6 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -3929,7 +3929,19 @@ static void do_versions(Main *main) } } } - + if(main->versionfile <= 231) { + Material *ma= main->mat.first; + while(ma) { + if(ma->ang==0.0) { + ma->ang= 1.0; + ma->ray_depth= 2; + ma->ray_depth_tra= 2; + ma->falloff_mir= 1.0; + ma->falloff_tra= 1.0; + } + ma= ma->id.next; + } + } /* don't forget to set version number in blender.c! */ } diff --git a/source/blender/include/butspace.h b/source/blender/include/butspace.h index f8f52fd6ea9..cb2b60826dd 100644 --- a/source/blender/include/butspace.h +++ b/source/blender/include/butspace.h @@ -135,6 +135,8 @@ void test_idbutton_cb(void *namev, void *arg2_unused); #define B_COLLAMP 1102 #define B_TEXCLEARLAMP 1103 #define B_SBUFF 1104 +#define B_SHADBUF 1105 +#define B_SHADRAY 1106 /* *********************** */ #define B_MATBUTS 1300 @@ -152,6 +154,8 @@ void test_idbutton_cb(void *namev, void *arg2_unused); #define B_MTEXCOPY 1211 #define B_MATLAY 1212 #define B_MATHALO 1213 +#define B_MATZTRANSP 1214 +#define B_MATRAYTRANSP 1215 /* *********************** */ #define B_TEXBUTS 1400 diff --git a/source/blender/makesdna/DNA_material_types.h b/source/blender/makesdna/DNA_material_types.h index 505dd319046..9162499ed48 100644 --- a/source/blender/makesdna/DNA_material_types.h +++ b/source/blender/makesdna/DNA_material_types.h @@ -57,7 +57,9 @@ typedef struct Material { float amb, emit, ang, spectra, ray_mirror; float alpha, ref, spec, zoffs, add; float kfac; /* for transparent solids */ - short ray_depth, pad1; + float fresnel_mir, falloff_mir; + float fresnel_tra, falloff_tra; + short ray_depth, ray_depth_tra; short har; char seed1, seed2; @@ -124,6 +126,8 @@ typedef struct Material { #define MA_HALO_SHADE 0x4000 #define MA_HALO_FLARE 0x8000 #define MA_RADIO 0x10000 +#define MA_RAYTRANSP 0x20000 +#define MA_RAYMIRROR 0x40000 /* diff_shader */ #define MA_DIFF_LAMBERT 0 diff --git a/source/blender/render/intern/include/rendercore.h b/source/blender/render/intern/include/rendercore.h index 0be15d90776..3e915b34b7c 100644 --- a/source/blender/render/intern/include/rendercore.h +++ b/source/blender/render/intern/include/rendercore.h @@ -38,10 +38,21 @@ struct HaloRen; +typedef struct ShadeResult +{ + float diff[3]; + float spec[3]; + float alpha; + +} ShadeResult; + + float mistfactor(float *co); /* dist en hoogte, return alpha */ void renderspothalo(unsigned short *col); void render_lighting_halo(struct HaloRen *har, float *colf); unsigned int calchalo_z(struct HaloRen *har, unsigned int zz); +void shade_lamp_loop(int mask, ShadeResult *shr); +float fresnel_fac(float *view, float *vn, float fresnel, float falloff); float spec(float inp, int hard); diff --git a/source/blender/render/intern/source/ray.c b/source/blender/render/intern/source/ray.c index 40e13899852..5120c81d9e5 100644 --- a/source/blender/render/intern/source/ray.c +++ b/source/blender/render/intern/source/ray.c @@ -46,6 +46,7 @@ #include "render.h" #include "render_intern.h" +#include "rendercore.h" #include "jitter.h" #define OCRES 64 @@ -1143,9 +1144,8 @@ static int d3dda(Isect *is) /* for now; mostly a duplicate of shadepixel() itself... could be unified once */ /* R.view has been set */ -static void shade_ray(Isect *is, int mask) +static void shade_ray(Isect *is, int mask, ShadeResult *shr) { - extern void shade_lamp_loop(int ); VertRen *v1, *v2, *v3; float n1[3], n2[3], n3[3]; float *o1, *o2, *o3; @@ -1166,15 +1166,17 @@ static void shade_ray(Isect *is, int mask) /* face normal, check for flip */ R.vno= R.vlr->n; - l= R.vlr->n[0]*R.view[0]+R.vlr->n[1]*R.view[1]+R.vlr->n[2]*R.view[2]; - if(l<0.0) { - flip= 1; - R.vlr->n[0]= -R.vlr->n[0]; - R.vlr->n[1]= -R.vlr->n[1]; - R.vlr->n[2]= -R.vlr->n[2]; - R.vlr->puno= ~(R.vlr->puno); + if((R.mat->mode & MA_RAYTRANSP)==0) { + l= R.vlr->n[0]*R.view[0]+R.vlr->n[1]*R.view[1]+R.vlr->n[2]*R.view[2]; + if(l<0.0) { + flip= 1; + R.vlr->n[0]= -R.vlr->n[0]; + R.vlr->n[1]= -R.vlr->n[1]; + R.vlr->n[2]= -R.vlr->n[2]; + R.vlr->puno= ~(R.vlr->puno); + } } - + if(R.vlr->v4) { if(is->isect==2) { v1= R.vlr->v3; @@ -1338,7 +1340,7 @@ static void shade_ray(Isect *is, int mask) VECCOPY(R.vn, R.vlr->n); } - shade_lamp_loop(mask); + shade_lamp_loop(mask, shr); if(flip) { R.vlr->n[0]= -R.vlr->n[0]; @@ -1348,20 +1350,121 @@ static void shade_ray(Isect *is, int mask) } } -/* the main recursive tracer itself */ -static void traceray(float f, short depth, float *start, float *vec, float *col, int mask) +static void refraction(float *refract, float *n, float *view, float index) { - extern unsigned short shortcol[4]; // only for old render, which stores ushort + float dot, fac; + + VECCOPY(refract, view); + if(index==0.0) return; + + dot= view[0]*n[0] + view[1]*n[1] + view[2]*n[2]; + + if(dot>0.0) { + fac= 1.0 - (1.0 - dot*dot)*index*index; + if(fac<= 0.0) return; + fac= -dot*index + sqrt(fac); + } + else { + index = 1.0/index; + fac= 1.0 - (1.0 - dot*dot)*index*index; + if(fac<= 0.0) return; + fac= -dot*index - sqrt(fac); + } + + refract[0]= index*view[0] + fac*n[0]; + refract[1]= index*view[1] + fac*n[1]; + refract[2]= index*view[2] + fac*n[2]; +} + +static void calc_dx_dy_refract(float *ref, float *n, float *view, float index) +{ + float dref[3], dview[3], dnor[3]; + + refraction(ref, n, view, index); + + dview[0]= view[0]+ O.dxview; + dview[1]= view[1]; + dview[2]= view[2]; + + if(R.vlr->flag & R_SMOOTH) { + VecAddf(dnor, n, O.dxno); + refraction(dref, dnor, dview, index); + } + else { + refraction(dref, n, dview, index); + } + VecSubf(O.dxrefract, ref, dref); + + dview[0]= view[0]; + dview[1]= view[1]+ O.dyview; + + if(R.vlr->flag & R_SMOOTH) { + VecAddf(dnor, n, O.dyno); + refraction(dref, dnor, dview, index); + } + else { + refraction(dref, n, dview, index); + } + VecSubf(O.dyrefract, ref, dref); + +} + + +/* orn = original face normal */ +static void reflection(float *ref, float *n, float *view, float *orn) +{ + float f1; + + f1= -2.0*(n[0]*view[0]+ n[1]*view[1]+ n[2]*view[2]); + + if(orn==NULL) { + // heuristic, should test this! is to prevent normal going to the back + if(f1> -0.2) f1= -0.2; + } + + ref[0]= (view[0]+f1*n[0]); + ref[1]= (view[1]+f1*n[1]); + ref[2]= (view[2]+f1*n[2]); + + if(orn) { + /* test phong normals, then we should prevent vector going to the back */ + f1= ref[0]*orn[0]+ ref[1]*orn[1]+ ref[2]*orn[2]; + if(f1>0.0) { + f1+= .01; + ref[0]-= f1*orn[0]; + ref[1]-= f1*orn[1]; + ref[2]-= f1*orn[2]; + } + } +} + +static void color_combine(float *result, float fac1, float fac2, float *col1, float *col2) +{ + float col1t[3], col2t[3]; + + col1t[0]= sqrt(col1[0]); + col1t[1]= sqrt(col1[1]); + col1t[2]= sqrt(col1[2]); + col2t[0]= sqrt(col2[0]); + col2t[1]= sqrt(col2[1]); + col2t[2]= sqrt(col2[2]); + + result[0]= (fac1*col1t[0] + fac2*col2t[0]); + result[0]*= result[0]; + result[1]= (fac1*col1t[1] + fac2*col2t[1]); + result[1]*= result[1]; + result[2]= (fac1*col1t[2] + fac2*col2t[2]); + result[2]*= result[2]; +} + +/* the main recursive tracer itself */ +static void traceray(short depth, float *start, float *vec, float *col, int mask) +{ + ShadeResult shr; Isect isec; - float f1, fr, fg, fb; + float f, f1, fr, fg, fb; float ref[3]; - if(depth<0) return; - - fr= R.mat->mirr; - fg= R.mat->mirg; - fb= R.mat->mirb; - VECCOPY(isec.start, start); isec.end[0]= start[0]+g_oc.ocsize*vec[0]; isec.end[1]= start[1]+g_oc.ocsize*vec[1]; @@ -1374,26 +1477,65 @@ static void traceray(float f, short depth, float *start, float *vec, float *col, VECCOPY(R.view, vec); Normalise(R.view); - shade_ray(&isec, mask); // returns shortcol + shade_ray(&isec, mask, &shr); - f1= 1.0-f; + if(depth>0) { - col[0]= f*fr*(shortcol[0]/65535.0)+ f1*col[0]; - col[1]= f*fg*(shortcol[1]/65535.0)+ f1*col[1]; - col[2]= f*fb*(shortcol[2]/65535.0)+ f1*col[2]; - - /* is already new material: */ - if(R.mat->ray_mirror>0.0) { - f1= -2*(R.vn[0]*R.view[0]+R.vn[1]*R.view[1]+R.vn[2]*R.view[2]); - if(f1> -0.2) f1= -0.2; + if(R.mat->mode & MA_RAYMIRROR) { + f= R.mat->ray_mirror; + if(f!=0.0) f*= fresnel_fac(R.view, R.vn, R.mat->fresnel_mir, R.mat->falloff_mir); + } + else f= 0.0; - ref[0]= (R.view[0]+f1*R.vn[0]); - ref[1]= (R.view[1]+f1*R.vn[1]); - ref[2]= (R.view[2]+f1*R.vn[2]); + /* have to do it here, make local vars... */ + fr= R.mat->mirr; + fg= R.mat->mirg; + fb= R.mat->mirb; + + if(R.mat->mode & MA_RAYTRANSP && shr.alpha!=1.0) { + float f, f1, refract[3], tracol[3]; + + refraction(refract, R.vn, R.view, R.mat->ang); + traceray(depth-1, R.co, refract, tracol, mask); + + f= shr.alpha; f1= 1.0-f; + shr.diff[0]= f*shr.diff[0] + f1*tracol[0]; + shr.diff[1]= f*shr.diff[1] + f1*tracol[1]; + shr.diff[2]= f*shr.diff[2] + f1*tracol[2]; + shr.alpha= 1.0; + } - f*= R.mat->ray_mirror; - traceray(f, depth-1, R.co, ref, col, mask); + if(f!=0.0) { + + reflection(ref, R.vn, R.view, NULL); + traceray(depth-1, R.co, ref, col, mask); + + f1= 1.0-f; + + /* combine */ + //color_combine(col, f*fr*(1.0-shr.spec[0]), f1, col, shr.diff); + //col[0]+= shr.spec[0]; + //col[1]+= shr.spec[1]; + //col[2]+= shr.spec[2]; + + col[0]= f*fr*(1.0-shr.spec[0])*col[0] + f1*shr.diff[0] + shr.spec[0]; + + col[1]= f*fg*(1.0-shr.spec[1])*col[1] + f1*shr.diff[1] + shr.spec[1]; + + col[2]= f*fb*(1.0-shr.spec[2])*col[2] + f1*shr.diff[2] + shr.spec[2]; + } + else { + col[0]= shr.diff[0] + shr.spec[0]; + col[1]= shr.diff[1] + shr.spec[1]; + col[2]= shr.diff[2] + shr.spec[2]; + } } + else { + col[0]= shr.diff[0] + shr.spec[0]; + col[1]= shr.diff[1] + shr.spec[1]; + col[2]= shr.diff[2] + shr.spec[2]; + } + } else { /* sky */ char skycol[4]; @@ -1402,13 +1544,10 @@ static void traceray(float f, short depth, float *start, float *vec, float *col, Normalise(R.view); RE_sky(skycol); - - f1= 1.0-f; - f/= 255.0; - col[0]= f*fr*skycol[0]+ f1*col[0]; - col[1]= f*fg*skycol[1]+ f1*col[1]; - col[2]= f*fb*skycol[2]+ f1*col[2]; + col[0]= skycol[0]/255.0; + col[1]= skycol[1]/255.0; + col[2]= skycol[2]/255.0; } } @@ -1497,94 +1636,174 @@ static void *jitter_cube(int resol) } -/* ***************** extern calls ************** */ +/* ***************** main calls ************** */ /* extern call from render loop */ -void ray_mirror(int mask) +void ray_trace(int mask, ShadeResult *shr) { - float i, vec[3]; + VlakRen *vlr; + float i, f, f1, fr, fg, fb, vec[3], mircol[3], tracol[3]; + int do_tra, do_mir; + + do_tra= ((R.mat->mode & MA_RAYTRANSP) && shr->alpha!=1.0); + do_mir= ((R.mat->mode & MA_RAYMIRROR) && R.mat->ray_mirror!=0.0); + vlr= R.vlr; if(R.r.mode & R_OSA) { - VlakRen *vlr; - float accum[3], rco[3], rvno[3], col[3], ref[3], dxref[3], dyref[3]; - float div= 0.0; + float accum[3], rco[3], ref[3], dxref[3], dyref[3]; + float accur[3], refract[3], divr=0.0, div= 0.0; int j; + if(do_tra) calc_dx_dy_refract(refract, R.vn, R.view, R.mat->ang); + accum[0]= accum[1]= accum[2]= 0.0; + accur[0]= accur[1]= accur[2]= 0.0; /* store variables which change during tracing */ VECCOPY(rco, R.co); - VECCOPY(rvno, R.vno); VECCOPY(ref, R.ref); VECCOPY(dxref, O.dxref); VECCOPY(dyref, O.dyref); - vlr= R.vlr; - + for(j=0; j0.0) { - i+= .01; - vec[0]-= i*rvno[0]; - vec[1]-= i*rvno[1]; - vec[2]-= i*rvno[2]; - } - - R.co[0]+= (jit[j][0]-0.5)*O.dxco[0] + (jit[j][1]-0.5)*O.dyco[0] ; - R.co[1]+= (jit[j][0]-0.5)*O.dxco[1] + (jit[j][1]-0.5)*O.dyco[1] ; - R.co[2]+= (jit[j][0]-0.5)*O.dxco[2] + (jit[j][1]-0.5)*O.dyco[2] ; - - /* we use a new mask here, only shadow uses it */ - /* result in accum, this is copied to R.refcol for shade_lamp_loop */ - traceray(1.0, R.mat->ray_depth, R.co, vec, col, 1<mat; - R.matren= R.mat->ren; + R.co[0]+= (jit[j][0]-0.5)*O.dxco[0] + (jit[j][1]-0.5)*O.dyco[0] ; + R.co[1]+= (jit[j][0]-0.5)*O.dxco[1] + (jit[j][1]-0.5)*O.dyco[1] ; + R.co[2]+= (jit[j][0]-0.5)*O.dxco[2] + (jit[j][1]-0.5)*O.dyco[2] ; + + traceray(R.mat->ray_depth_tra, R.co, vec, tracol, mask); + + VecAddf(accur, accur, tracol); + divr+= 1.0; + + /* restore */ + VECCOPY(R.co, rco); + R.vlr= vlr; + R.mat= vlr->mat; + R.matren= R.mat->ren; + } + + if(do_mir) { + vec[0]= ref[0] + 2.0*(jit[j][0]-0.5)*dxref[0] + 2.0*(jit[j][1]-0.5)*dyref[0] ; + vec[1]= ref[1] + 2.0*(jit[j][0]-0.5)*dxref[1] + 2.0*(jit[j][1]-0.5)*dyref[1] ; + vec[2]= ref[2] + 2.0*(jit[j][0]-0.5)*dxref[2] + 2.0*(jit[j][1]-0.5)*dyref[2] ; + + /* prevent normal go to backside */ + i= vec[0]*R.vlr->n[0]+ vec[1]*R.vlr->n[1]+ vec[2]*R.vlr->n[2]; + if(i>0.0) { + i+= .01; + vec[0]-= i*R.vlr->n[0]; + vec[1]-= i*R.vlr->n[1]; + vec[2]-= i*R.vlr->n[2]; + } + + R.co[0]+= (jit[j][0]-0.5)*O.dxco[0] + (jit[j][1]-0.5)*O.dyco[0] ; + R.co[1]+= (jit[j][0]-0.5)*O.dxco[1] + (jit[j][1]-0.5)*O.dyco[1] ; + R.co[2]+= (jit[j][0]-0.5)*O.dxco[2] + (jit[j][1]-0.5)*O.dyco[2] ; + + /* we use a new mask here, only shadow uses it */ + /* result in accum, this is copied to shade_lamp_loop */ + traceray(R.mat->ray_depth, R.co, vec, mircol, 1<mat; + R.matren= R.mat->ren; + } } } - R.refcol[0]= R.mat->ray_mirror; - R.refcol[1]= R.mat->ray_mirror*accum[0]/div; - R.refcol[2]= R.mat->ray_mirror*accum[1]/div; - R.refcol[3]= R.mat->ray_mirror*accum[2]/div; + + if(divr!=0.0) { + f= shr->alpha; f1= 1.0-f; f1/= divr; + shr->diff[0]= f*shr->diff[0] + f1*accur[0]; + shr->diff[1]= f*shr->diff[1] + f1*accur[1]; + shr->diff[2]= f*shr->diff[2] + f1*accur[2]; + shr->alpha= 1.0; + } + + if(div!=0.0) { + i= R.mat->ray_mirror; + fr= R.mat->mirr; + fg= R.mat->mirg; + fb= R.mat->mirb; + + /* result */ + f= i*fr*(1.0-shr->spec[0]); f1= 1.0-i; f/= div; + shr->diff[0]= f*accum[0] + f1*shr->diff[0]; + + f= i*fg*(1.0-shr->spec[1]); f1= 1.0-i; f/= div; + shr->diff[1]= f*accum[1] + f1*shr->diff[1]; + + f= i*fb*(1.0-shr->spec[2]); f1= 1.0-i; f/= div; + shr->diff[2]= f*accum[2] + f1*shr->diff[2]; + } } else { - i= -2.0*(R.vn[0]*R.view[0]+R.vn[1]*R.view[1]+R.vn[2]*R.view[2]); - vec[0]= (R.view[0]+i*R.vn[0]); - vec[1]= (R.view[1]+i*R.vn[1]); - vec[2]= (R.view[2]+i*R.vn[2]); - - /* test phong normals, then we should prevent vector going to the back */ - if(R.vlr->flag & R_SMOOTH) { - i= vec[0]*R.vno[0]+ vec[1]*R.vno[1]+ vec[2]*R.vno[2]; - if(i>0.0) { - i+= .01; - vec[0]-= i*R.vno[0]; - vec[1]-= i*R.vno[1]; - vec[2]-= i*R.vno[2]; - } + if(do_tra) { + float rvn[3], view[3], rco[3], ref[3], refract[3]; + + /* store variables which change during tracing */ + VECCOPY(view, R.view); + VECCOPY(rco, R.co); + VECCOPY(rvn, R.vn); + VECCOPY(ref, R.ref); + + refraction(refract, R.vn, R.view, R.mat->ang); + traceray(R.mat->ray_depth_tra, R.co, refract, tracol, mask); + + f= shr->alpha; f1= 1.0-f; + shr->diff[0]= f*shr->diff[0] + f1*tracol[0]; + shr->diff[1]= f*shr->diff[1] + f1*tracol[1]; + shr->diff[2]= f*shr->diff[2] + f1*tracol[2]; + shr->alpha= 1.0; + + /* store variables which change during tracing */ + VECCOPY(R.view, view); + VECCOPY(R.co, rco); + VECCOPY(R.ref, ref); + VECCOPY(R.vn, rvn); + R.vlr= vlr; + R.mat= vlr->mat; + R.matren= R.mat->ren; } - /* result in r.refcol, this is added in shade_lamp_loop */ - i= R.mat->ray_mirror; - traceray(1.0, R.mat->ray_depth, R.co, vec, R.refcol+1, mask); - R.refcol[0]= i; - R.refcol[1]*= i; - R.refcol[2]*= i; - R.refcol[3]*= i; + if(do_mir) { + i= R.mat->ray_mirror*fresnel_fac(R.view, R.vn, R.mat->fresnel_mir, R.mat->falloff_mir); + if(i!=0.0) { + fr= R.mat->mirr; + fg= R.mat->mirg; + fb= R.mat->mirb; + + if(R.vlr->flag & R_SMOOTH) + reflection(vec, R.vn, R.view, R.vlr->n); + else + reflection(vec, R.vn, R.view, NULL); + + traceray(R.mat->ray_depth, R.co, vec, mircol, mask); + + f= i*fr*(1.0-shr->spec[0]); f1= 1.0-i; + shr->diff[0]= f*mircol[0] + f1*shr->diff[0]; + + f= i*fg*(1.0-shr->spec[1]); f1= 1.0-i; + shr->diff[1]= f*mircol[1] + f1*shr->diff[1]; + + f= i*fb*(1.0-shr->spec[2]); f1= 1.0-i; + shr->diff[2]= f*mircol[2] + f1*shr->diff[2]; + } + } } } diff --git a/source/blender/render/intern/source/renderHelp.c b/source/blender/render/intern/source/renderHelp.c index 6566e982f1d..d1ee202748d 100644 --- a/source/blender/render/intern/source/renderHelp.c +++ b/source/blender/render/intern/source/renderHelp.c @@ -265,8 +265,8 @@ void set_normalflags(void) for(a1=0; a1>8]; else vlr++; - - if(vlr->flag & R_NOPUNOFLIP) { + + if((vlr->flag & R_NOPUNOFLIP)) { /* we flip render normal here, is not that neat, but otherwise render() needs rewrite... */ vlr->n[0]= -vlr->n[0]; vlr->n[1]= -vlr->n[1]; diff --git a/source/blender/render/intern/source/rendercore.c b/source/blender/render/intern/source/rendercore.c index c86a8299538..d1bc18fb544 100644 --- a/source/blender/render/intern/source/rendercore.c +++ b/source/blender/render/intern/source/rendercore.c @@ -1552,12 +1552,22 @@ void RE_calc_R_ref() } +float fresnel_fac(float *view, float *vn, float fresnel, float falloff) +{ + float fac= fabs(view[0]*vn[0] + view[1]*vn[1] + view[2]*vn[2]); + + if(falloff>0.0) fac= pow(fac, falloff); else fac= 1.0; + if(fac>1.0) fac= 1.0; + + return (1.0 - fresnel*fac); +} + /* mask is used to define the amount of rays/samples */ -void shade_lamp_loop(int mask) +void shade_lamp_loop(int mask, ShadeResult *shr) { LampRen *lar; Material *ma; - float i, inp, inpr, t, lv[3], lampdist, ld = 0, ir, ig, ib, isr=0,isg=0,isb=0; + float i, inp, inpr, t, lv[3], lampdist, ld = 0; float lvrot[3], *vn, *view, shadfac, soft; int a; @@ -1565,8 +1575,12 @@ void shade_lamp_loop(int mask) view= R.view; ma= R.matren; + memset(shr, 0, sizeof(ShadeResult)); + /* separate loop */ if(ma->mode & MA_ONLYSHADOW) { + float ir; + shadfac= ir= 0.0; for(a=0; a0.0) shadfac/= ir; - ma->alpha= (R.mat->alpha)*(1.0-shadfac); - - shortcol[0]=shortcol[1]=shortcol[2]= 0; + shr->alpha= (R.mat->alpha)*(1.0-shadfac); return; } @@ -1615,6 +1627,8 @@ void shade_lamp_loop(int mask) ma->g= R.vcol[1]; ma->b= R.vcol[2]; } + + ma->alpha= R.mat->alpha; // copy to render material, for fresnel and spectra if(ma->texco) { if(ma->mode & (MA_VERTEXCOLP|MA_FACETEXTURE)) { @@ -1626,38 +1640,18 @@ void shade_lamp_loop(int mask) } if(ma->mode & MA_SHLESS) { - ir= ma->r; - ig= ma->g; - ib= ma->b; - - if(usegamtab) { - a= 65535*ir; - if(a<0) a=0; else if(a>65535) a= 65535; - shortcol[0]= igamtab2[a]; - a= 65535*ig; - if(a<0) a=0; else if(a>65535) a= 65535; - shortcol[1]= igamtab2[a]; - a= 65535*ib; - if(a<0) a=0; else if(a>65535) a= 65535; - shortcol[2]= igamtab2[a]; - } - else { - a= 65535*ir; - if(a<0) shortcol[0]= 0; else if(a>65535) shortcol[0]= 65535; else shortcol[0]= a; - a= 65535*ig; - if(a<0) shortcol[1]= 0; else if(a>65535) shortcol[1]= 65535; else shortcol[1]= a; - a= 65535*ib; - if(a<0) shortcol[2]= 0; else if(a>65535) shortcol[2]= 65535; else shortcol[2]= a; - } + shr->diff[0]= ma->r; + shr->diff[1]= ma->g; + shr->diff[2]= ma->b; return; } if( (ma->mode & (MA_VERTEXCOL+MA_VERTEXCOLP))== MA_VERTEXCOL ) { - ir= ma->emit+R.vcol[0]; - ig= ma->emit+R.vcol[1]; - ib= ma->emit+R.vcol[2]; + shr->diff[0]= ma->emit+R.vcol[0]; + shr->diff[1]= ma->emit+R.vcol[1]; + shr->diff[2]= ma->emit+R.vcol[2]; } - else ir= ig= ib= ma->emit; + else shr->diff[0]= shr->diff[1]= shr->diff[2]= ma->emit; for(a=0; ashb, inp); if(shadfac>0.0) { shadfac*= inp*soft*lar->energy; - ir -= shadfac; - ig -= shadfac; - ib -= shadfac; + shr->diff[0] -= shadfac; + shr->diff[1] -= shadfac; + shr->diff[2] -= shadfac; continue; } @@ -1839,9 +1833,9 @@ void shade_lamp_loop(int mask) } t= ma->spec*spec(t, ma->har); - isr+= t*(lar->r * ma->specr); - isg+= t*(lar->g * ma->specg); - isb+= t*(lar->b * ma->specb); + shr->spec[0]+= t*(lar->r * ma->specr); + shr->spec[1]+= t*(lar->g * ma->specg); + shr->spec[2]+= t*(lar->b * ma->specb); } else { /* specular shaders */ @@ -1858,93 +1852,55 @@ void shade_lamp_loop(int mask) t= shadfac*ma->spec*lampdist*specfac; - isr+= t*(lar->r * ma->specr); - isg+= t*(lar->g * ma->specg); - isb+= t*(lar->b * ma->specb); + shr->spec[0]+= t*(lar->r * ma->specr); + shr->spec[1]+= t*(lar->g * ma->specg); + shr->spec[2]+= t*(lar->b * ma->specb); } } } /* in case 'no diffuse' we still do most calculus, spec can be in shadow */ if(i>0.0 && !(lar->mode & LA_NO_DIFF)) { - ir+= i*lar->r; - ig+= i*lar->g; - ib+= i*lar->b; + shr->diff[0]+= i*lar->r; + shr->diff[1]+= i*lar->g; + shr->diff[2]+= i*lar->b; } } - - /* sum shading here, to make all variables local (because of raytrace) */ - if(ir<0.0) ir= 0.0; else ir*= ma->r; - ir+= ma->ambr +ma->amb*R.rad[0]; - - if(ig<0.0) ig= 0.0; else ig*= ma->g; - ig+= ma->ambg +ma->amb*R.rad[1]; - - if(ib<0.0) ib= 0.0; else ib*= ma->b; - ib+= ma->ambb +ma->amb*R.rad[2]; - - if(isr<0.0) isr= 0.0; - if(isg<0.0) isg= 0.0; - if(isb<0.0) isb= 0.0; - if(ma->mode & MA_ZTRA) { /* ztra shade */ + if(ma->mode & (MA_ZTRA|MA_RAYTRANSP)) { + if(ma->fresnel_tra!=0.0) + ma->alpha*= fresnel_fac(R.view, R.vn, ma->fresnel_tra, ma->falloff_tra); + if(ma->spectra!=0.0) { - t = MAX3(isr, isb, isg); + t = MAX3(shr->spec[0], shr->spec[1], shr->spec[2]); t *= ma->spectra; if(t>1.0) t= 1.0; - if(ma->mapto & MAP_ALPHA) ma->alpha= (1.0-t)*ma->alpha+t; - else ma->alpha= (1.0-t)*R.mat->alpha+t; + ma->alpha= (1.0-t)*ma->alpha+t; } } - /* Result of ray_mirror() is written in R.refcol. - Ugly is that shade_lamp_loop is called from within ray_mirror as well */ - if(R.r.mode & R_RAYTRACE) { - if(ma->ray_mirror!=0.0) { - static int only_once= 1; - if(only_once) { - float mirr= ma->mirr, mirg= ma->mirg, mirb= ma->mirb; - extern void ray_mirror(int); - - only_once= 0; - ray_mirror(mask); - only_once= 1; - - /* this is because the material mir color can be textured */ - ma->mirr= mirr; ma->mirb= mirb; ma->mirg= mirg; - } - } - } + shr->alpha= ma->alpha; + + if(shr->spec[0]<0.0) shr->spec[0]= 0.0; + if(shr->spec[1]<0.0) shr->spec[1]= 0.0; + if(shr->spec[2]<0.0) shr->spec[2]= 0.0; + + if(shr->diff[0]<0.0) shr->diff[0]= 0.0; else shr->diff[0]*= ma->r; + shr->diff[0]+= ma->ambr +ma->amb*R.rad[0]; - if(R.refcol[0]==0.0) { - a= 65535.0*( ir + isr); - if(a>65535) a=65535; else if(a<0) a= 0; - shortcol[0]= a; - a= 65535.0*(ig + isg); - if(a>65535) a=65535; else if(a<0) a= 0; - shortcol[1]= a; - a= 65535*(ib + isb); - if(a>65535) a=65535; else if(a<0) a= 0; - shortcol[2]= a; - } - else { - a= 65535.0*( ma->mirr*R.refcol[1] + (1.0 - ma->mirr*R.refcol[0])*ir +isr); - if(a>65535) a=65535; else if(a<0) a= 0; - shortcol[0]= a; - a= 65535.0*( ma->mirg*R.refcol[2] + (1.0 - ma->mirg*R.refcol[0])*ig +isg); - if(a>65535) a=65535; else if(a<0) a= 0; - shortcol[1]= a; - a= 65535.0*( ma->mirb*R.refcol[3] + (1.0 - ma->mirb*R.refcol[0])*ib +isb); - if(a>65535) a=65535; else if(a<0) a= 0; - shortcol[2]= a; + if(shr->diff[1]<0.0) shr->diff[1]= 0.0; else shr->diff[1]*= ma->g; + shr->diff[1]+= ma->ambg +ma->amb*R.rad[1]; + + if(shr->diff[2]<0.0) shr->diff[2]= 0.0; else shr->diff[2]*= ma->b; + shr->diff[2]+= ma->ambb +ma->amb*R.rad[2]; + + if(R.refcol[0]!=0.0) { + shr->diff[0]= ma->mirr*R.refcol[1] + (1.0 - ma->mirr*R.refcol[0])*shr->diff[0]; + shr->diff[1]= ma->mirg*R.refcol[2] + (1.0 - ma->mirg*R.refcol[0])*shr->diff[1]; + shr->diff[2]= ma->mirb*R.refcol[3] + (1.0 - ma->mirb*R.refcol[0])*shr->diff[2]; } - if(usegamtab) { - shortcol[0]= igamtab2[ shortcol[0] ]; - shortcol[1]= igamtab2[ shortcol[1] ]; - shortcol[2]= igamtab2[ shortcol[2] ]; - } } @@ -1955,6 +1911,7 @@ void shadepixel(float x, float y, int vlaknr, int mask) static VertRen *v1, *v2, *v3; static float t00, t01, t10, t11, dvlak, n1[3], n2[3], n3[3]; static float s00, s01, s10, s11; + ShadeResult shr; float *o1, *o2, *o3; float u, v, l, dl, hox, hoy, detsh, fac, deler, alpha; char *cp1, *cp2, *cp3; @@ -2350,7 +2307,33 @@ void shadepixel(float x, float y, int vlaknr, int mask) R.winco[1]= (y+(R.ystart))/(float)R.afmy; } - shade_lamp_loop(mask); + shade_lamp_loop(mask, &shr); + + if(R.r.mode & R_RAYTRACE) { + if(R.matren->ray_mirror!=0.0 || (R.mat->mode & MA_RAYTRANSP && shr.alpha!=1.0)) { + extern void ray_trace(int, ShadeResult *); + + ray_trace(mask, &shr); + } + } + + fac= shr.diff[0] + shr.spec[0]; + if(fac<=0.0) shortcol[0]= 0; else if(fac>=1.0) shortcol[0]= 65535; + else shortcol[0]= 65535.0*fac; + + fac= shr.diff[1] + shr.spec[1]; + if(fac<=0.0) shortcol[1]= 0; else if(fac>=1.0) shortcol[1]= 65535; + else shortcol[1]= 65535.0*fac; + + fac= shr.diff[2] + shr.spec[2]; + if(fac<=0.0) shortcol[2]= 0; else if(fac>=1.0) shortcol[2]= 65535; + else shortcol[2]= 65535.0*fac; + + if(usegamtab) { + shortcol[0]= igamtab2[ shortcol[0] ]; + shortcol[1]= igamtab2[ shortcol[1] ]; + shortcol[2]= igamtab2[ shortcol[2] ]; + } /* MIST */ if( (R.wrld.mode & WO_MIST) && (R.matren->mode & MA_NOMIST)==0 ){ @@ -2358,8 +2341,8 @@ void shadepixel(float x, float y, int vlaknr, int mask) } else alpha= 1.0; - if(R.matren->alpha!=1.0 || alpha!=1.0) { - fac= alpha*(R.matren->alpha); + if(shr.alpha!=1.0 || alpha!=1.0) { + fac= alpha*(shr.alpha); /* gamma */ if(R.osa && usegamtab) fac*= fac; diff --git a/source/blender/renderconverter/intern/convertBlenderScene.c b/source/blender/renderconverter/intern/convertBlenderScene.c index 3f20e1166f6..310000b8624 100644 --- a/source/blender/renderconverter/intern/convertBlenderScene.c +++ b/source/blender/renderconverter/intern/convertBlenderScene.c @@ -1660,7 +1660,7 @@ static void init_render_mesh(Object *ob) vlr->mat= ma; vlr->puno= mface->puno; vlr->flag= mface->flag; - if(me->flag & ME_NOPUNOFLIP) { + if((me->flag & ME_NOPUNOFLIP) || (ma->mode & MA_RAYTRANSP)) { vlr->flag |= R_NOPUNOFLIP; vlr->puno= 15; } @@ -2132,7 +2132,7 @@ static void init_render_surf(Object *ob) vlr->mat= matar[ dl->col]; vlr->ec= ME_V1V2+ME_V2V3; vlr->flag= dl->rt; - if(cu->flag & CU_NOPUNOFLIP) { + if( (cu->flag & CU_NOPUNOFLIP) || (vlr->mat->mode & MA_RAYTRANSP)) { vlr->flag |= R_NOPUNOFLIP; vlr->puno= 15; } @@ -2272,7 +2272,7 @@ static void init_render_surf(Object *ob) vlr->mat= matar[ dl->col]; vlr->ec= ME_V1V2+ME_V2V3; vlr->flag= dl->rt; - if(cu->flag & CU_NOPUNOFLIP) { + if( (cu->flag & CU_NOPUNOFLIP) || (vlr->mat->mode & MA_RAYTRANSP)) { vlr->flag |= R_NOPUNOFLIP; vlr->puno= 15; } diff --git a/source/blender/src/buttons_shading.c b/source/blender/src/buttons_shading.c index ec5b2710a01..452c5b4ccab 100644 --- a/source/blender/src/buttons_shading.c +++ b/source/blender/src/buttons_shading.c @@ -1662,15 +1662,23 @@ void do_lampbuts(unsigned short event) BIF_preview_changed(G.buts); } break; - case B_SBUFF: - { - la= G.buts->lockpoin; - la->bufsize = la->bufsize&=(~15); - allqueue(REDRAWBUTSSHADING, 0); - allqueue(REDRAWOOPS, 0); - /*la->bufsize = la->bufsize % 64;*/ - } + case B_SBUFF: + la= G.buts->lockpoin; + la->bufsize = la->bufsize&=(~15); + allqueue(REDRAWBUTSSHADING, 0); + allqueue(REDRAWOOPS, 0); break; + case B_SHADBUF: + la= G.buts->lockpoin; + la->mode &= ~LA_SHAD_RAY; + allqueue(REDRAWBUTSSHADING, 0); + allqueue(REDRAWVIEW3D, 0); + break; + case B_SHADRAY: + la= G.buts->lockpoin; + la->mode &= ~LA_SHAD; + allqueue(REDRAWBUTSSHADING, 0); + break; } if(event) freefastshade(); @@ -1816,8 +1824,8 @@ static void lamp_panel_spot(Object *ob, Lamp *la) uiBlockSetCol(block, TH_BUT_SETTING1); uiBlockBeginAlign(block); - uiDefButS(block, TOG|BIT|13, B_REDR,"Ray Shadow", 10,180,80,19,&la->mode, 0, 0, 0, 0, "Use ray tracing for shadow"); - uiDefButS(block, TOG|BIT|0, REDRAWVIEW3D, "Buf.Shadow",10,160,80,19,&la->mode, 0, 0, 0, 0, "Lets spotlight produce shadows using shadow buffer"); + uiDefButS(block, TOG|BIT|13, B_SHADRAY,"Ray Shadow", 10,180,80,19,&la->mode, 0, 0, 0, 0, "Use ray tracing for shadow"); + uiDefButS(block, TOG|BIT|0, B_SHADBUF, "Buf.Shadow",10,160,80,19,&la->mode, 0, 0, 0, 0, "Lets spotlight produce shadows using shadow buffer"); uiBlockEndAlign(block); uiDefButS(block, TOG|BIT|5, 0,"OnlyShadow", 10,120,80,19,&la->mode, 0, 0, 0, 0, "Causes spotlight to cast shadows only without illuminating objects"); @@ -2005,6 +2013,23 @@ void do_matbuts(unsigned short event) ma->lay= 1; scrarea_queue_winredraw(curarea); } + break; + case B_MATZTRANSP: + ma= G.buts->lockpoin; + if(ma) { + ma->mode &= ~MA_RAYTRANSP; + allqueue(REDRAWBUTSSHADING, 0); + BIF_preview_changed(G.buts); + } + break; + case B_MATRAYTRANSP: + ma= G.buts->lockpoin; + if(ma) { + ma->mode &= ~MA_ZTRA; + allqueue(REDRAWBUTSSHADING, 0); + BIF_preview_changed(G.buts); + } + break; } } @@ -2216,6 +2241,33 @@ static void material_panel_texture(Material *ma) uiBlockSetCol(block, TH_AUTO); } +static void material_panel_raytrace(Material *ma) +{ + uiBlock *block; + + block= uiNewBlock(&curarea->uiblocks, "material_panel_raytrace", UI_EMBOSS, UI_HELV, curarea->win); + uiNewPanelTabbed("Shaders", "Material"); + if(uiNewPanel(curarea, block, "Raytrace", "Material", 640, 0, 318, 204)==0) return; + + uiBlockBeginAlign(block); + uiDefButF(block, NUMSLI, B_MATPRV, "RayMir ", 10,160,200,19, &(ma->ray_mirror), 0.0, 1.0, 0, 2, "Sets the amount mirror reflection for raytrace"); + uiDefButS(block, NUM, B_MATPRV, "Depth:", 210,160,100,19, &(ma->ray_depth), 0.0, 6.0, 0, 0, "Amount of inter-reflections calculated maximal "); + uiDefButF(block, NUMSLI, B_MATPRV, "Fresnel ", 10,140,200,19, &(ma->fresnel_mir), 0.0, 1.0, 0, 2, "Sets Fresnel falloff for mirror reflection"); + uiDefButF(block, NUM, B_MATPRV, "Falloff ", 210,140,100,19, &(ma->falloff_mir), 0.0, 5.0, 0, 2, "Sets the falloff strength of Fresnel"); + + uiBlockBeginAlign(block); + uiDefButF(block, NUMSLI, B_MATPRV, "Ang Index ",10,80,200,19, &(ma->ang), 0.0, 1.0, 0, 2, "Sets the angular index of refraction for raytrace"); + uiDefButS(block, NUM, B_MATPRV, "Depth:", 210,80,100,19, &(ma->ray_depth_tra), 0.0, 6.0, 0, 0, "Amount of refractions calculated maximal "); + uiDefButF(block, NUMSLI, B_MATPRV, "Fresnel ", 10,60,200,19, &(ma->fresnel_tra), 0.0, 1.0, 0, 2, "Sets Fresnel falloff for transparency"); + uiDefButF(block, NUM, B_MATPRV, "Falloff ", 210,60,100,19, &(ma->falloff_tra), 0.0, 5.0, 0, 2, "Sets the falloff strength of Fresnel"); + uiBlockEndAlign(block); + + uiBlockSetCol(block, TH_BUT_SETTING1); + uiDefButI(block, TOG|BIT|18, B_MATPRV, "Ray Mirror", 160,185,150,19, &(ma->mode), 0, 0, 0, 0, "Enables raytracing for mirror reflection rendering"); + uiDefButI(block, TOG|BIT|17, B_MATRAYTRANSP,"Ray Transp",160,105,150,19, &(ma->mode), 0, 0, 0, 0, "Enables raytracing for transparency rendering"); + +} + static void material_panel_shading(Material *ma) { uiBlock *block; @@ -2287,13 +2339,9 @@ static void material_panel_shading(Material *ma) uiDefButF(block, NUMSLI, B_MATPRV, "Size:", 90, 100,150,19, &(ma->param[2]), 0.0, 1.53, 0, 0, "Sets the size of specular toon area"); uiDefButF(block, NUMSLI, B_MATPRV, "Smooth:",90, 80,150,19, &(ma->param[3]), 0.0, 1.0, 0, 0, "Sets the smoothness of specular toon area"); } - + uiBlockEndAlign(block); /* default shading variables */ - uiBlockBeginAlign(block); - uiDefButF(block, NUMSLI, 0, "RayMir ", 9,55,154,19, &(ma->ray_mirror), 0.0, 1.0, 0, 0, "Sets the amount mirror reflection for raytrace"); - uiDefButS(block, NUM, 0, "Depth:", 163,55,80,19, &(ma->ray_depth), 0.0, 6.0, 0, 0, "Amount of inter-reflections calculated maximal "); - uiBlockEndAlign(block); uiDefButF(block, NUMSLI, B_MATPRV, "Amb ", 9,30,117,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 ", 133,30,110,19, &(ma->emit), 0.0, 1.0, 0, 0, "Sets the amount of light the material emits"); uiDefButF(block, NUMSLI, B_MATPRV, "Add ", 9,10,117,19, &(ma->add), 0.0, 1.0, 0, 0, "Sets a glow factor for transparant materials"); @@ -2305,7 +2353,7 @@ static void material_panel_shading(Material *ma) uiDefButI(block, TOG|BIT|1, 0, "Shadow", 245,142,65,18, &(ma->mode), 0, 0, 0, 0, "Makes material receive shadows from spotlights"); uiDefButI(block, TOG|BIT|16, 0, "Radio", 245,123,65,18, &(ma->mode), 0, 0, 0, 0, "Enables material for radiosty rendering"); uiDefButI(block, TOG|BIT|3, 0, "Wire", 245,104,65,18, &(ma->mode), 0, 0, 0, 0, "Renders only the edges of faces as a wireframe"); - uiDefButI(block, TOG|BIT|6, 0, "ZTransp", 245,85, 65,18, &(ma->mode), 0, 0, 0, 0, "Enables Z-Buffering of transparent faces"); + uiDefButI(block, TOG|BIT|6, B_MATZTRANSP,"ZTransp", 245,85, 65,18, &(ma->mode), 0, 0, 0, 0, "Enables Z-Buffering of transparent faces"); uiDefButI(block, TOG|BIT|9, 0, "Env", 245,66, 65,18, &(ma->mode), 0, 0, 0, 0, "Causes faces to disappear: allows world to show through"); uiDefButI(block, TOG|BIT|10, 0, "OnlyShadow", 245,47, 65,18, &(ma->mode), 0, 0, 0, 0, "Renders shadows falling on material only"); uiDefButI(block, TOG|BIT|14, 0, "No Mist", 245,28, 65,18, &(ma->mode), 0, 0, 0, 0, "Sets the material to ignore mist values"); @@ -2482,6 +2530,7 @@ void material_panels() if(ma) { material_panel_shading(ma); + material_panel_raytrace(ma); material_panel_texture(ma); mtex= ma->mtex[ ma->texact ]; diff --git a/source/blender/src/previewrender.c b/source/blender/src/previewrender.c index 5b4bff52cb2..0b302a40602 100644 --- a/source/blender/src/previewrender.c +++ b/source/blender/src/previewrender.c @@ -86,8 +86,8 @@ #include "RE_renderconverter.h" -#define PR_RECTX 121 -#define PR_RECTY 121 +#define PR_RECTX 141 +#define PR_RECTY 141 #define PR_XMIN 10 #define PR_YMIN 5 #define PR_XMAX 200 @@ -219,6 +219,14 @@ static int ray_previewrender(int x, static unsigned int previewback(int type, int x, int y) { + + /* checkerboard, for later + x+= PR_RECTX/2; + y+= PR_RECTX/2; + if( ((x/24) + (y/24)) & 1) return 0x40404040; + else return 0xa0a0a0a0; + */ + if(type & MA_DARK) { if(abs(x)>abs(y)) return 0; else return 0x40404040; @@ -667,8 +675,40 @@ static float pr2_lamp[3]= {-8.8, -5.6, -1.5}; static float pr1_col[3]= {0.8, 0.8, 0.8}; static float pr2_col[3]= {0.5, 0.6, 0.7}; +static void refraction_prv(int *x, int *y, float *n, float index) +{ + float dot, fac, view[3], len; + + + if(index==0.0) return; + + view[0]= index*(float)*x; + view[1]= ((float)*y)/index; + view[2]= 20.0; + len= Normalise(view); + + dot= view[0]*n[0] + view[1]*n[1] + view[2]*n[2]; + + if(dot>0.0) { + fac= 1.0 - (1.0 - dot*dot)*index*index; + if(fac<= 0.0) return; + fac= -dot*index + sqrt(fac); + } + else { + index = 1.0/index; + fac= 1.0 - (1.0 - dot*dot)*index*index; + if(fac<= 0.0) return; + fac= -dot*index - sqrt(fac); + } + + *x= (int)(len*(index*view[0] + fac*n[0])); + *y= (int)(len*(index*view[1] + fac*n[1])); +} + + static void shade_preview_pixel(float *vec, int x, int y,char *rect, int smooth) { + extern float fresnel_fac(float *view, float *vn, float fresnel, float falloff); Material *mat; float v1,inp, inprspec=0, isr=0.0, isb=0.0, isg=0.0; float ir=0.0, ib=0.0, ig=0.0; @@ -678,13 +718,6 @@ static void shade_preview_pixel(float *vec, int x, int y,char *rect, int smooth) char tracol; mat= R.matren; - /* pr1_lamp[0]= mat->mtex[0]->ofs[0]; */ - /* pr1_lamp[1]= mat->mtex[0]->ofs[1]; */ - /* pr1_lamp[2]= mat->mtex[0]->ofs[2]; */ - - /* pr2_lamp[0]= mat->mtex[0]->size[0]; */ - /* pr2_lamp[1]= mat->mtex[0]->size[1]; */ - /* pr2_lamp[2]= mat->mtex[0]->size[2]; */ v1= 1.0/PR_RECTX; view[0]= v1*x; @@ -738,7 +771,8 @@ static void shade_preview_pixel(float *vec, int x, int y,char *rect, int smooth) inp= -2.0*(R.vn[0]*view[0]+R.vn[1]*view[1]+R.vn[2]*view[2]); R.ref[0]= (view[0]+inp*R.vn[0]); - R.ref[1]= -(view[1]+inp*R.vn[1]); + R.ref[1]= (view[1]+inp*R.vn[1]); + if(smooth) R.ref[1]= -R.ref[1]; R.ref[2]= (view[2]+inp*R.vn[2]); } @@ -815,6 +849,38 @@ static void shade_preview_pixel(float *vec, int x, int y,char *rect, int smooth) ig+= inp*la[1]; ib+= inp*la[2]; } + + /* drawing checkerboard and sky */ + if(mat->mode & MA_RAYMIRROR) { + float col, div, y, z; + int fac; + + /* rotate a bit in x */ + y= R.ref[1]; z= R.ref[2]; + R.ref[1]= 0.98*y - 0.17*z; + R.ref[2]= 0.17*y + 0.98*z; + + /* scale */ + div= (0.85*R.ref[1]); + + R.refcol[0]= mat->ray_mirror*fresnel_fac(view, R.vn, mat->fresnel_mir, mat->falloff_mir);; + + if(div<0.0) { + /* minus 0.5 prevents too many small tiles in distance */ + fac= (int)(R.ref[0]/(div-0.1) ) + (int)(R.ref[2]/(div-0.1) ); + if(fac & 1) col= 0.8; + else col= 0.3; + + R.refcol[1]= R.refcol[0]*col; + R.refcol[2]= R.refcol[1]; + R.refcol[3]= R.refcol[2]; + } + else { + R.refcol[1]= 0.0; + R.refcol[2]= R.refcol[0]*0.3*div; + R.refcol[3]= R.refcol[0]*0.8*div; + } + } if(R.refcol[0]==0.0) { a= 255.0*( mat->r*ir +mat->ambr +isr); @@ -840,18 +906,25 @@ static void shade_preview_pixel(float *vec, int x, int y,char *rect, int smooth) } } - if(mat->alpha!=1.0) { - - alpha= mat->alpha; - - /* ztra shade */ - if(mat->spectra!=0.0) { - inp= mat->spectra*inprspec; - if(inp>1.0) inp= 1.0; - - alpha= (1.0-inp)*alpha+ inp; + alpha= mat->alpha; + + if(mat->mode & (MA_ZTRA|MA_RAYTRANSP)) + if(mat->fresnel_tra!=0.0) + alpha*= fresnel_fac(view, R.vn, mat->fresnel_tra, mat->falloff_tra); + + /* ztra shade */ + if(mat->spectra!=0.0) { + inp = MAX3(isr, isg, isb); + inp *= mat->spectra; + if(inp>1.0) inp= 1.0; + alpha= (1.0-inp)*alpha+inp; + } + + if(alpha!=1.0) { + if(mat->mode & MA_RAYTRANSP) { + refraction_prv(&x, &y, R.vn, mat->ang); } - + tracol= previewback(mat->pr_back, x, y) & 255; tracol= (1.0-alpha)*tracol; @@ -859,7 +932,6 @@ static void shade_preview_pixel(float *vec, int x, int y,char *rect, int smooth) rect[0]= tracol+ (rect[0]*alpha) ; rect[1]= tracol+ (rect[1]*alpha) ; rect[2]= tracol+ (rect[2]*alpha) ; - } } @@ -924,6 +996,7 @@ void BIF_previewrender(SpaceButs *sbuts) MTC_Mat4One(R.viewinv); R.osatex= 0; + if(mat) { /* rendervars */ init_render_world();