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