1 /* Emacs style mode select   -*- C++ -*-
2  *-----------------------------------------------------------------------------
3  *
4  *
5  *  PrBoom: a Doom port merged with LxDoom and LSDLDoom
6  *  based on BOOM, a modified and improved DOOM engine
7  *  Copyright (C) 1999 by
8  *  id Software, Chi Hoang, Lee Killough, Jim Flynn, Rand Phares, Ty Halderman
9  *  Copyright (C) 1999-2000 by
10  *  Jess Haas, Nicolas Kalkhof, Colin Phipps, Florian Schulze
11  *  Copyright 2005, 2006 by
12  *  Florian Schulze, Colin Phipps, Neil Stevens, Andrey Budko
13  *  Copyright 2007 by
14  *  Andrey Budko, Roman Marchenko
15  *
16  *  This program is free software; you can redistribute it and/or
17  *  modify it under the terms of the GNU General Public License
18  *  as published by the Free Software Foundation; either version 2
19  *  of the License, or (at your option) any later version.
20  *
21  *  This program is distributed in the hope that it will be useful,
22  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
23  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
24  *  GNU General Public License for more details.
25  *
26  *  You should have received a copy of the GNU General Public License
27  *  along with this program; if not, write to the Free Software
28  *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
29  *  02111-1307, USA.
30  *
31  * DESCRIPTION:
32  *
33  *---------------------------------------------------------------------
34  */
35 
36 #ifdef HAVE_CONFIG_H
37 #include "config.h"
38 #endif
39 
40 #include "gl_opengl.h"
41 
42 #include "z_zone.h"
43 #include <math.h>
44 #include <SDL.h>
45 #include "doomtype.h"
46 #include "w_wad.h"
47 #include "m_argv.h"
48 #include "d_event.h"
49 #include "v_video.h"
50 #include "doomstat.h"
51 #include "r_bsp.h"
52 #include "r_main.h"
53 #include "r_draw.h"
54 #include "r_sky.h"
55 #include "r_plane.h"
56 #include "r_data.h"
57 #include "r_things.h"
58 #include "r_fps.h"
59 #include "p_maputl.h"
60 #include "m_bbox.h"
61 #include "lprintf.h"
62 #include "gl_intern.h"
63 #include "gl_struct.h"
64 #include "p_spec.h"
65 #include "i_system.h"
66 #include "m_argv.h"
67 #include "i_video.h"
68 #include "i_main.h"
69 #include "am_map.h"
70 #include "sc_man.h"
71 #include "st_stuff.h"
72 #include "e6y.h"//e6y
73 #ifdef USE_CUSTOM_QSORT
74 #include "qsort.h"
75 #endif
76 
77 // All OpenGL extentions will be disabled in gl_compatibility mode
78 int gl_compatibility = 0;
79 
80 int gl_vsync = true;
81 int gl_clear;
82 
83 int gl_preprocessed = false;
84 
85 int gl_spriteindex;
86 int scene_has_overlapped_sprites;
87 
88 int gl_blend_animations;
89 
90 int gl_use_display_lists;
91 int flats_display_list;
92 int flats_display_list_size = 0;
93 int flats_detail_display_list;
94 int flats_detail_display_list_size = 0;
95 
96 // e6y
97 // This variables toggles the use of a trick to prevent the clearning of the
98 // z-buffer between frames. When this variable is set to "1", the game will not
99 // clear the z-buffer between frames. This will result in increased performance
100 // only on very old hardware and might cause problems for some display hardware.
101 int gl_ztrick;
102 int gl_ztrickframe = 0;
103 float gldepthmin, gldepthmax;
104 
105 unsigned int invul_method;
106 float bw_red = 0.3f;
107 float bw_green = 0.59f;
108 float bw_blue = 0.11f;
109 
110 extern int tran_filter_pct;
111 
112 dboolean use_fog=false;
113 
114 int gl_nearclip=5;
115 int gl_texture_filter;
116 int gl_sprite_filter;
117 int gl_patch_filter;
118 int gl_texture_filter_anisotropic = 0;
119 
120 //sprites
121 spriteclipmode_t gl_spriteclip;
122 const char *gl_spriteclipmodes[] = {"constant", "full", "smart"};
123 int gl_spriteclip_threshold;
124 float gl_spriteclip_threshold_f;
125 int gl_sprites_frustum_culling;
126 int gl_sprite_offset_default;	// item out of floor offset Mead 8/13/03
127 float gl_sprite_offset;       // precalcilated float value for gl_sprite_offset_default
128 int gl_sprite_blend;  // e6y: smooth sprite edges
129 int gl_mask_sprite_threshold;
130 float gl_mask_sprite_threshold_f;
131 
132 GLuint gld_DisplayList=0;
133 int fog_density=200;
134 static float extra_red=0.0f;
135 static float extra_green=0.0f;
136 static float extra_blue=0.0f;
137 static float extra_alpha=0.0f;
138 
139 GLfloat gl_whitecolor[4]={1.0f,1.0f,1.0f,1.0f};
140 
gld_InitTextureParams(void)141 void gld_InitTextureParams(void)
142 {
143   typedef struct tex_filter_s
144   {
145     dboolean mipmap;
146     int tex_filter;
147     int mipmap_filter;
148     const char *tex_filter_name;
149     const char *mipmap_filter_name;
150   } tex_filter_t;
151 
152   typedef struct tex_format_s
153   {
154     int tex_format;
155     const char *tex_format_name;
156   } tex_format_t;
157 
158   tex_filter_t params[filter_count] = {
159     {false, GL_NEAREST, GL_NEAREST,                "GL_NEAREST", "GL_NEAREST"},
160     {false, GL_LINEAR,  GL_LINEAR,                 "GL_LINEAR",  "GL_LINEAR"},
161     {true,  GL_NEAREST, GL_NEAREST_MIPMAP_NEAREST, "GL_NEAREST", "GL_NEAREST_MIPMAP_NEAREST"},
162     {true,  GL_NEAREST, GL_NEAREST_MIPMAP_LINEAR,  "GL_NEAREST", "GL_NEAREST_MIPMAP_LINEAR"},
163     {true,  GL_LINEAR,  GL_LINEAR_MIPMAP_NEAREST,  "GL_LINEAR",  "GL_LINEAR_MIPMAP_NEAREST"},
164     {true,  GL_LINEAR,  GL_LINEAR_MIPMAP_LINEAR,   "GL_LINEAR",  "GL_LINEAR_MIPMAP_LINEAR"},
165   };
166 
167   tex_format_t tex_formats[] = {
168     {GL_RGBA2,   "GL_RGBA2"},
169     {GL_RGBA4,   "GL_RGBA4"},
170     {GL_RGB5_A1, "GL_RGB5_A1"},
171     {GL_RGBA8,   "GL_RGBA8"},
172     {GL_RGBA,    "GL_RGBA"},
173     {0, NULL}
174   };
175 
176   int i;
177   int *var[MIP_COUNT] = {&gl_texture_filter, &gl_sprite_filter, &gl_patch_filter};
178 
179   for (i = 0; i < MIP_COUNT; i++)
180   {
181 #ifdef USE_GLU_MIPMAP
182     tex_filter[i].mipmap     = params[*var[i]].mipmap;
183 #else
184     tex_filter[i].mipmap     = false;
185 #endif
186     tex_filter[i].mag_filter = params[*var[i]].tex_filter;
187     tex_filter[i].min_filter = params[*var[i]].mipmap_filter;
188   }
189 
190   if (tex_filter[MIP_TEXTURE].mipmap)
191   {
192     gl_shared_texture_palette = false;
193   }
194 
195   i = 0;
196   while (tex_formats[i].tex_format_name)
197   {
198     if (!strcasecmp(gl_tex_format_string, tex_formats[i].tex_format_name))
199     {
200       gl_tex_format = tex_formats[i].tex_format;
201       lprintf(LO_INFO,"Using texture format %s.\n", tex_formats[i].tex_format_name);
202       break;
203     }
204     i++;
205   }
206 }
207 
gld_MultisamplingInit(void)208 void gld_MultisamplingInit(void)
209 {
210   if (render_multisampling)
211   {
212     extern int gl_colorbuffer_bits;
213     extern int gl_depthbuffer_bits;
214 
215     gl_colorbuffer_bits = 32;
216     SDL_GL_SetAttribute( SDL_GL_BUFFER_SIZE, gl_colorbuffer_bits );
217 
218     if (gl_depthbuffer_bits!=8 && gl_depthbuffer_bits!=16 && gl_depthbuffer_bits!=24)
219       gl_depthbuffer_bits = 16;
220     SDL_GL_SetAttribute( SDL_GL_DEPTH_SIZE, gl_depthbuffer_bits );
221 
222     SDL_GL_SetAttribute ( SDL_GL_MULTISAMPLESAMPLES, render_multisampling );
223     SDL_GL_SetAttribute ( SDL_GL_MULTISAMPLEBUFFERS, 1 );
224   }
225 }
226 
gld_MultisamplingCheck(void)227 void gld_MultisamplingCheck(void)
228 {
229   if (render_multisampling)
230   {
231     int test = -1;
232     SDL_GL_GetAttribute (SDL_GL_MULTISAMPLESAMPLES, &test);
233     if (test!=render_multisampling)
234     {
235       void M_SaveDefaults (void);
236       int i=render_multisampling;
237       render_multisampling = 0;
238       M_SaveDefaults ();
239       I_Error("Couldn't set %dX multisamples for %dx%d video mode", i, SCREENWIDTH, SCREENHEIGHT);
240     }
241   }
242 }
243 
gld_MultisamplingSet(void)244 void gld_MultisamplingSet(void)
245 {
246   if (render_multisampling)
247   {
248     int use_multisampling = map_use_multisamling ||
249       (!(automapmode & am_active) || (automapmode & am_overlay));
250 
251     gld_EnableMultisample(use_multisampling);
252   }
253 }
254 
gld_LoadGLDefs(const char * defsLump)255 int gld_LoadGLDefs(const char * defsLump)
256 {
257   typedef enum
258   {
259     TAG_SKYBOX,
260     TAG_DETAIL,
261 
262     TAG_MAX
263   } gldef_type_e;
264 
265   // these are the core types available in the *DEFS lump
266   static const char *CoreKeywords[TAG_MAX + 1] =
267   {
268     "skybox",
269     "detail",
270 
271     NULL
272   };
273 
274   int result = false;
275 
276   if (W_CheckNumForName(defsLump) != -1)
277   {
278     SC_OpenLump(defsLump);
279 
280     // Get actor class name.
281     while (SC_GetString())
282     {
283       switch (SC_MatchString(CoreKeywords))
284       {
285       case TAG_SKYBOX:
286         result = true;
287         gld_ParseSkybox();
288         break;
289       case TAG_DETAIL:
290         result = true;
291         gld_ParseDetail();
292         break;
293       }
294     }
295 
296     SC_Close();
297   }
298 
299   return result;
300 }
301 
302 
303 
gld_Init(int width,int height)304 void gld_Init(int width, int height)
305 {
306   GLfloat params[4]={0.0f,0.0f,1.0f,0.0f};
307 
308   lprintf(LO_INFO,"GL_VENDOR: %s\n",glGetString(GL_VENDOR));
309   lprintf(LO_INFO,"GL_RENDERER: %s\n",glGetString(GL_RENDERER));
310   lprintf(LO_INFO,"GL_VERSION: %s\n",glGetString(GL_VERSION));
311   lprintf(LO_INFO,"GL_EXTENSIONS:\n");
312   {
313     char ext_name[256];
314     const char *extensions = (const char*)glGetString(GL_EXTENSIONS);
315     const char *rover = extensions;
316     const char *p = rover;
317 
318     while (*rover)
319     {
320       size_t len = 0;
321       p = rover;
322       while (*p && *p != ' ')
323       {
324         p++;
325         len++;
326       }
327       if (*p)
328       {
329         len = MIN(len, sizeof(ext_name)-1);
330         memset(ext_name, 0, sizeof(ext_name));
331         strncpy(ext_name, rover, len);
332         lprintf(LO_INFO,"\t%s\n", ext_name);
333       }
334       rover = p;
335       while (*rover && *rover == ' ')
336         rover++;
337     }
338   }
339 
340   gld_InitOpenGL(gl_compatibility);
341   gld_InitPalettedTextures();
342   gld_InitTextureParams();
343 
344   glViewport(0, 0, SCREENWIDTH, SCREENHEIGHT);
345 
346   glClearColor(0.0f, 0.5f, 0.5f, 1.0f);
347   glClearDepth(1.0f);
348 
349   glEnable(GL_BLEND);
350   glEnable(GL_DEPTH_CLAMP_NV);
351   glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
352   glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
353   glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); // proff_dis
354   glShadeModel(GL_FLAT);
355   gld_EnableTexture2D(GL_TEXTURE0_ARB, true);
356   glDepthFunc(GL_LEQUAL);
357   glEnable(GL_ALPHA_TEST);
358   glAlphaFunc(GL_GEQUAL,0.5f);
359   glDisable(GL_CULL_FACE);
360   glTexEnvf(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_MODULATE);
361 
362   glTexGenfv(GL_Q,GL_EYE_PLANE,params);
363   glTexGenf(GL_S,GL_TEXTURE_GEN_MODE,GL_EYE_LINEAR);
364   glTexGenf(GL_T,GL_TEXTURE_GEN_MODE,GL_EYE_LINEAR);
365   glTexGenf(GL_Q,GL_TEXTURE_GEN_MODE,GL_EYE_LINEAR);
366 
367   //e6y
368   glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
369   glClear(GL_COLOR_BUFFER_BIT);
370   gld_Finish();
371   glClear(GL_COLOR_BUFFER_BIT);
372   glClearColor(0.0f, 0.5f, 0.5f, 1.0f);
373 
374   // e6y
375   // if you have a prior crash in the game,
376   // you can restore the gamma values to at least a linear value
377   // with -resetgamma command-line switch
378   gld_ResetGammaRamp();
379 
380   gld_InitLightTable();
381   gld_InitSky();
382   M_ChangeLightMode();
383   M_ChangeAllowFog();
384 
385   gld_InitDetail();
386   gld_InitShadows();
387 
388 #ifdef HAVE_LIBSDL_IMAGE
389   gld_InitHiRes();
390 #endif
391 
392   // Create FBO object and associated render targets
393 #ifdef USE_FBO_TECHNIQUE
394   gld_InitFBO();
395   atexit(gld_FreeScreenSizeFBO);
396 #endif
397 
398   if(!gld_LoadGLDefs("GLBDEFS"))
399   {
400     gld_LoadGLDefs("GLDEFS");
401   }
402 
403   gld_ResetLastTexture();
404 
405   atexit(gld_CleanMemory); //e6y
406 }
407 
gld_InitCommandLine(void)408 void gld_InitCommandLine(void)
409 {
410 }
411 
412 //
413 // Textured automap
414 //
415 
416 #ifdef USE_CUSTOM_QSORT
qsort_subsectors_by_pic(subsector_t ** arr,unsigned int n)417 void qsort_subsectors_by_pic(subsector_t **arr, unsigned int n)
418 {
419   #define cmp_subsectors_by_pic(a, b) ((*a)->sector->floorpic > (*b)->sector->floorpic)
420   QSORT(subsector_t*, arr, n, cmp_subsectors_by_pic);
421 }
422 #else
dicmp_visible_subsectors_by_pic(const void * a,const void * b)423 static int C_DECL dicmp_visible_subsectors_by_pic(const void *a, const void *b)
424 {
425   return (*((const subsector_t *const *)b))->sector->floorpic -
426          (*((const subsector_t *const *)a))->sector->floorpic;
427 }
428 #endif
429 
430 static int visible_subsectors_count_prev = -1;
gld_ResetTexturedAutomap(void)431 void gld_ResetTexturedAutomap(void)
432 {
433   visible_subsectors_count_prev = -1;
434 }
435 
gld_MapDrawSubsectors(player_t * plr,int fx,int fy,fixed_t mx,fixed_t my,int fw,int fh,fixed_t scale)436 void gld_MapDrawSubsectors(player_t *plr, int fx, int fy, fixed_t mx, fixed_t my, int fw, int fh, fixed_t scale)
437 {
438   extern int ddt_cheating;
439 
440   static subsector_t **visible_subsectors = NULL;
441   static int visible_subsectors_size = 0;
442   int visible_subsectors_count;
443 
444   int i;
445   float alpha;
446   float coord_scale;
447   GLTexture *gltexture;
448 
449   alpha = (float)((automapmode & am_overlay) ? map_textured_overlay_trans : map_textured_trans) / 100.0f;
450   if (alpha == 0)
451     return;
452 
453   if (numsubsectors > visible_subsectors_size)
454   {
455     visible_subsectors_size = numsubsectors;
456     visible_subsectors = realloc(visible_subsectors, visible_subsectors_size * sizeof(visible_subsectors[0]));
457   }
458 
459   visible_subsectors_count = 0;
460   if (ddt_cheating)
461   {
462     visible_subsectors_count = numsubsectors;
463   }
464   else
465   {
466     for (i = 0; i < numsubsectors; i++)
467     {
468       visible_subsectors_count += map_subsectors[i];
469     }
470   }
471 
472   // Do not sort static visible_subsectors array at all
473   // if there are no new visible subsectors.
474   if (visible_subsectors_count != visible_subsectors_count_prev)
475   {
476     visible_subsectors_count_prev = visible_subsectors_count;
477 
478     visible_subsectors_count = 0;
479     for (i = 0; i < numsubsectors; i++)
480     {
481       if (map_subsectors[i] || ddt_cheating)
482       {
483         visible_subsectors[visible_subsectors_count++] = &subsectors[i];
484       }
485     }
486 
487     // sort subsectors by texture
488 #ifdef USE_CUSTOM_QSORT
489     qsort_subsectors_by_pic(visible_subsectors, visible_subsectors_count);
490 #else
491     qsort(visible_subsectors, visible_subsectors_count,
492       sizeof(visible_subsectors[0]), dicmp_visible_subsectors_by_pic);
493 #endif
494   }
495 
496   glMatrixMode(GL_MODELVIEW);
497   glPushMatrix();
498   glScissor(fx, SCREENHEIGHT - (fy + fh), fw, fh);
499   glEnable(GL_SCISSOR_TEST);
500 
501   if (automapmode & am_rotate)
502   {
503     float pivotx = (float)(fx + fw / 2);
504     float pivoty = (float)(fy + fh / 2);
505 
506     float rot = -(float)(ANG90 - am_viewangle) / (float)(1u << 31) * 180.0f;
507 
508     // Apply the automap's rotation to the vertexes.
509     glTranslatef(pivotx, pivoty, 0.0f);
510     glRotatef(rot, 0.0f, 0.0f, 1.0f);
511     glTranslatef(-pivotx, -pivoty, 0.0f);
512   }
513 
514   glTranslatef(
515     (float)fx - (float)mx / (float)FRACUNIT * (float)scale / (float)FRACUNIT,
516     (float)fy + (float)fh + (float)my / (float)FRACUNIT * (float)scale / (float)FRACUNIT,
517     0);
518   coord_scale = (float)scale / (float)(1<<FRACTOMAPBITS) / (float)FRACUNIT * MAP_COEFF;
519   glScalef(-coord_scale, -coord_scale, 1.0f);
520 
521   for (i = 0; i < visible_subsectors_count; i++)
522   {
523     subsector_t *sub = visible_subsectors[i];
524     int ssidx = sub - subsectors;
525 
526     gltexture = gld_RegisterFlat(flattranslation[sub->sector->floorpic], true);
527     if (gltexture)
528     {
529       sector_t tempsec;
530       int floorlight;
531       float light;
532       float floor_uoffs, floor_voffs;
533       int loopnum;
534 
535       // For lighting and texture determination
536       sector_t *sec = R_FakeFlat(sub->sector, &tempsec, &floorlight, NULL, false);
537 
538       gld_BindFlat(gltexture, 0);
539       light = gld_Calc2DLightLevel(floorlight);
540       gld_StaticLightAlpha(light, alpha);
541 
542       // Find texture origin.
543       floor_uoffs = (float)sec->floor_xoffs/(float)(FRACUNIT*64);
544       floor_voffs = (float)sec->floor_yoffs/(float)(FRACUNIT*64);
545 
546       for (loopnum = 0; loopnum < subsectorloops[ssidx].loopcount; loopnum++)
547       {
548         int vertexnum;
549         GLLoopDef *currentloop = &subsectorloops[ssidx].loops[loopnum];
550 
551         if (!currentloop)
552           continue;
553 
554         // set the mode (GL_TRIANGLE_FAN)
555         glBegin(currentloop->mode);
556         // go through all vertexes of this loop
557         for (vertexnum = currentloop->vertexindex; vertexnum < (currentloop->vertexindex + currentloop->vertexcount); vertexnum++)
558         {
559           glTexCoord2f(flats_vbo[vertexnum].u + floor_uoffs, flats_vbo[vertexnum].v + floor_voffs);
560           glVertex3f(flats_vbo[vertexnum].x, flats_vbo[vertexnum].z, 0);
561         }
562         glEnd();
563       }
564     }
565   }
566 
567   glMatrixMode(GL_MODELVIEW);
568   glPopMatrix();
569   glDisable(GL_SCISSOR_TEST);
570 }
571 
gld_DrawTriangleStrip(GLWall * wall,gl_strip_coords_t * c)572 void gld_DrawTriangleStrip(GLWall *wall, gl_strip_coords_t *c)
573 {
574   glBegin(GL_TRIANGLE_STRIP);
575 
576   glTexCoord2fv((const GLfloat*)&c->t[0]);
577   glVertex3fv((const GLfloat*)&c->v[0]);
578 
579   glTexCoord2fv((const GLfloat*)&c->t[1]);
580   glVertex3fv((const GLfloat*)&c->v[1]);
581 
582   glTexCoord2fv((const GLfloat*)&c->t[2]);
583   glVertex3fv((const GLfloat*)&c->v[2]);
584 
585   glTexCoord2fv((const GLfloat*)&c->t[3]);
586   glVertex3fv((const GLfloat*)&c->v[3]);
587 
588   glEnd();
589 }
590 
gld_DrawNumPatch_f(float x,float y,int lump,int cm,enum patch_translation_e flags)591 void gld_DrawNumPatch_f(float x, float y, int lump, int cm, enum patch_translation_e flags)
592 {
593   GLTexture *gltexture;
594   float fU1,fU2,fV1,fV2;
595   float width,height;
596   float xpos, ypos;
597   int cmap;
598   int leftoffset, topoffset;
599 
600   //e6y
601   dboolean bFakeColormap;
602   static float cm2RGB[CR_LIMIT + 1][4] = {
603     {0.50f ,0.00f, 0.00f, 1.00f}, //CR_BRICK
604     {1.00f ,1.00f, 1.00f, 1.00f}, //CR_TAN
605     {1.00f ,1.00f, 1.00f, 1.00f}, //CR_GRAY
606     {0.00f ,1.00f, 0.00f, 1.00f}, //CR_GREEN
607     {0.50f ,0.20f, 1.00f, 1.00f}, //CR_BROWN
608     {1.00f ,1.00f, 0.00f, 1.00f}, //CR_GOLD
609     {1.00f ,0.00f, 0.00f, 1.00f}, //CR_RED
610     {0.80f ,0.80f, 1.00f, 1.00f}, //CR_BLUE
611     {1.00f ,0.50f, 0.25f, 1.00f}, //CR_ORANGE
612     {1.00f ,1.00f, 0.00f, 1.00f}, //CR_YELLOW
613     {0.50f ,0.50f, 1.00f, 1.00f}, //CR_BLUE2
614     {1.00f ,1.00f, 1.00f, 1.00f}, //CR_LIMIT
615   };
616 
617   cmap = ((flags & VPT_TRANS) ? cm : CR_DEFAULT);
618   gltexture=gld_RegisterPatch(lump, cmap);
619   gld_BindPatch(gltexture, cmap);
620 
621   if (!gltexture)
622     return;
623   fV1=0.0f;
624   fV2=gltexture->scaleyfac;
625   if (flags & VPT_FLIP)
626   {
627     fU1=gltexture->scalexfac;
628     fU2=0.0f;
629   }
630   else
631   {
632     fU1=0.0f;
633     fU2=gltexture->scalexfac;
634   }
635 
636   if (flags & VPT_NOOFFSET)
637   {
638     leftoffset = 0;
639     topoffset = 0;
640   }
641   else
642   {
643     leftoffset = gltexture->leftoffset;
644     topoffset = gltexture->topoffset;
645   }
646 
647   if (flags & VPT_STRETCH_MASK)
648   {
649     stretch_param_t *params = &stretch_params[flags & VPT_ALIGN_MASK];
650 
651     xpos   = (float)((x - leftoffset) * params->video->width)  / 320.0f + params->deltax1;
652     ypos   = (float)((y - topoffset)  * params->video->height) / 200.0f + params->deltay1;
653     width  = (float)(gltexture->realtexwidth     * params->video->width)  / 320.0f;
654     height = (float)(gltexture->realtexheight    * params->video->height) / 200.0f;
655   }
656   else
657   {
658     xpos   = (float)(x - leftoffset);
659     ypos   = (float)(y - topoffset);
660     width  = (float)(gltexture->realtexwidth);
661     height = (float)(gltexture->realtexheight);
662   }
663 
664   bFakeColormap =
665     (gltexture->flags & GLTEXTURE_HIRES) &&
666     (lumpinfo[lump].flags & LUMP_CM2RGB);
667   if (bFakeColormap)
668   {
669     if (!(flags & VPT_TRANS) && (cm != CR_GRAY))
670     {
671       cm = CR_RED;
672     }
673     glColor3f(cm2RGB[cm][0], cm2RGB[cm][1], cm2RGB[cm][2]);//, cm2RGB[cm][3]);
674   }
675   else
676   {
677     // e6y
678     // This is a workaround for some on-board Intel video cards.
679     // Do you know more elegant solution?
680     glColor3f(1.0f, 1.0f, 1.0f);
681   }
682 
683   glBegin(GL_TRIANGLE_STRIP);
684     glTexCoord2f(fU1, fV1); glVertex2f((xpos),(ypos));
685     glTexCoord2f(fU1, fV2); glVertex2f((xpos),(ypos+height));
686     glTexCoord2f(fU2, fV1); glVertex2f((xpos+width),(ypos));
687     glTexCoord2f(fU2, fV2); glVertex2f((xpos+width),(ypos+height));
688   glEnd();
689 
690   if (bFakeColormap)
691   {
692     glColor3f(1.0f,1.0f,1.0f);
693   }
694 }
695 
gld_DrawNumPatch(int x,int y,int lump,int cm,enum patch_translation_e flags)696 void gld_DrawNumPatch(int x, int y, int lump, int cm, enum patch_translation_e flags)
697 {
698   gld_DrawNumPatch_f((float)x, (float)y, lump, cm, flags);
699 }
700 
gld_FillFlat(int lump,int x,int y,int width,int height,enum patch_translation_e flags)701 void gld_FillFlat(int lump, int x, int y, int width, int height, enum patch_translation_e flags)
702 {
703   GLTexture *gltexture;
704   float fU1, fU2, fV1, fV2;
705 
706   //e6y: Boom colormap should not be applied for background
707   int saved_boom_cm = boom_cm;
708   boom_cm = 0;
709 
710   gltexture = gld_RegisterFlat(lump, false);
711   gld_BindFlat(gltexture, 0);
712 
713   //e6y
714   boom_cm = saved_boom_cm;
715 
716   if (!gltexture)
717     return;
718 
719   if (flags & VPT_STRETCH)
720   {
721     x = x * SCREENWIDTH / 320;
722     y = y * SCREENHEIGHT / 200;
723     width = width * SCREENWIDTH / 320;
724     height = height * SCREENHEIGHT / 200;
725   }
726 
727   fU1 = 0;
728   fV1 = 0;
729   fU2 = (float)width / (float)gltexture->realtexwidth;
730   fV2 = (float)height / (float)gltexture->realtexheight;
731 
732   glBegin(GL_TRIANGLE_STRIP);
733     glTexCoord2f(fU1, fV1); glVertex2f((float)(x),(float)(y));
734     glTexCoord2f(fU1, fV2); glVertex2f((float)(x),(float)(y + height));
735     glTexCoord2f(fU2, fV1); glVertex2f((float)(x + width),(float)(y));
736     glTexCoord2f(fU2, fV2); glVertex2f((float)(x + width),(float)(y + height));
737   glEnd();
738 }
739 
gld_FillPatch(int lump,int x,int y,int width,int height,enum patch_translation_e flags)740 void gld_FillPatch(int lump, int x, int y, int width, int height, enum patch_translation_e flags)
741 {
742   GLTexture *gltexture;
743   float fU1, fU2, fV1, fV2;
744 
745   //e6y: Boom colormap should not be applied for background
746   int saved_boom_cm = boom_cm;
747   boom_cm = 0;
748 
749   gltexture = gld_RegisterPatch(lump, false);
750   gld_BindPatch(gltexture, CR_DEFAULT);
751 
752   if (!gltexture)
753     return;
754 
755   x = x - gltexture->leftoffset;
756   y = y - gltexture->topoffset;
757 
758   //e6y
759   boom_cm = saved_boom_cm;
760 
761   if (flags & VPT_STRETCH)
762   {
763     x = x * SCREENWIDTH / 320;
764     y = y * SCREENHEIGHT / 200;
765     width = width * SCREENWIDTH / 320;
766     height = height * SCREENHEIGHT / 200;
767   }
768 
769   fU1 = 0;
770   fV1 = 0;
771   fU2 = (float)width / (float)gltexture->realtexwidth;
772   fV2 = (float)height / (float)gltexture->realtexheight;
773 
774   glBegin(GL_TRIANGLE_STRIP);
775     glTexCoord2f(fU1, fV1); glVertex2f((float)(x),(float)(y));
776     glTexCoord2f(fU1, fV2); glVertex2f((float)(x),(float)(y + height));
777     glTexCoord2f(fU2, fV1); glVertex2f((float)(x + width),(float)(y));
778     glTexCoord2f(fU2, fV2); glVertex2f((float)(x + width),(float)(y + height));
779   glEnd();
780 }
781 
gld_BeginLines(void)782 void gld_BeginLines(void)
783 {
784   gld_EnableTexture2D(GL_TEXTURE0_ARB, false);
785 #if defined(USE_VERTEX_ARRAYS) || defined(USE_VBO)
786   glEnableClientState(GL_VERTEX_ARRAY);
787   memset(map_lines.count, 0, MAP_COLORS_COUNT * sizeof(map_lines.count[0]));
788 #endif
789 }
790 
gld_EndLines(void)791 void gld_EndLines(void)
792 {
793   gld_EnableTexture2D(GL_TEXTURE0_ARB, true);
794 
795 #if defined(USE_VERTEX_ARRAYS) || defined(USE_VBO)
796   glVertexPointer(3, GL_FLOAT, sizeof(flats_vbo[0]), flats_vbo_x);
797   glDisableClientState(GL_VERTEX_ARRAY);
798 #endif
799 }
800 
gld_DrawMapLines(void)801 void gld_DrawMapLines(void)
802 {
803 #if defined(USE_VERTEX_ARRAYS) || defined(USE_VBO)
804   int i;
805   const unsigned char *playpal = V_GetPlaypal();
806 
807   float alpha = ((automapmode & am_overlay) ? map_lines_overlay_trans / 100.0f : 1.0f);
808   if (alpha == 0)
809     return;
810 
811   for (i = 0; i < MAP_COLORS_COUNT; i++)
812   {
813     if (map_lines.count[i] > 0)
814     {
815       glColor4f(
816         (float)playpal[3 * i + 0] / 255.0f,
817         (float)playpal[3 * i + 1] / 255.0f,
818         (float)playpal[3 * i + 2] / 255.0f,
819         alpha);
820 
821       glVertexPointer(2, GL_FLOAT, 0, map_lines.points[i]);
822 
823       glDrawArrays(GL_LINES, 0, map_lines.count[i]/2);
824     }
825   }
826 #endif
827 }
828 
gld_DrawLine_f(float x0,float y0,float x1,float y1,int BaseColor)829 void gld_DrawLine_f(float x0, float y0, float x1, float y1, int BaseColor)
830 {
831 #if defined(USE_VERTEX_ARRAYS) || defined(USE_VBO)
832   if (!map_lines.points[BaseColor])
833   {
834     map_lines.points[BaseColor] = malloc(128 * 4 * sizeof(map_lines.points[0][0]));
835     map_lines.maxsize[BaseColor] = 128;
836   }
837   if (map_lines.count[BaseColor] + 4 >= map_lines.maxsize[BaseColor])
838   {
839     map_lines.maxsize[BaseColor] = map_lines.maxsize[BaseColor] * 2;
840     map_lines.points[BaseColor] = realloc(map_lines.points[BaseColor], map_lines.maxsize[BaseColor] * 4 * sizeof(map_lines.points[0][0]));
841   }
842 
843   map_lines.points[BaseColor][map_lines.count[BaseColor]++] = x0;
844   map_lines.points[BaseColor][map_lines.count[BaseColor]++] = y0;
845   map_lines.points[BaseColor][map_lines.count[BaseColor]++] = x1;
846   map_lines.points[BaseColor][map_lines.count[BaseColor]++] = y1;
847 #else
848   const unsigned char *playpal = V_GetPlaypal();
849 
850   float alpha = ((automapmode & am_overlay) ? map_lines_overlay_trans / 100.0f : 1.0f);
851   if (alpha == 0)
852     return;
853 
854   glColor4f((float)playpal[3*BaseColor]/255.0f,
855             (float)playpal[3*BaseColor+1]/255.0f,
856             (float)playpal[3*BaseColor+2]/255.0f,
857             alpha);
858   glBegin(GL_LINES);
859     glVertex2f( x0, y0 );
860     glVertex2f( x1, y1 );
861   glEnd();
862 #endif
863 }
864 
gld_DrawLine(int x0,int y0,int x1,int y1,int BaseColor)865 void gld_DrawLine(int x0, int y0, int x1, int y1, int BaseColor)
866 {
867   gld_DrawLine_f((float)x0, (float)y0, (float)x1, (float)y1, BaseColor);
868 }
869 
gld_DrawWeapon(int weaponlump,vissprite_t * vis,int lightlevel)870 void gld_DrawWeapon(int weaponlump, vissprite_t *vis, int lightlevel)
871 {
872   GLTexture *gltexture;
873   float fU1,fU2,fV1,fV2;
874   int x1,y1,x2,y2;
875   float light;
876 
877   gltexture=gld_RegisterPatch(firstspritelump+weaponlump, CR_DEFAULT);
878   if (!gltexture)
879     return;
880   gld_BindPatch(gltexture, CR_DEFAULT);
881   fU1=0;
882   fV1=0;
883   fU2=gltexture->scalexfac;
884   fV2=gltexture->scaleyfac;
885   // e6y
886   // More precise weapon drawing:
887   // Shotgun from DSV3_War looks correctly now. Especially during movement.
888   // There is no more line of graphics under certain weapons.
889   x1=viewwindowx+vis->x1;
890   x2=x1+(int)((float)gltexture->realtexwidth*pspritexscale_f);
891   y1=viewwindowy+centery-(int)(((float)vis->texturemid/(float)FRACUNIT)*pspriteyscale_f);
892   y2=y1+(int)((float)gltexture->realtexheight*pspriteyscale_f)+1;
893   // e6y: don't do the gamma table correction on the lighting
894   light = (float)lightlevel / 255.0f;
895 
896   // e6y
897   // Fix of no warning (flashes between shadowed and solid)
898   // when invisibility is about to go
899   if (/*(viewplayer->mo->flags & MF_SHADOW) && */!vis->colormap)
900   {
901     glBlendFunc(GL_DST_COLOR, GL_ONE_MINUS_SRC_ALPHA);
902     glAlphaFunc(GL_GEQUAL,0.1f);
903     //glColor4f(0.2f,0.2f,0.2f,(float)tran_filter_pct/100.0f);
904     glColor4f(0.2f,0.2f,0.2f,0.33f);
905   }
906   else
907   {
908     if (viewplayer->mo->flags & MF_TRANSLUCENT)
909       gld_StaticLightAlpha(light,(float)tran_filter_pct/100.0f);
910     else
911       gld_StaticLight(light);
912   }
913   glBegin(GL_TRIANGLE_STRIP);
914     glTexCoord2f(fU1, fV1); glVertex2f((float)(x1),(float)(y1));
915     glTexCoord2f(fU1, fV2); glVertex2f((float)(x1),(float)(y2));
916     glTexCoord2f(fU2, fV1); glVertex2f((float)(x2),(float)(y1));
917     glTexCoord2f(fU2, fV2); glVertex2f((float)(x2),(float)(y2));
918   glEnd();
919   if(!vis->colormap)
920   {
921     glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
922     glAlphaFunc(GL_GEQUAL,0.5f);
923   }
924   glColor3f(1.0f,1.0f,1.0f);
925 }
926 
gld_FillBlock(int x,int y,int width,int height,int col)927 void gld_FillBlock(int x, int y, int width, int height, int col)
928 {
929   const unsigned char *playpal = V_GetPlaypal();
930 
931   gld_EnableTexture2D(GL_TEXTURE0_ARB, false);
932   glColor3f((float)playpal[3*col]/255.0f,
933             (float)playpal[3*col+1]/255.0f,
934             (float)playpal[3*col+2]/255.0f);
935   glBegin(GL_TRIANGLE_STRIP);
936     glVertex2i( x, y );
937     glVertex2i( x, y+height );
938     glVertex2i( x+width, y );
939     glVertex2i( x+width, y+height );
940   glEnd();
941   glColor3f(1.0f,1.0f,1.0f);
942   gld_EnableTexture2D(GL_TEXTURE0_ARB, true);
943 }
944 
gld_SetPalette(int palette)945 void gld_SetPalette(int palette)
946 {
947   static int last_palette = 0;
948   extra_red=0.0f;
949   extra_green=0.0f;
950   extra_blue=0.0f;
951   extra_alpha=0.0f;
952   if (palette < 0)
953     palette = last_palette;
954   last_palette = palette;
955   if (gl_shared_texture_palette) {
956     const unsigned char *playpal;
957     unsigned char pal[1024];
958     int i;
959 
960     playpal = V_GetPlaypal();
961     playpal += (768*palette);
962     for (i=0; i<256; i++) {
963       int col;
964 
965       if (fixedcolormap)
966         col = fixedcolormap[i];
967       else if (fullcolormap)
968         col = fullcolormap[i];
969       else
970         col = i;
971       pal[i*4+0] = playpal[col*3+0];
972       pal[i*4+1] = playpal[col*3+1];
973       pal[i*4+2] = playpal[col*3+2];
974       pal[i*4+3] = 255;
975     }
976     pal[transparent_pal_index*4+0]=0;
977     pal[transparent_pal_index*4+1]=0;
978     pal[transparent_pal_index*4+2]=0;
979     pal[transparent_pal_index*4+3]=0;
980     GLEXT_glColorTableEXT(GL_SHARED_TEXTURE_PALETTE_EXT, GL_RGBA, 256, GL_RGBA, GL_UNSIGNED_BYTE, pal);
981   } else {
982     if (palette>0)
983     {
984       if (palette<=8)
985       {
986         extra_red=(float)palette/2.0f;
987         extra_green=0.0f;
988         extra_blue=0.0f;
989         extra_alpha=(float)palette/10.0f;
990       }
991       else
992         if (palette<=12)
993         {
994           palette=palette-8;
995           extra_red=(float)palette*1.0f;
996           extra_green=(float)palette*0.8f;
997           extra_blue=(float)palette*0.1f;
998           extra_alpha=(float)palette/11.0f;
999         }
1000         else
1001           if (palette==13)
1002           {
1003             extra_red=0.4f;
1004             extra_green=1.0f;
1005             extra_blue=0.0f;
1006             extra_alpha=0.2f;
1007           }
1008     }
1009     if (extra_red>1.0f)
1010       extra_red=1.0f;
1011     if (extra_green>1.0f)
1012       extra_green=1.0f;
1013     if (extra_blue>1.0f)
1014       extra_blue=1.0f;
1015     if (extra_alpha>1.0f)
1016       extra_alpha=1.0f;
1017   }
1018 }
1019 
gld_ReadScreen(void)1020 unsigned char *gld_ReadScreen(void)
1021 { // NSM convert to static
1022   static unsigned char *scr = NULL;
1023   static unsigned char *buffer = NULL;
1024   static int scr_size = 0;
1025   static int buffer_size = 0;
1026 
1027   int i, size;
1028 
1029   size = REAL_SCREENWIDTH * 3;
1030   if (!buffer || size > buffer_size)
1031   {
1032     buffer_size = size;
1033     buffer = realloc (buffer, size);
1034   }
1035   size = REAL_SCREENWIDTH * REAL_SCREENHEIGHT * 3;
1036   if (!scr || size > scr_size)
1037   {
1038     scr_size = size;
1039     scr = realloc (scr, size);
1040   }
1041 
1042   if (buffer && scr)
1043   {
1044       GLint pack_aligment;
1045       glGetIntegerv(GL_PACK_ALIGNMENT, &pack_aligment);
1046       glPixelStorei(GL_PACK_ALIGNMENT, 1);
1047 
1048       glFlush();
1049       glReadPixels(0, 0, REAL_SCREENWIDTH, REAL_SCREENHEIGHT, GL_RGB, GL_UNSIGNED_BYTE, scr);
1050 
1051       glPixelStorei(GL_PACK_ALIGNMENT, pack_aligment);
1052 
1053       gld_ApplyGammaRamp(scr, REAL_SCREENWIDTH * 3, REAL_SCREENWIDTH, REAL_SCREENHEIGHT);
1054 
1055       for (i=0; i<REAL_SCREENHEIGHT/2; i++)
1056       {
1057         memcpy(buffer, &scr[i*REAL_SCREENWIDTH*3], REAL_SCREENWIDTH*3);
1058         memcpy(&scr[i*REAL_SCREENWIDTH*3],
1059           &scr[(REAL_SCREENHEIGHT-(i+1))*REAL_SCREENWIDTH*3], REAL_SCREENWIDTH*3);
1060         memcpy(&scr[(REAL_SCREENHEIGHT-(i+1))*REAL_SCREENWIDTH*3], buffer, REAL_SCREENWIDTH*3);
1061       }
1062     }
1063 
1064   return scr;
1065 }
1066 
gld_Set2DMode(void)1067 GLvoid gld_Set2DMode(void)
1068 {
1069   glMatrixMode(GL_MODELVIEW);
1070   glLoadIdentity();
1071   glMatrixMode(GL_PROJECTION);
1072   glLoadIdentity();
1073   glOrtho(
1074     (GLdouble) 0,
1075     (GLdouble) REAL_SCREENWIDTH,
1076     (GLdouble) REAL_SCREENHEIGHT,
1077     (GLdouble) 0,
1078     (GLdouble) -1.0,
1079     (GLdouble) 1.0
1080   );
1081   glDisable(GL_DEPTH_TEST);
1082 }
1083 
gld_InitDrawScene(void)1084 void gld_InitDrawScene(void)
1085 {
1086   gld_ResetDrawInfo();
1087 }
1088 
gld_Finish(void)1089 void gld_Finish(void)
1090 {
1091   gld_Set2DMode();
1092   glFinish();
1093   SDL_GL_SwapBuffers();
1094 }
1095 
1096 GLuint flats_vbo_id = 0; // ID of VBO
1097 
1098 vbo_xyz_uv_t *flats_vbo = NULL;
1099 
1100 GLSeg *gl_segs=NULL;
1101 GLSeg *gl_lines=NULL;
1102 
1103 byte rendermarker=0;
1104 byte *segrendered; // true if sector rendered (only here for malloc)
1105 byte *linerendered[2]; // true if linedef rendered (only here for malloc)
1106 
1107 float roll     = 0.0f;
1108 float yaw      = 0.0f;
1109 float inv_yaw  = 0.0f;
1110 float pitch    = 0.0f;
1111 float cos_inv_yaw, sin_inv_yaw;
1112 float paperitems_pitch;
1113 float cos_paperitems_pitch, sin_paperitems_pitch;
1114 
1115 #define __glPi 3.14159265358979323846
1116 
infinitePerspective(GLdouble fovy,GLdouble aspect,GLdouble znear)1117 static void infinitePerspective(GLdouble fovy, GLdouble aspect, GLdouble znear)
1118 {
1119 	GLdouble left, right, bottom, top;
1120 	GLdouble m[16];
1121 
1122 	top = znear * tan(fovy * __glPi / 360.0);
1123 	bottom = -top;
1124 	left = bottom * aspect;
1125 	right = top * aspect;
1126 
1127 	//qglFrustum(left, right, bottom, top, znear, zfar);
1128 
1129 	m[ 0] = (2 * znear) / (right - left);
1130 	m[ 4] = 0;
1131 	m[ 8] = (right + left) / (right - left);
1132 	m[12] = 0;
1133 
1134 	m[ 1] = 0;
1135 	m[ 5] = (2 * znear) / (top - bottom);
1136 	m[ 9] = (top + bottom) / (top - bottom);
1137 	m[13] = 0;
1138 
1139 	m[ 2] = 0;
1140 	m[ 6] = 0;
1141 	//m[10] = - (zfar + znear) / (zfar - znear);
1142 	//m[14] = - (2 * zfar * znear) / (zfar - znear);
1143 	m[10] = -1;
1144 	m[14] = -2 * znear;
1145 
1146 	m[ 3] = 0;
1147 	m[ 7] = 0;
1148 	m[11] = -1;
1149 	m[15] = 0;
1150 
1151 	glMultMatrixd(m);
1152 }
1153 
gld_Clear(void)1154 void gld_Clear(void)
1155 {
1156   int clearbits = 0;
1157 
1158 #ifndef PRBOOM_DEBUG
1159   if (gl_clear)
1160 #endif
1161     clearbits |= GL_COLOR_BUFFER_BIT;
1162 
1163   // flashing red HOM indicators
1164   if (flashing_hom)
1165   {
1166     clearbits |= GL_COLOR_BUFFER_BIT;
1167     glClearColor (gametic % 20 < 9 ? 1.0f : 0.0f, 0.0f, 0.0f, 1.0f);
1168   }
1169 
1170   if (gl_use_stencil)
1171     clearbits |= GL_STENCIL_BUFFER_BIT;
1172 
1173   if (!gl_ztrick)
1174     clearbits |= GL_DEPTH_BUFFER_BIT;
1175 
1176   if (clearbits)
1177     glClear(clearbits);
1178 
1179   if (gl_ztrick)
1180   {
1181     gl_ztrickframe = !gl_ztrickframe;
1182     if (gl_ztrickframe)
1183     {
1184       gldepthmin = 0.0f;
1185       gldepthmax = 0.49999f;
1186       glDepthFunc(GL_LEQUAL);
1187     }
1188     else
1189     {
1190       gldepthmin = 1.0f;
1191       gldepthmax = 0.5f;
1192       glDepthFunc(GL_GEQUAL);
1193     }
1194     glDepthRange(gldepthmin, gldepthmax);
1195   }
1196 }
1197 
gld_StartDrawScene(void)1198 void gld_StartDrawScene(void)
1199 {
1200   extern int screenblocks;
1201   int height;
1202 
1203   gld_MultisamplingSet();
1204 
1205   if (gl_shared_texture_palette)
1206     glEnable(GL_SHARED_TEXTURE_PALETTE_EXT);
1207   gld_SetPalette(-1);
1208 
1209   if (screenblocks == 11)
1210     height = SCREENHEIGHT;
1211   else if (screenblocks == 10)
1212     height = SCREENHEIGHT;
1213   else
1214     height = (screenblocks*SCREENHEIGHT/10) & ~7;
1215 
1216   glViewport(viewwindowx, SCREENHEIGHT-(height+viewwindowy-((height-viewheight)/2)), viewwidth, height);
1217   glScissor(viewwindowx, SCREENHEIGHT-(viewheight+viewwindowy), viewwidth, viewheight);
1218   glEnable(GL_SCISSOR_TEST);
1219   // Player coordinates
1220   xCamera=-(float)viewx/MAP_SCALE;
1221   yCamera=(float)viewy/MAP_SCALE;
1222   zCamera=(float)viewz/MAP_SCALE;
1223 
1224   yaw=270.0f-(float)(viewangle>>ANGLETOFINESHIFT)*360.0f/FINEANGLES;
1225   inv_yaw=180.0f-yaw;
1226   cos_inv_yaw = (float)cos(inv_yaw * M_PI / 180.f);
1227   sin_inv_yaw = (float)sin(inv_yaw * M_PI / 180.f);
1228 
1229   gl_spriteindex = 0;
1230 
1231   //e6y: fog in frame
1232   gl_use_fog = !gl_compatibility &&
1233     (gl_fog || gl_lightmode == gl_lightmode_fogbased) &&
1234     !frame_fixedcolormap && !boom_cm;
1235 
1236 //e6y
1237   mlook_or_fov = GetMouseLook() || (render_fov != FOV90);
1238   if(!mlook_or_fov)
1239   {
1240     pitch = 0.0f;
1241     paperitems_pitch = 0.0f;
1242 
1243     skyXShift = -2.0f * ((yaw + 90.0f) / 90.0f);
1244     skyYShift = 200.0f / 319.5f;
1245   }
1246   else
1247   {
1248     float f = viewPitch * 2 + 50 / skyscale;
1249     f = BETWEEN(0, 127, f);
1250     skyXShift = -2.0f * ((yaw + 90.0f) / 90.0f / skyscale);
1251     skyYShift = f / 128.0f + 200.0f / 320.0f / skyscale;
1252 
1253     pitch = (float)(float)(viewpitch>>ANGLETOFINESHIFT) * 360.0f / FINEANGLES;
1254     paperitems_pitch = ((pitch > 87.0f && pitch <= 90.0f) ? 87.0f : pitch);
1255     viewPitch = (pitch > 180 ? pitch - 360 : pitch);
1256   }
1257   cos_paperitems_pitch = (float)cos(paperitems_pitch * M_PI / 180.f);
1258   sin_paperitems_pitch = (float)sin(paperitems_pitch * M_PI / 180.f);
1259   gl_mask_sprite_threshold_f = (gl_sprite_blend ? (float)gl_mask_sprite_threshold / 100.0f : 0.5f);
1260 
1261   gld_InitFrameSky();
1262 
1263   invul_method = 0;
1264   if (players[displayplayer].fixedcolormap == 32)
1265   {
1266     if (gl_boom_colormaps && !gl_has_hires)
1267     {
1268       invul_method = INVUL_CM;
1269     }
1270     else
1271     {
1272       if (gl_version >= OPENGL_VERSION_1_3)
1273       {
1274         invul_method = INVUL_BW;
1275       }
1276       else
1277       {
1278         invul_method = INVUL_INV;
1279       }
1280     }
1281   }
1282 
1283 #ifdef USE_FBO_TECHNIQUE
1284   if (gl_use_motionblur)
1285   {
1286     ticcmd_t *cmd = &players[displayplayer].cmd;
1287     int camera_speed = cmd->forwardmove * cmd->forwardmove + cmd->sidemove * cmd->sidemove;
1288     MotionBlurOn = camera_speed > gl_motionblur_minspeed_pow2;
1289   }
1290 
1291   SceneInTexture = (gl_ext_framebuffer_object) &&
1292     ((invul_method & INVUL_BW) || (MotionBlurOn));
1293 
1294   // Vortex: Set FBO object
1295   if (SceneInTexture)
1296   {
1297     GLEXT_glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, glSceneImageFBOTexID);
1298     glTexEnvi(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_MODULATE);
1299   }
1300   else
1301 #endif
1302   if (invul_method & INVUL_BW)
1303   {
1304     glTexEnvi(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_COMBINE);
1305     glTexEnvi(GL_TEXTURE_ENV,GL_COMBINE_RGB,GL_DOT3_RGB);
1306     glTexEnvi(GL_TEXTURE_ENV,GL_SOURCE0_RGB,GL_PRIMARY_COLOR);
1307     glTexEnvi(GL_TEXTURE_ENV,GL_OPERAND0_RGB,GL_SRC_COLOR);
1308     glTexEnvi(GL_TEXTURE_ENV,GL_SOURCE1_RGB,GL_TEXTURE);
1309     glTexEnvi(GL_TEXTURE_ENV,GL_OPERAND1_RGB,GL_SRC_COLOR);
1310   }
1311 
1312   gld_Clear();
1313 
1314   glEnable(GL_DEPTH_TEST);
1315 
1316   glMatrixMode(GL_PROJECTION);
1317   glLoadIdentity();
1318 
1319 //e6y  infinitePerspective(64.0f, 320.0f/200.0f, (float)gl_nearclip/100.0f);
1320   infinitePerspective(render_fovy, render_ratio, (float)gl_nearclip/100.0f);//e6y
1321 
1322   glMatrixMode(GL_MODELVIEW);
1323   glLoadIdentity();
1324   glRotatef(roll,  0.0f, 0.0f, 1.0f);
1325   glRotatef(pitch, 1.0f, 0.0f, 0.0f);
1326   glRotatef(yaw,   0.0f, 1.0f, 0.0f);
1327   glTranslatef(-xCamera, -zCamera, -yCamera);
1328 
1329   rendermarker++;
1330   scene_has_overlapped_sprites = false;
1331   scene_has_wall_details = 0;
1332   scene_has_flat_details = 0;
1333 }
1334 
1335 //e6y
gld_ProcessExtraAlpha(void)1336 static void gld_ProcessExtraAlpha(void)
1337 {
1338   if (extra_alpha>0.0f)
1339   {
1340     glDisable(GL_ALPHA_TEST);
1341     glColor4f(extra_red, extra_green, extra_blue, extra_alpha);
1342     gld_EnableTexture2D(GL_TEXTURE0_ARB, false);
1343     glBegin(GL_TRIANGLE_STRIP);
1344       glVertex2f( 0.0f, 0.0f);
1345       glVertex2f( 0.0f, (float)SCREENHEIGHT);
1346       glVertex2f( (float)SCREENWIDTH, 0.0f);
1347       glVertex2f( (float)SCREENWIDTH, (float)SCREENHEIGHT);
1348     glEnd();
1349     gld_EnableTexture2D(GL_TEXTURE0_ARB, true);
1350     glEnable(GL_ALPHA_TEST);
1351   }
1352 }
1353 
1354 //e6y
gld_InvertScene(void)1355 static void gld_InvertScene(void)
1356 {
1357   glBlendFunc(GL_ONE_MINUS_DST_COLOR, GL_ZERO);
1358   glColor4f(1,1,1,1);
1359   gld_EnableTexture2D(GL_TEXTURE0_ARB, false);
1360   glBegin(GL_TRIANGLE_STRIP);
1361     glVertex2f( 0.0f, 0.0f);
1362     glVertex2f( 0.0f, (float)SCREENHEIGHT);
1363     glVertex2f( (float)SCREENWIDTH, 0.0f);
1364     glVertex2f( (float)SCREENWIDTH, (float)SCREENHEIGHT);
1365   glEnd();
1366   gld_EnableTexture2D(GL_TEXTURE0_ARB, true);
1367   glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1368 }
1369 
gld_EndDrawScene(void)1370 void gld_EndDrawScene(void)
1371 {
1372   glDisable(GL_POLYGON_SMOOTH);
1373 
1374   glViewport(0, 0, SCREENWIDTH, SCREENHEIGHT);
1375   gl_EnableFog(false);
1376   gld_Set2DMode();
1377 
1378   if (viewangleoffset <= 1024<<ANGLETOFINESHIFT ||
1379     viewangleoffset >=-1024<<ANGLETOFINESHIFT)
1380   { // don't draw on side views
1381     R_DrawPlayerSprites();
1382   }
1383 
1384   // e6y
1385   // Effect of invulnerability uses a colormap instead of hard-coding now
1386   // See nuts.wad
1387   // http://www.doomworld.com/idgames/index.php?id=11402
1388 
1389 #ifdef USE_FBO_TECHNIQUE
1390   // Vortex: Black and white effect
1391   if (SceneInTexture)
1392   {
1393     // below if scene is in texture
1394     if (!invul_method)
1395     {
1396       gld_ProcessExtraAlpha();
1397     }
1398 
1399     // Vortex: Restore original RT
1400     GLEXT_glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
1401 
1402     glBindTexture(GL_TEXTURE_2D, glSceneImageTextureFBOTexID);
1403 
1404     // Setup blender
1405     if (invul_method & INVUL_BW)
1406     {
1407       glTexEnvi(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_COMBINE);
1408       glTexEnvi(GL_TEXTURE_ENV,GL_COMBINE_RGB,GL_DOT3_RGB);
1409       glTexEnvi(GL_TEXTURE_ENV,GL_SOURCE0_RGB,GL_PRIMARY_COLOR);
1410       glTexEnvi(GL_TEXTURE_ENV,GL_OPERAND0_RGB,GL_SRC_COLOR);
1411       glTexEnvi(GL_TEXTURE_ENV,GL_SOURCE1_RGB,GL_TEXTURE);
1412       glTexEnvi(GL_TEXTURE_ENV,GL_OPERAND1_RGB,GL_SRC_COLOR);
1413 
1414       if (gl_invul_bw_method == 0)
1415         glColor3f(0.3f, 0.3f, 0.4f);
1416       else
1417         glColor3f(bw_red, bw_green, bw_blue);
1418     }
1419     else
1420     {
1421       glColor3f(1.0f, 1.0f, 1.0f);
1422     }
1423 
1424     //e6y: motion bloor effect for strafe50
1425     if (MotionBlurOn)
1426     {
1427       extern int renderer_fps;
1428       static float motionblur_alpha = 1.0f;
1429 
1430       if (realframe)
1431       {
1432         motionblur_alpha = (float)((atan(-renderer_fps/gl_motionblur_a))/gl_motionblur_b)+gl_motionblur_c;
1433       }
1434 
1435       glBlendFunc(GL_CONSTANT_ALPHA_EXT, GL_ONE_MINUS_CONSTANT_ALPHA_EXT);
1436       GLEXT_glBlendColorEXT(1.0f, 1.0f, 1.0f, motionblur_alpha);
1437     }
1438 
1439     glBegin(GL_TRIANGLE_STRIP);
1440     {
1441       glTexCoord2f(0.0f, 1.0f); glVertex2f(0.0f, 0.0f);
1442       glTexCoord2f(0.0f, 0.0f); glVertex2f(0.0f, (float)SCREENHEIGHT);
1443       glTexCoord2f(1.0f, 1.0f); glVertex2f((float)SCREENWIDTH, 0.0f);
1444       glTexCoord2f(1.0f, 0.0f); glVertex2f((float)SCREENWIDTH, (float)SCREENHEIGHT);
1445     }
1446     glEnd();
1447 
1448 
1449     if (MotionBlurOn)
1450     {
1451       glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1452     }
1453 
1454     glTexEnvi(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_MODULATE);
1455   }
1456   else
1457 #endif
1458   {
1459     if (invul_method & INVUL_INV)
1460     {
1461       gld_InvertScene();
1462     }
1463     if (invul_method & INVUL_BW)
1464     {
1465       glTexEnvi(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_MODULATE);
1466     }
1467 
1468     if (!invul_method)
1469     {
1470       gld_ProcessExtraAlpha();
1471     }
1472   }
1473 
1474   glColor3f(1.0f,1.0f,1.0f);
1475   glDisable(GL_SCISSOR_TEST);
1476   glDisable(GL_ALPHA_TEST);
1477   if (gl_shared_texture_palette)
1478     glDisable(GL_SHARED_TEXTURE_PALETTE_EXT);
1479 }
1480 
gld_AddDrawWallItem(GLDrawItemType itemtype,void * itemdata)1481 static void gld_AddDrawWallItem(GLDrawItemType itemtype, void *itemdata)
1482 {
1483   if (gl_blend_animations)
1484   {
1485     anim_t *anim;
1486     int currpic, nextpic;
1487     GLWall *wall = (GLWall*)itemdata;
1488     float oldalpha = wall->alpha;
1489 
1490     switch (itemtype)
1491     {
1492     case GLDIT_FWALL:
1493       anim = anim_flats[wall->gltexture->index - firstflat].anim;
1494       if (anim)
1495       {
1496         wall->alpha = 1.0f - ((float)tic_vars.frac + ((leveltime - 1) % anim->speed) * 65536.0f) / (65536.0f * anim->speed);
1497         gld_AddDrawItem(GLDIT_FAWALL, itemdata);
1498 
1499         currpic = wall->gltexture->index - firstflat - anim->basepic;
1500         nextpic = anim->basepic + (currpic + 1) % anim->numpics;
1501         wall->alpha = oldalpha;
1502         wall->gltexture = gld_RegisterFlat(nextpic, true);
1503       }
1504       break;
1505     case GLDIT_WALL:
1506     case GLDIT_MWALL:
1507       anim = anim_textures[wall->gltexture->index].anim;
1508       if (anim)
1509       {
1510         if (itemtype == GLDIT_WALL || itemtype == GLDIT_MWALL)
1511         {
1512           wall->alpha = 1.0f - ((float)tic_vars.frac + ((leveltime - 1) % anim->speed) * 65536.0f) / (65536.0f * anim->speed);
1513           gld_AddDrawItem(GLDIT_AWALL, itemdata);
1514 
1515           currpic = wall->gltexture->index - anim->basepic;
1516           nextpic = anim->basepic + (currpic + 1) % anim->numpics;
1517           wall->alpha = oldalpha;
1518           wall->gltexture = gld_RegisterTexture(nextpic, true, false);
1519         }
1520       }
1521       break;
1522     }
1523   }
1524 
1525   if (((GLWall*)itemdata)->gltexture->detail)
1526     scene_has_wall_details++;
1527 
1528   gld_AddDrawItem(itemtype, itemdata);
1529 }
1530 
1531 /*****************
1532  *               *
1533  * Walls         *
1534  *               *
1535  *****************/
1536 
gld_DrawWall(GLWall * wall)1537 static void gld_DrawWall(GLWall *wall)
1538 {
1539   int has_detail;
1540   unsigned int flags;
1541 
1542   rendered_segs++;
1543 
1544   has_detail =
1545     scene_has_details &&
1546     gl_arb_multitexture &&
1547     (wall->flag < GLDWF_SKY) &&
1548     (wall->gltexture->detail) &&
1549     gld_IsDetailVisible(xCamera, yCamera,
1550       wall->glseg->x1, wall->glseg->z1,
1551       wall->glseg->x2, wall->glseg->z2);
1552 
1553   // Do not repeat middle texture vertically
1554   // to avoid visual glitches for textures with holes
1555   if ((wall->flag == GLDWF_M2S) && (wall->flag < GLDWF_SKY))
1556     flags = GLTEXTURE_CLAMPY;
1557   else
1558     flags = 0;
1559 
1560   gld_BindTexture(wall->gltexture, flags);
1561   gld_BindDetailARB(wall->gltexture, has_detail);
1562 
1563   if (!wall->gltexture)
1564   {
1565     glColor4f(1.0f,0.0f,0.0f,1.0f);
1566   }
1567 
1568   if (has_detail)
1569   {
1570     gld_DrawWallWithDetail(wall);
1571   }
1572   else
1573   {
1574     if ((wall->flag == GLDWF_TOPFLUD) || (wall->flag == GLDWF_BOTFLUD))
1575     {
1576       gl_strip_coords_t c;
1577 
1578       gld_BindFlat(wall->gltexture, 0);
1579 
1580       gld_SetupFloodStencil(wall);
1581       gld_SetupFloodedPlaneCoords(wall, &c);
1582       gld_SetupFloodedPlaneLight(wall);
1583       gld_DrawTriangleStrip(wall, &c);
1584 
1585       gld_ClearFloodStencil(wall);
1586     }
1587     else
1588     {
1589       gld_StaticLightAlpha(wall->light, wall->alpha);
1590 
1591       glBegin(GL_TRIANGLE_FAN);
1592 
1593       // lower left corner
1594       glTexCoord2f(wall->ul,wall->vb);
1595       glVertex3f(wall->glseg->x1,wall->ybottom,wall->glseg->z1);
1596 
1597       // split left edge of wall
1598       if (gl_seamless && !wall->glseg->fracleft)
1599         gld_SplitLeftEdge(wall, false);
1600 
1601       // upper left corner
1602       glTexCoord2f(wall->ul,wall->vt);
1603       glVertex3f(wall->glseg->x1,wall->ytop,wall->glseg->z1);
1604 
1605       // upper right corner
1606       glTexCoord2f(wall->ur,wall->vt);
1607       glVertex3f(wall->glseg->x2,wall->ytop,wall->glseg->z2);
1608 
1609       // split right edge of wall
1610       if (gl_seamless && !wall->glseg->fracright)
1611         gld_SplitRightEdge(wall, false);
1612 
1613       // lower right corner
1614       glTexCoord2f(wall->ur,wall->vb);
1615       glVertex3f(wall->glseg->x2,wall->ybottom,wall->glseg->z2);
1616 
1617       glEnd();
1618     }
1619   }
1620 }
1621 
1622 #define LINE seg->linedef
1623 #define CALC_Y_VALUES(w, lineheight, floor_height, ceiling_height)\
1624   (w).ytop=((float)(ceiling_height)/(float)MAP_SCALE)+SMALLDELTA;\
1625   (w).ybottom=((float)(floor_height)/(float)MAP_SCALE)-SMALLDELTA;\
1626   lineheight=((float)fabs(((ceiling_height)/(float)FRACUNIT)-((floor_height)/(float)FRACUNIT)))
1627 
1628 #define OU(w,seg) (((float)((seg)->sidedef->textureoffset)/(float)FRACUNIT)/(float)(w).gltexture->buffer_width)
1629 #define OV(w,seg) (((float)((seg)->sidedef->rowoffset)/(float)FRACUNIT)/(float)(w).gltexture->buffer_height)
1630 #define OV_PEG(w,seg,v_offset) (OV((w),(seg))-(((float)(v_offset)/(float)FRACUNIT)/(float)(w).gltexture->buffer_height))
1631 #define URUL(w, seg, backseg, linelength)\
1632   if (backseg){\
1633     (w).ur=OU((w),(seg));\
1634     (w).ul=(w).ur+((linelength)/(float)(w).gltexture->buffer_width);\
1635   }else{\
1636     (w).ul=OU((w),(seg));\
1637     (w).ur=(w).ul+((linelength)/(float)(w).gltexture->buffer_width);\
1638   }
1639 
1640 #define CALC_TEX_VALUES_TOP(w, seg, backseg, peg, linelength, lineheight)\
1641   (w).flag=GLDWF_TOP;\
1642   URUL(w, seg, backseg, linelength);\
1643   if (peg){\
1644     (w).vb=OV((w),(seg))+((w).gltexture->scaleyfac);\
1645     (w).vt=((w).vb-((float)(lineheight)/(float)(w).gltexture->buffer_height));\
1646   }else{\
1647     (w).vt=OV((w),(seg));\
1648     (w).vb=(w).vt+((float)(lineheight)/(float)(w).gltexture->buffer_height);\
1649   }
1650 
1651 #define CALC_TEX_VALUES_MIDDLE1S(w, seg, backseg, peg, linelength, lineheight)\
1652   (w).flag=GLDWF_M1S;\
1653   URUL(w, seg, backseg, linelength);\
1654   if (peg){\
1655     (w).vb=OV((w),(seg))+((w).gltexture->scaleyfac);\
1656     (w).vt=((w).vb-((float)(lineheight)/(float)(w).gltexture->buffer_height));\
1657   }else{\
1658     (w).vt=OV((w),(seg));\
1659     (w).vb=(w).vt+((float)(lineheight)/(float)(w).gltexture->buffer_height);\
1660   }
1661 
1662 #define CALC_TEX_VALUES_BOTTOM(w, seg, backseg, peg, linelength, lineheight, v_offset)\
1663   (w).flag=GLDWF_BOT;\
1664   URUL(w, seg, backseg, linelength);\
1665   if (peg){\
1666     (w).vb=OV_PEG((w),(seg),(v_offset))+((w).gltexture->scaleyfac);\
1667     (w).vt=((w).vb-((float)(lineheight)/(float)(w).gltexture->buffer_height));\
1668   }else{\
1669     (w).vt=OV((w),(seg));\
1670     (w).vb=(w).vt+((float)(lineheight)/(float)(w).gltexture->buffer_height);\
1671   }
1672 
gld_AddWall(seg_t * seg)1673 void gld_AddWall(seg_t *seg)
1674 {
1675   GLWall wall;
1676   GLTexture *temptex;
1677   sector_t *frontsector;
1678   sector_t *backsector;
1679   sector_t ftempsec; // needed for R_FakeFlat
1680   sector_t btempsec; // needed for R_FakeFlat
1681   float lineheight, linelength;
1682   int rellight = 0;
1683   int backseg;
1684 
1685   int side = (seg->sidedef == &sides[seg->linedef->sidenum[0]] ? 0 : 1);
1686   if (linerendered[side][seg->linedef->iLineID] == rendermarker)
1687     return;
1688   linerendered[side][seg->linedef->iLineID] = rendermarker;
1689   linelength = lines[seg->linedef->iLineID].texel_length;
1690   wall.glseg=&gl_lines[seg->linedef->iLineID];
1691   backseg = seg->sidedef != &sides[seg->linedef->sidenum[0]];
1692 
1693   if (!seg->frontsector)
1694     return;
1695   frontsector=R_FakeFlat(seg->frontsector, &ftempsec, NULL, NULL, false); // for boom effects
1696   if (!frontsector)
1697     return;
1698 
1699   // e6y: fake contrast stuff
1700   // Original doom added/removed one light level ((1<<LIGHTSEGSHIFT) == 16)
1701   // for walls exactly vertical/horizontal on the map
1702   if (fake_contrast)
1703   {
1704     rellight = seg->linedef->dx == 0 ? +gl_rellight : seg->linedef->dy==0 ? -gl_rellight : 0;
1705   }
1706   wall.light=gld_CalcLightLevel(frontsector->lightlevel+rellight+(extralight<<5));
1707   wall.fogdensity = gld_CalcFogDensity(frontsector,
1708     frontsector->lightlevel + (gl_lightmode == gl_lightmode_fogbased ? rellight : 0),
1709     GLDIT_WALL);
1710   wall.alpha=1.0f;
1711   wall.gltexture=NULL;
1712   wall.seg = seg; //e6y
1713 
1714   if (!seg->backsector) /* onesided */
1715   {
1716     if (frontsector->ceilingpic==skyflatnum)
1717     {
1718       wall.ytop=MAXCOORD;
1719       wall.ybottom=(float)frontsector->ceilingheight/MAP_SCALE;
1720       gld_AddSkyTexture(&wall, frontsector->sky, frontsector->sky, SKY_CEILING);
1721     }
1722     if (frontsector->floorpic==skyflatnum)
1723     {
1724       wall.ytop=(float)frontsector->floorheight/MAP_SCALE;
1725       wall.ybottom=-MAXCOORD;
1726       gld_AddSkyTexture(&wall, frontsector->sky, frontsector->sky, SKY_FLOOR);
1727     }
1728     temptex=gld_RegisterTexture(texturetranslation[seg->sidedef->midtexture], true, false);
1729     if (temptex && frontsector->ceilingheight > frontsector->floorheight)
1730     {
1731       wall.gltexture=temptex;
1732       CALC_Y_VALUES(wall, lineheight, frontsector->floorheight, frontsector->ceilingheight);
1733       CALC_TEX_VALUES_MIDDLE1S(
1734         wall, seg, backseg, (LINE->flags & ML_DONTPEGBOTTOM)>0,
1735         linelength, lineheight
1736       );
1737       gld_AddDrawWallItem(GLDIT_WALL, &wall);
1738     }
1739   }
1740   else /* twosided */
1741   {
1742     sector_t *fs, *bs;
1743     int toptexture, midtexture, bottomtexture;
1744     fixed_t floor_height,ceiling_height;
1745     fixed_t max_floor, min_floor;
1746     fixed_t max_ceiling, min_ceiling;
1747     //fixed_t max_floor_tex, min_ceiling_tex;
1748 
1749     backsector=R_FakeFlat(seg->backsector, &btempsec, NULL, NULL, true); // for boom effects
1750     if (!backsector)
1751       return;
1752 
1753     if (frontsector->floorheight > backsector->floorheight)
1754     {
1755       max_floor = frontsector->floorheight;
1756       min_floor = backsector->floorheight;
1757     }
1758     else
1759     {
1760       max_floor = backsector->floorheight;
1761       min_floor = frontsector->floorheight;
1762     }
1763 
1764     if (frontsector->ceilingheight > backsector->ceilingheight)
1765     {
1766       max_ceiling = frontsector->ceilingheight;
1767       min_ceiling = backsector->ceilingheight;
1768     }
1769     else
1770     {
1771       max_ceiling = backsector->ceilingheight;
1772       min_ceiling = frontsector->ceilingheight;
1773     }
1774 
1775     //max_floor_tex = max_floor + seg->sidedef->rowoffset;
1776     //min_ceiling_tex = min_ceiling + seg->sidedef->rowoffset;
1777 
1778     if (backseg)
1779     {
1780       fs = backsector;
1781       bs = frontsector;
1782     }
1783     else
1784     {
1785       fs = frontsector;
1786       bs = backsector;
1787     }
1788 
1789     toptexture = texturetranslation[seg->sidedef->toptexture];
1790     midtexture = texturetranslation[seg->sidedef->midtexture];
1791     bottomtexture = texturetranslation[seg->sidedef->bottomtexture];
1792 
1793     /* toptexture */
1794     ceiling_height=frontsector->ceilingheight;
1795     floor_height=backsector->ceilingheight;
1796     if (frontsector->ceilingpic==skyflatnum)// || backsector->ceilingpic==skyflatnum)
1797     {
1798       wall.ytop= MAXCOORD;
1799       if (
1800           // e6y
1801           // There is no more HOM in the starting area on Memento Mori map29 and on map30.
1802           // Old code:
1803           // (backsector->ceilingheight==backsector->floorheight) &&
1804           // (backsector->ceilingpic==skyflatnum)
1805           (backsector->ceilingpic==skyflatnum) &&
1806           (backsector->ceilingheight<=backsector->floorheight)
1807          )
1808       {
1809         // e6y
1810         // There is no more visual glitches with sky on Icarus map14 sector 187
1811         // Old code: wall.ybottom=(float)backsector->floorheight/MAP_SCALE;
1812         wall.ybottom=((float)(backsector->floorheight +
1813           (seg->sidedef->rowoffset > 0 ? seg->sidedef->rowoffset : 0)))/MAP_SCALE;
1814         gld_AddSkyTexture(&wall, frontsector->sky, backsector->sky, SKY_CEILING);
1815       }
1816       else
1817       {
1818         if (bs->ceilingpic == skyflatnum && fs->ceilingpic != skyflatnum &&
1819           toptexture == NO_TEXTURE && midtexture == NO_TEXTURE)
1820         {
1821           wall.ybottom=(float)min_ceiling/MAP_SCALE;
1822           gld_AddSkyTexture(&wall, frontsector->sky, backsector->sky, SKY_CEILING);
1823         }
1824         else
1825         {
1826           if ((toptexture != NO_TEXTURE && midtexture == NO_TEXTURE) ||
1827             backsector->ceilingpic != skyflatnum ||
1828             backsector->ceilingheight <= frontsector->floorheight)
1829           {
1830             wall.ybottom=(float)max_ceiling/MAP_SCALE;
1831             gld_AddSkyTexture(&wall, frontsector->sky, backsector->sky, SKY_CEILING);
1832           }
1833         }
1834       }
1835     }
1836     if (floor_height<ceiling_height)
1837     {
1838       if (!((frontsector->ceilingpic==skyflatnum) && (backsector->ceilingpic==skyflatnum)))
1839       {
1840         temptex=gld_RegisterTexture(toptexture, true, false);
1841         if (!temptex && gl_use_stencil && backsector &&
1842           !(seg->linedef->r_flags & RF_ISOLATED) &&
1843           /*frontsector->ceilingpic != skyflatnum && */backsector->ceilingpic != skyflatnum &&
1844           !(backsector->flags & NULL_SECTOR))
1845         {
1846           wall.ytop=((float)(ceiling_height)/(float)MAP_SCALE)+SMALLDELTA;
1847           wall.ybottom=((float)(floor_height)/(float)MAP_SCALE)-SMALLDELTA;
1848           if (wall.ybottom >= zCamera)
1849           {
1850             wall.flag=GLDWF_TOPFLUD;
1851             temptex=gld_RegisterFlat(flattranslation[seg->backsector->ceilingpic], true);
1852             if (temptex)
1853             {
1854               wall.gltexture=temptex;
1855               gld_AddDrawWallItem(GLDIT_FWALL, &wall);
1856             }
1857           }
1858         }
1859         else
1860         if (temptex)
1861         {
1862           wall.gltexture=temptex;
1863           CALC_Y_VALUES(wall, lineheight, floor_height, ceiling_height);
1864           CALC_TEX_VALUES_TOP(
1865             wall, seg, backseg, (LINE->flags & (/*e6y ML_DONTPEGBOTTOM | */ML_DONTPEGTOP))==0,
1866             linelength, lineheight
1867           );
1868           gld_AddDrawWallItem(GLDIT_WALL, &wall);
1869         }
1870       }
1871     }
1872 
1873     /* midtexture */
1874     //e6y
1875     if (comp[comp_maskedanim])
1876       temptex=gld_RegisterTexture(seg->sidedef->midtexture, true, false);
1877     else
1878 
1879     // e6y
1880     // Animated middle textures with a zero index should be forced
1881     // See spacelab.wad (http://www.doomworld.com/idgames/index.php?id=6826)
1882     temptex=gld_RegisterTexture(midtexture, true, true);
1883     if (temptex && seg->sidedef->midtexture != NO_TEXTURE && backsector->ceilingheight>frontsector->floorheight)
1884     {
1885       int top, bottom;
1886       wall.gltexture=temptex;
1887 
1888       if ( (LINE->flags & ML_DONTPEGBOTTOM) >0)
1889       {
1890         //floor_height=max_floor_tex;
1891         floor_height=MAX(seg->frontsector->floorheight, seg->backsector->floorheight)+(seg->sidedef->rowoffset);
1892         ceiling_height=floor_height+(wall.gltexture->realtexheight<<FRACBITS);
1893       }
1894       else
1895       {
1896         //ceiling_height=min_ceiling_tex;
1897         ceiling_height=MIN(seg->frontsector->ceilingheight, seg->backsector->ceilingheight)+(seg->sidedef->rowoffset);
1898         floor_height=ceiling_height-(wall.gltexture->realtexheight<<FRACBITS);
1899       }
1900 
1901       // Depending on missing textures and possible plane intersections
1902       // decide which planes to use for the polygon
1903       if (seg->frontsector != seg->backsector ||
1904         seg->frontsector->heightsec != -1)
1905       {
1906         sector_t *f, *b;
1907 
1908         f = (seg->frontsector->heightsec == -1 ? seg->frontsector : &ftempsec);
1909         b = (seg->backsector->heightsec == -1 ? seg->backsector : &btempsec);
1910 
1911         // Set up the top
1912         if (frontsector->ceilingpic != skyflatnum ||
1913             backsector->ceilingpic != skyflatnum)
1914         {
1915           if (toptexture == NO_TEXTURE)
1916             // texture is missing - use the higher plane
1917             top = MAX(f->ceilingheight, b->ceilingheight);
1918           else
1919             top = MIN(f->ceilingheight, b->ceilingheight);
1920         }
1921         else
1922           top = ceiling_height;
1923 
1924         // Set up the bottom
1925         if (frontsector->floorpic != skyflatnum ||
1926             backsector->floorpic != skyflatnum ||
1927             frontsector->floorheight != backsector->floorheight)
1928         {
1929           if (seg->sidedef->bottomtexture == NO_TEXTURE)
1930             // texture is missing - use the lower plane
1931             bottom = MIN(f->floorheight, b->floorheight);
1932           else
1933             // normal case - use the higher plane
1934             bottom = MAX(f->floorheight, b->floorheight);
1935         }
1936         else
1937         {
1938           bottom = floor_height;
1939         }
1940 
1941         //let's clip away some unnecessary parts of the polygon
1942         if (ceiling_height < top)
1943           top = ceiling_height;
1944         if (floor_height > bottom)
1945           bottom = floor_height;
1946       }
1947       else
1948       {
1949         // both sides of the line are in the same sector
1950         top = ceiling_height;
1951         bottom = floor_height;
1952       }
1953 
1954       if (top <= bottom)
1955         goto bottomtexture;
1956 
1957       wall.ytop = (float)top/(float)MAP_SCALE;
1958       wall.ybottom = (float)bottom/(float)MAP_SCALE;
1959 
1960       wall.flag = GLDWF_M2S;
1961       URUL(wall, seg, backseg, linelength);
1962 
1963       wall.vt = (float)((-top + ceiling_height) >> FRACBITS)/(float)wall.gltexture->realtexheight;
1964       wall.vb = (float)((-bottom + ceiling_height) >> FRACBITS)/(float)wall.gltexture->realtexheight;
1965 
1966       if (seg->linedef->tranlump >= 0 && general_translucency)
1967         wall.alpha=(float)tran_filter_pct/100.0f;
1968       gld_AddDrawWallItem((wall.alpha == 1.0f ? GLDIT_MWALL : GLDIT_TWALL), &wall);
1969       wall.alpha=1.0f;
1970     }
1971 bottomtexture:
1972     /* bottomtexture */
1973     ceiling_height=backsector->floorheight;
1974     floor_height=frontsector->floorheight;
1975     if (frontsector->floorpic==skyflatnum)
1976     {
1977       wall.ybottom=-MAXCOORD;
1978       if (
1979           (backsector->ceilingheight==backsector->floorheight) &&
1980           (backsector->floorpic==skyflatnum)
1981          )
1982       {
1983         wall.ytop=(float)backsector->floorheight/MAP_SCALE;
1984         gld_AddSkyTexture(&wall, frontsector->sky, backsector->sky, SKY_FLOOR);
1985       }
1986       else
1987       {
1988         if (bs->floorpic == skyflatnum &&// fs->floorpic != skyflatnum &&
1989           bottomtexture == NO_TEXTURE && midtexture == NO_TEXTURE)
1990         {
1991           wall.ytop=(float)max_floor/MAP_SCALE;
1992           gld_AddSkyTexture(&wall, frontsector->sky, backsector->sky, SKY_CEILING);
1993         }
1994         else
1995         {
1996           if ((bottomtexture != NO_TEXTURE && midtexture == NO_TEXTURE) ||
1997             backsector->floorpic != skyflatnum ||
1998             backsector->floorheight >= frontsector->ceilingheight)
1999           {
2000             wall.ytop=(float)min_floor/MAP_SCALE;
2001             gld_AddSkyTexture(&wall, frontsector->sky, backsector->sky, SKY_FLOOR);
2002           }
2003         }
2004       }
2005     }
2006     if (floor_height<ceiling_height)
2007     {
2008       temptex=gld_RegisterTexture(bottomtexture, true, false);
2009       if (!temptex && gl_use_stencil && backsector &&
2010         !(seg->linedef->r_flags & RF_ISOLATED) &&
2011         /*frontsector->floorpic != skyflatnum && */backsector->floorpic != skyflatnum &&
2012         !(backsector->flags & NULL_SECTOR))
2013       {
2014         wall.ytop=((float)(ceiling_height)/(float)MAP_SCALE)+SMALLDELTA;
2015         wall.ybottom=((float)(floor_height)/(float)MAP_SCALE)-SMALLDELTA;
2016         if (wall.ytop <= zCamera)
2017         {
2018           wall.flag = GLDWF_BOTFLUD;
2019           temptex=gld_RegisterFlat(flattranslation[seg->backsector->floorpic], true);
2020           if (temptex)
2021           {
2022             wall.gltexture=temptex;
2023             gld_AddDrawWallItem(GLDIT_FWALL, &wall);
2024           }
2025         }
2026       }
2027       else
2028       if (temptex)
2029       {
2030         wall.gltexture=temptex;
2031         CALC_Y_VALUES(wall, lineheight, floor_height, ceiling_height);
2032         CALC_TEX_VALUES_BOTTOM(
2033           wall, seg, backseg, (LINE->flags & ML_DONTPEGBOTTOM)>0,
2034           linelength, lineheight,
2035           floor_height-frontsector->ceilingheight
2036         );
2037         gld_AddDrawWallItem(GLDIT_WALL, &wall);
2038       }
2039     }
2040   }
2041 }
2042 
2043 #undef LINE
2044 #undef CALC_Y_VALUES
2045 #undef OU
2046 #undef OV
2047 #undef OV_PEG
2048 #undef CALC_TEX_VALUES_TOP
2049 #undef CALC_TEX_VALUES_MIDDLE1S
2050 #undef CALC_TEX_VALUES_BOTTOM
2051 #undef ADDWALL
2052 
2053 /*****************
2054  *               *
2055  * Flats         *
2056  *               *
2057  *****************/
2058 
gld_DrawFlat(GLFlat * flat)2059 static void gld_DrawFlat(GLFlat *flat)
2060 {
2061   int loopnum; // current loop number
2062   GLLoopDef *currentloop; // the current loop
2063   dboolean has_detail;
2064   int has_offset;
2065   unsigned int flags;
2066 
2067   rendered_visplanes++;
2068 
2069   has_detail =
2070     scene_has_details &&
2071     gl_arb_multitexture &&
2072     flat->gltexture->detail;
2073 
2074   has_offset = (has_detail || (flat->flags & GLFLAT_HAVE_OFFSET));
2075 
2076   if ((sectorloops[flat->sectornum].flags & SECTOR_CLAMPXY) && (!has_detail) &&
2077       ((tex_filter[MIP_TEXTURE].mag_filter == GL_NEAREST) ||
2078        (flat->gltexture->flags & GLTEXTURE_HIRES)) &&
2079       !(flat->flags & GLFLAT_HAVE_OFFSET))
2080     flags = GLTEXTURE_CLAMPXY;
2081   else
2082     flags = 0;
2083 
2084   gld_BindFlat(flat->gltexture, flags);
2085   gld_StaticLightAlpha(flat->light, flat->alpha);
2086 
2087 #if defined(USE_VERTEX_ARRAYS) || defined(USE_VBO)
2088   glMatrixMode(GL_MODELVIEW);
2089   glPushMatrix();
2090   glTranslatef(0.0f,flat->z,0.0f);
2091 #endif
2092 
2093   if (has_offset)
2094   {
2095     glMatrixMode(GL_TEXTURE);
2096     glPushMatrix();
2097     glTranslatef(flat->uoffs, flat->voffs, 0.0f);
2098   }
2099 
2100   gld_BindDetailARB(flat->gltexture, has_detail);
2101   if (has_detail)
2102   {
2103     float w, h, dx, dy;
2104     detail_t *detail = flat->gltexture->detail;
2105 
2106     GLEXT_glActiveTextureARB(GL_TEXTURE1_ARB);
2107     gld_StaticLightAlpha(flat->light, flat->alpha);
2108 
2109     glPushMatrix();
2110 
2111     w = flat->gltexture->detail_width;
2112     h = flat->gltexture->detail_height;
2113     dx = detail->offsetx;
2114     dy = detail->offsety;
2115 
2116     if ((flat->flags & GLFLAT_HAVE_OFFSET) || dx || dy)
2117     {
2118       glTranslatef(flat->uoffs * w + dx, flat->voffs * h + dy, 0.0f);
2119     }
2120 
2121     glScalef(w, h, 1.0f);
2122   }
2123 
2124   if (flat->sectornum>=0)
2125   {
2126     // go through all loops of this sector
2127 #if defined(USE_VERTEX_ARRAYS) || defined(USE_VBO)
2128     if (gl_use_display_lists)
2129     {
2130       int display_list = (has_detail ? flats_detail_display_list : flats_display_list);
2131       glCallList(display_list + flat->sectornum);
2132     }
2133     else
2134     {
2135       for (loopnum=0; loopnum<sectorloops[flat->sectornum].loopcount; loopnum++)
2136       {
2137         // set the current loop
2138         currentloop=&sectorloops[flat->sectornum].loops[loopnum];
2139         glDrawArrays(currentloop->mode,currentloop->vertexindex,currentloop->vertexcount);
2140       }
2141     }
2142 #else
2143     for (loopnum=0; loopnum<sectorloops[flat->sectornum].loopcount; loopnum++)
2144     {
2145       int vertexnum;
2146       // set the current loop
2147       currentloop=&sectorloops[flat->sectornum].loops[loopnum];
2148       if (!currentloop)
2149         continue;
2150       // set the mode (GL_TRIANGLES, GL_TRIANGLE_STRIP or GL_TRIANGLE_FAN)
2151       glBegin(currentloop->mode);
2152       // go through all vertexes of this loop
2153       for (vertexnum=currentloop->vertexindex; vertexnum<(currentloop->vertexindex+currentloop->vertexcount); vertexnum++)
2154       {
2155         // set texture coordinate of this vertex
2156         if (has_detail)
2157         {
2158           GLEXT_glMultiTexCoord2fvARB(GL_TEXTURE0_ARB, (GLfloat*)&flats_vbo[vertexnum].u);
2159           GLEXT_glMultiTexCoord2fvARB(GL_TEXTURE1_ARB, (GLfloat*)&flats_vbo[vertexnum].u);
2160         }
2161         else
2162         {
2163           glTexCoord2fv((GLfloat*)&flats_vbo[vertexnum].u);
2164         }
2165         // set vertex coordinate
2166         //glVertex3fv((GLfloat*)&flats_vbo[vertexnum].x);
2167         glVertex3f(flats_vbo[vertexnum].x, flat->z, flats_vbo[vertexnum].z);
2168       }
2169       // end of loop
2170       glEnd();
2171     }
2172 #endif
2173   }
2174 
2175   //e6y
2176   if (has_detail)
2177   {
2178     glPopMatrix();
2179     GLEXT_glActiveTextureARB(GL_TEXTURE0_ARB);
2180   }
2181 
2182   if (has_offset)
2183   {
2184     glPopMatrix();
2185   }
2186 
2187 #if defined(USE_VERTEX_ARRAYS) || defined(USE_VBO)
2188   glMatrixMode(GL_MODELVIEW);
2189   glPopMatrix();
2190 #endif
2191 }
2192 
2193 // gld_AddFlat
2194 //
2195 // This draws on flat for the sector "num"
2196 // The ceiling boolean indicates if the flat is a floor(false) or a ceiling(true)
2197 
gld_AddFlat(int sectornum,dboolean ceiling,visplane_t * plane)2198 static void gld_AddFlat(int sectornum, dboolean ceiling, visplane_t *plane)
2199 {
2200   sector_t *sector; // the sector we want to draw
2201   sector_t tempsec; // needed for R_FakeFlat
2202   int floorlightlevel;      // killough 3/16/98: set floor lightlevel
2203   int ceilinglightlevel;    // killough 4/11/98
2204   GLFlat flat;
2205 
2206   if (sectornum<0)
2207     return;
2208   flat.sectornum=sectornum;
2209   sector=&sectors[sectornum]; // get the sector
2210   sector=R_FakeFlat(sector, &tempsec, &floorlightlevel, &ceilinglightlevel, false); // for boom effects
2211   flat.flags = (ceiling ? GLFLAT_CEILING : 0);
2212 
2213   if (!ceiling) // if it is a floor ...
2214   {
2215     if (sector->floorpic == skyflatnum) // don't draw if sky
2216       return;
2217     // get the texture. flattranslation is maintained by doom and
2218     // contains the number of the current animation frame
2219     flat.gltexture=gld_RegisterFlat(flattranslation[plane->picnum], true);
2220     if (!flat.gltexture)
2221       return;
2222     // get the lightlevel from floorlightlevel
2223     flat.light=gld_CalcLightLevel(plane->lightlevel+(extralight<<5));
2224     flat.fogdensity = gld_CalcFogDensity(sector, plane->lightlevel, GLDIT_FLOOR);
2225     // calculate texture offsets
2226     if (sector->floor_xoffs | sector->floor_yoffs)
2227     {
2228       flat.flags |= GLFLAT_HAVE_OFFSET;
2229       flat.uoffs=(float)sector->floor_xoffs/(float)(FRACUNIT*64);
2230       flat.voffs=(float)sector->floor_yoffs/(float)(FRACUNIT*64);
2231     }
2232     else
2233     {
2234       flat.uoffs=0.0f;
2235       flat.voffs=0.0f;
2236     }
2237   }
2238   else // if it is a ceiling ...
2239   {
2240     if (sector->ceilingpic == skyflatnum) // don't draw if sky
2241       return;
2242     // get the texture. flattranslation is maintained by doom and
2243     // contains the number of the current animation frame
2244     flat.gltexture=gld_RegisterFlat(flattranslation[plane->picnum], true);
2245     if (!flat.gltexture)
2246       return;
2247     // get the lightlevel from ceilinglightlevel
2248     flat.light=gld_CalcLightLevel(plane->lightlevel+(extralight<<5));
2249     flat.fogdensity = gld_CalcFogDensity(sector, plane->lightlevel, GLDIT_CEILING);
2250     // calculate texture offsets
2251     if (sector->ceiling_xoffs | sector->ceiling_yoffs)
2252     {
2253       flat.flags |= GLFLAT_HAVE_OFFSET;
2254       flat.uoffs=(float)sector->ceiling_xoffs/(float)(FRACUNIT*64);
2255       flat.voffs=(float)sector->ceiling_yoffs/(float)(FRACUNIT*64);
2256     }
2257     else
2258     {
2259       flat.uoffs=0.0f;
2260       flat.voffs=0.0f;
2261     }
2262   }
2263 
2264   // get height from plane
2265   flat.z=(float)plane->height/MAP_SCALE;
2266 
2267   if (gl_blend_animations)
2268   {
2269     anim_t *anim = anim_flats[flat.gltexture->index - firstflat].anim;
2270     if (anim)
2271     {
2272       int currpic, nextpic;
2273 
2274       flat.alpha = 1.0f - ((float)tic_vars.frac + ((leveltime - 1) % anim->speed) * 65536.0f) / (65536.0f * anim->speed);
2275       gld_AddDrawItem(((flat.flags & GLFLAT_CEILING) ? GLDIT_ACEILING : GLDIT_AFLOOR), &flat);
2276 
2277       currpic = flat.gltexture->index - firstflat - anim->basepic;
2278       nextpic = anim->basepic + (currpic + 1) % anim->numpics;
2279       flat.gltexture = gld_RegisterFlat(nextpic, true);
2280     }
2281   }
2282 
2283   flat.alpha = 1.0;
2284 
2285   if (flat.gltexture->detail)
2286     scene_has_flat_details++;
2287 
2288   gld_AddDrawItem(((flat.flags & GLFLAT_CEILING) ? GLDIT_CEILING : GLDIT_FLOOR), &flat);
2289 }
2290 
gld_AddPlane(int subsectornum,visplane_t * floor,visplane_t * ceiling)2291 void gld_AddPlane(int subsectornum, visplane_t *floor, visplane_t *ceiling)
2292 {
2293   subsector_t *subsector;
2294 
2295   subsector = &subsectors[subsectornum];
2296   if (!subsector)
2297     return;
2298 
2299   // render the floor
2300   if (floor && floor->height < viewz)
2301     gld_AddFlat(subsector->sector->iSectorID, false, floor);
2302   // render the ceiling
2303   if (ceiling && ceiling->height > viewz)
2304     gld_AddFlat(subsector->sector->iSectorID, true, ceiling);
2305 }
2306 
2307 /*****************
2308  *               *
2309  * Sprites       *
2310  *               *
2311  *****************/
2312 
gld_DrawSprite(GLSprite * sprite)2313 static void gld_DrawSprite(GLSprite *sprite)
2314 {
2315   GLint blend_src, blend_dst;
2316   int restore = 0;
2317 
2318   rendered_vissprites++;
2319 
2320   gld_BindPatch(sprite->gltexture,sprite->cm);
2321 
2322   if (!(sprite->flags & MF_NO_DEPTH_TEST))
2323   {
2324     if(sprite->flags & MF_SHADOW)
2325     {
2326       glGetIntegerv(GL_BLEND_SRC, &blend_src);
2327       glGetIntegerv(GL_BLEND_DST, &blend_dst);
2328       glBlendFunc(GL_DST_COLOR, GL_ONE_MINUS_SRC_ALPHA);
2329       //glColor4f(0.2f,0.2f,0.2f,(float)tran_filter_pct/100.0f);
2330       glAlphaFunc(GL_GEQUAL,0.1f);
2331       glColor4f(0.2f,0.2f,0.2f,0.33f);
2332       restore = 1;
2333     }
2334     else
2335     {
2336       if(sprite->flags & MF_TRANSLUCENT)
2337         gld_StaticLightAlpha(sprite->light,(float)tran_filter_pct/100.0f);
2338       else
2339         gld_StaticLight(sprite->light);
2340     }
2341   }
2342 
2343   if (!render_paperitems && !(sprite->flags & (MF_SOLID | MF_SPAWNCEILING)))
2344   {
2345     float x1, x2, x3, x4, z1, z2, z3, z4;
2346     float y1, y2, cy, ycenter, y1c, y2c;
2347     float y1z2_y, y2z2_y;
2348 
2349     ycenter = (float)fabs(sprite->y1 - sprite->y2) * 0.5f;
2350     y1c = sprite->y1 - ycenter;
2351     y2c = sprite->y2 - ycenter;
2352     cy = sprite->y + ycenter;
2353 
2354     y1z2_y = -(y1c * sin_paperitems_pitch);
2355     y2z2_y = -(y2c * sin_paperitems_pitch);
2356 
2357     x1 = +(sprite->x1 * cos_inv_yaw - y1z2_y * sin_inv_yaw) + sprite->x;
2358     x2 = +(sprite->x2 * cos_inv_yaw - y1z2_y * sin_inv_yaw) + sprite->x;
2359     x3 = +(sprite->x1 * cos_inv_yaw - y2z2_y * sin_inv_yaw) + sprite->x;
2360     x4 = +(sprite->x2 * cos_inv_yaw - y2z2_y * sin_inv_yaw) + sprite->x;
2361 
2362     y1 = +(y1c * cos_paperitems_pitch) + cy;
2363     y2 = +(y2c * cos_paperitems_pitch) + cy;
2364 
2365     z1 = -(sprite->x1 * sin_inv_yaw + y1z2_y * cos_inv_yaw) + sprite->z;
2366     z2 = -(sprite->x2 * sin_inv_yaw + y1z2_y * cos_inv_yaw) + sprite->z;
2367     z3 = -(sprite->x1 * sin_inv_yaw + y2z2_y * cos_inv_yaw) + sprite->z;
2368     z4 = -(sprite->x2 * sin_inv_yaw + y2z2_y * cos_inv_yaw) + sprite->z;
2369 
2370     glBegin(GL_TRIANGLE_STRIP);
2371     glTexCoord2f(sprite->ul, sprite->vt); glVertex3f(x1, y1, z1);
2372     glTexCoord2f(sprite->ur, sprite->vt); glVertex3f(x2, y1, z2);
2373     glTexCoord2f(sprite->ul, sprite->vb); glVertex3f(x3, y2, z3);
2374     glTexCoord2f(sprite->ur, sprite->vb); glVertex3f(x4, y2, z4);
2375     glEnd();
2376   }
2377   else
2378   {
2379     float x1, x2, y1, y2, z1, z2;
2380 
2381     x1 = +(sprite->x1 * cos_inv_yaw) + sprite->x;
2382     x2 = +(sprite->x2 * cos_inv_yaw) + sprite->x;
2383 
2384     y1 = sprite->y + sprite->y1;
2385     y2 = sprite->y + sprite->y2;
2386 
2387     z2 = -(sprite->x1 * sin_inv_yaw) + sprite->z;
2388     z1 = -(sprite->x2 * sin_inv_yaw) + sprite->z;
2389 
2390     glBegin(GL_TRIANGLE_STRIP);
2391     glTexCoord2f(sprite->ul, sprite->vt); glVertex3f(x1, y1, z2);
2392     glTexCoord2f(sprite->ur, sprite->vt); glVertex3f(x2, y1, z1);
2393     glTexCoord2f(sprite->ul, sprite->vb); glVertex3f(x1, y2, z2);
2394     glTexCoord2f(sprite->ur, sprite->vb); glVertex3f(x2, y2, z1);
2395     glEnd();
2396   }
2397 
2398   if (restore)
2399   {
2400     glBlendFunc(blend_src, blend_dst);
2401     glAlphaFunc(GL_GEQUAL, gl_mask_sprite_threshold_f);
2402   }
2403 }
2404 
gld_ProjectSprite(mobj_t * thing)2405 void gld_ProjectSprite(mobj_t* thing)
2406 {
2407   fixed_t   tx;
2408   spritedef_t   *sprdef;
2409   spriteframe_t *sprframe;
2410   int       lump;
2411   dboolean   flip;
2412   int heightsec;      // killough 3/27/98
2413 
2414   // transform the origin point
2415   //e6y
2416   fixed_t tr_x, tr_y;
2417   fixed_t fx, fy, fz;
2418   fixed_t gxt, gyt;
2419   fixed_t tz;
2420 
2421   GLSprite sprite;
2422   const rpatch_t* patch;
2423 
2424   int frustum_culling = HaveMouseLook() && gl_sprites_frustum_culling;
2425   int mlook = HaveMouseLook() || (render_fov > FOV90);
2426 
2427   if (!paused && movement_smooth)
2428   {
2429     fx = thing->PrevX + FixedMul (tic_vars.frac, thing->x - thing->PrevX);
2430     fy = thing->PrevY + FixedMul (tic_vars.frac, thing->y - thing->PrevY);
2431     fz = thing->PrevZ + FixedMul (tic_vars.frac, thing->z - thing->PrevZ);
2432   }
2433   else
2434   {
2435     fx = thing->x;
2436     fy = thing->y;
2437     fz = thing->z;
2438   }
2439 
2440   tr_x = fx - viewx;
2441   tr_y = fy - viewy;
2442 
2443   gxt = FixedMul(tr_x, viewcos);
2444   gyt = -FixedMul(tr_y, viewsin);
2445 
2446   tz = gxt - gyt;
2447 
2448   // thing is behind view plane?
2449   if (tz < r_near_clip_plane)
2450     return;
2451 
2452   gxt = -FixedMul(tr_x, viewsin);
2453   gyt = FixedMul(tr_y, viewcos);
2454   tx = -(gyt + gxt);
2455 
2456   //e6y
2457   if (!render_paperitems && mlook)
2458   {
2459     if (tz >= MINZ && (D_abs(tx) >> 5) > tz)
2460       return;
2461   }
2462   else
2463   {
2464     // too far off the side?
2465     if (D_abs(tx) > (tz << 2))
2466       return;
2467   }
2468 
2469   // decide which patch to use for sprite relative to player
2470 #ifdef RANGECHECK
2471   if ((unsigned) thing->sprite >= (unsigned)numsprites)
2472     I_Error ("R_ProjectSprite: Invalid sprite number %i", thing->sprite);
2473 #endif
2474 
2475   sprdef = &sprites[thing->sprite];
2476 
2477 #ifdef RANGECHECK
2478   if ((thing->frame&FF_FRAMEMASK) >= sprdef->numframes)
2479     I_Error ("R_ProjectSprite: Invalid sprite frame %i : %i", thing->sprite, thing->frame);
2480 #endif
2481 
2482   if (!sprdef->spriteframes)
2483     I_Error("R_ProjectSprite: Missing spriteframes %i : %i", thing->sprite, thing->frame);
2484 
2485   sprframe = &sprdef->spriteframes[thing->frame & FF_FRAMEMASK];
2486 
2487   if (sprframe->rotate)
2488   {
2489     // choose a different rotation based on player view
2490     angle_t rot;
2491     angle_t ang = R_PointToAngle(fx, fy);
2492     if (sprframe->lump[0] == sprframe->lump[1])
2493     {
2494       rot = (ang - thing->angle + (angle_t)(ANG45/2)*9) >> 28;
2495     }
2496     else
2497     {
2498       rot = (ang - thing->angle + (angle_t)(ANG45 / 2) * 9 -
2499         (angle_t)(ANG180 / 16)) >> 28;
2500     }
2501     lump = sprframe->lump[rot];
2502     flip = (dboolean)(sprframe->flip & (1 << rot));
2503   }
2504   else
2505   {
2506     // use single rotation for all views
2507     lump = sprframe->lump[0];
2508     flip = (dboolean)(sprframe->flip & 1);
2509   }
2510   lump += firstspritelump;
2511 
2512   patch = R_CachePatchNum(lump);
2513   thing->patch_width = patch->width;
2514 
2515   // killough 4/9/98: clip things which are out of view due to height
2516   if(!mlook)
2517   {
2518     int x1, x2;
2519     fixed_t xscale = FixedDiv(projection, tz);
2520     /* calculate edges of the shape
2521     * cph 2003/08/1 - fraggle points out that this offset must be flipped
2522     * if the sprite is flipped; e.g. FreeDoom imp is messed up by this. */
2523     if (flip)
2524       tx -= (patch->width - patch->leftoffset) << FRACBITS;
2525     else
2526       tx -= patch->leftoffset << FRACBITS;
2527 
2528     x1 = (centerxfrac + FixedMul(tx, xscale)) >> FRACBITS;
2529     tx += patch->width << FRACBITS;
2530     x2 = ((centerxfrac + FixedMul (tx, xscale) - FRACUNIT/2) >> FRACBITS);
2531 
2532     // off the side?
2533     if (x1 > viewwidth || x2 < 0)
2534       goto unlock_patch;
2535   }
2536 
2537   // killough 3/27/98: exclude things totally separated
2538   // from the viewer, by either water or fake ceilings
2539   // killough 4/11/98: improve sprite clipping for underwater/fake ceilings
2540 
2541   heightsec = thing->subsector->sector->heightsec;
2542   if (heightsec != -1)   // only clip things which are in special sectors
2543   {
2544     int phs = viewplayer->mo->subsector->sector->heightsec;
2545     fixed_t gzt = fz + (patch->topoffset << FRACBITS);
2546     if (phs != -1 && viewz < sectors[phs].floorheight ?
2547         fz >= sectors[heightsec].floorheight :
2548         gzt < sectors[heightsec].floorheight)
2549       goto unlock_patch;
2550     if (phs != -1 && viewz > sectors[phs].ceilingheight ?
2551         gzt < sectors[heightsec].ceilingheight && viewz >= sectors[heightsec].ceilingheight :
2552         fz >= sectors[heightsec].ceilingheight)
2553       goto unlock_patch;
2554   }
2555 
2556   //e6y FIXME!!!
2557   if (thing == players[displayplayer].mo && walkcamera.type != 2)
2558     goto unlock_patch;
2559 
2560   sprite.x =-(float)fx / MAP_SCALE;
2561   sprite.y = (float)fz / MAP_SCALE;
2562   sprite.z = (float)fy / MAP_SCALE;
2563 
2564   // Bring items up out of floor by configurable amount times .01 Mead 8/13/03
2565   sprite.y += gl_sprite_offset;
2566 
2567   sprite.x2 = (float)patch->leftoffset / MAP_COEFF;
2568   sprite.x1 = sprite.x2 - ((float)patch->width / MAP_COEFF);
2569   sprite.y1 = (float)patch->topoffset / MAP_COEFF;
2570   sprite.y2 = sprite.y1 - ((float)patch->height / MAP_COEFF);
2571 
2572   // e6y
2573   // if the sprite is below the floor, and it's not a hanger/floater/missile,
2574   // and it's not a fully dead corpse, move it up
2575   if ((gl_spriteclip != spriteclip_const) &&
2576       (sprite.y2 < 0) && (sprite.y2 >= (float)(-gl_spriteclip_threshold_f)) &&
2577       !(thing->flags & (MF_SPAWNCEILING|MF_FLOAT|MF_MISSILE|MF_NOGRAVITY)) &&
2578       ((gl_spriteclip == spriteclip_always) || !((thing->flags & MF_CORPSE) && thing->tics == -1)))
2579   {
2580     sprite.y1 -= sprite.y2;
2581     sprite.y2 = 0.0f;
2582   }
2583 
2584   if (frustum_culling)
2585   {
2586     if (!gld_SphereInFrustum(
2587       sprite.x + cos_inv_yaw * (sprite.x1 + sprite.x2) / 2.0f,
2588       sprite.y + (sprite.y1 + sprite.y2) / 2.0f,
2589       sprite.z - sin_inv_yaw * (sprite.x1 + sprite.x2) / 2.0f,
2590       //1.5 == sqrt(2) + small delta for MF_FOREGROUND
2591       (float)(MAX(patch->width, patch->height)) / MAP_COEFF / 2.0f * 1.5f))
2592     {
2593       goto unlock_patch;
2594     }
2595   }
2596 
2597   sprite.scale = FixedDiv(projectiony, tz);;
2598   if ((thing->frame & FF_FULLBRIGHT) || show_alive)
2599   {
2600     sprite.fogdensity = 0.0f;
2601     sprite.light = 1.0f;
2602   }
2603   else
2604   {
2605     sprite.light = gld_CalcLightLevel(thing->subsector->sector->lightlevel+(extralight<<5));
2606     sprite.fogdensity = gld_CalcFogDensity(thing->subsector->sector, thing->subsector->sector->lightlevel, GLDIT_SPRITE);
2607   }
2608   sprite.cm = CR_LIMIT + (int)((thing->flags & MF_TRANSLATION) >> (MF_TRANSSHIFT));
2609   sprite.gltexture = gld_RegisterPatch(lump, sprite.cm);
2610   if (!sprite.gltexture)
2611     goto unlock_patch;
2612   sprite.flags = thing->flags;
2613 
2614   if (thing->flags & MF_FOREGROUND)
2615     scene_has_overlapped_sprites = true;
2616 
2617   sprite.index = gl_spriteindex++;
2618   sprite.xy = thing->x + (thing->y >> 16);
2619 
2620   sprite.vt = 0.0f;
2621   sprite.vb = sprite.gltexture->scaleyfac;
2622   if (flip)
2623   {
2624     sprite.ul = 0.0f;
2625     sprite.ur = sprite.gltexture->scalexfac;
2626   }
2627   else
2628   {
2629     sprite.ul = sprite.gltexture->scalexfac;
2630     sprite.ur = 0.0f;
2631   }
2632 
2633   //e6y: support for transparent sprites
2634   if (sprite.flags & MF_NO_DEPTH_TEST)
2635   {
2636     gld_AddDrawItem(GLDIT_ASPRITE, &sprite);
2637   }
2638   else
2639   {
2640     gld_AddDrawItem((gl_sprite_blend || (sprite.flags & (MF_SHADOW | MF_TRANSLUCENT)) ? GLDIT_TSPRITE : GLDIT_SPRITE), &sprite);
2641     gld_ProcessThingShadow(thing);
2642   }
2643 
2644 unlock_patch:
2645   R_UnlockPatchNum(lump);
2646 }
2647 
2648 /*****************
2649  *               *
2650  * Draw          *
2651  *               *
2652  *****************/
2653 
2654 //e6y
gld_ProcessWall(GLWall * wall)2655 void gld_ProcessWall(GLWall *wall)
2656 {
2657   // e6y
2658   // The ultimate 'ATI sucks' fix: Some of ATIs graphics cards are so unprecise when
2659   // rendering geometry that each and every border between polygons must be seamless,
2660   // otherwise there are rendering artifacts worse than anything that could be seen
2661   // on Geforce 2's! Made this a menu option because the speed impact is quite severe
2662   // and this special handling is not necessary on modern NVidia cards.
2663   if (gl_seamless)
2664   {
2665     seg_t *seg = wall->seg;
2666 
2667     wall->glseg->fracleft  = 0;
2668     wall->glseg->fracright = 0;
2669 
2670     gld_RecalcVertexHeights(seg->linedef->v1);
2671     gld_RecalcVertexHeights(seg->linedef->v2);
2672   }
2673 
2674   gld_DrawWall(wall);
2675 }
2676 
2677 #ifdef USE_CUSTOM_QSORT
qsort_walls_by_tex(GLDrawItem * arr,unsigned int n)2678 void qsort_walls_by_tex(GLDrawItem *arr, unsigned int n)
2679 {
2680   #define cmp_walls_by_tex(a, b) ((a)->item.wall->gltexture > (b)->item.wall->gltexture)
2681   QSORT(GLDrawItem, arr, n, cmp_walls_by_tex);
2682 }
2683 
qsort_flats_by_tex(GLDrawItem * arr,unsigned int n)2684 void qsort_flats_by_tex(GLDrawItem *arr, unsigned int n)
2685 {
2686   #define cmp_flats_by_tex(a, b) ((a)->item.flat->gltexture > (b)->item.flat->gltexture)
2687   QSORT(GLDrawItem, arr, n, cmp_flats_by_tex);
2688 }
2689 
qsort_sprites_by_tex(GLDrawItem * arr,unsigned int n)2690 void qsort_sprites_by_tex(GLDrawItem *arr, unsigned int n)
2691 {
2692   #define cmp_sprites_by_tex(a, b) ((a)->item.sprite->gltexture > (b)->item.sprite->gltexture)
2693   QSORT(GLDrawItem, arr, n, cmp_sprites_by_tex);
2694 }
2695 
qsort_sprites_by_scale(GLDrawItem * arr,unsigned int n)2696 void qsort_sprites_by_scale(GLDrawItem *arr, unsigned int n)
2697 {
2698   #define cmp_sprites_by_scale(a, b) ( \
2699     (a)->item.sprite->scale != (b)->item.sprite->scale ? \
2700     (a)->item.sprite->scale > (b)->item.sprite->scale : \
2701     (a)->item.sprite->gltexture > (b)->item.sprite->gltexture )
2702   QSORT(GLDrawItem, arr, n, cmp_sprites_by_scale);
2703 }
2704 #else
dicmp_wall(const void * a,const void * b)2705 static int C_DECL dicmp_wall(const void *a, const void *b)
2706 {
2707   GLTexture *tx1 = ((const GLDrawItem *)a)->item.wall->gltexture;
2708   GLTexture *tx2 = ((const GLDrawItem *)b)->item.wall->gltexture;
2709   return tx1 - tx2;
2710 }
dicmp_flat(const void * a,const void * b)2711 static int C_DECL dicmp_flat(const void *a, const void *b)
2712 {
2713   GLTexture *tx1 = ((const GLDrawItem *)a)->item.flat->gltexture;
2714   GLTexture *tx2 = ((const GLDrawItem *)b)->item.flat->gltexture;
2715   return tx1 - tx2;
2716 }
dicmp_sprite(const void * a,const void * b)2717 static int C_DECL dicmp_sprite(const void *a, const void *b)
2718 {
2719   GLTexture *tx1 = ((const GLDrawItem *)a)->item.sprite->gltexture;
2720   GLTexture *tx2 = ((const GLDrawItem *)b)->item.sprite->gltexture;
2721   return tx1 - tx2;
2722 }
2723 
dicmp_sprite_scale(const void * a,const void * b)2724 static int C_DECL dicmp_sprite_scale(const void *a, const void *b)
2725 {
2726   GLSprite *sprite1 = ((const GLDrawItem *)a)->item.sprite;
2727   GLSprite *sprite2 = ((const GLDrawItem *)b)->item.sprite;
2728 
2729   if (sprite1->scale != sprite2->scale)
2730   {
2731     return sprite2->scale - sprite1->scale;
2732   }
2733   else
2734   {
2735     return sprite1->gltexture - sprite2->gltexture;
2736   }
2737 }
2738 #endif
2739 
gld_DrawItemsSortByTexture(GLDrawItemType itemtype)2740 static void gld_DrawItemsSortByTexture(GLDrawItemType itemtype)
2741 {
2742 #ifdef USE_CUSTOM_QSORT
2743   typedef void(*DICMP_ITEM)(GLDrawItem *arr, unsigned int n);
2744 
2745   static DICMP_ITEM itemfuncs[GLDIT_TYPES] = {
2746     0,
2747     qsort_walls_by_tex, qsort_walls_by_tex, qsort_walls_by_tex, qsort_walls_by_tex, qsort_walls_by_tex,
2748     qsort_walls_by_tex, qsort_walls_by_tex,
2749     qsort_flats_by_tex, qsort_flats_by_tex,
2750     qsort_flats_by_tex, qsort_flats_by_tex,
2751     qsort_sprites_by_tex, qsort_sprites_by_scale, qsort_sprites_by_tex,
2752     0,
2753   };
2754 
2755   if (itemfuncs[itemtype] && gld_drawinfo.num_items[itemtype] > 1)
2756   {
2757     (itemfuncs[itemtype])(gld_drawinfo.items[itemtype], gld_drawinfo.num_items[itemtype]);
2758   }
2759 #else
2760   typedef int(C_DECL *DICMP_ITEM)(const void *a, const void *b);
2761 
2762   static DICMP_ITEM itemfuncs[GLDIT_TYPES] = {
2763     0,
2764     dicmp_wall, dicmp_wall, dicmp_wall, dicmp_wall, dicmp_wall,
2765     dicmp_wall, dicmp_wall,
2766     dicmp_flat, dicmp_flat,
2767     dicmp_flat, dicmp_flat,
2768     dicmp_sprite, dicmp_sprite_scale, dicmp_sprite,
2769     0,
2770   };
2771 
2772   if (itemfuncs[itemtype] && gld_drawinfo.num_items[itemtype] > 1)
2773   {
2774     qsort(gld_drawinfo.items[itemtype], gld_drawinfo.num_items[itemtype],
2775       sizeof(gld_drawinfo.items[itemtype]), itemfuncs[itemtype]);
2776   }
2777 #endif
2778 }
2779 
2780 static int no_overlapped_sprites;
dicmp_sprite_by_pos(const void * a,const void * b)2781 static int C_DECL dicmp_sprite_by_pos(const void *a, const void *b)
2782 {
2783   GLSprite *s1 = ((const GLDrawItem *)a)->item.sprite;
2784   GLSprite *s2 = ((const GLDrawItem *)b)->item.sprite;
2785   int res = s2->xy - s1->xy;
2786   no_overlapped_sprites = no_overlapped_sprites && res;
2787   return res;
2788 }
2789 
gld_DrawItemsSort(GLDrawItemType itemtype,int (C_DECL * PtFuncCompare)(const void *,const void *))2790 static void gld_DrawItemsSort(GLDrawItemType itemtype, int (C_DECL *PtFuncCompare)(const void *, const void *))
2791 {
2792   qsort(gld_drawinfo.items[itemtype], gld_drawinfo.num_items[itemtype],
2793     sizeof(gld_drawinfo.items[itemtype]), PtFuncCompare);
2794 }
2795 
gld_DrawItemsSortSprites(GLDrawItemType itemtype)2796 static void gld_DrawItemsSortSprites(GLDrawItemType itemtype)
2797 {
2798   static const float delta = 0.2f / MAP_COEFF;
2799   int i;
2800 
2801   if (scene_has_overlapped_sprites && sprites_doom_order == DOOM_ORDER_STATIC)
2802   {
2803     for (i = 0; i < gld_drawinfo.num_items[itemtype]; i++)
2804     {
2805       GLSprite *sprite = gld_drawinfo.items[itemtype][i].item.sprite;
2806       if (sprite->flags & MF_FOREGROUND)
2807       {
2808         sprite->index = gl_spriteindex;
2809         sprite->x -= delta * sin_inv_yaw;
2810         sprite->z -= delta * cos_inv_yaw;
2811       }
2812     }
2813   }
2814 
2815   if (sprites_doom_order == DOOM_ORDER_DYNAMIC)
2816   {
2817     no_overlapped_sprites = true;
2818     gld_DrawItemsSort(itemtype, dicmp_sprite_by_pos); // back to front
2819 
2820     if (!no_overlapped_sprites)
2821     {
2822       // there are overlapped sprites
2823       int count = gld_drawinfo.num_items[itemtype];
2824 
2825       i = 1;
2826       while (i < count)
2827       {
2828         GLSprite *sprite1 = gld_drawinfo.items[itemtype][i - 1].item.sprite;
2829         GLSprite *sprite2 = gld_drawinfo.items[itemtype][i - 0].item.sprite;
2830 
2831         if (sprite1->xy == sprite2->xy)
2832         {
2833           GLSprite *sprite = (sprite1->index > sprite2->index ? sprite1 : sprite2);
2834           i++;
2835           while (i < count && gld_drawinfo.items[itemtype][i].item.sprite->xy == sprite1->xy)
2836           {
2837             if (gld_drawinfo.items[itemtype][i].item.sprite->index > sprite->index)
2838             {
2839               sprite = gld_drawinfo.items[itemtype][i].item.sprite;
2840             }
2841             i++;
2842           }
2843 
2844           // 'nearest'
2845           sprite->index = gl_spriteindex;
2846           sprite->x -= delta * sin_inv_yaw;
2847           sprite->z -= delta * cos_inv_yaw;
2848         }
2849         i++;
2850       }
2851     }
2852   }
2853 
2854   gld_DrawItemsSortByTexture(itemtype);
2855 }
2856 
2857 //
2858 // projected walls
2859 //
gld_DrawProjectedWalls(GLDrawItemType itemtype)2860 void gld_DrawProjectedWalls(GLDrawItemType itemtype)
2861 {
2862   int i;
2863 
2864   if (gl_use_stencil && gld_drawinfo.num_items[itemtype] > 0)
2865   {
2866     // Push bleeding floor/ceiling textures back a little in the z-buffer
2867     // so they don't interfere with overlapping mid textures.
2868     glPolygonOffset(1.0f, 128.0f);
2869     glEnable(GL_POLYGON_OFFSET_FILL);
2870 
2871     glEnable(GL_STENCIL_TEST);
2872     gld_DrawItemsSortByTexture(itemtype);
2873     for (i = gld_drawinfo.num_items[itemtype] - 1; i >= 0; i--)
2874     {
2875       GLWall *wall = gld_drawinfo.items[itemtype][i].item.wall;
2876 
2877       if (gl_use_fog)
2878       {
2879         // calculation of fog density for flooded walls
2880         if (wall->seg->backsector)
2881         {
2882           wall->fogdensity = gld_CalcFogDensity(wall->seg->frontsector,
2883             wall->seg->backsector->lightlevel, itemtype);
2884         }
2885 
2886         gld_SetFog(wall->fogdensity);
2887       }
2888 
2889       gld_ProcessWall(wall);
2890     }
2891     glDisable(GL_STENCIL_TEST);
2892 
2893     glPolygonOffset(0.0f, 0.0f);
2894     glDisable(GL_POLYGON_OFFSET_FILL);
2895   }
2896 }
2897 
gld_InitDisplayLists(void)2898 void gld_InitDisplayLists(void)
2899 {
2900   int i;
2901   int loopnum; // current loop number
2902   GLLoopDef *currentloop;
2903 
2904   if (gl_use_display_lists)
2905   {
2906     flats_display_list_size = numsectors;
2907     flats_display_list = glGenLists(flats_display_list_size);
2908 
2909     glEnableClientState(GL_TEXTURE_COORD_ARRAY);
2910     glEnableClientState(GL_VERTEX_ARRAY);
2911     glDisableClientState(GL_COLOR_ARRAY);
2912 
2913     if (gl_ext_arb_vertex_buffer_object)
2914     {
2915       GLEXT_glBindBufferARB(GL_ARRAY_BUFFER, flats_vbo_id);
2916     }
2917     glVertexPointer(3, GL_FLOAT, sizeof(flats_vbo[0]), flats_vbo_x);
2918     glTexCoordPointer(2, GL_FLOAT, sizeof(flats_vbo[0]), flats_vbo_u);
2919 
2920     for (i = 0; i < flats_display_list_size; i++)
2921     {
2922       glNewList(flats_display_list + i, GL_COMPILE);
2923 
2924       for (loopnum = 0; loopnum < sectorloops[i].loopcount; loopnum++)
2925       {
2926         // set the current loop
2927         currentloop = &sectorloops[i].loops[loopnum];
2928         glDrawArrays(currentloop->mode, currentloop->vertexindex, currentloop->vertexcount);
2929       }
2930 
2931       glEndList();
2932     }
2933 
2934     // duplicated display list for flats with enabled detail ARB
2935     if (details_count && gl_arb_multitexture)
2936     {
2937       flats_detail_display_list_size = numsectors;
2938       flats_detail_display_list = glGenLists(flats_detail_display_list_size);
2939 
2940       gld_EnableClientCoordArray(GL_TEXTURE1_ARB, true);
2941 
2942       for (i = 0; i < flats_display_list_size; i++)
2943       {
2944         glNewList(flats_detail_display_list + i, GL_COMPILE);
2945 
2946         for (loopnum = 0; loopnum < sectorloops[i].loopcount; loopnum++)
2947         {
2948           // set the current loop
2949           currentloop = &sectorloops[i].loops[loopnum];
2950           glDrawArrays(currentloop->mode, currentloop->vertexindex, currentloop->vertexcount);
2951         }
2952 
2953         glEndList();
2954       }
2955 
2956       gld_EnableClientCoordArray(GL_TEXTURE1_ARB, false);
2957     }
2958 
2959     if (gl_ext_arb_vertex_buffer_object)
2960     {
2961       // bind with 0, so, switch back to normal pointer operation
2962       GLEXT_glBindBufferARB(GL_ARRAY_BUFFER, 0);
2963     }
2964     glDisableClientState(GL_TEXTURE_COORD_ARRAY);
2965     glDisableClientState(GL_VERTEX_ARRAY);
2966     glDisableClientState(GL_COLOR_ARRAY);
2967   }
2968 }
2969 
gld_CleanDisplayLists(void)2970 void gld_CleanDisplayLists(void)
2971 {
2972   if (gl_use_display_lists)
2973   {
2974     if (flats_display_list_size > 0)
2975     {
2976       glDeleteLists(flats_display_list, flats_display_list_size);
2977       flats_display_list = 0;
2978       flats_display_list_size = 0;
2979     }
2980 
2981     if (flats_detail_display_list_size > 0)
2982     {
2983       glDeleteLists(flats_detail_display_list, flats_detail_display_list_size);
2984       flats_detail_display_list = 0;
2985       flats_detail_display_list_size = 0;
2986     }
2987   }
2988 }
2989 
gld_DrawScene(player_t * player)2990 void gld_DrawScene(player_t *player)
2991 {
2992   int i;
2993   int skybox;
2994 
2995   //e6y: must call it twice for correct initialisation
2996   glEnable(GL_ALPHA_TEST);
2997 
2998   //e6y: the same with fog
2999   gl_EnableFog(true);
3000   gl_EnableFog(false);
3001 
3002   gld_EnableDetail(false);
3003   gld_InitFrameDetails();
3004 
3005 #if defined(USE_VERTEX_ARRAYS) || defined(USE_VBO)
3006   if (!gl_use_display_lists)
3007   {
3008     glEnableClientState(GL_TEXTURE_COORD_ARRAY);
3009     glEnableClientState(GL_VERTEX_ARRAY);
3010     glDisableClientState(GL_COLOR_ARRAY);
3011   }
3012 #endif
3013 
3014   //e6y: skybox
3015   skybox = 0;
3016   if (gl_drawskys != skytype_none)
3017   {
3018     skybox = gld_DrawBoxSkyBox();
3019   }
3020 
3021   if (!skybox)
3022   {
3023     if (gl_drawskys == skytype_skydome)
3024     {
3025       gld_DrawDomeSkyBox();
3026     }
3027     //e6y: 3d emulation of screen quad
3028     if (gl_drawskys == skytype_screen)
3029     {
3030       gld_DrawScreenSkybox();
3031     }
3032   }
3033 
3034 #if defined(USE_VERTEX_ARRAYS) || defined(USE_VBO)
3035   if (!gl_use_display_lists)
3036   {
3037     if (gl_ext_arb_vertex_buffer_object)
3038     {
3039       GLEXT_glBindBufferARB(GL_ARRAY_BUFFER, flats_vbo_id);
3040     }
3041     glVertexPointer(3, GL_FLOAT, sizeof(flats_vbo[0]), flats_vbo_x);
3042     glTexCoordPointer(2, GL_FLOAT, sizeof(flats_vbo[0]), flats_vbo_u);
3043   }
3044 #endif
3045 
3046   //
3047   // opaque stuff
3048   //
3049 
3050   glBlendFunc(GL_ONE, GL_ZERO);
3051 
3052   // solid geometry
3053   glDisable(GL_ALPHA_TEST);
3054 
3055   // enable backside removing
3056   glEnable(GL_CULL_FACE);
3057 
3058   // floors
3059   glCullFace(GL_FRONT);
3060   gld_DrawItemsSortByTexture(GLDIT_FLOOR);
3061   for (i = gld_drawinfo.num_items[GLDIT_FLOOR] - 1; i >= 0; i--)
3062   {
3063     gld_SetFog(gld_drawinfo.items[GLDIT_FLOOR][i].item.flat->fogdensity);
3064     gld_DrawFlat(gld_drawinfo.items[GLDIT_FLOOR][i].item.flat);
3065   }
3066 
3067   // ceilings
3068   glCullFace(GL_BACK);
3069   gld_DrawItemsSortByTexture(GLDIT_CEILING);
3070   for (i = gld_drawinfo.num_items[GLDIT_CEILING] - 1; i >= 0; i--)
3071   {
3072     gld_SetFog(gld_drawinfo.items[GLDIT_CEILING][i].item.flat->fogdensity);
3073     gld_DrawFlat(gld_drawinfo.items[GLDIT_CEILING][i].item.flat);
3074   }
3075 
3076   // disable backside removing
3077   glDisable(GL_CULL_FACE);
3078 
3079   // detail texture works only with flats and walls
3080   gld_EnableDetail(false);
3081 
3082   // top, bottom, one-sided walls
3083   gld_DrawItemsSortByTexture(GLDIT_WALL);
3084   for (i = gld_drawinfo.num_items[GLDIT_WALL] - 1; i >= 0; i--)
3085   {
3086     gld_SetFog(gld_drawinfo.items[GLDIT_WALL][i].item.wall->fogdensity);
3087     gld_ProcessWall(gld_drawinfo.items[GLDIT_WALL][i].item.wall);
3088   }
3089 
3090   // masked geometry
3091   glEnable(GL_ALPHA_TEST);
3092 
3093   gld_DrawItemsSortByTexture(GLDIT_MWALL);
3094 
3095   if (!gl_arb_multitexture && render_usedetail && gl_use_stencil &&
3096       gld_drawinfo.num_items[GLDIT_MWALL] > 0)
3097   {
3098     // opaque mid walls without holes
3099     for (i = gld_drawinfo.num_items[GLDIT_MWALL] - 1; i >= 0; i--)
3100     {
3101       GLWall *wall = gld_drawinfo.items[GLDIT_MWALL][i].item.wall;
3102       if (!(wall->gltexture->flags & GLTEXTURE_HASHOLES))
3103       {
3104         gld_SetFog(wall->fogdensity);
3105         gld_ProcessWall(wall);
3106       }
3107     }
3108 
3109     // opaque mid walls with holes
3110 
3111     glEnable(GL_STENCIL_TEST);
3112     glStencilFunc(GL_ALWAYS, 1, ~0);
3113     glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
3114 
3115     for (i = gld_drawinfo.num_items[GLDIT_MWALL] - 1; i >= 0; i--)
3116     {
3117       GLWall *wall = gld_drawinfo.items[GLDIT_MWALL][i].item.wall;
3118       if (wall->gltexture->flags & GLTEXTURE_HASHOLES)
3119       {
3120         gld_SetFog(wall->fogdensity);
3121         gld_ProcessWall(wall);
3122       }
3123     }
3124 
3125     glStencilFunc(GL_EQUAL, 1, ~0);
3126     glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
3127 
3128     glTexEnvf (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);
3129     glBlendFunc (GL_DST_COLOR, GL_SRC_COLOR);
3130 
3131     // details for opaque mid walls with holes
3132     gld_DrawItemsSortByDetail(GLDIT_MWALL);
3133     for (i = gld_drawinfo.num_items[GLDIT_MWALL] - 1; i >= 0; i--)
3134     {
3135       GLWall *wall = gld_drawinfo.items[GLDIT_MWALL][i].item.wall;
3136       if (wall->gltexture->flags & GLTEXTURE_HASHOLES)
3137       {
3138         gld_SetFog(wall->fogdensity);
3139         gld_DrawWallDetail_NoARB(wall);
3140       }
3141     }
3142 
3143     //restoring
3144     glTexEnvf(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_MODULATE);
3145     glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
3146     glClear(GL_STENCIL_BUFFER_BIT);
3147     glDisable(GL_STENCIL_TEST);
3148   }
3149   else
3150   {
3151     // opaque mid walls
3152     for (i = gld_drawinfo.num_items[GLDIT_MWALL] - 1; i >= 0; i--)
3153     {
3154       gld_SetFog(gld_drawinfo.items[GLDIT_MWALL][i].item.wall->fogdensity);
3155       gld_ProcessWall(gld_drawinfo.items[GLDIT_MWALL][i].item.wall);
3156     }
3157   }
3158 
3159   gl_EnableFog(false);
3160   gld_EnableDetail(false);
3161 
3162   // projected walls
3163   gld_DrawProjectedWalls(GLDIT_FWALL);
3164 
3165   gl_EnableFog(false);
3166   glEnable(GL_ALPHA_TEST);
3167 
3168   // normal sky (not a skybox)
3169   if (!skybox && (gl_drawskys == skytype_none || gl_drawskys == skytype_standard))
3170   {
3171     rendered_segs += gld_drawinfo.num_items[GLDIT_SWALL];
3172     // fake strips of sky
3173     gld_DrawStripsSky();
3174   }
3175 
3176   // opaque sprites
3177   glAlphaFunc(GL_GEQUAL, gl_mask_sprite_threshold_f);
3178   gld_DrawItemsSortSprites(GLDIT_SPRITE);
3179   for (i = gld_drawinfo.num_items[GLDIT_SPRITE] - 1; i >= 0; i--)
3180   {
3181     gld_SetFog(gld_drawinfo.items[GLDIT_SPRITE][i].item.sprite->fogdensity);
3182     gld_DrawSprite(gld_drawinfo.items[GLDIT_SPRITE][i].item.sprite);
3183   }
3184   glAlphaFunc(GL_GEQUAL, 0.5f);
3185 
3186   // mode for viewing all the alive monsters
3187   if (show_alive)
3188   {
3189     const int period = 250;
3190     float color;
3191     int step = (SDL_GetTicks() % (period * 2)) + 1;
3192     if (step > period)
3193     {
3194       step = period * 2 - step;
3195     }
3196     color = 0.1f + 0.9f * (float)step / (float)period;
3197 
3198     R_AddAllAliveMonstersSprites();
3199     glDisable(GL_DEPTH_TEST);
3200     gld_DrawItemsSortByTexture(GLDIT_ASPRITE);
3201     glColor4f(1.0f, color, color, 1.0f);
3202     for (i = gld_drawinfo.num_items[GLDIT_ASPRITE] - 1; i >= 0; i--)
3203     {
3204       gld_DrawSprite(gld_drawinfo.items[GLDIT_ASPRITE][i].item.sprite);
3205     }
3206     glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
3207     glEnable(GL_DEPTH_TEST);
3208   }
3209 
3210   //
3211   // transparent stuff
3212   //
3213 
3214   glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
3215 
3216   if (gl_blend_animations)
3217   {
3218     // enable backside removing
3219     glEnable(GL_CULL_FACE);
3220 
3221     // animated floors
3222     glCullFace(GL_FRONT);
3223     gld_DrawItemsSortByTexture(GLDIT_AFLOOR);
3224     for (i = gld_drawinfo.num_items[GLDIT_AFLOOR] - 1; i >= 0; i--)
3225     {
3226       gld_SetFog(gld_drawinfo.items[GLDIT_AFLOOR][i].item.flat->fogdensity);
3227       gld_DrawFlat(gld_drawinfo.items[GLDIT_AFLOOR][i].item.flat);
3228     }
3229 
3230     glCullFace(GL_BACK);
3231     gld_DrawItemsSortByTexture(GLDIT_ACEILING);
3232     for (i = gld_drawinfo.num_items[GLDIT_ACEILING] - 1; i >= 0; i--)
3233     {
3234       gld_SetFog(gld_drawinfo.items[GLDIT_ACEILING][i].item.flat->fogdensity);
3235       gld_DrawFlat(gld_drawinfo.items[GLDIT_ACEILING][i].item.flat);
3236     }
3237 
3238     // disable backside removing
3239     glDisable(GL_CULL_FACE);
3240   }
3241 
3242   if (gl_blend_animations)
3243   {
3244     gld_DrawItemsSortByTexture(GLDIT_AWALL);
3245     for (i = gld_drawinfo.num_items[GLDIT_AWALL] - 1; i >= 0; i--)
3246     {
3247       gld_SetFog(gld_drawinfo.items[GLDIT_AWALL][i].item.wall->fogdensity);
3248       gld_ProcessWall(gld_drawinfo.items[GLDIT_AWALL][i].item.wall);
3249     }
3250 
3251     // projected animated walls
3252     gld_DrawProjectedWalls(GLDIT_FAWALL);
3253   }
3254 
3255   gld_RenderShadows();
3256 
3257   if (gld_drawinfo.num_items[GLDIT_TWALL] > 0 || gld_drawinfo.num_items[GLDIT_TSPRITE] > 0)
3258   {
3259     if (gld_drawinfo.num_items[GLDIT_TWALL] > 0)
3260     {
3261       // if translucency percentage is less than 50,
3262       // then all translucent textures and sprites disappear completely
3263       // without this line
3264       glAlphaFunc(GL_GREATER, 0.0f);
3265 
3266       // transparent walls
3267       for (i = gld_drawinfo.num_items[GLDIT_TWALL] - 1; i >= 0; i--)
3268       {
3269         gld_SetFog(gld_drawinfo.items[GLDIT_TWALL][i].item.wall->fogdensity);
3270         gld_ProcessWall(gld_drawinfo.items[GLDIT_TWALL][i].item.wall);
3271       }
3272     }
3273 
3274     glEnable(GL_ALPHA_TEST);
3275 
3276     // transparent sprites
3277     // sorting is necessary only for transparent sprites.
3278     // from back to front
3279     if (gld_drawinfo.num_items[GLDIT_TSPRITE] > 0)
3280     {
3281       glAlphaFunc(GL_GEQUAL, gl_mask_sprite_threshold_f);
3282       glDepthMask(GL_FALSE);
3283       gld_DrawItemsSortSprites(GLDIT_TSPRITE);
3284       for (i = gld_drawinfo.num_items[GLDIT_TSPRITE] - 1; i >= 0; i--)
3285       {
3286         gld_SetFog(gld_drawinfo.items[GLDIT_TSPRITE][i].item.sprite->fogdensity);
3287         gld_DrawSprite(gld_drawinfo.items[GLDIT_TSPRITE][i].item.sprite);
3288       }
3289       glDepthMask(GL_TRUE);
3290     }
3291 
3292     // restoring
3293     glAlphaFunc(GL_GEQUAL, 0.5f);
3294   }
3295 
3296   // e6y: detail
3297   if (!gl_arb_multitexture && render_usedetail)
3298     gld_DrawDetail_NoARB();
3299 
3300   gld_EnableDetail(false);
3301 
3302 #if defined(USE_VERTEX_ARRAYS) || defined(USE_VBO)
3303   if (!gl_use_display_lists)
3304   {
3305     if (gl_ext_arb_vertex_buffer_object)
3306     {
3307       // bind with 0, so, switch back to normal pointer operation
3308       GLEXT_glBindBufferARB(GL_ARRAY_BUFFER, 0);
3309     }
3310     glDisableClientState(GL_TEXTURE_COORD_ARRAY);
3311     glDisableClientState(GL_VERTEX_ARRAY);
3312     glDisableClientState(GL_COLOR_ARRAY);
3313   }
3314 #endif
3315 }
3316