Index: source/blender/render/intern/source/ray.c =================================================================== RCS file: /cvsroot/bf-blender/blender/source/blender/render/intern/source/ray.c,v retrieving revision 1.66 diff -u -b -B -u -r1.66 ray.c --- source/blender/render/intern/source/ray.c 29 Nov 2005 20:18:31 -0000 1.66 +++ source/blender/render/intern/source/ray.c 28 Dec 2005 04:12:46 -0000 @@ -1442,30 +1442,31 @@ } -static void refraction(float *refract, float *n, float *view, float index) +static int refraction(float *refract, float *n, float *view, float index) { float dot, fac; VECCOPY(refract, view); - index= 1.0/index; dot= view[0]*n[0] + view[1]*n[1] + view[2]*n[2]; if(dot>0.0) { + index = 1.0/index; fac= 1.0 - (1.0 - dot*dot)*index*index; - if(fac<= 0.0) return; + if(fac<= 0.0) return 0; fac= -dot*index + sqrt(fac); } else { - index = 1.0/index; fac= 1.0 - (1.0 - dot*dot)*index*index; - if(fac<= 0.0) return; + if(fac<= 0.0) return 0; 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]; + + return 1; } /* orn = original face normal */ @@ -1512,6 +1513,25 @@ } #endif +static float shade_by_transmission(Isect *is, ShadeInput *shi, ShadeResult *shr) +{ + float dx, dy, dz, d; + + if (0 == (shi->mat->mode & (MA_RAYTRANSP|MA_ZTRA))) + return -1; + + /* 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); + + shr->alpha *= d; + if (shr->alpha > 1.0) shr->alpha= 1.0; + + return d; +} + /* the main recursive tracer itself */ static void traceray(short depth, float *start, float *vec, float *col, VlakRen *vlr, int mask, int osatex, int traflag) { @@ -1529,18 +1549,24 @@ isec.vlrorig= vlr; if( d3dda(&isec) ) { + float d= 1.0; shi.mask= mask; shi.osatex= osatex; shi.depth= 1; // only now to indicate tracing shade_ray(&isec, &shi, &shr); + if (traflag & RAY_TRA) + d= shade_by_transmission(&isec, &shi, &shr); if(depth>0) { - if(shi.mat->mode & (MA_RAYTRANSP|MA_ZTRA) && shr.alpha!=1.0) { - float f, f1, refract[3], tracol[4]; + if(shi.mat->mode & (MA_RAYTRANSP|MA_ZTRA) && shr.alpha < 1.0) { + float nf, f, f1, refract[3], tracol[4]; + tracol[0]= shi.r; + tracol[1]= shi.g; + tracol[2]= shi.b; tracol[3]= col[3]; // we pass on and accumulate alpha if(shi.mat->mode & MA_RAYTRANSP) { @@ -1550,10 +1576,12 @@ norm[0]= - shi.vn[0]; norm[1]= - shi.vn[1]; norm[2]= - shi.vn[2]; - refraction(refract, norm, shi.view, shi.ang); + if (!refraction(refract, norm, shi.view, shi.ang)) + reflection(refract, norm, shi.view, shi.vn); } else { - refraction(refract, shi.vn, shi.view, shi.ang); + if (!refraction(refract, shi.vn, shi.view, shi.ang)) + reflection(refract, shi.vn, shi.view, shi.vn); } traflag |= RAY_TRA; traceray(depth-1, shi.co, refract, tracol, shi.vlr, shi.mask, osatex, traflag ^ RAY_TRAFLIP); @@ -1562,9 +1590,10 @@ traceray(depth-1, shi.co, shi.view, tracol, shi.vlr, shi.mask, osatex, 0); f= shr.alpha; f1= 1.0-f; - fr= 1.0+ shi.mat->filter*(shi.r-1.0); - fg= 1.0+ shi.mat->filter*(shi.g-1.0); - fb= 1.0+ shi.mat->filter*(shi.b-1.0); + nf= d * shi.mat->filter; + fr= 1.0+ nf*(shi.r-1.0); + fg= 1.0+ nf*(shi.g-1.0); + fb= 1.0+ nf*(shi.b-1.0); shr.diff[0]= f*shr.diff[0] + f1*fr*tracol[0]; shr.diff[1]= f*shr.diff[1] + f1*fg*tracol[1]; shr.diff[2]= f*shr.diff[2] + f1*fb*tracol[2]; @@ -1824,7 +1853,7 @@ shadfac[3]= (1.0-alpha)*shadfac[3]; } -static void ray_trace_shadow_tra(Isect *is, int depth) +static void ray_trace_shadow_tra(Isect *is, int depth, int traflag) { /* ray to lamp, find first face that intersects, check alpha properties, if it has col[3]>0.0 continue. so exit when alpha is full */ @@ -1832,6 +1861,7 @@ ShadeResult shr; if( d3dda(is)) { + float d= 1.0; /* we got a face */ shi.mask= 1; @@ -1839,9 +1869,11 @@ shi.depth= 1; // only now to indicate tracing shade_ray(is, &shi, &shr); + if (traflag & RAY_TRA) + d= shade_by_transmission(is, &shi, &shr); /* mix colors based on shadfac (rgb + amount of light factor) */ - addAlphaLight(is->col, shr.diff, shr.alpha, shi.mat->filter); + addAlphaLight(is->col, shr.diff, shr.alpha, d*shi.mat->filter); if(depth>0 && is->col[3]>0.0) { @@ -1849,7 +1881,7 @@ VECCOPY(is->start, shi.co); is->vlrorig= shi.vlr; - ray_trace_shadow_tra(is, depth-1); + ray_trace_shadow_tra(is, depth-1, traflag | RAY_TRA); } } } @@ -2184,7 +2216,7 @@ isec.col[0]= isec.col[1]= isec.col[2]= 1.0; isec.col[3]= 1.0; - ray_trace_shadow_tra(&isec, DEPTH_SHADOW_TRA); + ray_trace_shadow_tra(&isec, DEPTH_SHADOW_TRA, 0); QUATCOPY(shadfac, isec.col); //printf("shadfac %f %f %f %f\n", shadfac[0], shadfac[1], shadfac[2], shadfac[3]); } @@ -2240,7 +2272,7 @@ isec.col[0]= isec.col[1]= isec.col[2]= 1.0; isec.col[3]= 1.0; - ray_trace_shadow_tra(&isec, DEPTH_SHADOW_TRA); + ray_trace_shadow_tra(&isec, DEPTH_SHADOW_TRA, 0); shadfac[0] += isec.col[0]; shadfac[1] += isec.col[1]; shadfac[2] += isec.col[2];