Graphics source in C: hsalgs/hiq_pxls.c
Ken Turkowski
ken at turtleva.UUCP
Fri Dec 16 13:25:47 AEST 1983
echo x - hsalgs/hiq_pxls.c
cat >hsalgs/hiq_pxls.c <<'!Funky!Stuff!'
/* ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
hiq_pxls.c - writes pixels for front-to-back algorithms using coverage
bits. Uses four corner points of pixel to properly average
over texture and small highlights.
Entries:
- hiq_pxls(X_pos,coverage,tp_lft_pxl,bt_lft_pxl,tp_rgt_pxl,bt_rgt_pxl)
NOTE! - must be loaded with ftb_pxls.c to pick up getseg and putseg
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */
#define X 0
#define Y 1
#define Z 2
#define R 0
#define G 1
#define B 2
#define T 3
#define XN 4
#define YN 5
#define ZN 6
#define TX_X 7
#define TX_Y 8
#define NORMS 9
#define NORM_PARMS 6
#define LT_R 3
#define LT_G 4
#define LT_B 5
#define TX_RES 128 /* texture image resolution */
#define HRES 640
#define TRANS_MIN .02 /* minimum effective transmittance */
#define HILIT_MIN .02 /* minimum effective highlight factor */
#define MAXOBJ 2
#define TRUE 1
#define FALSE 0
#define sqr(x) ((x)*(x))
extern short cvr[HRES+2];
extern double red[HRES+2],grn[HRES+2],blu[HRES+2]; /* scanline buffer */
/* global variables for pixel output routine */
extern short num_lights,hilit_power,txtr,object;
extern struct { short r,g,b,t,s; } texture[MAXOBJ][TX_RES][TX_RES];
/* +++++++++++++++++++++++++++ HIQ_PXLS +++++++++++++++++++++++++++++++++++ */
void hiq_pxls(X_pos,covrge,tp_lft_pxl,bt_lft_pxl,tp_rgt_pxl,bt_rgt_pxl)
/* blend pixels using coverage bits */
short X_pos; double covrge,tp_lft_pxl[],bt_lft_pxl[],
tp_rgt_pxl[],bt_rgt_pxl[];
{ double oldcvr,newred,newgrn,newblu,px_trans;
short i;
struct { short r,g,b,t,s; } txtr_val;
newred = tp_lft_pxl[R]; newgrn = tp_lft_pxl[G]; newblu = tp_lft_pxl[B];
if (txtr) /* color from texture */
{ av_texture(&txtr_val,tp_lft_pxl,bt_lft_pxl,tp_rgt_pxl,bt_rgt_pxl);
newred *= txtr_val.r / 255.;
newgrn *= txtr_val.g / 255.;
newblu *= txtr_val.b / 255.;
}
/* transmittance from texture */
px_trans = txtr? tp_lft_pxl[T] * txtr_val.t / 255. : tp_lft_pxl[T];
if (hilit_power > 0.) for (i=0; i<num_lights; i++) /* hilight */
{ short k,x_cross,y_cross; double hilit_value,av_hilit(),pow(),sqrt();
double maj_xc,min_xc,maj_yc,min_yc,vtl,vbl,vtr,vbr,avrg,mgntud;
k = NORMS + i*NORM_PARMS; /* offset for highlight normals */
maj_xc = tp_lft_pxl[k+X] * bt_rgt_pxl[k+X]; /* get zero crossings */
min_xc = bt_lft_pxl[k+X] * tp_rgt_pxl[k+X]; /* x zero crossings */
if ((maj_xc <= 0.) || (min_xc <=0.)) x_cross = TRUE;
else x_cross = FALSE;
maj_yc = tp_lft_pxl[k+Y] * bt_rgt_pxl[k+Y]; /* Y zero crossings */
min_yc = bt_lft_pxl[k+Y] * tp_rgt_pxl[k+Y];
if ((maj_yc <= 0.) || (min_yc <=0.)) y_cross = TRUE;
else y_cross = FALSE;
mgntud = sqr(tp_lft_pxl[k+X])+sqr(tp_lft_pxl[k+Y])+sqr(tp_lft_pxl[k+Z]);
vtl = pow(sqr(tp_lft_pxl[k+Z]) / mgntud ,(double)hilit_power);
mgntud = sqr(bt_lft_pxl[k+X])+sqr(bt_lft_pxl[k+Y])+sqr(bt_lft_pxl[k+Z]);
vbl = pow(sqr(bt_lft_pxl[k+Z]) / mgntud ,(double)hilit_power);
mgntud = sqr(tp_rgt_pxl[k+X])+sqr(tp_rgt_pxl[k+Y])+sqr(tp_rgt_pxl[k+Z]);
vtr = pow(sqr(tp_rgt_pxl[k+Z]) / mgntud ,(double)hilit_power);
mgntud = sqr(bt_rgt_pxl[k+X])+sqr(bt_rgt_pxl[k+Y])+sqr(bt_rgt_pxl[k+Z]);
vbr = pow(sqr(bt_rgt_pxl[k+Z]) / mgntud ,(double)hilit_power);
avrg = (vtl + vbl + vtr + vbr) / 4.; /* average of 4 corner values */
if ((avrg <= HILIT_MIN) && (!(x_cross || y_cross))) continue;
else hilit_value = avrg; /* skip out if no highlight */
/* ----- sub-sample highlight if zero crossing or high variance ----- */
if ((sqrt(sqr(vtl-avrg) + sqr(vbl-avrg) + sqr(vtr-avrg) +
sqr(vbr-avrg)) > HILIT_MIN * 2.) || x_cross || y_cross)
{ if (maj_xc < min_xc)
if ((maj_yc < min_yc) || (maj_xc < min_yc)) /* major diag. */
hilit_value = av_hilit(k,bt_lft_pxl,tp_rgt_pxl);
else /* minor diag. */
hilit_value = av_hilit(k,bt_rgt_pxl,tp_lft_pxl);
else
if ((min_yc < maj_yc) || (min_xc < maj_yc)) /* minor diag. */
hilit_value = av_hilit(k,bt_rgt_pxl,tp_lft_pxl);
else /* major diag. */
hilit_value = av_hilit(k,bt_lft_pxl,tp_rgt_pxl);
}
if (txtr) hilit_value *= txtr_val.s / 255.; /* sum highlights */
newred = newred + (tp_lft_pxl[k+LT_R] - newred) * hilit_value;
newgrn = newgrn + (tp_lft_pxl[k+LT_G] - newgrn) * hilit_value;
newblu = newblu + (tp_lft_pxl[k+LT_B] - newblu) * hilit_value;
if (px_trans > (1.0 - hilit_value)) px_trans = 1.0 - hilit_value;
}
if (px_trans > TRANS_MIN) covrge *= 1.0 - px_trans; /* transmittance */
oldcvr = cvr[X_pos]; /* get previous pixel coverage */
if (oldcvr == 0.)
{ cvr[X_pos] = covrge * 255. + .5; /* no previous coverage */
if (cvr[X_pos] > 0)
{ red[X_pos] = newred; grn[X_pos] = newgrn; blu[X_pos] = newblu; }
}
else if (oldcvr < 255.) /* partial previous coverage */
{ oldcvr /= 255.; /* convert to 0. <= oldcvr <= 1. */
if ((oldcvr + covrge) >= 1.) /* pixel fully covered */
{ covrge = 1. - oldcvr; cvr[X_pos] = 255; }
else /* pixel partially covered */
{ double adj;
adj = oldcvr + covrge; cvr[X_pos] = adj * 255. + .5;
oldcvr /= adj; covrge /= adj;
}
red[X_pos] = red[X_pos] * oldcvr + newred * covrge;
grn[X_pos] = grn[X_pos] * oldcvr + newgrn * covrge;
blu[X_pos] = blu[X_pos] * oldcvr + newblu * covrge;
}
}
/* ++++++++++++++++++++++++++++ AV_HILIT ++++++++++++++++++++++++++++++ */
double av_hilit(k,pxl1,pxl2) /* subsample highlight between 2 pixel positions */
short k; double pxl1[],pxl2[];
{ double tx,ty,tz,val1,val2,val3,val4,val5,mag_norm,pow();
mag_norm = sqr(pxl1[k+X]) + sqr(pxl1[k+Y]) + sqr(pxl1[k+Z]);
val1 = pow(sqr(pxl1[k+Z])/mag_norm , (double)hilit_power); /*hilit at pxl1*/
tx = (pxl1[k+X] + pxl2[k+X])/2;
ty = (pxl1[k+Y] + pxl2[k+Y])/2;
tz = (pxl1[k+Z] + pxl2[k+Z])/2;
mag_norm = sqr(tx) + sqr(ty) + sqr(tz);
val3 = pow(sqr(tz)/mag_norm , (double)hilit_power); /*hilit midway between*/
mag_norm = sqr((pxl1[k+X] + tx)/2) + sqr((pxl1[k+Y] + ty)/2) +
sqr((pxl1[k+Z] + tz)/2);
val2 = pow(sqr((pxl1[k+Z] + tz)/2)/mag_norm,(double)hilit_power);/*1/4 pt.*/
mag_norm = sqr((pxl2[k+X] + tx)/2) + sqr((pxl2[k+Y] + ty)/2) +
sqr((pxl2[k+Z] + tz)/2);
val4 = pow(sqr((pxl2[k+Z] + tz)/2)/mag_norm,(double)hilit_power);/*3/4 pt.*/
mag_norm = sqr(pxl2[k+X]) + sqr(pxl2[k+Y]) + sqr(pxl2[k+Z]);
val5 = pow(sqr(pxl2[k+Z])/mag_norm , (double)hilit_power); /*hilit at pxl2*/
return (val1 + val2 + val3 + val4 + val5) / 5.;
}
/* ++++++++++++++++++++++ AV_TEXTURE ++++++++++++++++++++++++++++++++ */
av_texture(txtr_val,tp_lft_pxl,bt_lft_pxl,tp_rgt_pxl,bt_rgt_pxl)
/* average texture values for anti-aliasing */
double tp_lft_pxl[],bt_lft_pxl[],tp_rgt_pxl[],bt_rgt_pxl[];
struct { short r,g,b,t,s; } *txtr_val;
{ short tx_tl,tx_bl,tx_tr,tx_br,ty_tl,ty_bl,ty_tr,ty_br;
struct { short r,g,b,t,s; } maj_avrge,min_avrge;
/* texture coordinates at 4 corners */
tx_tl = (short)(TX_RES * tp_lft_pxl[TX_X]);
ty_tl = (short)(TX_RES * tp_lft_pxl[TX_Y]);
tx_bl = (short)(TX_RES * bt_lft_pxl[TX_X]);
ty_bl = (short)(TX_RES * bt_lft_pxl[TX_Y]);
tx_tr = (short)(TX_RES * tp_rgt_pxl[TX_X]);
ty_tr = (short)(TX_RES * tp_rgt_pxl[TX_Y]);
tx_br = (short)(TX_RES * bt_rgt_pxl[TX_X]);
ty_br = (short)(TX_RES * bt_rgt_pxl[TX_Y]);
crawl_to(&maj_avrge,tx_tl,ty_tl,tx_br,ty_br);
crawl_to(&min_avrge,tx_bl,ty_bl,tx_tr,ty_tr);
txtr_val->r = (maj_avrge.r + min_avrge.r) / 2;
txtr_val->g = (maj_avrge.g + min_avrge.g) / 2;
txtr_val->b = (maj_avrge.b + min_avrge.b) / 2;
txtr_val->t = (maj_avrge.t + min_avrge.t) / 2;
txtr_val->s = (maj_avrge.s + min_avrge.s) / 2;
}
/* +++++++++++++++++++++++++++ CRAWL_TO ++++++++++++++++++++++++++++++++ */
crawl_to(value,x1,y1,x2,y2) /* iterate from p1 to p2 averaging en route */
struct {short r,g,b,t,s; } *value; short x1,y1,x2,y2;
{ short i,sign,temp; struct {short r,g,b,t,s; } *txtr_ptr;
if (y2 < y1) /* ensure y goes positively */
{ temp = y2; y2 = y1; y1 = temp;
temp = x2; x2 = x1; x1 = temp; }
if (x2 < x1) sign = -1; else sign = 1;
txtr_ptr = &texture[object][x1%TX_RES][y1%TX_RES]; /* store initial pt. */
value->r = txtr_ptr->r; value->g = txtr_ptr->g; value->b = txtr_ptr->b;
value->t = txtr_ptr->t; value->s = txtr_ptr->s; i = 1;
while ((x1 != x2) && (y1 != y2))
{ if ((y2 - y1)/2 >= abs(x2 - x1)) y1++;
else if (abs((x2 - x1)/2) >= (y2 - y1)) x1 += sign;
else { x1 += sign; y1++; }
txtr_ptr = &texture[object][x1%TX_RES][y1%TX_RES]; /* add new values */
value->r += txtr_ptr->r; value->g += txtr_ptr->g;
value->b += txtr_ptr->b;
value->t += txtr_ptr->t; value->s += txtr_ptr->s; i++;
}
value->r /= i; value->g /= i; value->b /= i;
value->t /= i; value->s /= i;
}
!Funky!Stuff!
More information about the Comp.sources.unix
mailing list