s_aatritemp.h revision bf80e1ed620836e2ca0dd3f7d2d4cb187d17563d
1/* $Id: s_aatritemp.h,v 1.29 2002/04/19 14:05:50 brianp Exp $ */
2
3/*
4 * Mesa 3-D graphics library
5 * Version:  4.1
6 *
7 * Copyright (C) 1999-2002  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 = SWRAST_CONTEXT(ctx)->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_UNITS][4];  /* texture S */
80   GLfloat tPlane[MAX_TEXTURE_UNITS][4];  /* texture T */
81   GLfloat uPlane[MAX_TEXTURE_UNITS][4];  /* texture R */
82   GLfloat vPlane[MAX_TEXTURE_UNITS][4];  /* texture Q */
83   GLfloat texWidth[MAX_TEXTURE_UNITS], texHeight[MAX_TEXTURE_UNITS];
84#endif
85   GLfloat bf = SWRAST_CONTEXT(ctx)->_backface_sign;
86
87
88   INIT_SPAN(span, GL_POLYGON, 0, 0, SPAN_COVERAGE);
89
90   /* determine bottom to top order of vertices */
91   {
92      GLfloat y0 = v0->win[1];
93      GLfloat y1 = v1->win[1];
94      GLfloat y2 = v2->win[1];
95      if (y0 <= y1) {
96	 if (y1 <= y2) {
97	    vMin = v0;   vMid = v1;   vMax = v2;   /* y0<=y1<=y2 */
98	 }
99	 else if (y2 <= y0) {
100	    vMin = v2;   vMid = v0;   vMax = v1;   /* y2<=y0<=y1 */
101	 }
102	 else {
103	    vMin = v0;   vMid = v2;   vMax = v1;  bf = -bf; /* y0<=y2<=y1 */
104	 }
105      }
106      else {
107	 if (y0 <= y2) {
108	    vMin = v1;   vMid = v0;   vMax = v2;  bf = -bf; /* y1<=y0<=y2 */
109	 }
110	 else if (y2 <= y1) {
111	    vMin = v2;   vMid = v1;   vMax = v0;  bf = -bf; /* y2<=y1<=y0 */
112	 }
113	 else {
114	    vMin = v1;   vMid = v2;   vMax = v0;   /* y1<=y2<=y0 */
115	 }
116      }
117   }
118
119   majDx = vMax->win[0] - vMin->win[0];
120   majDy = vMax->win[1] - vMin->win[1];
121
122   {
123      const GLfloat botDx = vMid->win[0] - vMin->win[0];
124      const GLfloat botDy = vMid->win[1] - vMin->win[1];
125      const GLfloat area = majDx * botDy - botDx * majDy;
126      ltor = (GLboolean) (area < 0.0F);
127      /* Do backface culling */
128      if (area * bf < 0 || area == 0 || IS_INF_OR_NAN(area))
129	 return;
130   }
131
132#ifndef DO_OCCLUSION_TEST
133   ctx->OcclusionResult = GL_TRUE;
134#endif
135
136   /* Plane equation setup:
137    * We evaluate plane equations at window (x,y) coordinates in order
138    * to compute color, Z, fog, texcoords, etc.  This isn't terribly
139    * efficient but it's easy and reliable.
140    */
141#ifdef DO_Z
142   compute_plane(p0, p1, p2, p0[2], p1[2], p2[2], zPlane);
143   span->arrayMask |= SPAN_Z;
144#endif
145#ifdef DO_FOG
146   compute_plane(p0, p1, p2, v0->fog, v1->fog, v2->fog, fogPlane);
147   span->arrayMask |= SPAN_FOG;
148#endif
149#ifdef DO_RGBA
150   if (ctx->Light.ShadeModel == GL_SMOOTH) {
151      compute_plane(p0, p1, p2, v0->color[0], v1->color[0], v2->color[0], rPlane);
152      compute_plane(p0, p1, p2, v0->color[1], v1->color[1], v2->color[1], gPlane);
153      compute_plane(p0, p1, p2, v0->color[2], v1->color[2], v2->color[2], bPlane);
154      compute_plane(p0, p1, p2, v0->color[3], v1->color[3], v2->color[3], aPlane);
155   }
156   else {
157      constant_plane(v2->color[RCOMP], rPlane);
158      constant_plane(v2->color[GCOMP], gPlane);
159      constant_plane(v2->color[BCOMP], bPlane);
160      constant_plane(v2->color[ACOMP], aPlane);
161   }
162   span->arrayMask |= SPAN_RGBA;
163#endif
164#ifdef DO_INDEX
165   if (ctx->Light.ShadeModel == GL_SMOOTH) {
166      compute_plane(p0, p1, p2, (GLfloat) v0->index,
167                    (GLfloat) v1->index, (GLfloat) v2->index, iPlane);
168   }
169   else {
170      constant_plane((GLfloat) v2->index, iPlane);
171   }
172   span->arrayMask |= SPAN_INDEX;
173#endif
174#ifdef DO_SPEC
175   if (ctx->Light.ShadeModel == GL_SMOOTH) {
176      compute_plane(p0, p1, p2, v0->specular[0], v1->specular[0], v2->specular[0],srPlane);
177      compute_plane(p0, p1, p2, v0->specular[1], v1->specular[1], v2->specular[1],sgPlane);
178      compute_plane(p0, p1, p2, v0->specular[2], v1->specular[2], v2->specular[2],sbPlane);
179   }
180   else {
181      constant_plane(v2->specular[RCOMP], srPlane);
182      constant_plane(v2->specular[GCOMP], sgPlane);
183      constant_plane(v2->specular[BCOMP], sbPlane);
184   }
185   span->arrayMask |= SPAN_SPEC;
186#endif
187#ifdef DO_TEX
188   {
189      const struct gl_texture_object *obj = ctx->Texture.Unit[0]._Current;
190      const struct gl_texture_image *texImage = obj->Image[obj->BaseLevel];
191      const GLfloat invW0 = v0->win[3];
192      const GLfloat invW1 = v1->win[3];
193      const GLfloat invW2 = v2->win[3];
194      const GLfloat s0 = v0->texcoord[0][0] * invW0;
195      const GLfloat s1 = v1->texcoord[0][0] * invW1;
196      const GLfloat s2 = v2->texcoord[0][0] * invW2;
197      const GLfloat t0 = v0->texcoord[0][1] * invW0;
198      const GLfloat t1 = v1->texcoord[0][1] * invW1;
199      const GLfloat t2 = v2->texcoord[0][1] * invW2;
200      const GLfloat r0 = v0->texcoord[0][2] * invW0;
201      const GLfloat r1 = v1->texcoord[0][2] * invW1;
202      const GLfloat r2 = v2->texcoord[0][2] * invW2;
203      const GLfloat q0 = v0->texcoord[0][3] * invW0;
204      const GLfloat q1 = v1->texcoord[0][3] * invW1;
205      const GLfloat q2 = v2->texcoord[0][3] * invW2;
206      compute_plane(p0, p1, p2, s0, s1, s2, sPlane);
207      compute_plane(p0, p1, p2, t0, t1, t2, tPlane);
208      compute_plane(p0, p1, p2, r0, r1, r2, uPlane);
209      compute_plane(p0, p1, p2, q0, q1, q2, vPlane);
210      texWidth = (GLfloat) texImage->Width;
211      texHeight = (GLfloat) texImage->Height;
212   }
213   span->arrayMask |= (SPAN_TEXTURE | SPAN_LAMBDA);
214#elif defined(DO_MULTITEX)
215   {
216      GLuint u;
217      for (u = 0; u < ctx->Const.MaxTextureUnits; u++) {
218         if (ctx->Texture.Unit[u]._ReallyEnabled) {
219            const struct gl_texture_object *obj = ctx->Texture.Unit[u]._Current;
220            const struct gl_texture_image *texImage = obj->Image[obj->BaseLevel];
221            const GLfloat invW0 = v0->win[3];
222            const GLfloat invW1 = v1->win[3];
223            const GLfloat invW2 = v2->win[3];
224            const GLfloat s0 = v0->texcoord[u][0] * invW0;
225            const GLfloat s1 = v1->texcoord[u][0] * invW1;
226            const GLfloat s2 = v2->texcoord[u][0] * invW2;
227            const GLfloat t0 = v0->texcoord[u][1] * invW0;
228            const GLfloat t1 = v1->texcoord[u][1] * invW1;
229            const GLfloat t2 = v2->texcoord[u][1] * invW2;
230            const GLfloat r0 = v0->texcoord[u][2] * invW0;
231            const GLfloat r1 = v1->texcoord[u][2] * invW1;
232            const GLfloat r2 = v2->texcoord[u][2] * invW2;
233            const GLfloat q0 = v0->texcoord[u][3] * invW0;
234            const GLfloat q1 = v1->texcoord[u][3] * invW1;
235            const GLfloat q2 = v2->texcoord[u][3] * invW2;
236            compute_plane(p0, p1, p2, s0, s1, s2, sPlane[u]);
237            compute_plane(p0, p1, p2, t0, t1, t2, tPlane[u]);
238            compute_plane(p0, p1, p2, r0, r1, r2, uPlane[u]);
239            compute_plane(p0, p1, p2, q0, q1, q2, vPlane[u]);
240            texWidth[u]  = (GLfloat) texImage->Width;
241            texHeight[u] = (GLfloat) texImage->Height;
242         }
243      }
244   }
245   span->arrayMask |= (SPAN_TEXTURE | SPAN_LAMBDA);
246#endif
247
248   /* Begin bottom-to-top scan over the triangle.
249    * The long edge will either be on the left or right side of the
250    * triangle.  We always scan from the long edge toward the shorter
251    * edges, stopping when we find that coverage = 0.  If the long edge
252    * is on the left we scan left-to-right.  Else, we scan right-to-left.
253    */
254   yMin = vMin->win[1];
255   yMax = vMax->win[1];
256   iyMin = (GLint) yMin;
257   iyMax = (GLint) yMax + 1;
258
259   if (ltor) {
260      /* scan left to right */
261      const GLfloat *pMin = vMin->win;
262      const GLfloat *pMid = vMid->win;
263      const GLfloat *pMax = vMax->win;
264      const GLfloat dxdy = majDx / majDy;
265      const GLfloat xAdj = dxdy < 0.0F ? -dxdy : 0.0F;
266      GLfloat x = pMin[0] - (yMin - iyMin) * dxdy;
267      GLint iy;
268      for (iy = iyMin; iy < iyMax; iy++, x += dxdy) {
269         GLint ix, startX = (GLint) (x - xAdj);
270         GLuint count;
271         GLfloat coverage = 0.0F;
272
273         /* skip over fragments with zero coverage */
274         while (startX < MAX_WIDTH) {
275            coverage = compute_coveragef(pMin, pMid, pMax, startX, iy);
276            if (coverage > 0.0F)
277               break;
278            startX++;
279         }
280
281         /* enter interior of triangle */
282         ix = startX;
283         count = 0;
284         while (coverage > 0.0F) {
285            /* (cx,cy) = center of fragment */
286            const GLfloat cx = ix + 0.5F, cy = iy + 0.5F;
287#ifdef DO_INDEX
288            span->coverage[count] = (GLfloat) compute_coveragei(pMin, pMid, pMax, ix, iy);
289#else
290            span->coverage[count] = coverage;
291#endif
292#ifdef DO_Z
293            span->zArray[count] = (GLdepth) solve_plane(cx, cy, zPlane);
294#endif
295#ifdef DO_FOG
296	    span->fogArray[count] = solve_plane(cx, cy, fogPlane);
297#endif
298#ifdef DO_RGBA
299            span->color.rgba[count][RCOMP] = solve_plane_chan(cx, cy, rPlane);
300            span->color.rgba[count][GCOMP] = solve_plane_chan(cx, cy, gPlane);
301            span->color.rgba[count][BCOMP] = solve_plane_chan(cx, cy, bPlane);
302            span->color.rgba[count][ACOMP] = solve_plane_chan(cx, cy, aPlane);
303#endif
304#ifdef DO_INDEX
305            span->color.index[count] = (GLint) solve_plane(cx, cy, iPlane);
306#endif
307#ifdef DO_SPEC
308            span->specArray[count][RCOMP] = solve_plane_chan(cx, cy, srPlane);
309            span->specArray[count][GCOMP] = solve_plane_chan(cx, cy, sgPlane);
310            span->specArray[count][BCOMP] = solve_plane_chan(cx, cy, sbPlane);
311#endif
312#ifdef DO_TEX
313            {
314               const GLfloat invQ = solve_plane_recip(cx, cy, vPlane);
315               span->texcoords[0][count][0] = solve_plane(cx, cy, sPlane) * invQ;
316               span->texcoords[0][count][1] = solve_plane(cx, cy, tPlane) * invQ;
317               span->texcoords[0][count][2] = solve_plane(cx, cy, uPlane) * invQ;
318               span->lambda[0][count] = compute_lambda(sPlane, tPlane, vPlane,
319                                                      cx, cy, invQ,
320                                                      texWidth, texHeight);
321            }
322#elif defined(DO_MULTITEX)
323            {
324               GLuint unit;
325               for (unit = 0; unit < ctx->Const.MaxTextureUnits; unit++) {
326                  if (ctx->Texture.Unit[unit]._ReallyEnabled) {
327                     GLfloat invQ = solve_plane_recip(cx, cy, vPlane[unit]);
328                     span->texcoords[unit][count][0] = solve_plane(cx, cy, sPlane[unit]) * invQ;
329                     span->texcoords[unit][count][1] = solve_plane(cx, cy, tPlane[unit]) * invQ;
330                     span->texcoords[unit][count][2] = solve_plane(cx, cy, uPlane[unit]) * invQ;
331                     span->lambda[unit][count] = compute_lambda(sPlane[unit],
332                                      tPlane[unit], vPlane[unit], cx, cy, invQ,
333                                      texWidth[unit], texHeight[unit]);
334                  }
335               }
336            }
337#endif
338            ix++;
339            count++;
340            coverage = compute_coveragef(pMin, pMid, pMax, ix, iy);
341         }
342
343         if (ix <= startX)
344            continue;
345
346         span->x = startX;
347         span->y = iy;
348         span->end = (GLuint) ix - (GLuint) startX;
349         ASSERT(span->interpMask == 0);
350#if defined(DO_MULTITEX) || defined(DO_TEX)
351         _mesa_write_texture_span(ctx, span);
352#elif defined(DO_RGBA)
353         _mesa_write_rgba_span(ctx, span);
354#elif defined(DO_INDEX)
355         _mesa_write_index_span(ctx, span);
356#endif
357      }
358   }
359   else {
360      /* scan right to left */
361      const GLfloat *pMin = vMin->win;
362      const GLfloat *pMid = vMid->win;
363      const GLfloat *pMax = vMax->win;
364      const GLfloat dxdy = majDx / majDy;
365      const GLfloat xAdj = dxdy > 0 ? dxdy : 0.0F;
366      GLfloat x = pMin[0] - (yMin - iyMin) * dxdy;
367      GLint iy;
368      for (iy = iyMin; iy < iyMax; iy++, x += dxdy) {
369         GLint ix, left, startX = (GLint) (x + xAdj);
370         GLuint count, n;
371         GLfloat coverage = 0.0F;
372
373         /* make sure we're not past the window edge */
374         if (startX >= ctx->DrawBuffer->_Xmax) {
375            startX = ctx->DrawBuffer->_Xmax - 1;
376         }
377
378         /* skip fragments with zero coverage */
379         while (startX >= 0) {
380            coverage = compute_coveragef(pMin, pMax, pMid, startX, iy);
381            if (coverage > 0.0F)
382               break;
383            startX--;
384         }
385
386         /* enter interior of triangle */
387         ix = startX;
388         count = 0;
389         while (coverage > 0.0F) {
390            /* (cx,cy) = center of fragment */
391            const GLfloat cx = ix + 0.5F, cy = iy + 0.5F;
392#ifdef DO_INDEX
393            span->coverage[ix] = (GLfloat) compute_coveragei(pMin, pMax, pMid, ix, iy);
394#else
395            span->coverage[ix] = coverage;
396#endif
397#ifdef DO_Z
398            span->zArray[ix] = (GLdepth) solve_plane(cx, cy, zPlane);
399#endif
400#ifdef DO_FOG
401            span->fogArray[ix] = solve_plane(cx, cy, fogPlane);
402#endif
403#ifdef DO_RGBA
404            span->color.rgba[ix][RCOMP] = solve_plane_chan(cx, cy, rPlane);
405            span->color.rgba[ix][GCOMP] = solve_plane_chan(cx, cy, gPlane);
406            span->color.rgba[ix][BCOMP] = solve_plane_chan(cx, cy, bPlane);
407            span->color.rgba[ix][ACOMP] = solve_plane_chan(cx, cy, aPlane);
408#endif
409#ifdef DO_INDEX
410            span->color.index[ix] = (GLint) solve_plane(cx, cy, iPlane);
411#endif
412#ifdef DO_SPEC
413            span->specArray[ix][RCOMP] = solve_plane_chan(cx, cy, srPlane);
414            span->specArray[ix][GCOMP] = solve_plane_chan(cx, cy, sgPlane);
415            span->specArray[ix][BCOMP] = solve_plane_chan(cx, cy, sbPlane);
416#endif
417#ifdef DO_TEX
418            {
419               const GLfloat invQ = solve_plane_recip(cx, cy, vPlane);
420               span->texcoords[0][ix][0] = solve_plane(cx, cy, sPlane) * invQ;
421               span->texcoords[0][ix][1] = solve_plane(cx, cy, tPlane) * invQ;
422               span->texcoords[0][ix][2] = solve_plane(cx, cy, uPlane) * invQ;
423               span->lambda[0][ix] = compute_lambda(sPlane, tPlane, vPlane,
424                                          cx, cy, invQ, texWidth, texHeight);
425            }
426#elif defined(DO_MULTITEX)
427            {
428               GLuint unit;
429               for (unit = 0; unit < ctx->Const.MaxTextureUnits; unit++) {
430                  if (ctx->Texture.Unit[unit]._ReallyEnabled) {
431                     GLfloat invQ = solve_plane_recip(cx, cy, vPlane[unit]);
432                     span->texcoords[unit][ix][0] = solve_plane(cx, cy, sPlane[unit]) * invQ;
433                     span->texcoords[unit][ix][1] = solve_plane(cx, cy, tPlane[unit]) * invQ;
434                     span->texcoords[unit][ix][2] = solve_plane(cx, cy, uPlane[unit]) * invQ;
435                     span->lambda[unit][ix] = compute_lambda(sPlane[unit],
436                                                            tPlane[unit],
437                                                            vPlane[unit],
438                                                            cx, cy, invQ,
439                                                            texWidth[unit],
440                                                            texHeight[unit]);
441                  }
442               }
443            }
444#endif
445            ix--;
446            count++;
447            coverage = compute_coveragef(pMin, pMax, pMid, ix, iy);
448         }
449
450         if (startX <= ix)
451            continue;
452
453         n = (GLuint) startX - (GLuint) ix;
454
455         left = ix + 1;
456
457         /* shift all values to the left */
458         /* XXX this is temporary */
459         {
460            GLint j;
461            for (j = 0; j < (GLint) n; j++) {
462#ifdef DO_RGBA
463               COPY_4V(span->color.rgba[j], span->color.rgba[j + left]);
464#endif
465#ifdef DO_SPEC
466               COPY_4V(span->specArray[j], span->specArray[j + left]);
467#endif
468#ifdef DO_INDEX
469               span->color.index[j] = span->color.index[j + left];
470#endif
471#ifdef DO_Z
472               span->zArray[j] = span->zArray[j + left];
473#endif
474#ifdef DO_FOG
475               span->fogArray[j] = span->fogArray[j + left];
476#endif
477#ifdef DO_TEX
478               COPY_4V(span->texcoords[0][j], span->texcoords[0][j + left]);
479#endif
480#if defined(DO_MULTITEX) || defined(DO_TEX)
481               span->lambda[0][j] = span->lambda[0][j + left];
482#endif
483               span->coverage[j] = span->coverage[j + left];
484            }
485         }
486#ifdef DO_MULTITEX
487         /* shift texcoords */
488         {
489            GLuint unit;
490            for (unit = 0; unit < ctx->Const.MaxTextureUnits; unit++) {
491               if (ctx->Texture.Unit[unit]._ReallyEnabled) {
492                  GLint j;
493                  for (j = 0; j < (GLint) n; j++) {
494		     span->texcoords[unit][j][0] = span->texcoords[unit][j + left][0];
495                     span->texcoords[unit][j][1] = span->texcoords[unit][j + left][1];
496                     span->texcoords[unit][j][2] = span->texcoords[unit][j + left][2];
497                     span->lambda[unit][j] = span->lambda[unit][j + left];
498                  }
499               }
500            }
501         }
502#endif
503
504         span->x = left;
505         span->y = iy;
506         span->end = n;
507         ASSERT(span->interpMask == 0);
508#if defined(DO_MULTITEX) || defined(DO_TEX)
509         _mesa_write_texture_span(ctx, span);
510#elif defined(DO_RGBA)
511         _mesa_write_rgba_span(ctx, span);
512#elif defined(DO_INDEX)
513         _mesa_write_index_span(ctx, span);
514#endif
515      }
516   }
517}
518
519
520#ifdef DO_Z
521#undef DO_Z
522#endif
523
524#ifdef DO_FOG
525#undef DO_FOG
526#endif
527
528#ifdef DO_RGBA
529#undef DO_RGBA
530#endif
531
532#ifdef DO_INDEX
533#undef DO_INDEX
534#endif
535
536#ifdef DO_SPEC
537#undef DO_SPEC
538#endif
539
540#ifdef DO_TEX
541#undef DO_TEX
542#endif
543
544#ifdef DO_MULTITEX
545#undef DO_MULTITEX
546#endif
547
548#ifdef DO_OCCLUSION_TEST
549#undef DO_OCCLUSION_TEST
550#endif
551