1 /*
2 ** gl_sky.cpp
3 **
4 ** Draws the sky.  Loosely based on the JDoom sky and the ZDoomGL 0.66.2 sky.
5 **
6 **---------------------------------------------------------------------------
7 ** Copyright 2003 Tim Stump
8 ** Copyright 2005 Christoph Oelckers
9 ** Copyright 2009 Andrey Budko
10 ** All rights reserved.
11 **
12 ** Redistribution and use in source and binary forms, with or without
13 ** modification, are permitted provided that the following conditions
14 ** are met:
15 **
16 ** 1. Redistributions of source code must retain the above copyright
17 **    notice, this list of conditions and the following disclaimer.
18 ** 2. Redistributions in binary form must reproduce the above copyright
19 **    notice, this list of conditions and the following disclaimer in the
20 **    documentation and/or other materials provided with the distribution.
21 ** 3. The name of the author may not be used to endorse or promote products
22 **    derived from this software without specific prior written permission.
23 ** 4. Full disclosure of the entire project's source code, except for third
24 **    party libraries is mandatory. (NOTE: This clause is non-negotiable!)
25 **
26 ** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
27 ** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
28 ** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
29 ** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
30 ** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
31 ** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
32 ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
33 ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
34 ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
35 ** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36 **---------------------------------------------------------------------------
37 **
38 */
39 
40 #ifdef HAVE_CONFIG_H
41 #include "config.h"
42 #endif
43 
44 #include "gl_opengl.h"
45 
46 #include <SDL.h>
47 
48 #include "doomstat.h"
49 #include "v_video.h"
50 #include "gl_intern.h"
51 #include "r_plane.h"
52 #include "r_sky.h"
53 #include "r_main.h"
54 #include "sc_man.h"
55 #include "m_misc.h"
56 #include "lprintf.h"
57 
58 #include "e6y.h"
59 
60 typedef struct
61 {
62   int mode;
63   int vertexcount;
64   int vertexindex;
65   int use_texture;
66 } GLSkyLoopDef;
67 
68 typedef struct
69 {
70   int id;
71   int rows, columns;
72   int loopcount;
73   GLSkyLoopDef *loops;
74   vbo_vertex_t *data;
75 } GLSkyVBO;
76 
77 int gl_skymode;
78 int gl_drawskys;
79 // Sky stretching is rather pointless with the GL renderer
80 // now that it can handle all sky heights.
81 int gl_stretchsky = false;
82 
83 static PalEntry_t *SkyColor;
84 
85 SkyBoxParams_t SkyBox;
86 float y_offset_saved;
87 
88 // skybox
89 box_skybox_t *BoxSkybox = NULL;
90 int BoxSkyboxCount = 0;
91 
92 box_skybox_t *BoxSkybox_default;
93 
gld_InitSky(void)94 void gld_InitSky(void)
95 {
96   memset(&SkyBox, 0, sizeof(SkyBox));
97   SkyBox.index = -1;
98   y_offset_saved = 0;
99 }
100 
gld_InitFrameSky(void)101 void gld_InitFrameSky(void)
102 {
103   SkyBox.type = SKY_NONE;
104   SkyBox.wall.gltexture = NULL;
105   SkyBox.x_scale = 0;
106   SkyBox.y_scale = 0;
107   SkyBox.x_offset = 0;
108   SkyBox.y_offset = 0;
109   SkyBox.side = NULL;
110 }
111 
gld_DrawFakeSkyStrips(void)112 void gld_DrawFakeSkyStrips(void)
113 {
114   int i;
115 
116   // This draws a valid z-buffer into the stencil's contents to ensure it
117   // doesn't get overwritten by the level's geometry.
118 
119   // Because some of outdated hardware has no support for
120   // glColorMask(0, 0, 0, 0) or something,
121   // I need to render fake strips of sky before dome with using
122   // full clearing of color buffer (only in compatibility mode)
123 
124   if (!gl_compatibility)
125   {
126     glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); // no graphics
127   }
128   gld_EnableTexture2D(GL_TEXTURE0_ARB, false);
129 
130   for (i = gld_drawinfo.num_items[GLDIT_SWALL] - 1; i >= 0; i--)
131   {
132     GLWall* wall = gld_drawinfo.items[GLDIT_SWALL][i].item.wall;
133 
134     glBegin(GL_TRIANGLE_STRIP);
135     glVertex3f(wall->glseg->x1,wall->ytop,wall->glseg->z1);
136     glVertex3f(wall->glseg->x1,wall->ybottom,wall->glseg->z1);
137     glVertex3f(wall->glseg->x2,wall->ytop,wall->glseg->z2);
138     glVertex3f(wall->glseg->x2,wall->ybottom,wall->glseg->z2);
139     glEnd();
140   }
141 
142   gld_EnableTexture2D(GL_TEXTURE0_ARB, true);
143   if (!gl_compatibility)
144   {
145     glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
146   }
147   else
148   {
149     glClear(GL_COLOR_BUFFER_BIT);
150   }
151 }
152 
gld_GetScreenSkyScale(GLWall * wall,float * scale_x,float * scale_y)153 void gld_GetScreenSkyScale(GLWall *wall, float *scale_x, float *scale_y)
154 {
155   float sx, sy;
156 
157   sx = (wall->flag == GLDWF_SKYFLIP ? -128.0f : 128.0f);
158 
159   if (!mlook_or_fov)
160   {
161     sx = sx / (float)wall->gltexture->buffer_width;
162     sy = 200.0f / 160.0f;//wall->gltexture->buffer_height;
163   }
164   else
165   {
166     sx = sx * skyscale / (float)wall->gltexture->buffer_width;
167     sy = 127.0f * skyscale / 160.0f;
168   }
169 
170   *scale_x = sx;
171   *scale_y = sy;
172 }
173 
174 // Sky textures with a zero index should be forced
175 // See third episode of requiem.wad
gld_AddSkyTexture(GLWall * wall,int sky1,int sky2,int skytype)176 void gld_AddSkyTexture(GLWall *wall, int sky1, int sky2, int skytype)
177 {
178   side_t *s = NULL;
179   line_t *l = NULL;
180   wall->gltexture = NULL;
181 
182   if ((sky1) & PL_SKYFLAT)
183   {
184     l = &lines[sky1 & ~PL_SKYFLAT];
185   }
186   else
187   {
188     if ((sky2) & PL_SKYFLAT)
189     {
190       l = &lines[sky2 & ~PL_SKYFLAT];
191     }
192   }
193 
194   if (l)
195   {
196     s = *l->sidenum + sides;
197     SkyBox.side = s;
198     wall->gltexture = gld_RegisterTexture(texturetranslation[s->toptexture], false,
199       texturetranslation[s->toptexture] == skytexture || l->special == 271 || l->special == 272);
200     if (wall->gltexture)
201     {
202       if (!mlook_or_fov)
203       {
204         wall->skyyaw  = -2.0f*((-(float)((viewangle+s->textureoffset)>>ANGLETOFINESHIFT)*360.0f/FINEANGLES)/90.0f);
205         wall->skyymid = 200.0f/319.5f*(((float)s->rowoffset/(float)FRACUNIT - 28.0f)/100.0f);
206       }
207       else
208       {
209         wall->skyyaw  = -2.0f*(((270.0f-(float)((viewangle+s->textureoffset)>>ANGLETOFINESHIFT)*360.0f/FINEANGLES)+90.0f)/90.0f/skyscale);
210         wall->skyymid = skyYShift+(((float)s->rowoffset/(float)FRACUNIT)/100.0f);
211       }
212       wall->flag = (l->special == 272 ? GLDWF_SKY : GLDWF_SKYFLIP);
213     }
214   }
215   else
216   {
217     wall->gltexture = gld_RegisterTexture(skytexture, false, true);
218     if (wall->gltexture)
219     {
220       wall->skyyaw  = skyXShift;
221       wall->skyymid = skyYShift;
222       wall->flag = GLDWF_SKY;
223     }
224   }
225 
226   if (wall->gltexture)
227   {
228     SkyBox.type |= skytype;
229 
230     wall->gltexture->flags |= GLTEXTURE_SKY;
231 
232     gld_AddDrawItem(GLDIT_SWALL, wall);
233 
234     if (!SkyBox.wall.gltexture)
235     {
236       SkyBox.wall = *wall;
237 
238       switch (gl_drawskys)
239       {
240       case skytype_standard:
241         gld_GetScreenSkyScale(wall, &SkyBox.x_scale, &SkyBox.y_scale);
242         break;
243 
244       case skytype_screen:
245         if (s)
246         {
247           SkyBox.x_offset = (float)s->textureoffset;
248           SkyBox.y_offset = (float)s->rowoffset / (float)FRACUNIT;
249         }
250         break;
251       case skytype_skydome:
252         if (s)
253         {
254           SkyBox.x_offset = (float)s->textureoffset * 180.0f / (float)ANG180;
255           SkyBox.y_offset = (float)s->rowoffset / (float)FRACUNIT;
256         }
257         break;
258       }
259     }
260   }
261 }
262 
gld_DrawStripsSky(void)263 void gld_DrawStripsSky(void)
264 {
265   int i;
266   float skyymid_multiplier;
267   GLTexture *gltexture = NULL;
268 
269   if (gl_drawskys == skytype_standard)
270   {
271     if (comp[comp_skymap] && gl_shared_texture_palette)
272       glDisable(GL_SHARED_TEXTURE_PALETTE_EXT);
273 
274     if (comp[comp_skymap] && (invul_method & INVUL_BW))
275       glTexEnvi(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_MODULATE);
276 
277     glEnable(GL_TEXTURE_GEN_S);
278     glEnable(GL_TEXTURE_GEN_T);
279     glEnable(GL_TEXTURE_GEN_Q);
280     if (comp[comp_skymap] || !(invul_method & INVUL_BW))
281       glColor4fv(gl_whitecolor);
282 
283     SetTextureMode(TM_OPAQUE);
284   }
285 
286   gld_EnableDetail(false);
287   glMatrixMode(GL_TEXTURE);
288 
289   skyymid_multiplier = 1.0f;
290   if (wide_ratio & 4)
291   {
292     skyymid_multiplier = (float)BaseRatioSizes[wide_ratio].multiplier / 48.0f;
293   }
294 
295   for (i = gld_drawinfo.num_items[GLDIT_SWALL] - 1; i >= 0; i--)
296   {
297     GLWall *wall = gld_drawinfo.items[GLDIT_SWALL][i].item.wall;
298 
299     gltexture = (gl_drawskys == skytype_none ? NULL : wall->gltexture);
300     gld_BindTexture(gltexture, 0);
301 
302     if (!gltexture)
303     {
304       glColor4f(1.0f,0.0f,0.0f,1.0f);
305     }
306 
307     if (gltexture)
308     {
309       float sx, sy;
310 
311       glPushMatrix();
312 
313       gld_GetScreenSkyScale(wall, &sx, &sy);
314       glScalef(sx, sy * skyymid_multiplier, 1.0f);
315       glTranslatef(wall->skyyaw, wall->skyymid / skyymid_multiplier, 0.0f);
316     }
317 
318 #if 0
319     {
320       float r = (float)(wall->seg->sidedef - sides) / (float)(numsides - 1);
321       float g = (float)wall->seg->linedef->iLineID / (float)(numlines - 1);
322       float b = (float)i / (float)(gld_drawinfo.num_items[GLDIT_SWALL] - 1);
323       glColor4f(r, g, b, 1.0f);
324     }
325 #endif
326 
327     glBegin(GL_TRIANGLE_STRIP);
328     glVertex3f(wall->glseg->x1,wall->ytop,wall->glseg->z1);
329     glVertex3f(wall->glseg->x1,wall->ybottom,wall->glseg->z1);
330     glVertex3f(wall->glseg->x2,wall->ytop,wall->glseg->z2);
331     glVertex3f(wall->glseg->x2,wall->ybottom,wall->glseg->z2);
332     glEnd();
333 
334     if (gltexture)
335     {
336       glPopMatrix();
337     }
338   }
339 
340   glMatrixMode(GL_MODELVIEW);
341 
342   gld_DrawSkyCaps();
343 
344   if (gl_drawskys == skytype_standard)
345   {
346     glDisable(GL_TEXTURE_GEN_Q);
347     glDisable(GL_TEXTURE_GEN_T);
348     glDisable(GL_TEXTURE_GEN_S);
349 
350     if (comp[comp_skymap] && (invul_method & INVUL_BW))
351       glTexEnvi(GL_TEXTURE_ENV,GL_COMBINE_RGB,GL_COMBINE);
352 
353     if (comp[comp_skymap] && gl_shared_texture_palette)
354       glEnable(GL_SHARED_TEXTURE_PALETTE_EXT);
355 
356     SetTextureMode(TM_MODULATE);
357   }
358 }
359 
gld_DrawSkyCaps(void)360 void gld_DrawSkyCaps(void)
361 {
362   if (SkyBox.type && SkyBox.wall.gltexture)
363   {
364     dboolean mlook = GetMouseLook();
365 
366     if (mlook)
367     {
368       gld_BindTexture(SkyBox.wall.gltexture, 0);
369 
370       glMatrixMode(GL_TEXTURE);
371       glPushMatrix();
372 
373       glScalef(SkyBox.x_scale, SkyBox.y_scale, 1.0f);
374       glTranslatef(SkyBox.wall.skyyaw, SkyBox.wall.skyymid, 0.0f);
375 
376       if (SkyBox.type & SKY_CEILING)
377       {
378         glBegin(GL_TRIANGLE_STRIP);
379         glVertex3f(-MAXCOORD,+MAXCOORD,+MAXCOORD);
380         glVertex3f(+MAXCOORD,+MAXCOORD,+MAXCOORD);
381         glVertex3f(-MAXCOORD,+MAXCOORD,-MAXCOORD);
382         glVertex3f(+MAXCOORD,+MAXCOORD,-MAXCOORD);
383         glEnd();
384       }
385 
386       if (SkyBox.type & SKY_FLOOR)
387       {
388         glBegin(GL_TRIANGLE_STRIP);
389         glVertex3f(-MAXCOORD,-MAXCOORD,+MAXCOORD);
390         glVertex3f(+MAXCOORD,-MAXCOORD,+MAXCOORD);
391         glVertex3f(-MAXCOORD,-MAXCOORD,-MAXCOORD);
392         glVertex3f(+MAXCOORD,-MAXCOORD,-MAXCOORD);
393         glEnd();
394       }
395 
396       glPopMatrix();
397       glMatrixMode(GL_MODELVIEW);
398     }
399   }
400 }
401 
402 //===========================================================================
403 //
404 // averageColor
405 //  input is RGBA8 pixel format.
406 //	The resulting RGB color can be scaled uniformly so that the highest
407 //	component becomes one.
408 //
409 //===========================================================================
410 #define APART(c)			(((c)>>24)&0xff)
411 #define RPART(c)			(((c)>>16)&0xff)
412 #define GPART(c)			(((c)>>8)&0xff)
413 #define BPART(c)			((c)&0xff)
414 
averageColor(PalEntry_t * PalEntry,const unsigned int * data,int size,fixed_t maxout_factor)415 void averageColor(PalEntry_t * PalEntry, const unsigned int *data, int size, fixed_t maxout_factor)
416 {
417   int i;
418   int maxv;
419   unsigned int r, g, b;
420 
421   // First clear them.
422   r = g = b = 0;
423   if (size == 0)
424   {
425     PalEntry->r = 255;
426     PalEntry->g = 255;
427     PalEntry->b = 255;
428     return;
429   }
430   for(i = 0; i < size; i++)
431   {
432     r += BPART(data[i]);
433     g += GPART(data[i]);
434     b += RPART(data[i]);
435   }
436 
437   r = r / size;
438   g = g / size;
439   b = b / size;
440 
441   maxv=MAX(MAX(r,g),b);
442 
443   if(maxv && maxout_factor)
444   {
445     maxout_factor = FixedMul(maxout_factor, 255);
446     r = r * maxout_factor / maxv;
447     g = g * maxout_factor / maxv;
448     b = b * maxout_factor / maxv;
449   }
450 
451   PalEntry->r = r;
452   PalEntry->g = g;
453   PalEntry->b = b;
454   return;
455 }
456 
457 // It is an alternative way of drawing the sky (gl_drawskys == skytype_screen)
458 // This method make sense only for old hardware which have no support for GL_TEXTURE_GEN_*
459 // Voodoo as example
gld_DrawScreenSkybox(void)460 void gld_DrawScreenSkybox(void)
461 {
462   if (SkyBox.wall.gltexture)
463   {
464     #define WRAPANGLE (ANGLE_MAX/4)
465 
466     float fU1, fU2, fV1, fV2;
467     GLWall *wall = &SkyBox.wall;
468     angle_t angle;
469     int i, k;
470     float w;
471 
472     if (!gl_compatibility)
473     {
474       glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); // no graphics
475     }
476     gld_EnableTexture2D(GL_TEXTURE0_ARB, false);
477 
478     for (i = gld_drawinfo.num_items[GLDIT_SWALL] - 1; i >= 0; i--)
479     {
480       GLWall* wall = gld_drawinfo.items[GLDIT_SWALL][i].item.wall;
481 
482       glBegin(GL_TRIANGLE_STRIP);
483       glVertex3f(wall->glseg->x1,wall->ytop,wall->glseg->z1);
484       glVertex3f(wall->glseg->x1,wall->ybottom,wall->glseg->z1);
485       glVertex3f(wall->glseg->x2,wall->ytop,wall->glseg->z2);
486       glVertex3f(wall->glseg->x2,wall->ybottom,wall->glseg->z2);
487       glEnd();
488     }
489 
490     gld_EnableTexture2D(GL_TEXTURE0_ARB, true);
491     if (!gl_compatibility)
492     {
493       glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
494     }
495     else
496     {
497       glClear(GL_COLOR_BUFFER_BIT);
498     }
499 
500     if (!mlook_or_fov)
501     {
502       fV1 = SkyBox.y_offset / 127.0f;
503       fV2 = fV1 + 320.0f / 200.0f;
504     }
505     else
506     {
507       float f = viewPitch * 2 + 40 / skyscale;
508       f = BETWEEN(0, 127, f);
509       fV1 = (f + SkyBox.y_offset) / 127.0f * skyscale;
510       fV2 = fV1 + 1.0f;
511     }
512 
513     k = MAX(wall->gltexture->buffer_width, 256) / 256;
514     angle = ((viewangle - ANG45) / k) % WRAPANGLE;
515 
516     if (wall->flag == GLDWF_SKYFLIP)
517     {
518       fU1 = -((float)angle + SkyBox.x_offset) / (WRAPANGLE - 1);
519       fU2 = fU1 + 1.0f / k;
520     }
521     else
522     {
523       fU2 = ((float)angle + SkyBox.x_offset) / (WRAPANGLE - 1);
524       fU1 = fU2 + 1.0f / k;
525     }
526 
527     glDisable(GL_DEPTH_TEST);
528     glDisable(GL_ALPHA_TEST);
529 
530     glPushMatrix();
531     glMatrixMode(GL_MODELVIEW);
532     glLoadIdentity();
533 
534     glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
535     gld_BindTexture(wall->gltexture, 0);
536     w = 160.0f * SCREENWIDTH / WIDE_SCREENWIDTH;
537     glBegin(GL_TRIANGLE_STRIP);
538       glTexCoord2f(fU1, fV1); glVertex3f(-w, +100.5f, -screen_skybox_zplane);
539       glTexCoord2f(fU1, fV2); glVertex3f(-w, -100.5f, -screen_skybox_zplane);
540       glTexCoord2f(fU2, fV1); glVertex3f(+w, +100.5f, -screen_skybox_zplane);
541       glTexCoord2f(fU2, fV2); glVertex3f(+w, -100.5f, -screen_skybox_zplane);
542     glEnd();
543 
544     glPopMatrix();
545 
546     glEnable(GL_ALPHA_TEST);
547     glEnable(GL_DEPTH_TEST);
548   }
549 }
550 
551 // The texture offset to be applied to the texture coordinates in SkyVertex().
552 static int rows, columns;
553 static dboolean yflip;
554 static int texw;
555 static float yMult, yAdd;
556 static dboolean foglayer;
557 static float delta = 0.0f;
558 
559 int gl_sky_detail = 16;
560 
561 //-----------------------------------------------------------------------------
562 //
563 //
564 //
565 //-----------------------------------------------------------------------------
566 
gld_GetSkyCapColors(void)567 void gld_GetSkyCapColors(void)
568 {
569   int color, width, height;
570   int frame_fixedcolormap_saved;
571   unsigned char *buffer = NULL;
572   const unsigned char *playpal = V_GetPlaypal();
573   const lighttable_t *colormap;
574   const lighttable_t *fixedcolormap_saved;
575   PalEntry_t *ceiling_rgb = &SkyBox.CeilingSkyColor[0];
576   PalEntry_t *floor_rgb = &SkyBox.FloorSkyColor[0];
577 
578   // saving current colormap
579   fixedcolormap_saved = fixedcolormap;
580   frame_fixedcolormap_saved = frame_fixedcolormap;
581 
582   fixedcolormap = fullcolormap;
583   frame_fixedcolormap = 0;
584 
585   gld_BindTexture(SkyBox.wall.gltexture, 0);
586 
587   glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &width);
588   glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &height);
589 
590   buffer = malloc(width * height * 4);
591   glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, buffer);
592 
593   averageColor(ceiling_rgb, (unsigned int*)buffer, width * MIN(30, height), 0);
594 
595   if (height > 30)
596   {
597     averageColor(floor_rgb,
598       ((unsigned int*)buffer) + (height - 30) * width, width * 30, 0);
599   }
600   else
601   {
602     *floor_rgb = *ceiling_rgb;
603   }
604 
605   colormap = fullcolormap + INVERSECOLORMAP * 256 * sizeof(lighttable_t);
606 
607   color = V_BestColor(playpal, ceiling_rgb->r, ceiling_rgb->g, ceiling_rgb->b);
608   SkyBox.CeilingSkyColor[1].r = playpal[colormap[color] * 3 + 0];
609   SkyBox.CeilingSkyColor[1].g = playpal[colormap[color] * 3 + 1];
610   SkyBox.CeilingSkyColor[1].b = playpal[colormap[color] * 3 + 2];
611 
612   color = V_BestColor(playpal, floor_rgb->r, floor_rgb->g, floor_rgb->b);
613   SkyBox.FloorSkyColor[1].r = playpal[colormap[color] * 3 + 0];
614   SkyBox.FloorSkyColor[1].g = playpal[colormap[color] * 3 + 1];
615   SkyBox.FloorSkyColor[1].b = playpal[colormap[color] * 3 + 2];
616 
617   // restorin current colormap
618   fixedcolormap = fixedcolormap_saved;
619   frame_fixedcolormap = frame_fixedcolormap_saved;
620 
621   free(buffer);
622 }
623 
624 //-----------------------------------------------------------------------------
625 //
626 //
627 //
628 //-----------------------------------------------------------------------------
629 
SkyVertex(vbo_vertex_t * vbo,int r,int c)630 static void SkyVertex(vbo_vertex_t *vbo, int r, int c)
631 {
632   static fixed_t scale = 10000 << FRACBITS;
633   static angle_t maxSideAngle = ANG180 / 3;
634 
635   angle_t topAngle= (angle_t)(c / (float)columns * ANGLE_MAX);
636   angle_t sideAngle = maxSideAngle * (rows - r) / rows;
637   fixed_t height = finesine[sideAngle>>ANGLETOFINESHIFT];
638   fixed_t realRadius = FixedMul(scale, finecosine[sideAngle>>ANGLETOFINESHIFT]);
639   fixed_t x = FixedMul(realRadius, finecosine[topAngle>>ANGLETOFINESHIFT]);
640   fixed_t y = (!yflip) ? FixedMul(scale, height) : FixedMul(scale, height) * -1;
641   fixed_t z = FixedMul(realRadius, finesine[topAngle>>ANGLETOFINESHIFT]);
642   float timesRepeat;
643 
644   timesRepeat = (short)(4 * (256.0f / texw));
645   if (timesRepeat == 0.0f)
646     timesRepeat = 1.0f;
647 
648   if (!foglayer)
649   {
650     vbo->r = 255;
651     vbo->g = 255;
652     vbo->b = 255;
653     vbo->a = (r == 0 ? 0 : 255);
654 
655     // And the texture coordinates.
656     if(!yflip)	// Flipped Y is for the lower hemisphere.
657     {
658       vbo->u = (-timesRepeat * c / (float)columns) ;
659       vbo->v = (r / (float)rows) * 1.f * yMult + yAdd;
660     }
661     else
662     {
663       vbo->u = (-timesRepeat * c / (float)columns) ;
664       vbo->v = ((rows-r)/(float)rows) * 1.f * yMult + yAdd;
665     }
666 
667     if (SkyBox.wall.flag == GLDWF_SKYFLIP)
668       vbo->u = -vbo->u;
669   }
670 
671   if (r != 4)
672   {
673     y += FRACUNIT * 300;
674   }
675 
676   // And finally the vertex.
677   vbo->x =-(float)x/(float)MAP_SCALE;	// Doom mirrors the sky vertically!
678   vbo->y = (float)y/(float)MAP_SCALE + delta;
679   vbo->z = (float)z/(float)MAP_SCALE;
680 }
681 
682 GLSkyVBO sky_vbo[2];
683 
gld_BuildSky(int row_count,int col_count,SkyBoxParams_t * sky,int cm)684 static void gld_BuildSky(int row_count, int col_count, SkyBoxParams_t *sky, int cm)
685 {
686   int texh, c, r;
687   vbo_vertex_t *vertex_p;
688   int vertex_count = 2 * row_count * (col_count * 2 + 2) + col_count * 2;
689   int vbo_idx = (cm == INVERSECOLORMAP ? 1 : 0);
690   GLSkyVBO *vbo = &sky_vbo[vbo_idx];
691 
692   if ((vbo->columns != col_count) || (vbo->rows != row_count))
693   {
694     free(vbo->loops);
695     free(vbo->data);
696     memset(vbo, 0, sizeof(vbo[0]));
697   }
698 
699   if (!vbo->data)
700   {
701     memset(vbo, 0, sizeof(vbo[0]));
702     vbo->loops = malloc((row_count * 2 + 2) * sizeof(vbo->loops[0]));
703     // create vertex array
704     vbo->data = malloc(vertex_count * sizeof(vbo->data[0]));
705   }
706 
707   vbo->columns = col_count;
708   vbo->rows = row_count;
709 
710   texh = sky->wall.gltexture->buffer_height;
711   if (texh > 190 && gl_stretchsky)
712     texh = 190;
713   texw = sky->wall.gltexture->buffer_width;
714 
715   vertex_p = &vbo->data[0];
716   vbo->loopcount = 0;
717   for (yflip = 0; yflip < 2; yflip++)
718   {
719     vbo->loops[vbo->loopcount].mode = GL_TRIANGLE_FAN;
720     vbo->loops[vbo->loopcount].vertexindex = vertex_p - &vbo->data[0];
721     vbo->loops[vbo->loopcount].vertexcount = col_count;
722     vbo->loops[vbo->loopcount].use_texture = false;
723     vbo->loopcount++;
724 
725     yAdd = sky->y_offset / texh;
726     yMult = (texh <= 180 ? 1.0f : 180.0f / texh);
727     if (yflip == 0)
728     {
729       SkyColor = &sky->CeilingSkyColor[vbo_idx];
730     }
731     else
732     {
733       SkyColor = &sky->FloorSkyColor[vbo_idx];
734       if (texh <= 180) yMult = 1.0f; else yAdd += 180.0f / texh;
735     }
736 
737     delta = 0.0f;
738     foglayer = true;
739     for(c = 0; c < col_count; c++)
740     {
741       SkyVertex(vertex_p, 1, c);
742       vertex_p->r = SkyColor->r;
743       vertex_p->g = SkyColor->g;
744       vertex_p->b = SkyColor->b;
745       vertex_p->a = 255;
746       vertex_p++;
747     }
748     foglayer = false;
749 
750     delta = (yflip ? 5.0f : -5.0f) / MAP_COEFF;
751 
752     for(r = 0; r < row_count; r++)
753     {
754       vbo->loops[vbo->loopcount].mode = GL_TRIANGLE_STRIP;
755       vbo->loops[vbo->loopcount].vertexindex = vertex_p - &vbo->data[0];
756       vbo->loops[vbo->loopcount].vertexcount = 2 * col_count + 2;
757       vbo->loops[vbo->loopcount].use_texture = true;
758       vbo->loopcount++;
759 
760       for(c = 0; c <= col_count; c++)
761       {
762         SkyVertex(vertex_p++, r + (yflip ? 1 : 0), (c ? c : 0));
763         SkyVertex(vertex_p++, r + (yflip ? 0 : 1), (c ? c : 0));
764       }
765     }
766   }
767 }
768 
769 //-----------------------------------------------------------------------------
770 //
771 //
772 //
773 //-----------------------------------------------------------------------------
774 
RenderDome(SkyBoxParams_t * sky)775 static void RenderDome(SkyBoxParams_t *sky)
776 {
777   int i, j;
778   int vbosize;
779   GLSkyVBO *vbo;
780 
781   if (!sky || !sky->wall.gltexture)
782     return;
783 
784   if (invul_method == INVUL_CM && frame_fixedcolormap == INVERSECOLORMAP)
785     vbo = &sky_vbo[1];
786   else
787     vbo = &sky_vbo[0];
788 
789 
790 #if defined(USE_VERTEX_ARRAYS) || defined(USE_VBO)
791   // be sure the second ARB is not enabled
792   gld_EnableDetail(false);
793 #endif
794 
795   glRotatef(-180.0f + sky->x_offset, 0.f, 1.f, 0.f);
796 
797   rows = 4;
798   columns = 4 * gl_sky_detail;
799 
800   vbosize = 2 * rows * (columns * 2 + 2) + columns * 2;
801 
802   if (sky->y_offset != y_offset_saved ||
803       sky->wall.gltexture->index != sky->index)
804   {
805     y_offset_saved = sky->y_offset;
806 
807     if (sky->wall.gltexture->index != sky->index)
808     {
809       sky->index = sky->wall.gltexture->index;
810       gld_GetSkyCapColors();
811     }
812 
813     gld_BuildSky(rows, columns, sky, 0);
814     gld_BuildSky(rows, columns, sky, INVERSECOLORMAP);
815 
816 #ifdef USE_VBO
817     if (gl_ext_arb_vertex_buffer_object)
818     {
819       if (vbo->id)
820       {
821         // delete VBO when already exists
822         GLEXT_glDeleteBuffersARB(1, &vbo->id);
823       }
824       // generate a new VBO and get the associated ID
825       GLEXT_glGenBuffersARB(1, &vbo->id);
826       // bind VBO in order to use
827       GLEXT_glBindBufferARB(GL_ARRAY_BUFFER, vbo->id);
828       // upload data to VBO
829       GLEXT_glBufferDataARB(GL_ARRAY_BUFFER,
830         vbosize * sizeof(vbo->data[0]),
831         vbo->data, GL_STATIC_DRAW_ARB);
832     }
833 #endif
834   }
835 
836   gld_BindTexture(SkyBox.wall.gltexture, 0);
837 
838 #if defined(USE_VERTEX_ARRAYS) || defined(USE_VBO)
839   if (gl_ext_arb_vertex_buffer_object)
840   {
841     // bind VBO in order to use
842     GLEXT_glBindBufferARB(GL_ARRAY_BUFFER, vbo->id);
843   }
844 
845   // activate and specify pointers to arrays
846   glVertexPointer(3, GL_FLOAT, sizeof(vbo->data[0]), sky_vbo_x);
847   glTexCoordPointer(2, GL_FLOAT, sizeof(vbo->data[0]), sky_vbo_u);
848   glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(vbo->data[0]), sky_vbo_r);
849 
850   // activate vertex array, texture coord array and color arrays
851   glEnableClientState(GL_VERTEX_ARRAY);
852   glEnableClientState(GL_TEXTURE_COORD_ARRAY);
853   glEnableClientState(GL_COLOR_ARRAY);
854 #endif
855 
856   if (!gl_stretchsky)
857   {
858     int texh = sky->wall.gltexture->buffer_height;
859 
860     if (texh <= 180)
861     {
862       glScalef(1.0f, (float)texh / 230.0f, 1.0f);
863     }
864     else
865     {
866       if (texh > 190)
867         glScalef(1.0f, 230.0f / 240.0f, 1.0f);
868     }
869   }
870 
871   for(j = (HaveMouseLook() || !gl_stretchsky ? 0 : 1); j < 2; j++)
872   {
873     gld_EnableTexture2D(GL_TEXTURE0_ARB, j != 0);
874 
875     for(i = 0; i < vbo->loopcount; i++)
876     {
877       GLSkyLoopDef *loop = &vbo->loops[i];
878 
879       if (j == 0 ? loop->use_texture : !loop->use_texture)
880         continue;
881 
882 #if defined(USE_VERTEX_ARRAYS) || defined(USE_VBO)
883       glDrawArrays(loop->mode, loop->vertexindex, loop->vertexcount);
884 #else
885       {
886         int k;
887         glBegin(loop->mode);
888         for (k = loop->vertexindex; k < (loop->vertexindex + loop->vertexcount); k++)
889         {
890           vbo_vertex_t *v = &vbo->data[k];
891           if (loop->use_texture)
892           {
893             glTexCoord2fv((GLfloat*)&v->u);
894           }
895           glColor4ubv((GLubyte*)&v->r);
896           glVertex3fv((GLfloat*)&v->x);
897         }
898         glEnd();
899       }
900 #endif
901     }
902   }
903 
904   glScalef(1.0f, 1.0f, 1.0f);
905 
906   // current color is undefined after glDrawArrays
907   glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
908 
909 #if defined(USE_VERTEX_ARRAYS) || defined(USE_VBO)
910   if (gl_ext_arb_vertex_buffer_object)
911   {
912     // bind with 0, so, switch back to normal pointer operation
913     GLEXT_glBindBufferARB(GL_ARRAY_BUFFER, 0);
914   }
915   // deactivate color array
916   glDisableClientState(GL_COLOR_ARRAY);
917 #endif
918 }
919 
gld_DrawDomeSkyBox(void)920 void gld_DrawDomeSkyBox(void)
921 {
922   if (SkyBox.wall.gltexture)
923   {
924     GLint shading_mode = GL_FLAT;
925 
926     gld_DrawFakeSkyStrips();
927 
928     glGetIntegerv(GL_SHADE_MODEL, &shading_mode);
929     glShadeModel(GL_SMOOTH);
930 
931     glDepthMask(false);
932 
933     glDisable(GL_DEPTH_TEST);
934     glDisable(GL_ALPHA_TEST);
935     SetTextureMode(TM_OPAQUE);
936 
937     glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
938 
939     glPushMatrix();
940     glMatrixMode(GL_MODELVIEW);
941     glLoadIdentity();
942 
943     glRotatef(roll,  0.0f, 0.0f, 1.0f);
944     glRotatef(pitch, 1.0f, 0.0f, 0.0f);
945     glRotatef(yaw,   0.0f, 1.0f, 0.0f);
946     glScalef(-2.0f, 2.0f, 2.0f);
947     glTranslatef(0.f, -1250.0f / MAP_COEFF, 0.f);
948 
949     RenderDome(&SkyBox);
950 
951     glPopMatrix();
952 
953     glEnable(GL_ALPHA_TEST);
954     glEnable(GL_DEPTH_TEST);
955     glDepthMask(true);
956 
957     SetTextureMode(TM_MODULATE);
958 
959     glShadeModel(shading_mode);
960   }
961 }
962 
R_BoxSkyboxNumForName(const char * name)963 int R_BoxSkyboxNumForName(const char *name)
964 {
965   int i;
966 
967   for (i = 0; i < BoxSkyboxCount; i++)
968   {
969     if (!strcasecmp(BoxSkybox[i].name, name))
970     {
971       return i;
972     }
973   }
974 
975   return -1;
976 }
977 
R_SetBoxSkybox(int texture)978 void R_SetBoxSkybox(int texture)
979 {
980   int i;
981 
982   BoxSkybox_default = NULL;
983 
984   for (i = 0; i < BoxSkyboxCount; i++)
985   {
986     if (R_CheckTextureNumForName(BoxSkybox[i].name) == texture)
987     {
988       BoxSkybox_default = &BoxSkybox[i];
989       return;
990     }
991   }
992 }
993 
R_GetBoxSkybox(int index)994 box_skybox_t* R_GetBoxSkybox(int index)
995 {
996   if (index >= 0 && index < BoxSkyboxCount)
997     return &BoxSkybox[index];
998   else
999     return NULL;
1000 }
1001 
gld_ParseSkybox(void)1002 void gld_ParseSkybox(void)
1003 {
1004   if (SC_GetString())
1005   {
1006     box_skybox_t sb;
1007     memset(&sb, 0, sizeof(sb));
1008 
1009     strncpy(sb.name, sc_String, 8);
1010     sb.name[8] = 0;
1011     M_Strupr(sb.name);
1012 
1013     while (SC_Check())
1014     {
1015       SC_GetString();
1016       if (SC_Compare("fliptop"))
1017       {
1018         sb.fliptop = true;
1019       }
1020     }
1021 
1022     if (SC_GetString() && SC_Compare("{"))
1023     {
1024       int facecount = 0;
1025 
1026       while (SC_GetString() && !SC_Compare("}"))
1027       {
1028         if (facecount < 6)
1029         {
1030           strcpy(sb.faces[facecount], sc_String);
1031         }
1032         facecount++;
1033       }
1034 
1035       if (SC_Compare("}") && (facecount == 3 || facecount == 6))
1036       {
1037         int i;
1038         int ok = true;
1039 
1040         for (i = 0; i < facecount; i++)
1041         {
1042           if (R_CheckTextureNumForName(sb.faces[i]) == -1)
1043           {
1044             ok = false;
1045             break;
1046           }
1047         }
1048 
1049         if (ok)
1050         {
1051           BoxSkyboxCount++;
1052           BoxSkybox = realloc(BoxSkybox, BoxSkyboxCount * sizeof(BoxSkybox[0]));
1053           memcpy(&BoxSkybox[BoxSkyboxCount - 1], &sb, sizeof(sb));
1054         }
1055       }
1056     }
1057   }
1058 
1059   R_SetBoxSkybox(skytexture);
1060 }
1061 
gld_BindFace(box_skybox_t * sb,int index)1062 int gld_BindFace(box_skybox_t *sb, int index)
1063 {
1064   int lump;
1065   GLTexture *gltexture;
1066   char *name = sb->faces[index];
1067 
1068 #if 0
1069   lump = W_CheckNumForName(name);
1070   if (lump != -1)
1071   {
1072     gltexture = gld_RegisterPatch(lump, CR_DEFAULT);
1073     gltexture->wrap_mode = GLEXT_CLAMP_TO_EDGE;
1074     gld_BindPatch(gltexture, CR_DEFAULT);
1075     return true;
1076   }
1077 
1078   //lump = R_FlatNumForName(name);
1079   lump = (W_CheckNumForName)(name, ns_flats);
1080   if (lump != -1)
1081   {
1082     lump -= firstflat;
1083     gltexture = gld_RegisterFlat(lump, true);
1084     gltexture->wrap_mode = GLEXT_CLAMP_TO_EDGE;
1085     gld_BindFlat(gltexture);
1086     return true;
1087   }
1088 #endif
1089 
1090   lump = R_CheckTextureNumForName(name);
1091   if (lump != -1)
1092   {
1093     gltexture = gld_RegisterTexture(lump, false, false);
1094     gld_BindTexture(gltexture, GLTEXTURE_CLAMPXY);
1095     return true;
1096   }
1097 
1098   return false;
1099 }
1100 
gld_DrawBoxSkyBox(void)1101 int gld_DrawBoxSkyBox(void)
1102 {
1103   int faces;
1104   box_skybox_t *sb;
1105 
1106   if (BoxSkyboxCount == 0)
1107     return false;
1108 
1109   if (SkyBox.side)
1110   {
1111     sb = R_GetBoxSkybox(SkyBox.side->skybox_index);
1112   }
1113   else
1114   {
1115     sb = BoxSkybox_default;
1116   }
1117 
1118   if (!sb)
1119   {
1120     return false;
1121   }
1122 
1123   gld_DrawFakeSkyStrips();
1124 
1125   glDepthMask(false);
1126 
1127   glDisable(GL_DEPTH_TEST);
1128   glDisable(GL_ALPHA_TEST);
1129 
1130   SetTextureMode(TM_OPAQUE);
1131 
1132   glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1133 
1134   glMatrixMode(GL_MODELVIEW);
1135   glPushMatrix();
1136 
1137   glLoadIdentity();
1138 
1139   glRotatef(roll,  0.0f, 0.0f, 1.0f);
1140   glRotatef(pitch, 1.0f, 0.0f, 0.0f);
1141   glRotatef(yaw,   0.0f, 1.0f, 0.0f);
1142   glScalef(-2.0f, 2.0f, 2.0f);
1143 
1144   if (SkyBox.side)
1145   {
1146     float xoffset = (float)SkyBox.side->textureoffset * 180.0f / (float)ANG180;
1147     glRotatef(-180.0f + xoffset, 0.0f, 1.0f, 0.0f);
1148   }
1149 
1150   if (sb->faces[5][0])
1151   {
1152     faces = 4;
1153 
1154     // north
1155     gld_BindFace(sb, 0);
1156 
1157     glBegin(GL_TRIANGLE_FAN);
1158     glTexCoord2f(0.0f, 0.0f);
1159     glVertex3f(+MAXCOORD, MAXCOORD, -MAXCOORD);
1160     glTexCoord2f(1.0f, 0.0f);
1161     glVertex3f(-MAXCOORD, +MAXCOORD, -MAXCOORD);
1162     glTexCoord2f(1.0f, 1.0f);
1163     glVertex3f(-MAXCOORD, -MAXCOORD, -MAXCOORD);
1164     glTexCoord2f(0.0f, 1.0f);
1165     glVertex3f(+MAXCOORD, -MAXCOORD, -MAXCOORD);
1166     glEnd();
1167 
1168     // east
1169     gld_BindFace(sb, 1);
1170 
1171     glBegin(GL_TRIANGLE_FAN);
1172     glTexCoord2f(0.0f, 0.0f);
1173     glVertex3f(-MAXCOORD, +MAXCOORD, -MAXCOORD);
1174     glTexCoord2f(1.0f, 0.0f);
1175     glVertex3f(-MAXCOORD, +MAXCOORD, +MAXCOORD);
1176     glTexCoord2f(1.0f, 1.0f);
1177     glVertex3f(-MAXCOORD, -MAXCOORD, +MAXCOORD);
1178     glTexCoord2f(0.0f, 1.0f);
1179     glVertex3f(-MAXCOORD, -MAXCOORD, -MAXCOORD);
1180     glEnd();
1181 
1182     // south
1183     gld_BindFace(sb, 2);
1184 
1185     glBegin(GL_TRIANGLE_FAN);
1186     glTexCoord2f(0.0f, 0.0f);
1187     glVertex3f(-MAXCOORD, +MAXCOORD, +MAXCOORD);
1188     glTexCoord2f(1.0f, 0.0f);
1189     glVertex3f(+MAXCOORD, +MAXCOORD, +MAXCOORD);
1190     glTexCoord2f(1.0f, 1.0f);
1191     glVertex3f(+MAXCOORD, -MAXCOORD, +MAXCOORD);
1192     glTexCoord2f(0.0f, 1.0f);
1193     glVertex3f(-MAXCOORD, -MAXCOORD, +MAXCOORD);
1194     glEnd();
1195 
1196     // west
1197     gld_BindFace(sb, 3);
1198 
1199     glBegin(GL_TRIANGLE_FAN);
1200     glTexCoord2f(0.0f, 0.0f);
1201     glVertex3f(+MAXCOORD, +MAXCOORD, +MAXCOORD);
1202     glTexCoord2f(1.0f, 0.0f);
1203     glVertex3f(+MAXCOORD, +MAXCOORD, -MAXCOORD);
1204     glTexCoord2f(1.0f, 1.0f);
1205     glVertex3f(+MAXCOORD, -MAXCOORD, -MAXCOORD);
1206     glTexCoord2f(0.0f, 1.0f);
1207     glVertex3f(+MAXCOORD, -MAXCOORD, +MAXCOORD);
1208     glEnd();
1209   }
1210   else
1211   {
1212     faces = 1;
1213 
1214     // all 4 sides
1215     gld_BindFace(sb, 0);
1216 
1217     glBegin(GL_TRIANGLE_FAN);
1218     glTexCoord2f(0.0f, 0.0f);
1219     glVertex3f(+MAXCOORD, +MAXCOORD, -MAXCOORD);
1220     glTexCoord2f(.25f, 0);
1221     glVertex3f(-MAXCOORD, +MAXCOORD, -MAXCOORD);
1222     glTexCoord2f(.25f, 1);
1223     glVertex3f(-MAXCOORD, -MAXCOORD, -MAXCOORD);
1224     glTexCoord2f(0.0f, 1.0f);
1225     glVertex3f(+MAXCOORD, -MAXCOORD, -MAXCOORD);
1226     glEnd();
1227 
1228     // east
1229     glBegin(GL_TRIANGLE_FAN);
1230     glTexCoord2f(.25f, 0);
1231     glVertex3f(-MAXCOORD, +MAXCOORD, -MAXCOORD);
1232     glTexCoord2f(.5f, 0);
1233     glVertex3f(-MAXCOORD, +MAXCOORD, +MAXCOORD);
1234     glTexCoord2f(.5f, 1);
1235     glVertex3f(-MAXCOORD, -MAXCOORD, +MAXCOORD);
1236     glTexCoord2f(.25f, 1);
1237     glVertex3f(-MAXCOORD, -MAXCOORD, -MAXCOORD);
1238     glEnd();
1239 
1240     // south
1241     glBegin(GL_TRIANGLE_FAN);
1242     glTexCoord2f(.5f, 0);
1243     glVertex3f(-MAXCOORD, +MAXCOORD, +MAXCOORD);
1244     glTexCoord2f(.75f, 0);
1245     glVertex3f(+MAXCOORD, +MAXCOORD, +MAXCOORD);
1246     glTexCoord2f(.75f, 1);
1247     glVertex3f(+MAXCOORD, -MAXCOORD, +MAXCOORD);
1248     glTexCoord2f(.5f, 1);
1249     glVertex3f(-MAXCOORD, -MAXCOORD, +MAXCOORD);
1250     glEnd();
1251 
1252     // west
1253     glBegin(GL_TRIANGLE_FAN);
1254     glTexCoord2f(.75f, 0);
1255     glVertex3f(+MAXCOORD, +MAXCOORD, +MAXCOORD);
1256     glTexCoord2f(1.0f, 0.0f);
1257     glVertex3f(+MAXCOORD, +MAXCOORD, -MAXCOORD);
1258     glTexCoord2f(1.0f, 1.0f);
1259     glVertex3f(+MAXCOORD, -MAXCOORD, -MAXCOORD);
1260     glTexCoord2f(.75f, 1);
1261     glVertex3f(+MAXCOORD, -MAXCOORD, +MAXCOORD);
1262     glEnd();
1263   }
1264 
1265   // top
1266   gld_BindFace(sb, faces);
1267   glBegin(GL_TRIANGLE_FAN);
1268   if (!sb->fliptop)
1269   {
1270     glTexCoord2f(0.0f, 0.0f);
1271     glVertex3f(+MAXCOORD, +MAXCOORD, -MAXCOORD);
1272     glTexCoord2f(1.0f, 0.0f);
1273     glVertex3f(-MAXCOORD, +MAXCOORD, -MAXCOORD);
1274     glTexCoord2f(1.0f, 1.0f);
1275     glVertex3f(-MAXCOORD, +MAXCOORD, +MAXCOORD);
1276     glTexCoord2f(0.0f, 1.0f);
1277     glVertex3f(+MAXCOORD, +MAXCOORD, +MAXCOORD);
1278   }
1279   else
1280   {
1281     glTexCoord2f(0.0f, 0.0f);
1282     glVertex3f(+MAXCOORD, +MAXCOORD, +MAXCOORD);
1283     glTexCoord2f(1.0f, 0.0f);
1284     glVertex3f(-MAXCOORD, +MAXCOORD, +MAXCOORD);
1285     glTexCoord2f(1.0f, 1.0f);
1286     glVertex3f(-MAXCOORD, +MAXCOORD, -MAXCOORD);
1287     glTexCoord2f(0.0f, 1.0f);
1288     glVertex3f(+MAXCOORD, +MAXCOORD, -MAXCOORD);
1289   }
1290   glEnd();
1291 
1292   // bottom
1293   gld_BindFace(sb, faces + 1);
1294 
1295   glBegin(GL_TRIANGLE_FAN);
1296   glTexCoord2f(0.0f, 0.0f);
1297   glVertex3f(+MAXCOORD, -MAXCOORD, -MAXCOORD);
1298   glTexCoord2f(1.0f, 0.0f);
1299   glVertex3f(-MAXCOORD, -MAXCOORD, -MAXCOORD);
1300   glTexCoord2f(1.0f, 1.0f);
1301   glVertex3f(-MAXCOORD, -MAXCOORD, +MAXCOORD);
1302   glTexCoord2f(0.0f, 1.0f);
1303   glVertex3f(+MAXCOORD, -MAXCOORD, +MAXCOORD);
1304   glEnd();
1305 
1306   glPopMatrix();
1307 
1308   glEnable(GL_ALPHA_TEST);
1309   glEnable(GL_DEPTH_TEST);
1310   glDepthMask(true);
1311 
1312   SetTextureMode(TM_MODULATE);
1313 
1314   return true;
1315 }
1316