Added color filtering for raytrace transparency.
http://www.blender3d.org/cms/Transparent_filtering.514.0.html Choice was for using a single (new) filter value and have it working OK with existing alpha.
This commit is contained in:
@@ -64,6 +64,7 @@ typedef struct Material {
|
||||
float translucency;
|
||||
float fresnel_mir, fresnel_mir_i;
|
||||
float fresnel_tra, fresnel_tra_i;
|
||||
float filter, pad0; /* filter added, for raytrace transparency */
|
||||
short ray_depth, ray_depth_tra;
|
||||
short har;
|
||||
char seed1, seed2;
|
||||
|
||||
@@ -1457,7 +1457,9 @@ static void traceray(short depth, float *start, float *vec, float *col, VlakRen
|
||||
if(depth>0) {
|
||||
|
||||
if(shi.mat->mode & (MA_RAYTRANSP|MA_ZTRA) && shr.alpha!=1.0) {
|
||||
float f, f1, refract[3], tracol[3];
|
||||
float f, f1, refract[3], tracol[4];
|
||||
|
||||
tracol[3]= col[3]; // we pass on and accumulate alpha
|
||||
|
||||
if(shi.mat->mode & MA_RAYTRANSP) {
|
||||
/* odd depths: use normal facing viewer, otherwise flip */
|
||||
@@ -1478,16 +1480,21 @@ static void traceray(short depth, float *start, float *vec, float *col, VlakRen
|
||||
traceray(depth-1, shi.co, shi.view, tracol, shi.vlr, shi.mask, osatex, 0);
|
||||
|
||||
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];
|
||||
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);
|
||||
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];
|
||||
|
||||
shr.spec[0] *=f;
|
||||
shr.spec[1] *=f;
|
||||
shr.spec[2] *=f;
|
||||
|
||||
shr.alpha= 1.0;
|
||||
|
||||
col[3]= f1*tracol[3] + f;
|
||||
}
|
||||
else
|
||||
col[3]= 1.0;
|
||||
|
||||
if(shi.mat->mode & MA_RAYMIRROR) {
|
||||
f= shi.ray_mirror;
|
||||
@@ -1496,9 +1503,10 @@ static void traceray(short depth, float *start, float *vec, float *col, VlakRen
|
||||
else f= 0.0;
|
||||
|
||||
if(f!=0.0) {
|
||||
|
||||
float mircol[4];
|
||||
|
||||
reflection(ref, shi.vn, shi.view, NULL);
|
||||
traceray(depth-1, shi.co, ref, col, shi.vlr, shi.mask, osatex, 0);
|
||||
traceray(depth-1, shi.co, ref, mircol, shi.vlr, shi.mask, osatex, 0);
|
||||
|
||||
f1= 1.0-f;
|
||||
|
||||
@@ -1512,9 +1520,9 @@ static void traceray(short depth, float *start, float *vec, float *col, VlakRen
|
||||
fg= shi.mirg;
|
||||
fb= shi.mirb;
|
||||
|
||||
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];
|
||||
col[0]= f*fr*(1.0-shr.spec[0])*mircol[0] + f1*shr.diff[0] + shr.spec[0];
|
||||
col[1]= f*fg*(1.0-shr.spec[1])*mircol[1] + f1*shr.diff[1] + shr.spec[1];
|
||||
col[2]= f*fb*(1.0-shr.spec[2])*mircol[2] + f1*shr.diff[2] + shr.spec[2];
|
||||
}
|
||||
else {
|
||||
col[0]= shr.diff[0] + shr.spec[0];
|
||||
@@ -1530,7 +1538,6 @@ static void traceray(short depth, float *start, float *vec, float *col, VlakRen
|
||||
|
||||
}
|
||||
else { /* sky */
|
||||
|
||||
VECCOPY(shi.view, vec);
|
||||
Normalise(shi.view);
|
||||
|
||||
@@ -1676,7 +1683,7 @@ static float *jitter_plane(LampRen *lar, int xs, int ys)
|
||||
void ray_trace(ShadeInput *shi, ShadeResult *shr)
|
||||
{
|
||||
VlakRen *vlr;
|
||||
float i, f, f1, fr, fg, fb, vec[3], mircol[3], tracol[3];
|
||||
float i, f, f1, fr, fg, fb, vec[3], mircol[4], tracol[4];
|
||||
int do_tra, do_mir;
|
||||
|
||||
do_tra= ((shi->mat->mode & (MA_RAYTRANSP|MA_ZTRA)) && shr->alpha!=1.0);
|
||||
@@ -1686,6 +1693,8 @@ void ray_trace(ShadeInput *shi, ShadeResult *shr)
|
||||
if(do_tra) {
|
||||
float refract[3];
|
||||
|
||||
tracol[3]= shr->alpha;
|
||||
|
||||
if(shi->mat->mode & MA_RAYTRANSP) {
|
||||
refraction(refract, shi->vn, shi->view, shi->ang);
|
||||
traceray(shi->mat->ray_depth_tra, shi->co, refract, tracol, shi->vlr, shi->mask, 0, RAY_TRA|RAY_TRAFLIP);
|
||||
@@ -1694,10 +1703,14 @@ void ray_trace(ShadeInput *shi, ShadeResult *shr)
|
||||
traceray(shi->mat->ray_depth_tra, shi->co, shi->view, tracol, shi->vlr, shi->mask, 0, 0);
|
||||
|
||||
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;
|
||||
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);
|
||||
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];
|
||||
|
||||
shr->alpha= tracol[3];
|
||||
}
|
||||
|
||||
if(do_mir) {
|
||||
@@ -1727,29 +1740,31 @@ void ray_trace(ShadeInput *shi, ShadeResult *shr)
|
||||
}
|
||||
}
|
||||
|
||||
/* no premul here! */
|
||||
static void addAlphaLight(float *old, float *over)
|
||||
/* color 'shadfac' passes through 'col' with alpha and filter */
|
||||
/* filter is only applied on alpha defined transparent part */
|
||||
static void addAlphaLight(float *shadfac, float *col, float alpha, float filter)
|
||||
{
|
||||
float div= old[3]+over[3];
|
||||
|
||||
if(div > 0.0001) {
|
||||
old[0]= (over[3]*over[0] + old[3]*old[0])/div;
|
||||
old[1]= (over[3]*over[1] + old[3]*old[1])/div;
|
||||
old[2]= (over[3]*over[2] + old[3]*old[2])/div;
|
||||
}
|
||||
old[3]= over[3] + (1-over[3])*old[3];
|
||||
|
||||
float fr, fg, fb;
|
||||
|
||||
fr= 1.0+ filter*(col[0]-1.0);
|
||||
fg= 1.0+ filter*(col[1]-1.0);
|
||||
fb= 1.0+ filter*(col[2]-1.0);
|
||||
|
||||
shadfac[0]= alpha*col[0] + fr*(1.0-alpha)*shadfac[0];
|
||||
shadfac[1]= alpha*col[1] + fg*(1.0-alpha)*shadfac[1];
|
||||
shadfac[2]= alpha*col[2] + fb*(1.0-alpha)*shadfac[2];
|
||||
|
||||
shadfac[3]= (1.0-alpha)*shadfac[3];
|
||||
}
|
||||
|
||||
static void ray_trace_shadow_tra(Isect *is, int depth)
|
||||
{
|
||||
/* ray to lamp, find first face that intersects, check alpha properties,
|
||||
if it has alpha<1 continue. exit when alpha is full */
|
||||
if it has col[3]>0.0 continue. so exit when alpha is full */
|
||||
ShadeInput shi;
|
||||
ShadeResult shr;
|
||||
|
||||
if( d3dda(is)) {
|
||||
float col[4];
|
||||
/* we got a face */
|
||||
|
||||
shi.mask= 1;
|
||||
@@ -1758,12 +1773,10 @@ static void ray_trace_shadow_tra(Isect *is, int depth)
|
||||
|
||||
shade_ray(is, &shi, &shr);
|
||||
|
||||
/* add color */
|
||||
VECCOPY(col, shr.diff);
|
||||
col[3]= shr.alpha;
|
||||
addAlphaLight(is->col, col);
|
||||
|
||||
if(depth>0 && is->col[3]<1.0) {
|
||||
/* mix colors based on shadfac (rgb + amount of light factor) */
|
||||
addAlphaLight(is->col, shr.diff, shr.alpha, shi.mat->filter);
|
||||
|
||||
if(depth>0 && is->col[3]>0.0) {
|
||||
|
||||
/* adapt isect struct */
|
||||
VECCOPY(is->start, shi.co);
|
||||
@@ -1771,8 +1784,6 @@ static void ray_trace_shadow_tra(Isect *is, int depth)
|
||||
|
||||
ray_trace_shadow_tra(is, depth-1);
|
||||
}
|
||||
else if(is->col[3]>1.0) is->col[3]= 1.0;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2102,17 +2113,13 @@ void ray_shadow(ShadeInput *shi, LampRen *lar, float *shadfac)
|
||||
VECCOPY(isec.end, lampco);
|
||||
|
||||
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.0;
|
||||
isec.col[3]= 0.0; //alpha
|
||||
isec.col[3]= 1.0;
|
||||
|
||||
ray_trace_shadow_tra(&isec, DEPTH_SHADOW_TRA);
|
||||
|
||||
VECCOPY(shadfac, isec.col);
|
||||
// alpha to 'light'
|
||||
shadfac[3]= 1.0-isec.col[3];
|
||||
shadfac[0]= shadfac[3]+shadfac[0]*isec.col[3];
|
||||
shadfac[1]= shadfac[3]+shadfac[1]*isec.col[3];
|
||||
shadfac[2]= shadfac[3]+shadfac[2]*isec.col[3];
|
||||
QUATCOPY(shadfac, isec.col);
|
||||
//printf("shadfac %f %f %f %f\n", shadfac[0], shadfac[1], shadfac[2], shadfac[3]);
|
||||
}
|
||||
else if( d3dda(&isec)) shadfac[3]= 0.0;
|
||||
}
|
||||
|
||||
@@ -2189,9 +2189,15 @@ void *shadepixel(float x, float y, int z, int facenr, int mask, float *col)
|
||||
else alpha= 1.0;
|
||||
|
||||
if(shr.alpha!=1.0 || alpha!=1.0) {
|
||||
fac= alpha*(shr.alpha);
|
||||
|
||||
col[3]= fac;
|
||||
if(shi.mat->mode & MA_RAYTRANSP) {
|
||||
// sky was applied allready for ray transp, only do mist
|
||||
col[3]= shr.alpha;
|
||||
fac= alpha;
|
||||
}
|
||||
else {
|
||||
fac= alpha*(shr.alpha);
|
||||
col[3]= fac;
|
||||
}
|
||||
col[0]*= fac;
|
||||
col[1]*= fac;
|
||||
col[2]*= fac;
|
||||
@@ -2233,10 +2239,15 @@ void *shadepixel(float x, float y, int z, int facenr, int mask, float *col)
|
||||
|
||||
static void shadepixel_sky(float x, float y, int z, int facenr, int mask, float *colf)
|
||||
{
|
||||
VlakRen *vlr;
|
||||
float collector[4];
|
||||
|
||||
shadepixel(x, y, z, facenr, mask, colf);
|
||||
vlr= shadepixel(x, y, z, facenr, mask, colf);
|
||||
if(colf[3] != 1.0) {
|
||||
/* bail out when raytrace transparency (sky included already) */
|
||||
if(vlr && (R.r.mode & R_RAYTRACE))
|
||||
if(vlr->mat->mode & MA_RAYTRANSP) return;
|
||||
|
||||
renderSkyPixelFloat(collector, x, y);
|
||||
addAlphaOverFloat(collector, colf);
|
||||
QUATCOPY(colf, collector);
|
||||
|
||||
@@ -2316,7 +2316,7 @@ void abufsetrow(float *acolrow, int y)
|
||||
APixstr *ap, *apn;
|
||||
float *col, fcol[4], tempcol[4], sampcol[16*4], *scol, accumcol[4];
|
||||
float ys, fac, alpha[32];
|
||||
int x, part, a, zrow[100][3], totvlak, nr;
|
||||
int x, part, a, zrow[100][3], totface, nr;
|
||||
int sval;
|
||||
|
||||
if(y<0) return;
|
||||
@@ -2363,22 +2363,22 @@ void abufsetrow(float *acolrow, int y)
|
||||
for(x=0; x<R.rectx; x++, col+=4, ap++) {
|
||||
if(ap->p[0]) {
|
||||
/* sort in z */
|
||||
totvlak= 0;
|
||||
totface= 0;
|
||||
apn= ap;
|
||||
while(apn) {
|
||||
for(a=0; a<4; a++) {
|
||||
if(apn->p[a]) {
|
||||
zrow[totvlak][0]= apn->z[a];
|
||||
zrow[totvlak][1]= apn->p[a];
|
||||
zrow[totvlak][2]= apn->mask[a];
|
||||
totvlak++;
|
||||
if(totvlak>99) totvlak= 99;
|
||||
zrow[totface][0]= apn->z[a];
|
||||
zrow[totface][1]= apn->p[a];
|
||||
zrow[totface][2]= apn->mask[a];
|
||||
totface++;
|
||||
if(totface>99) totface= 99;
|
||||
}
|
||||
else break;
|
||||
}
|
||||
apn= apn->next;
|
||||
}
|
||||
if(totvlak==1) {
|
||||
if(totface==1) {
|
||||
|
||||
shadetrapixel((float)x, (float)y, ap->z[0], ap->p[0], ap->mask[0], fcol);
|
||||
|
||||
@@ -2399,7 +2399,7 @@ void abufsetrow(float *acolrow, int y)
|
||||
}
|
||||
else {
|
||||
|
||||
if(totvlak==2) {
|
||||
if(totface==2) {
|
||||
if(zrow[0][0] < zrow[1][0]) {
|
||||
a= zrow[0][0]; zrow[0][0]= zrow[1][0]; zrow[1][0]= a;
|
||||
a= zrow[0][1]; zrow[0][1]= zrow[1][1]; zrow[1][1]= a;
|
||||
@@ -2407,31 +2407,31 @@ void abufsetrow(float *acolrow, int y)
|
||||
}
|
||||
|
||||
}
|
||||
else { /* totvlak>2 */
|
||||
qsort(zrow, totvlak, sizeof(int)*3, vergzvlak);
|
||||
else { /* totface>2 */
|
||||
qsort(zrow, totface, sizeof(int)*3, vergzvlak);
|
||||
}
|
||||
|
||||
/* join when pixels are adjacent */
|
||||
|
||||
while(totvlak>0) {
|
||||
totvlak--;
|
||||
while(totface>0) {
|
||||
totface--;
|
||||
|
||||
shadetrapixel((float)x, (float)y, zrow[totvlak][0], zrow[totvlak][1], zrow[totvlak][2], fcol);
|
||||
shadetrapixel((float)x, (float)y, zrow[totface][0], zrow[totface][1], zrow[totface][2], fcol);
|
||||
|
||||
a= count_mask(zrow[totvlak][2]);
|
||||
a= count_mask(zrow[totface][2]);
|
||||
if( (R.r.mode & R_OSA ) && a<R.osa) {
|
||||
if(totvlak>0) {
|
||||
if(totface>0) {
|
||||
memset(sampcol, 0, 4*sizeof(float)*R.osa);
|
||||
sval= addtosampcol(sampcol, fcol, zrow[totvlak][2]);
|
||||
sval= addtosampcol(sampcol, fcol, zrow[totface][2]);
|
||||
|
||||
/* sval==0: alpha completely full */
|
||||
while( (sval != 0) && (totvlak>0) ) {
|
||||
a= count_mask(zrow[totvlak-1][2]);
|
||||
while( (sval != 0) && (totface>0) ) {
|
||||
a= count_mask(zrow[totface-1][2]);
|
||||
if(a==R.osa) break;
|
||||
totvlak--;
|
||||
totface--;
|
||||
|
||||
shadetrapixel((float)x, (float)y, zrow[totvlak][0], zrow[totvlak][1], zrow[totvlak][2], fcol);
|
||||
sval= addtosampcol(sampcol, fcol, zrow[totvlak][2]);
|
||||
shadetrapixel((float)x, (float)y, zrow[totface][0], zrow[totface][1], zrow[totface][2], fcol);
|
||||
sval= addtosampcol(sampcol, fcol, zrow[totface][2]);
|
||||
}
|
||||
scol= sampcol;
|
||||
accumcol[0]= scol[0]; accumcol[1]= scol[1];
|
||||
|
||||
@@ -2789,7 +2789,10 @@ static void material_panel_tramir(Material *ma)
|
||||
uiDefButF(block, NUMSLI, B_MATPRV, "Fac ", 170,140,140,20, &(ma->fresnel_mir_i), 1.0, 5.0, 10, 2, "Blending factor for Fresnel");
|
||||
|
||||
uiBlockBeginAlign(block);
|
||||
uiDefButF(block, NUM, B_DIFF, "Zoffs:", 10,110,100,20, &(ma->zoffs), 0.0, 10.0, 0, 0, "Gives faces an artificial offset in the Z buffer for Ztransp option");
|
||||
if(ma->mode & MA_RAYTRANSP)
|
||||
uiDefButF(block, NUM, B_MATPRV, "Filt:", 10,110,100,20, &(ma->filter), 0.0, 1.0, 0, 0, "Amount of filtering for transparent raytrace");
|
||||
else
|
||||
uiDefButF(block, NUM, B_DIFF, "Zoffs:", 10,110,100,20, &(ma->zoffs), 0.0, 10.0, 0, 0, "Gives faces an artificial offset in the Z buffer for Ztransp option");
|
||||
uiDefButI(block, TOG|BIT|6, B_MATZTRANSP,"ZTransp", 110,110,100,20, &(ma->mode), 0, 0, 0, 0, "Enables Z-Buffering of transparent faces");
|
||||
uiDefButI(block, TOG|BIT|17, B_MATRAYTRANSP,"Ray Transp",210,110,100,20, &(ma->mode), 0, 0, 0, 0, "Enables raytracing for transparency rendering");
|
||||
|
||||
|
||||
@@ -994,9 +994,19 @@ static void shade_preview_pixel(ShadeInput *shi, float *vec, int x, int y,char *
|
||||
|
||||
tracol= (1.0-alpha)*tracol;
|
||||
|
||||
rect[0]= tracol+ (rect[0]*alpha) ;
|
||||
rect[1]= tracol+ (rect[1]*alpha) ;
|
||||
rect[2]= tracol+ (rect[2]*alpha) ;
|
||||
if((mat->mode & MA_RAYTRANSP) && mat->filter!=0.0) {
|
||||
float fr= 1.0+ mat->filter*(shi->r-1.0);
|
||||
rect[0]= fr*tracol+ (rect[0]*alpha) ;
|
||||
fr= 1.0+ mat->filter*(shi->g-1.0);
|
||||
rect[1]= fr*tracol+ (rect[1]*alpha) ;
|
||||
fr= 1.0+ mat->filter*(shi->b-1.0);
|
||||
rect[2]= fr*tracol+ (rect[2]*alpha) ;
|
||||
}
|
||||
else {
|
||||
rect[0]= tracol+ (rect[0]*alpha) ;
|
||||
rect[1]= tracol+ (rect[1]*alpha) ;
|
||||
rect[2]= tracol+ (rect[2]*alpha) ;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user