s_aatritemp.h revision 02de45dcedc38b0e4ceacba440bfc11930ec90bb
1/* $Id: s_aatritemp.h,v 1.34 2003/01/28 00:14:32 brianp Exp $ */ 2 3/* 4 * Mesa 3-D graphics library 5 * Version: 5.1 6 * 7 * Copyright (C) 1999-2003 Brian Paul All Rights Reserved. 8 * 9 * Permission is hereby granted, free of charge, to any person obtaining a 10 * copy of this software and associated documentation files (the "Software"), 11 * to deal in the Software without restriction, including without limitation 12 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 13 * and/or sell copies of the Software, and to permit persons to whom the 14 * Software is furnished to do so, subject to the following conditions: 15 * 16 * The above copyright notice and this permission notice shall be included 17 * in all copies or substantial portions of the Software. 18 * 19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 20 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 22 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 23 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 24 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 25 */ 26 27 28/* 29 * Antialiased Triangle Rasterizer Template 30 * 31 * This file is #include'd to generate custom AA triangle rasterizers. 32 * NOTE: this code hasn't been optimized yet. That'll come after it 33 * works correctly. 34 * 35 * The following macros may be defined to indicate what auxillary information 36 * must be copmuted across the triangle: 37 * DO_Z - if defined, compute Z values 38 * DO_RGBA - if defined, compute RGBA values 39 * DO_INDEX - if defined, compute color index values 40 * DO_SPEC - if defined, compute specular RGB values 41 * DO_TEX - if defined, compute unit 0 STRQ texcoords 42 * DO_MULTITEX - if defined, compute all unit's STRQ texcoords 43 */ 44 45/*void triangle( GLcontext *ctx, GLuint v0, GLuint v1, GLuint v2, GLuint pv )*/ 46{ 47 const GLfloat *p0 = v0->win; 48 const GLfloat *p1 = v1->win; 49 const GLfloat *p2 = v2->win; 50 const SWvertex *vMin, *vMid, *vMax; 51 GLint iyMin, iyMax; 52 GLfloat yMin, yMax; 53 GLboolean ltor; 54 GLfloat majDx, majDy; /* major (i.e. long) edge dx and dy */ 55 56 struct sw_span span; 57 58#ifdef DO_Z 59 GLfloat zPlane[4]; 60#endif 61#ifdef DO_FOG 62 GLfloat fogPlane[4]; 63#else 64 GLfloat *fog = NULL; 65#endif 66#ifdef DO_RGBA 67 GLfloat rPlane[4], gPlane[4], bPlane[4], aPlane[4]; 68#endif 69#ifdef DO_INDEX 70 GLfloat iPlane[4]; 71#endif 72#ifdef DO_SPEC 73 GLfloat srPlane[4], sgPlane[4], sbPlane[4]; 74#endif 75#ifdef DO_TEX 76 GLfloat sPlane[4], tPlane[4], uPlane[4], vPlane[4]; 77 GLfloat texWidth, texHeight; 78#elif defined(DO_MULTITEX) 79 GLfloat sPlane[MAX_TEXTURE_COORD_UNITS][4]; /* texture S */ 80 GLfloat tPlane[MAX_TEXTURE_COORD_UNITS][4]; /* texture T */ 81 GLfloat uPlane[MAX_TEXTURE_COORD_UNITS][4]; /* texture R */ 82 GLfloat vPlane[MAX_TEXTURE_COORD_UNITS][4]; /* texture Q */ 83 GLfloat texWidth[MAX_TEXTURE_COORD_UNITS]; 84 GLfloat texHeight[MAX_TEXTURE_COORD_UNITS]; 85#endif 86 GLfloat bf = SWRAST_CONTEXT(ctx)->_backface_sign; 87 88 89 INIT_SPAN(span, GL_POLYGON, 0, 0, SPAN_COVERAGE); 90 91 /* determine bottom to top order of vertices */ 92 { 93 GLfloat y0 = v0->win[1]; 94 GLfloat y1 = v1->win[1]; 95 GLfloat y2 = v2->win[1]; 96 if (y0 <= y1) { 97 if (y1 <= y2) { 98 vMin = v0; vMid = v1; vMax = v2; /* y0<=y1<=y2 */ 99 } 100 else if (y2 <= y0) { 101 vMin = v2; vMid = v0; vMax = v1; /* y2<=y0<=y1 */ 102 } 103 else { 104 vMin = v0; vMid = v2; vMax = v1; bf = -bf; /* y0<=y2<=y1 */ 105 } 106 } 107 else { 108 if (y0 <= y2) { 109 vMin = v1; vMid = v0; vMax = v2; bf = -bf; /* y1<=y0<=y2 */ 110 } 111 else if (y2 <= y1) { 112 vMin = v2; vMid = v1; vMax = v0; bf = -bf; /* y2<=y1<=y0 */ 113 } 114 else { 115 vMin = v1; vMid = v2; vMax = v0; /* y1<=y2<=y0 */ 116 } 117 } 118 } 119 120 majDx = vMax->win[0] - vMin->win[0]; 121 majDy = vMax->win[1] - vMin->win[1]; 122 123 { 124 const GLfloat botDx = vMid->win[0] - vMin->win[0]; 125 const GLfloat botDy = vMid->win[1] - vMin->win[1]; 126 const GLfloat area = majDx * botDy - botDx * majDy; 127 /* Do backface culling */ 128 if (area * bf < 0 || area == 0 || IS_INF_OR_NAN(area)) 129 return; 130 ltor = (GLboolean) (area < 0.0F); 131 } 132 133#ifndef DO_OCCLUSION_TEST 134 ctx->OcclusionResult = GL_TRUE; 135#endif 136 137 /* Plane equation setup: 138 * We evaluate plane equations at window (x,y) coordinates in order 139 * to compute color, Z, fog, texcoords, etc. This isn't terribly 140 * efficient but it's easy and reliable. 141 */ 142#ifdef DO_Z 143 compute_plane(p0, p1, p2, p0[2], p1[2], p2[2], zPlane); 144 span.arrayMask |= SPAN_Z; 145#endif 146#ifdef DO_FOG 147 compute_plane(p0, p1, p2, v0->fog, v1->fog, v2->fog, fogPlane); 148 span.arrayMask |= SPAN_FOG; 149#endif 150#ifdef DO_RGBA 151 if (ctx->Light.ShadeModel == GL_SMOOTH) { 152 compute_plane(p0, p1, p2, v0->color[RCOMP], v1->color[RCOMP], v2->color[RCOMP], rPlane); 153 compute_plane(p0, p1, p2, v0->color[GCOMP], v1->color[GCOMP], v2->color[GCOMP], gPlane); 154 compute_plane(p0, p1, p2, v0->color[BCOMP], v1->color[BCOMP], v2->color[BCOMP], bPlane); 155 compute_plane(p0, p1, p2, v0->color[ACOMP], v1->color[ACOMP], v2->color[ACOMP], aPlane); 156 } 157 else { 158 constant_plane(v2->color[RCOMP], rPlane); 159 constant_plane(v2->color[GCOMP], gPlane); 160 constant_plane(v2->color[BCOMP], bPlane); 161 constant_plane(v2->color[ACOMP], aPlane); 162 } 163 span.arrayMask |= SPAN_RGBA; 164#endif 165#ifdef DO_INDEX 166 if (ctx->Light.ShadeModel == GL_SMOOTH) { 167 compute_plane(p0, p1, p2, (GLfloat) v0->index, 168 (GLfloat) v1->index, (GLfloat) v2->index, iPlane); 169 } 170 else { 171 constant_plane((GLfloat) v2->index, iPlane); 172 } 173 span.arrayMask |= SPAN_INDEX; 174#endif 175#ifdef DO_SPEC 176 if (ctx->Light.ShadeModel == GL_SMOOTH) { 177 compute_plane(p0, p1, p2, v0->specular[RCOMP], v1->specular[RCOMP], v2->specular[RCOMP], srPlane); 178 compute_plane(p0, p1, p2, v0->specular[GCOMP], v1->specular[GCOMP], v2->specular[GCOMP], sgPlane); 179 compute_plane(p0, p1, p2, v0->specular[BCOMP], v1->specular[BCOMP], v2->specular[BCOMP], sbPlane); 180 } 181 else { 182 constant_plane(v2->specular[RCOMP], srPlane); 183 constant_plane(v2->specular[GCOMP], sgPlane); 184 constant_plane(v2->specular[BCOMP], sbPlane); 185 } 186 span.arrayMask |= SPAN_SPEC; 187#endif 188#ifdef DO_TEX 189 { 190 const struct gl_texture_object *obj = ctx->Texture.Unit[0]._Current; 191 const struct gl_texture_image *texImage = obj->Image[obj->BaseLevel]; 192 const GLfloat invW0 = v0->win[3]; 193 const GLfloat invW1 = v1->win[3]; 194 const GLfloat invW2 = v2->win[3]; 195 const GLfloat s0 = v0->texcoord[0][0] * invW0; 196 const GLfloat s1 = v1->texcoord[0][0] * invW1; 197 const GLfloat s2 = v2->texcoord[0][0] * invW2; 198 const GLfloat t0 = v0->texcoord[0][1] * invW0; 199 const GLfloat t1 = v1->texcoord[0][1] * invW1; 200 const GLfloat t2 = v2->texcoord[0][1] * invW2; 201 const GLfloat r0 = v0->texcoord[0][2] * invW0; 202 const GLfloat r1 = v1->texcoord[0][2] * invW1; 203 const GLfloat r2 = v2->texcoord[0][2] * invW2; 204 const GLfloat q0 = v0->texcoord[0][3] * invW0; 205 const GLfloat q1 = v1->texcoord[0][3] * invW1; 206 const GLfloat q2 = v2->texcoord[0][3] * invW2; 207 compute_plane(p0, p1, p2, s0, s1, s2, sPlane); 208 compute_plane(p0, p1, p2, t0, t1, t2, tPlane); 209 compute_plane(p0, p1, p2, r0, r1, r2, uPlane); 210 compute_plane(p0, p1, p2, q0, q1, q2, vPlane); 211 texWidth = (GLfloat) texImage->Width; 212 texHeight = (GLfloat) texImage->Height; 213 } 214 span.arrayMask |= (SPAN_TEXTURE | SPAN_LAMBDA); 215#elif defined(DO_MULTITEX) 216 { 217 GLuint u; 218 for (u = 0; u < ctx->Const.MaxTextureUnits; u++) { 219 if (ctx->Texture.Unit[u]._ReallyEnabled) { 220 const struct gl_texture_object *obj = ctx->Texture.Unit[u]._Current; 221 const struct gl_texture_image *texImage = obj->Image[obj->BaseLevel]; 222 const GLfloat invW0 = v0->win[3]; 223 const GLfloat invW1 = v1->win[3]; 224 const GLfloat invW2 = v2->win[3]; 225 const GLfloat s0 = v0->texcoord[u][0] * invW0; 226 const GLfloat s1 = v1->texcoord[u][0] * invW1; 227 const GLfloat s2 = v2->texcoord[u][0] * invW2; 228 const GLfloat t0 = v0->texcoord[u][1] * invW0; 229 const GLfloat t1 = v1->texcoord[u][1] * invW1; 230 const GLfloat t2 = v2->texcoord[u][1] * invW2; 231 const GLfloat r0 = v0->texcoord[u][2] * invW0; 232 const GLfloat r1 = v1->texcoord[u][2] * invW1; 233 const GLfloat r2 = v2->texcoord[u][2] * invW2; 234 const GLfloat q0 = v0->texcoord[u][3] * invW0; 235 const GLfloat q1 = v1->texcoord[u][3] * invW1; 236 const GLfloat q2 = v2->texcoord[u][3] * invW2; 237 compute_plane(p0, p1, p2, s0, s1, s2, sPlane[u]); 238 compute_plane(p0, p1, p2, t0, t1, t2, tPlane[u]); 239 compute_plane(p0, p1, p2, r0, r1, r2, uPlane[u]); 240 compute_plane(p0, p1, p2, q0, q1, q2, vPlane[u]); 241 texWidth[u] = (GLfloat) texImage->Width; 242 texHeight[u] = (GLfloat) texImage->Height; 243 } 244 } 245 } 246 span.arrayMask |= (SPAN_TEXTURE | SPAN_LAMBDA); 247#endif 248 249 /* Begin bottom-to-top scan over the triangle. 250 * The long edge will either be on the left or right side of the 251 * triangle. We always scan from the long edge toward the shorter 252 * edges, stopping when we find that coverage = 0. If the long edge 253 * is on the left we scan left-to-right. Else, we scan right-to-left. 254 */ 255 yMin = vMin->win[1]; 256 yMax = vMax->win[1]; 257 iyMin = (GLint) yMin; 258 iyMax = (GLint) yMax + 1; 259 260 if (ltor) { 261 /* scan left to right */ 262 const GLfloat *pMin = vMin->win; 263 const GLfloat *pMid = vMid->win; 264 const GLfloat *pMax = vMax->win; 265 const GLfloat dxdy = majDx / majDy; 266 const GLfloat xAdj = dxdy < 0.0F ? -dxdy : 0.0F; 267 GLfloat x = pMin[0] - (yMin - iyMin) * dxdy; 268 GLint iy; 269 for (iy = iyMin; iy < iyMax; iy++, x += dxdy) { 270 GLint ix, startX = (GLint) (x - xAdj); 271 GLuint count; 272 GLfloat coverage = 0.0F; 273 274 /* skip over fragments with zero coverage */ 275 while (startX < MAX_WIDTH) { 276 coverage = compute_coveragef(pMin, pMid, pMax, startX, iy); 277 if (coverage > 0.0F) 278 break; 279 startX++; 280 } 281 282 /* enter interior of triangle */ 283 ix = startX; 284 count = 0; 285 while (coverage > 0.0F) { 286 /* (cx,cy) = center of fragment */ 287 const GLfloat cx = ix + 0.5F, cy = iy + 0.5F; 288 struct span_arrays *array = span.array; 289#ifdef DO_INDEX 290 array->coverage[count] = (GLfloat) compute_coveragei(pMin, pMid, pMax, ix, iy); 291#else 292 array->coverage[count] = coverage; 293#endif 294#ifdef DO_Z 295 array->z[count] = (GLdepth) solve_plane(cx, cy, zPlane); 296#endif 297#ifdef DO_FOG 298 array->fog[count] = solve_plane(cx, cy, fogPlane); 299#endif 300#ifdef DO_RGBA 301 array->rgba[count][RCOMP] = solve_plane_chan(cx, cy, rPlane); 302 array->rgba[count][GCOMP] = solve_plane_chan(cx, cy, gPlane); 303 array->rgba[count][BCOMP] = solve_plane_chan(cx, cy, bPlane); 304 array->rgba[count][ACOMP] = solve_plane_chan(cx, cy, aPlane); 305#endif 306#ifdef DO_INDEX 307 array->index[count] = (GLint) solve_plane(cx, cy, iPlane); 308#endif 309#ifdef DO_SPEC 310 array->spec[count][RCOMP] = solve_plane_chan(cx, cy, srPlane); 311 array->spec[count][GCOMP] = solve_plane_chan(cx, cy, sgPlane); 312 array->spec[count][BCOMP] = solve_plane_chan(cx, cy, sbPlane); 313#endif 314#ifdef DO_TEX 315 { 316 const GLfloat invQ = solve_plane_recip(cx, cy, vPlane); 317 array->texcoords[0][count][0] = solve_plane(cx, cy, sPlane) * invQ; 318 array->texcoords[0][count][1] = solve_plane(cx, cy, tPlane) * invQ; 319 array->texcoords[0][count][2] = solve_plane(cx, cy, uPlane) * invQ; 320 array->lambda[0][count] = compute_lambda(sPlane, tPlane, vPlane, 321 cx, cy, invQ, 322 texWidth, texHeight); 323 } 324#elif defined(DO_MULTITEX) 325 { 326 GLuint unit; 327 for (unit = 0; unit < ctx->Const.MaxTextureUnits; unit++) { 328 if (ctx->Texture.Unit[unit]._ReallyEnabled) { 329 GLfloat invQ = solve_plane_recip(cx, cy, vPlane[unit]); 330 array->texcoords[unit][count][0] = solve_plane(cx, cy, sPlane[unit]) * invQ; 331 array->texcoords[unit][count][1] = solve_plane(cx, cy, tPlane[unit]) * invQ; 332 array->texcoords[unit][count][2] = solve_plane(cx, cy, uPlane[unit]) * invQ; 333 array->lambda[unit][count] = compute_lambda(sPlane[unit], 334 tPlane[unit], vPlane[unit], cx, cy, invQ, 335 texWidth[unit], texHeight[unit]); 336 } 337 } 338 } 339#endif 340 ix++; 341 count++; 342 coverage = compute_coveragef(pMin, pMid, pMax, ix, iy); 343 } 344 345 if (ix <= startX) 346 continue; 347 348 span.x = startX; 349 span.y = iy; 350 span.end = (GLuint) ix - (GLuint) startX; 351 ASSERT(span.interpMask == 0); 352#if defined(DO_MULTITEX) || defined(DO_TEX) 353 _mesa_write_texture_span(ctx, &span); 354#elif defined(DO_RGBA) 355 _mesa_write_rgba_span(ctx, &span); 356#elif defined(DO_INDEX) 357 _mesa_write_index_span(ctx, &span); 358#endif 359 } 360 } 361 else { 362 /* scan right to left */ 363 const GLfloat *pMin = vMin->win; 364 const GLfloat *pMid = vMid->win; 365 const GLfloat *pMax = vMax->win; 366 const GLfloat dxdy = majDx / majDy; 367 const GLfloat xAdj = dxdy > 0 ? dxdy : 0.0F; 368 GLfloat x = pMin[0] - (yMin - iyMin) * dxdy; 369 GLint iy; 370 for (iy = iyMin; iy < iyMax; iy++, x += dxdy) { 371 GLint ix, left, startX = (GLint) (x + xAdj); 372 GLuint count, n; 373 GLfloat coverage = 0.0F; 374 375 /* make sure we're not past the window edge */ 376 if (startX >= ctx->DrawBuffer->_Xmax) { 377 startX = ctx->DrawBuffer->_Xmax - 1; 378 } 379 380 /* skip fragments with zero coverage */ 381 while (startX >= 0) { 382 coverage = compute_coveragef(pMin, pMax, pMid, startX, iy); 383 if (coverage > 0.0F) 384 break; 385 startX--; 386 } 387 388 /* enter interior of triangle */ 389 ix = startX; 390 count = 0; 391 while (coverage > 0.0F) { 392 /* (cx,cy) = center of fragment */ 393 const GLfloat cx = ix + 0.5F, cy = iy + 0.5F; 394 struct span_arrays *array = span.array; 395#ifdef DO_INDEX 396 array->coverage[ix] = (GLfloat) compute_coveragei(pMin, pMax, pMid, ix, iy); 397#else 398 array->coverage[ix] = coverage; 399#endif 400#ifdef DO_Z 401 array->z[ix] = (GLdepth) solve_plane(cx, cy, zPlane); 402#endif 403#ifdef DO_FOG 404 array->fog[ix] = solve_plane(cx, cy, fogPlane); 405#endif 406#ifdef DO_RGBA 407 array->rgba[ix][RCOMP] = solve_plane_chan(cx, cy, rPlane); 408 array->rgba[ix][GCOMP] = solve_plane_chan(cx, cy, gPlane); 409 array->rgba[ix][BCOMP] = solve_plane_chan(cx, cy, bPlane); 410 array->rgba[ix][ACOMP] = solve_plane_chan(cx, cy, aPlane); 411#endif 412#ifdef DO_INDEX 413 array->index[ix] = (GLint) solve_plane(cx, cy, iPlane); 414#endif 415#ifdef DO_SPEC 416 array->spec[ix][RCOMP] = solve_plane_chan(cx, cy, srPlane); 417 array->spec[ix][GCOMP] = solve_plane_chan(cx, cy, sgPlane); 418 array->spec[ix][BCOMP] = solve_plane_chan(cx, cy, sbPlane); 419#endif 420#ifdef DO_TEX 421 { 422 const GLfloat invQ = solve_plane_recip(cx, cy, vPlane); 423 array->texcoords[0][ix][0] = solve_plane(cx, cy, sPlane) * invQ; 424 array->texcoords[0][ix][1] = solve_plane(cx, cy, tPlane) * invQ; 425 array->texcoords[0][ix][2] = solve_plane(cx, cy, uPlane) * invQ; 426 array->lambda[0][ix] = compute_lambda(sPlane, tPlane, vPlane, 427 cx, cy, invQ, texWidth, texHeight); 428 } 429#elif defined(DO_MULTITEX) 430 { 431 GLuint unit; 432 for (unit = 0; unit < ctx->Const.MaxTextureUnits; unit++) { 433 if (ctx->Texture.Unit[unit]._ReallyEnabled) { 434 GLfloat invQ = solve_plane_recip(cx, cy, vPlane[unit]); 435 array->texcoords[unit][ix][0] = solve_plane(cx, cy, sPlane[unit]) * invQ; 436 array->texcoords[unit][ix][1] = solve_plane(cx, cy, tPlane[unit]) * invQ; 437 array->texcoords[unit][ix][2] = solve_plane(cx, cy, uPlane[unit]) * invQ; 438 array->lambda[unit][ix] = compute_lambda(sPlane[unit], 439 tPlane[unit], 440 vPlane[unit], 441 cx, cy, invQ, 442 texWidth[unit], 443 texHeight[unit]); 444 } 445 } 446 } 447#endif 448 ix--; 449 count++; 450 coverage = compute_coveragef(pMin, pMax, pMid, ix, iy); 451 } 452 453 if (startX <= ix) 454 continue; 455 456 n = (GLuint) startX - (GLuint) ix; 457 458 left = ix + 1; 459 460 /* shift all values to the left */ 461 /* XXX this is temporary */ 462 { 463 struct span_arrays *array = span.array; 464 GLint j; 465 for (j = 0; j < (GLint) n; j++) { 466#ifdef DO_RGBA 467 COPY_CHAN4(array->rgba[j], array->rgba[j + left]); 468#endif 469#ifdef DO_SPEC 470 COPY_CHAN4(array->spec[j], array->spec[j + left]); 471#endif 472#ifdef DO_INDEX 473 array->index[j] = array->index[j + left]; 474#endif 475#ifdef DO_Z 476 array->z[j] = array->z[j + left]; 477#endif 478#ifdef DO_FOG 479 array->fog[j] = array->fog[j + left]; 480#endif 481#ifdef DO_TEX 482 COPY_4V(array->texcoords[0][j], array->texcoords[0][j + left]); 483#endif 484#if defined(DO_MULTITEX) || defined(DO_TEX) 485 array->lambda[0][j] = array->lambda[0][j + left]; 486#endif 487 array->coverage[j] = array->coverage[j + left]; 488 } 489 } 490#ifdef DO_MULTITEX 491 /* shift texcoords */ 492 { 493 struct span_arrays *array = span.array; 494 GLuint unit; 495 for (unit = 0; unit < ctx->Const.MaxTextureUnits; unit++) { 496 if (ctx->Texture.Unit[unit]._ReallyEnabled) { 497 GLint j; 498 for (j = 0; j < (GLint) n; j++) { 499 array->texcoords[unit][j][0] = array->texcoords[unit][j + left][0]; 500 array->texcoords[unit][j][1] = array->texcoords[unit][j + left][1]; 501 array->texcoords[unit][j][2] = array->texcoords[unit][j + left][2]; 502 array->lambda[unit][j] = array->lambda[unit][j + left]; 503 } 504 } 505 } 506 } 507#endif 508 509 span.x = left; 510 span.y = iy; 511 span.end = n; 512 ASSERT(span.interpMask == 0); 513#if defined(DO_MULTITEX) || defined(DO_TEX) 514 _mesa_write_texture_span(ctx, &span); 515#elif defined(DO_RGBA) 516 _mesa_write_rgba_span(ctx, &span); 517#elif defined(DO_INDEX) 518 _mesa_write_index_span(ctx, &span); 519#endif 520 } 521 } 522} 523 524 525#ifdef DO_Z 526#undef DO_Z 527#endif 528 529#ifdef DO_FOG 530#undef DO_FOG 531#endif 532 533#ifdef DO_RGBA 534#undef DO_RGBA 535#endif 536 537#ifdef DO_INDEX 538#undef DO_INDEX 539#endif 540 541#ifdef DO_SPEC 542#undef DO_SPEC 543#endif 544 545#ifdef DO_TEX 546#undef DO_TEX 547#endif 548 549#ifdef DO_MULTITEX 550#undef DO_MULTITEX 551#endif 552 553#ifdef DO_OCCLUSION_TEST 554#undef DO_OCCLUSION_TEST 555#endif 556