|
|
/*
** Copyright 1991, 1992, 1993, Silicon Graphics, Inc. ** All Rights Reserved. ** ** This is UNPUBLISHED PROPRIETARY SOURCE CODE of Silicon Graphics, Inc.; ** the contents of this file may not be disclosed to third parties, copied or ** duplicated in any form, in whole or in part, without the prior written ** permission of Silicon Graphics, Inc. ** ** RESTRICTED RIGHTS LEGEND: ** Use, duplication or disclosure by the Government is subject to restrictions ** as set forth in subdivision (c)(1)(ii) of the Rights in Technical Data ** and Computer Software clause at DFARS 252.227-7013, and/or in similar or ** successor clauses in the FAR, DOD or NASA FAR Supplement. Unpublished - ** rights reserved under the Copyright Laws of the United States. */ #include "precomp.h"
#pragma hdrstop
#ifdef GL_WIN_phong_shading
#include "phong.h"
#endif //GL_WIN_phong_shading
/*
** Normal form of a line: Ax + By + C = 0. When evaluated at a point P, ** the value is zero when P is on the line. For points off the line, ** the sign of the value determines which side of the line P is on. */ typedef struct { __GLfloat a, b, c;
/*
** The sign of an edge is determined by plugging the third vertex ** of the triangle into the line equation. This flag is GL_TRUE when ** the sign is positive. */ GLboolean edgeSign; } __glLineEquation;
/*
** Machine state for rendering triangles. */ typedef struct { __GLfloat dyAB; __GLfloat dyBC; __glLineEquation ab; __glLineEquation bc; __glLineEquation ca; __GLfloat area; GLint areaSign; } __glTriangleMachine;
/*
** Plane equation coefficients. One plane equation exists for each of ** the parameters being computed across the surface of the triangle. */ typedef struct { __GLfloat a, b, c, d; } __glPlaneEquation;
/*
** Cache for some of the coverage computation constants. */ typedef struct { __GLfloat dx, dy; GLint samples; GLint samplesSquared; __GLfloat samplesSquaredInv; GLboolean lastCoverageWasOne; __GLfloat leftDelta, rightDelta; __GLfloat bottomDelta, topDelta; } __glCoverageStuff;
/*
** Compute the constants A, B and C for a line equation in the general ** form: Ax + By + C = 0. A given point at (x,y) can be plugged into ** the left side of the equation and yield a number which indiates whether ** or not the point is on the line. If the result is zero, then the point ** is on the line. The sign of the result determines which side of ** the line the point is on. To handle tie cases properly we need a way ** to assign a point on the edge to only one triangle. To do this, we ** look at the sign of the equation evaluated at "c". For edges whose ** sign at "c" is positive, we allow points on the edge to be in the ** triangle. */ static void FindLineEqation(__glLineEquation *eq, const __GLvertex *a, const __GLvertex *b, const __GLvertex *c) { __GLfloat dy, dx, valueAtC;
/*
** Sort a,b so that the ordering of the verticies is consistent, ** regardless of the order given to this procedure. */ if (b->window.y < a->window.y) { const __GLvertex *temp = b; b = a; a = temp; } else if ((b->window.y == a->window.y) && (b->window.x < a->window.x)) { const __GLvertex *temp = b; b = a; a = temp; }
dy = b->window.y - a->window.y; dx = b->window.x - a->window.x; eq->a = -dy; eq->b = dx; eq->c = dy * a->window.x - dx * a->window.y;
valueAtC = eq->a * c->window.x + eq->b * c->window.y + eq->c; if (valueAtC > 0) { eq->edgeSign = GL_TRUE; } else { eq->edgeSign = GL_FALSE; } }
/*
** Given three points in (x,y,p) find the plane equation coeffecients ** for the plane that contains the three points. First find the cross ** product of two of the vectors defined by the three points, then ** use one of the points to find "d". */ static void FindPlaneEquation(__glPlaneEquation *eq, const __GLvertex *a, const __GLvertex *b, const __GLvertex *c, __GLfloat p1, __GLfloat p2, __GLfloat p3) { __GLfloat v1x, v1y, v1p; __GLfloat v2x, v2y, v2p; __GLfloat nx, ny, np, k;
/* find vector v1 */ v1x = b->window.x - a->window.x; v1y = b->window.y - a->window.y; v1p = p2 - p1;
/* find vector v2 */ v2x = c->window.x - a->window.x; v2y = c->window.y - a->window.y; v2p = p3 - p1;
/* find the cross product (== normal) for the plane */ nx = v1y*v2p - v1p*v2y; ny = v1p*v2x - v1x*v2p; np = v1x*v2y - v1y*v2x;
/*
** V dot N = k. Find k. We can use any of the three points on ** the plane, so we use a. */ k = a->window.x*nx + a->window.y*ny + p1*np;
/*
** Finally, setup the plane equation coeffecients. Force c to be one ** by dividing everything through by c. */ eq->a = nx / np; eq->b = ny / np; eq->c = ((__GLfloat) 1.0); eq->d = -k / np; }
/*
** Solve for p in the plane equation. */ static __GLfloat FindP(__glPlaneEquation *eq, __GLfloat x, __GLfloat y) { return -(eq->a * x + eq->b * y + eq->d); }
/*
** See if a given point is on the same side of the edge as the other ** vertex in the triangle not part of this edge. When the line ** equation evaluates to zero, make points which are on lines with ** a negative edge sign (edgeSign GL_FALSE) part of the triangle. */ #define In(eq,x,y) \
(((eq)->a * (x) + (eq)->b * (y) + (eq)->c > 0) == (eq)->edgeSign)
/*
** Determine if the point x,y is in or out of the triangle. Evaluate ** each line equation for the point and compare the sign of the result ** with the edgeSign flag. */ #define Inside(tm,x,y) \
(In(&(tm)->ab, x, y) && In(&(tm)->bc, x, y) && In(&(tm)->ca, x, y))
#define FILTER_WIDTH ((__GLfloat) 1.0)
#define FILTER_HEIGHT ((__GLfloat) 1.0)
/*
** Precompute stuff that is constant for all coverage tests. */ static void FASTCALL ComputeCoverageStuff(__glCoverageStuff *cs, GLint samples) { __GLfloat dx, dy, fs = samples; __GLfloat half = ((__GLfloat) 0.5);
cs->dx = dx = FILTER_WIDTH / fs; cs->dy = dy = FILTER_HEIGHT / fs; cs->leftDelta = -(FILTER_WIDTH / 2) + dx * half; cs->rightDelta = (FILTER_WIDTH / 2) - dx * half; cs->bottomDelta = -(FILTER_HEIGHT / 2) + dy * half; cs->topDelta = (FILTER_HEIGHT / 2) - dy * half; cs->samplesSquared = samples * samples; cs->samplesSquaredInv = ((__GLfloat) 1.0) / cs->samplesSquared; cs->samples = samples; }
/*
** Return an estimate of the pixel coverage using sub-sampling. */ static __GLfloat Coverage(__glTriangleMachine *tm, __GLfloat *xs, __GLfloat *ys, __glCoverageStuff *cs) { GLint xx, yy, hits, samples; __GLfloat dx, dy, yBottom, px, py; __GLfloat minX, minY, maxX, maxY;
hits = 0; samples = cs->samples; dx = cs->dx; dy = cs->dy; px = *xs + cs->leftDelta; yBottom = *ys + cs->bottomDelta;
/*
** If the last coverage was one (the pixel to the left in x from us), ** then if the upper right and lower right sample positions are ** also in then this entire pixel must be in. */ if (cs->lastCoverageWasOne) { __GLfloat urx, ury; urx = *xs + cs->rightDelta; ury = *ys + cs->topDelta; if (Inside(tm, urx, ury) && Inside(tm, urx, yBottom)) { return ((__GLfloat) 1.0); } }
/*
** Setup minimum and maximum x,y coordinates. The min and max values ** are used to find a "good" point that is actually within the ** triangle so that parameter values can be computed correctly. */ minX = 999999; maxX = __glMinusOne; minY = 999999; maxY = __glMinusOne; for (xx = 0; xx < samples; xx++) { py = yBottom; for (yy = 0; yy < samples; yy++) { if (Inside(tm, px, py)) { if (px < minX) minX = px; if (px > maxX) maxX = px; if (py < minY) minY = py; if (py > maxY) maxY = py; hits++; } py += dy; } px += dx; } if (hits) { /*
** Return the average of the two coordinates which is guaranteed ** to be in the triangle. */ *xs = (minX + maxX) * ((__GLfloat) 0.5); *ys = (minY + maxY) * ((__GLfloat) 0.5); if (hits == cs->samplesSquared) { /* Keep track when the last coverage was one */ cs->lastCoverageWasOne = GL_TRUE; return ((__GLfloat) 1.0); } } cs->lastCoverageWasOne = GL_FALSE; return hits * cs->samplesSquaredInv; }
/*
** Force f to have no more precision than the subpixel precision allows. ** Even though "f" is biased this still works and does not generate an ** overflow. */ #define __GL_FIX_PRECISION(f) \
((__GLfloat) ((GLint) (f * (1 << gc->constants.subpixelBits))) \ / (1 << gc->constants.subpixelBits))
void FASTCALL __glFillAntiAliasedTriangle(__GLcontext *gc, __GLvertex *a, __GLvertex *b, __GLvertex *c, GLboolean ccw) { __glTriangleMachine tm; __glCoverageStuff cs; __GLcolor *ca, *cb, *cc, *flatColor; GLint x, y, left, right, bottom, top, samples; __glPlaneEquation qwp, zp, rp, gp, bp, ap, ezp, sp, tp; __glPlaneEquation fp; GLboolean rgbMode; __GLcolorBuffer *cfb = gc->drawBuffer; __GLfloat zero = __glZero; __GLfloat area, ax, bx, cx, ay, by, cy; __GLshade *sh = &gc->polygon.shader; GLuint modeFlags = gc->polygon.shader.modeFlags;
#ifdef __GL_LINT
ccw = ccw; #endif
/*
** Recompute the area of the triangle after constraining the incoming ** coordinates to the subpixel precision. The viewport bias gives ** more precision (typically) than the subpixel precision. Because of ** this the algorithim below can fail to reject an essentially empty ** triangle and instead fill a large area. The scan converter fill ** routines (eg polydraw.c) don't have this trouble because of the ** very nature of edge walking. ** ** NOTE: Notice that here as in other places, when the area calculation ** is done we are careful to do it as a series of subtractions followed by ** multiplications. This is done to guarantee that no overflow will ** occur (remember that the coordinates are biased by a potentially large ** number, and that multiplying two biased numbers will square the bias). */ ax = __GL_FIX_PRECISION(a->window.x); bx = __GL_FIX_PRECISION(b->window.x); cx = __GL_FIX_PRECISION(c->window.x); ay = __GL_FIX_PRECISION(a->window.y); by = __GL_FIX_PRECISION(b->window.y); cy = __GL_FIX_PRECISION(c->window.y); area = (ax - cx) * (by - cy) - (bx - cx) * (ay - cy); if (area == zero) { return; }
ca = a->color; cb = b->color; cc = c->color; flatColor = gc->vertex.provoking->color;
/*
** Construct plane equations for all of the parameters that are ** computed for the triangle: z, r, g, b, a, s, t, f */ if (modeFlags & __GL_SHADE_DEPTH_ITER) { FindPlaneEquation(&zp, a, b, c, a->window.z, b->window.z, c->window.z); }
if (modeFlags & __GL_SHADE_COMPUTE_FOG) { FindPlaneEquation(&ezp, a, b, c, a->eyeZ, b->eyeZ, c->eyeZ); } else if (modeFlags & __GL_SHADE_INTERP_FOG) { FindPlaneEquation(&fp, a, b, c, a->fog, b->fog, c->fog); }
if (modeFlags & __GL_SHADE_TEXTURE) { __GLfloat one = __glOne; __GLfloat aWInv = a->window.w; __GLfloat bWInv = b->window.w; __GLfloat cWInv = c->window.w; FindPlaneEquation(&qwp, a, b, c, a->texture.w * aWInv, b->texture.w * bWInv, c->texture.w * cWInv); FindPlaneEquation(&sp, a, b, c, a->texture.x * aWInv, b->texture.x * bWInv, c->texture.x * cWInv); FindPlaneEquation(&tp, a, b, c, a->texture.y * aWInv, b->texture.y * bWInv, c->texture.y * cWInv); } rgbMode = gc->modes.rgbMode; if (modeFlags & __GL_SHADE_SMOOTH) { FindPlaneEquation(&rp, a, b, c, ca->r, cb->r, cc->r); if (rgbMode) { FindPlaneEquation(&gp, a, b, c, ca->g, cb->g, cc->g); FindPlaneEquation(&bp, a, b, c, ca->b, cb->b, cc->b); FindPlaneEquation(&ap, a, b, c, ca->a, cb->a, cc->a); } }
/*
** Compute general form of the line equations for each of the ** edges of the triangle. */ FindLineEqation(&tm.ab, a, b, c); FindLineEqation(&tm.bc, b, c, a); FindLineEqation(&tm.ca, c, a, b);
/* Compute bounding box of the triangle */ left = (GLint)a->window.x; if (b->window.x < left) left = (GLint)b->window.x; if (c->window.x < left) left = (GLint)c->window.x; right = (GLint)a->window.x; if (b->window.x > right) right = (GLint)b->window.x; if (c->window.x > right) right = (GLint)c->window.x; bottom = (GLint)a->window.y; if (b->window.y < bottom) bottom = (GLint)b->window.y; if (c->window.y < bottom) bottom = (GLint)c->window.y; top = (GLint)a->window.y; if (b->window.y > top) top = (GLint)b->window.y; if (c->window.y > top) top = (GLint)c->window.y;
/* Bloat the bounding box when anti aliasing */ left -= (GLint)FILTER_WIDTH; right += (GLint)FILTER_WIDTH; bottom -= (GLint)FILTER_HEIGHT; top += (GLint)FILTER_HEIGHT; /* Init coverage computations */ samples = (gc->state.hints.polygonSmooth == GL_NICEST) ? 8 : 4; ComputeCoverageStuff(&cs, samples); /* Scan over the bounding box of the triangle */ for (y = bottom; y <= top; y++) { cs.lastCoverageWasOne = GL_FALSE; for (x = left; x <= right; x++) { __GLfloat coverage; __GLfloat xs, ys;
if (modeFlags & __GL_SHADE_STIPPLE) { /*
** Check the window coordinate against the stipple and ** and see if the pixel can be written */ GLint row = y & 31; GLint col = x & 31; if ((gc->polygon.stipple[row] & (1<<col)) == 0) { /*
** Stipple bit is clear. Do not render this pixel ** of the triangle. */ continue; } } xs = x + __glHalf; /* sample point is at pixel center */ ys = y + __glHalf; coverage = Coverage(&tm, &xs, &ys, &cs); if (coverage != zero) { __GLfragment frag;
/*
** Fill in fragment for rendering. First compute the color ** of the fragment. */ if (modeFlags & __GL_SHADE_SMOOTH) { frag.color.r = FindP(&rp, xs, ys); if (rgbMode) { frag.color.g = FindP(&gp, xs, ys); frag.color.b = FindP(&bp, xs, ys); frag.color.a = FindP(&ap, xs, ys); } } else { frag.color.r = flatColor->r; if (rgbMode) { frag.color.g = flatColor->g; frag.color.b = flatColor->b; frag.color.a = flatColor->a; } } /*
** Texture the fragment. */ if (modeFlags & __GL_SHADE_TEXTURE) { __GLfloat qw, s, t, rho; qw = FindP(&qwp, xs, ys); s = FindP(&sp, xs, ys); t = FindP(&tp, xs, ys); rho = (*gc->procs.calcPolygonRho)(gc, sh, s, t, qw); #ifdef NT
if( qw == (__GLfloat) 0.0 ) s = t = (__GLfloat) 0; else { s /= qw; t /= qw; } #else
s /= qw; t /= qw; #endif
(*gc->procs.texture)(gc, &frag.color, s, t, rho); } /*
** Fog the resulting color. */ if (modeFlags & __GL_SHADE_COMPUTE_FOG) { __GLfloat eyeZ = FindP(&ezp, xs, ys); __glFogFragmentSlow(gc, &frag, eyeZ); } else if (modeFlags & __GL_SHADE_INTERP_FOG) { __GLfloat fog = FindP(&fp, xs, ys); __glFogColorSlow(gc, &(frag.color), &(frag.color), fog); }
/*
** Apply anti-aliasing effect */ if (rgbMode) { frag.color.a *= coverage; } else { frag.color.r = __glBuildAntiAliasIndex(frag.color.r, coverage); } /*
** Finally, render the fragment. */ frag.x = (GLint)xs; frag.y = (GLint)ys; if (modeFlags & __GL_SHADE_DEPTH_ITER) { frag.z = (__GLzValue)FindP(&zp, xs, ys); } (*gc->procs.store)(cfb, &frag); } } } }
#ifdef GL_WIN_phong_shading
void FASTCALL __glFillAntiAliasedPhongTriangle(__GLcontext *gc, __GLvertex *a, __GLvertex *b, __GLvertex *c, GLboolean ccw) { #if 1
__glTriangleMachine tm; __glCoverageStuff cs; __GLcolor *ca, *cb, *cc, *flatColor; GLint x, y, left, right, bottom, top, samples; __glPlaneEquation qwp, zp, rp, gp, bp, ap, ezp, sp, tp; __glPlaneEquation exp, eyp, ewp, nxp, nyp, nzp; __glPlaneEquation fp; GLboolean rgbMode; __GLcolorBuffer *cfb = gc->drawBuffer; __GLfloat zero = __glZero; __GLfloat area, ax, bx, cx, ay, by, cy; __GLshade *sh = &gc->polygon.shader; GLuint modeFlags = gc->polygon.shader.modeFlags; __GLcoord *na, *nb, *nc, ea, eb, ec; GLuint msm_colorMaterialChange, flags=0; GLboolean needColor, needEye; __GLphongShader *phong = &gc->polygon.shader.phong; if (gc->polygon.shader.phong.face == __GL_FRONTFACE) msm_colorMaterialChange = gc->light.back.colorMaterialChange; else msm_colorMaterialChange = gc->light.back.colorMaterialChange;
if ((gc->state.enables.general & __GL_COLOR_MATERIAL_ENABLE) && msm_colorMaterialChange && (modeFlags & __GL_SHADE_RGB)) flags |= __GL_PHONG_NEED_COLOR_XPOLATE;
//Compute Invariant color if possible
if (((!(flags & __GL_PHONG_NEED_COLOR_XPOLATE) || !(msm_colorMaterialChange & (__GL_MATERIAL_AMBIENT | __GL_MATERIAL_EMISSIVE))) && (modeFlags & __GL_SHADE_RGB)) && !(flags & __GL_PHONG_NEED_EYE_XPOLATE)) { ComputePhongInvarientRGBColor (gc); flags |= __GL_PHONG_INV_COLOR_VALID; } //Store the flags
gc->polygon.shader.phong.flags |= flags;
needColor = (gc->polygon.shader.phong.flags & __GL_PHONG_NEED_COLOR_XPOLATE); needEye = (gc->polygon.shader.phong.flags & __GL_PHONG_NEED_EYE_XPOLATE);
#ifdef __GL_LINT
ccw = ccw; #endif
/*
** Recompute the area of the triangle after constraining the incoming ** coordinates to the subpixel precision. The viewport bias gives ** more precision (typically) than the subpixel precision. Because of ** this the algorithim below can fail to reject an essentially empty ** triangle and instead fill a large area. The scan converter fill ** routines (eg polydraw.c) don't have this trouble because of the ** very nature of edge walking. ** ** NOTE: Notice that here as in other places, when the area calculation ** is done we are careful to do it as a series of subtractions followed by ** multiplications. This is done to guarantee that no overflow will ** occur (remember that the coordinates are biased by a potentially large ** number, and that multiplying two biased numbers will square the bias). */ ax = __GL_FIX_PRECISION(a->window.x); bx = __GL_FIX_PRECISION(b->window.x); cx = __GL_FIX_PRECISION(c->window.x); ay = __GL_FIX_PRECISION(a->window.y); by = __GL_FIX_PRECISION(b->window.y); cy = __GL_FIX_PRECISION(c->window.y); area = (ax - cx) * (by - cy) - (bx - cx) * (ay - cy); if (area == zero) { return; }
na = &a->normal; nb = &b->normal; nc = &c->normal;
if (needColor) { ca = a->color; cb = b->color; cc = c->color; flatColor = gc->vertex.provoking->color; }
if (needEye) { ea.x = a->eyeX; ea.y = a->eyeY; ea.z = a->eyeZ; ea.w = a->eyeW; eb.x = b->eyeX; eb.y = b->eyeY; eb.z = b->eyeZ; eb.w = b->eyeW; ec.x = c->eyeX; ec.y = c->eyeY; ec.z = c->eyeZ; ec.w = c->eyeW; }
/*
** Construct plane equations for all of the parameters that are ** computed for the triangle: z, r, g, b, a, s, t, f */ if (modeFlags & __GL_SHADE_DEPTH_ITER) { FindPlaneEquation(&zp, a, b, c, a->window.z, b->window.z, c->window.z); }
#ifdef GL_WIN_specular_fog
if (modeFlags & __GL_SHADE_COMPUTE_FOG) { FindPlaneEquation(&ezp, a, b, c, a->eyeZ, b->eyeZ, c->eyeZ); } else if (modeFlags & __GL_SHADE_INTERP_FOG) { __GLfloat aFog = 1.0f, bFog = 1.0f, cFog = 1.0f;
if (gc->polygon.shader.modeFlags & __GL_SHADE_SPEC_FOG) { aFog = ComputeSpecValue (gc, a); bFog = ComputeSpecValue (gc, b); cFog = ComputeSpecValue (gc, c); }
if (gc->polygon.shader.modeFlags & __GL_SHADE_SLOW_FOG) { aFog *= a->fog; bFog *= b->fog; cFog *= c->fog; }
FindPlaneEquation(&fp, a, b, c, aFog, bFog, cFog); } #else //GL_WIN_specular_fog
if (modeFlags & __GL_SHADE_SLOW_FOG) { FindPlaneEquation(&ezp, a, b, c, a->eyeZ, b->eyeZ, c->eyeZ); } else if (modeFlags & __GL_SHADE_INTERP_FOG) { FindPlaneEquation(&fp, a, b, c, a->fog, b->fog, c->fog); } #endif //GL_WIN_specular_fog
if (modeFlags & __GL_SHADE_TEXTURE) { __GLfloat one = __glOne; __GLfloat aWInv = a->window.w; __GLfloat bWInv = b->window.w; __GLfloat cWInv = c->window.w; FindPlaneEquation(&qwp, a, b, c, a->texture.w * aWInv, b->texture.w * bWInv, c->texture.w * cWInv); FindPlaneEquation(&sp, a, b, c, a->texture.x * aWInv, b->texture.x * bWInv, c->texture.x * cWInv); FindPlaneEquation(&tp, a, b, c, a->texture.y * aWInv, b->texture.y * bWInv, c->texture.y * cWInv); }
rgbMode = gc->modes.rgbMode;
if (needColor) { if (modeFlags & __GL_SHADE_SMOOTH) { FindPlaneEquation(&rp, a, b, c, ca->r, cb->r, cc->r); if (rgbMode) { FindPlaneEquation(&gp, a, b, c, ca->g, cb->g, cc->g); FindPlaneEquation(&bp, a, b, c, ca->b, cb->b, cc->b); FindPlaneEquation(&ap, a, b, c, ca->a, cb->a, cc->a); } } } if (needEye) { FindPlaneEquation(&exp, a, b, c, ea.x, eb.x, ec.x); FindPlaneEquation(&eyp, a, b, c, ea.y, eb.y, ec.y); // FindPlaneEquation(&ezp, a, b, c, ea.z, eb.z, ec.z);
FindPlaneEquation(&ewp, a, b, c, ea.w, eb.w, ec.w); }
FindPlaneEquation(&nxp, a, b, c, na->x, nb->x, nc->x); FindPlaneEquation(&nyp, a, b, c, na->y, nb->y, nc->y); FindPlaneEquation(&nzp, a, b, c, na->z, nb->z, nc->z);
/*
** Compute general form of the line equations for each of the ** edges of the triangle. */ FindLineEqation(&tm.ab, a, b, c); FindLineEqation(&tm.bc, b, c, a); FindLineEqation(&tm.ca, c, a, b);
/* Compute bounding box of the triangle */ left = (GLint)a->window.x; if (b->window.x < left) left = (GLint)b->window.x; if (c->window.x < left) left = (GLint)c->window.x; right = (GLint)a->window.x; if (b->window.x > right) right = (GLint)b->window.x; if (c->window.x > right) right = (GLint)c->window.x; bottom = (GLint)a->window.y; if (b->window.y < bottom) bottom = (GLint)b->window.y; if (c->window.y < bottom) bottom = (GLint)c->window.y; top = (GLint)a->window.y; if (b->window.y > top) top = (GLint)b->window.y; if (c->window.y > top) top = (GLint)c->window.y;
/* Bloat the bounding box when anti aliasing */ left -= (GLint)FILTER_WIDTH; right += (GLint)FILTER_WIDTH; bottom -= (GLint)FILTER_HEIGHT; top += (GLint)FILTER_HEIGHT;
/* Init coverage computations */ samples = (gc->state.hints.polygonSmooth == GL_NICEST) ? 8 : 4; ComputeCoverageStuff(&cs, samples);
/* Scan over the bounding box of the triangle */ for (y = bottom; y <= top; y++) { cs.lastCoverageWasOne = GL_FALSE; for (x = left; x <= right; x++) { __GLfloat coverage; __GLfloat xs, ys;
if (modeFlags & __GL_SHADE_STIPPLE) { /*
** Check the window coordinate against the stipple and ** and see if the pixel can be written */ GLint row = y & 31; GLint col = x & 31; if ((gc->polygon.stipple[row] & (1<<col)) == 0) { /*
** Stipple bit is clear. Do not render this pixel ** of the triangle. */ continue; } }
xs = x + __glHalf; /* sample point is at pixel center */ ys = y + __glHalf; coverage = Coverage(&tm, &xs, &ys, &cs); if (coverage != zero) { __GLfragment frag; /*
** Fill in fragment for rendering. First compute the color ** of the fragment. */ phong->nTmp.x = FindP(&nxp, xs, ys); phong->nTmp.y = FindP(&nyp, xs, ys); phong->nTmp.z = FindP(&nzp, xs, ys);
if (needColor) { phong->tmpColor.r = FindP(&rp, xs, ys); if (modeFlags & __GL_SHADE_RGB) { phong->tmpColor.g = FindP(&gp, xs, ys); phong->tmpColor.b = FindP(&bp, xs, ys); phong->tmpColor.a = FindP(&ap, xs, ys); } } if (needEye) { phong->eTmp.x = FindP(&exp, xs, ys); phong->eTmp.y = FindP(&eyp, xs, ys); phong->eTmp.z = FindP(&ezp, xs, ys); phong->eTmp.w = FindP(&ewp, xs, ys); } if (modeFlags & __GL_SHADE_RGB) (*gc->procs.phong.ComputeRGBColor) (gc, &(frag.color)); else (*gc->procs.phong.ComputeCIColor) (gc, &(frag.color));
/*
** Texture the fragment. */ if (modeFlags & __GL_SHADE_TEXTURE) { __GLfloat qw, s, t, rho;
qw = FindP(&qwp, xs, ys); s = FindP(&sp, xs, ys); t = FindP(&tp, xs, ys); rho = (*gc->procs.calcPolygonRho)(gc, sh, s, t, qw); if( qw == (__GLfloat) 0.0 ) s = t = (__GLfloat) 0; else { s /= qw; t /= qw; } (*gc->procs.texture)(gc, &frag.color, s, t, rho); }
/*
** Fog the resulting color. */ if (modeFlags & __GL_SHADE_COMPUTE_FOG) { __GLfloat eyeZ = FindP(&ezp, xs, ys); __glFogFragmentSlow(gc, &frag, eyeZ); } else if (modeFlags & __GL_SHADE_INTERP_FOG) { __GLfloat fog = FindP(&fp, xs, ys); __glFogColorSlow(gc, &(frag.color), &(frag.color), fog); }
/*
** Apply anti-aliasing effect */ if (rgbMode) { frag.color.a *= coverage; } else { frag.color.r = __glBuildAntiAliasIndex(frag.color.r, coverage); }
/*
** Finally, render the fragment. */ frag.x = (GLint)xs; frag.y = (GLint)ys; if (modeFlags & __GL_SHADE_DEPTH_ITER) { frag.z = (__GLzValue)FindP(&zp, xs, ys); } (*gc->procs.store)(cfb, &frag); } } } #endif
} #endif //GL_WIN_phong_shading
|