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=§orloops[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=§orloops[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=§ors[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 = §orloops[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 = §orloops[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