1 // SONIC ROBO BLAST 2
2 //-----------------------------------------------------------------------------
3 // Copyright (C) 1998-2020 by Sonic Team Junior.
4 //
5 // This program is free software distributed under the
6 // terms of the GNU General Public License, version 2.
7 // See the 'LICENSE' file for more details.
8 //-----------------------------------------------------------------------------
9 /// \file r_opengl.c
10 /// \brief OpenGL API for Sonic Robo Blast 2
11 
12 #if defined (_WIN32)
13 //#define WIN32_LEAN_AND_MEAN
14 #define RPC_NO_WINDOWS_H
15 #include <windows.h>
16 #endif
17 #undef GETTEXT
18 #ifdef __GNUC__
19 #include <unistd.h>
20 #endif
21 
22 #include <stdarg.h>
23 #include <math.h>
24 #include "r_opengl.h"
25 #include "r_vbo.h"
26 
27 #if defined (HWRENDER) && !defined (NOROPENGL)
28 
29 struct GLRGBAFloat
30 {
31 	GLfloat red;
32 	GLfloat green;
33 	GLfloat blue;
34 	GLfloat alpha;
35 };
36 typedef struct GLRGBAFloat GLRGBAFloat;
37 static const GLubyte white[4] = { 255, 255, 255, 255 };
38 
39 // ==========================================================================
40 //                                                                  CONSTANTS
41 // ==========================================================================
42 
43 // With OpenGL 1.1+, the first texture should be 1
44 static GLuint NOTEXTURE_NUM = 0;
45 
46 #define      N_PI_DEMI               (M_PIl/2.0f) //(1.5707963268f)
47 
48 #define      ASPECT_RATIO            (1.0f)  //(320.0f/200.0f)
49 #define      FAR_CLIPPING_PLANE      32768.0f // Draw further! Tails 01-21-2001
50 static float NEAR_CLIPPING_PLANE =   NZCLIP_PLANE;
51 
52 // **************************************************************************
53 //                                                                    GLOBALS
54 // **************************************************************************
55 
56 
57 static  GLuint      tex_downloaded  = 0;
58 static  GLfloat     fov             = 90.0f;
59 static  FBITFIELD   CurrentPolyFlags;
60 
61 // Linked list of all textures.
62 static FTextureInfo *TexCacheTail = NULL;
63 static FTextureInfo *TexCacheHead = NULL;
64 
65 RGBA_t  myPaletteData[256];
66 GLint   screen_width    = 0;               // used by Draw2DLine()
67 GLint   screen_height   = 0;
68 GLbyte  screen_depth    = 0;
69 GLint   textureformatGL = 0;
70 GLint maximumAnisotropy = 0;
71 static GLboolean MipMap = GL_FALSE;
72 static GLint min_filter = GL_LINEAR;
73 static GLint mag_filter = GL_LINEAR;
74 static GLint anisotropic_filter = 0;
75 static boolean model_lighting = false;
76 
77 const GLubyte *gl_version = NULL;
78 const GLubyte *gl_renderer = NULL;
79 const GLubyte *gl_extensions = NULL;
80 
81 //Hurdler: 04/10/2000: added for the kick ass coronas as Boris wanted;-)
82 static GLfloat modelMatrix[16];
83 static GLfloat projMatrix[16];
84 static GLint   viewport[4];
85 
86 // Sryder:	NextTexAvail is broken for these because palette changes or changes to the texture filter or antialiasing
87 //			flush all of the stored textures, leaving them unavailable at times such as between levels
88 //			These need to start at 0 and be set to their number, and be reset to 0 when deleted so that intel GPUs
89 //			can know when the textures aren't there, as textures are always considered resident in their virtual memory
90 static GLuint screentexture = 0;
91 static GLuint startScreenWipe = 0;
92 static GLuint endScreenWipe = 0;
93 static GLuint finalScreenTexture = 0;
94 
95 // shortcut for ((float)1/i)
96 static const GLfloat byte2float[256] = {
97 	0.000000f, 0.003922f, 0.007843f, 0.011765f, 0.015686f, 0.019608f, 0.023529f, 0.027451f,
98 	0.031373f, 0.035294f, 0.039216f, 0.043137f, 0.047059f, 0.050980f, 0.054902f, 0.058824f,
99 	0.062745f, 0.066667f, 0.070588f, 0.074510f, 0.078431f, 0.082353f, 0.086275f, 0.090196f,
100 	0.094118f, 0.098039f, 0.101961f, 0.105882f, 0.109804f, 0.113725f, 0.117647f, 0.121569f,
101 	0.125490f, 0.129412f, 0.133333f, 0.137255f, 0.141176f, 0.145098f, 0.149020f, 0.152941f,
102 	0.156863f, 0.160784f, 0.164706f, 0.168627f, 0.172549f, 0.176471f, 0.180392f, 0.184314f,
103 	0.188235f, 0.192157f, 0.196078f, 0.200000f, 0.203922f, 0.207843f, 0.211765f, 0.215686f,
104 	0.219608f, 0.223529f, 0.227451f, 0.231373f, 0.235294f, 0.239216f, 0.243137f, 0.247059f,
105 	0.250980f, 0.254902f, 0.258824f, 0.262745f, 0.266667f, 0.270588f, 0.274510f, 0.278431f,
106 	0.282353f, 0.286275f, 0.290196f, 0.294118f, 0.298039f, 0.301961f, 0.305882f, 0.309804f,
107 	0.313726f, 0.317647f, 0.321569f, 0.325490f, 0.329412f, 0.333333f, 0.337255f, 0.341176f,
108 	0.345098f, 0.349020f, 0.352941f, 0.356863f, 0.360784f, 0.364706f, 0.368627f, 0.372549f,
109 	0.376471f, 0.380392f, 0.384314f, 0.388235f, 0.392157f, 0.396078f, 0.400000f, 0.403922f,
110 	0.407843f, 0.411765f, 0.415686f, 0.419608f, 0.423529f, 0.427451f, 0.431373f, 0.435294f,
111 	0.439216f, 0.443137f, 0.447059f, 0.450980f, 0.454902f, 0.458824f, 0.462745f, 0.466667f,
112 	0.470588f, 0.474510f, 0.478431f, 0.482353f, 0.486275f, 0.490196f, 0.494118f, 0.498039f,
113 	0.501961f, 0.505882f, 0.509804f, 0.513726f, 0.517647f, 0.521569f, 0.525490f, 0.529412f,
114 	0.533333f, 0.537255f, 0.541177f, 0.545098f, 0.549020f, 0.552941f, 0.556863f, 0.560784f,
115 	0.564706f, 0.568627f, 0.572549f, 0.576471f, 0.580392f, 0.584314f, 0.588235f, 0.592157f,
116 	0.596078f, 0.600000f, 0.603922f, 0.607843f, 0.611765f, 0.615686f, 0.619608f, 0.623529f,
117 	0.627451f, 0.631373f, 0.635294f, 0.639216f, 0.643137f, 0.647059f, 0.650980f, 0.654902f,
118 	0.658824f, 0.662745f, 0.666667f, 0.670588f, 0.674510f, 0.678431f, 0.682353f, 0.686275f,
119 	0.690196f, 0.694118f, 0.698039f, 0.701961f, 0.705882f, 0.709804f, 0.713726f, 0.717647f,
120 	0.721569f, 0.725490f, 0.729412f, 0.733333f, 0.737255f, 0.741177f, 0.745098f, 0.749020f,
121 	0.752941f, 0.756863f, 0.760784f, 0.764706f, 0.768627f, 0.772549f, 0.776471f, 0.780392f,
122 	0.784314f, 0.788235f, 0.792157f, 0.796078f, 0.800000f, 0.803922f, 0.807843f, 0.811765f,
123 	0.815686f, 0.819608f, 0.823529f, 0.827451f, 0.831373f, 0.835294f, 0.839216f, 0.843137f,
124 	0.847059f, 0.850980f, 0.854902f, 0.858824f, 0.862745f, 0.866667f, 0.870588f, 0.874510f,
125 	0.878431f, 0.882353f, 0.886275f, 0.890196f, 0.894118f, 0.898039f, 0.901961f, 0.905882f,
126 	0.909804f, 0.913726f, 0.917647f, 0.921569f, 0.925490f, 0.929412f, 0.933333f, 0.937255f,
127 	0.941177f, 0.945098f, 0.949020f, 0.952941f, 0.956863f, 0.960784f, 0.964706f, 0.968628f,
128 	0.972549f, 0.976471f, 0.980392f, 0.984314f, 0.988235f, 0.992157f, 0.996078f, 1.000000f
129 };
130 
131 // -----------------+
132 // GL_DBG_Printf    : Output debug messages to debug log if DEBUG_TO_FILE is defined,
133 //                  : else do nothing
134 // Returns          :
135 // -----------------+
136 
137 #ifdef DEBUG_TO_FILE
138 FILE *gllogstream;
139 #endif
140 
GL_DBG_Printf(const char * format,...)141 FUNCPRINTF void GL_DBG_Printf(const char *format, ...)
142 {
143 #ifdef DEBUG_TO_FILE
144 	char str[4096] = "";
145 	va_list arglist;
146 
147 	if (!gllogstream)
148 		gllogstream = fopen("ogllog.txt", "w");
149 
150 	va_start(arglist, format);
151 	vsnprintf(str, 4096, format, arglist);
152 	va_end(arglist);
153 
154 	fwrite(str, strlen(str), 1, gllogstream);
155 #else
156 	(void)format;
157 #endif
158 }
159 
160 // -----------------+
161 // GL_MSG_Warning   : Raises a warning.
162 //                  :
163 // Returns          :
164 // -----------------+
165 
GL_MSG_Warning(const char * format,...)166 static void GL_MSG_Warning(const char *format, ...)
167 {
168 	char str[4096] = "";
169 	va_list arglist;
170 
171 	va_start(arglist, format);
172 	vsnprintf(str, 4096, format, arglist);
173 	va_end(arglist);
174 
175 #ifdef HAVE_SDL
176 	CONS_Alert(CONS_WARNING, "%s", str);
177 #endif
178 #ifdef DEBUG_TO_FILE
179 	if (!gllogstream)
180 		gllogstream = fopen("ogllog.txt", "w");
181 	fwrite(str, strlen(str), 1, gllogstream);
182 #endif
183 }
184 
185 // -----------------+
186 // GL_MSG_Error     : Raises an error.
187 //                  :
188 // Returns          :
189 // -----------------+
190 
GL_MSG_Error(const char * format,...)191 static void GL_MSG_Error(const char *format, ...)
192 {
193 	char str[4096] = "";
194 	va_list arglist;
195 
196 	va_start(arglist, format);
197 	vsnprintf(str, 4096, format, arglist);
198 	va_end(arglist);
199 
200 #ifdef HAVE_SDL
201 	CONS_Alert(CONS_ERROR, "%s", str);
202 #endif
203 #ifdef DEBUG_TO_FILE
204 	if (!gllogstream)
205 		gllogstream = fopen("ogllog.txt", "w");
206 	fwrite(str, strlen(str), 1, gllogstream);
207 #endif
208 }
209 
210 #ifdef STATIC_OPENGL
211 /* 1.0 functions */
212 /* Miscellaneous */
213 #define pglClearColor glClearColor
214 //glClear
215 #define pglColorMask glColorMask
216 #define pglAlphaFunc glAlphaFunc
217 #define pglBlendFunc glBlendFunc
218 #define pglCullFace glCullFace
219 #define pglPolygonOffset glPolygonOffset
220 #define pglScissor glScissor
221 #define pglEnable glEnable
222 #define pglDisable glDisable
223 #define pglGetFloatv glGetFloatv
224 //glGetIntegerv
225 //glGetString
226 #define pglHint glHint
227 
228 /* Depth Buffer */
229 #define pglClearDepth glClearDepth
230 #define pglDepthFunc glDepthFunc
231 #define pglDepthMask glDepthMask
232 #define pglDepthRange glDepthRange
233 
234 /* Transformation */
235 #define pglMatrixMode glMatrixMode
236 #define pglViewport glViewport
237 #define pglPushMatrix glPushMatrix
238 #define pglPopMatrix glPopMatrix
239 #define pglLoadIdentity glLoadIdentity
240 #define pglMultMatrixf glMultMatrixf
241 #define pglRotatef glRotatef
242 #define pglScalef glScalef
243 #define pglTranslatef glTranslatef
244 
245 /* Drawing Functions */
246 #define pglColor4ubv glColor4ubv
247 #define pglVertexPointer glVertexPointer
248 #define pglNormalPointer glNormalPointer
249 #define pglTexCoordPointer glTexCoordPointer
250 #define pglColorPointer glColorPointer
251 #define pglDrawArrays glDrawArrays
252 #define pglDrawElements glDrawElements
253 #define pglEnableClientState glEnableClientState
254 #define pglDisableClientState glDisableClientState
255 
256 /* Lighting */
257 #define pglShadeModel glShadeModel
258 #define pglLightfv glLightfv
259 #define pglLightModelfv glLightModelfv
260 #define pglMaterialfv glMaterialfv
261 #define pglMateriali glMateriali
262 
263 /* Raster functions */
264 #define pglPixelStorei glPixelStorei
265 #define pglReadPixels glReadPixels
266 
267 /* Texture mapping */
268 #define pglTexEnvi glTexEnvi
269 #define pglTexParameteri glTexParameteri
270 #define pglTexImage2D glTexImage2D
271 #define pglTexSubImage2D glTexSubImage2D
272 
273 /* 1.1 functions */
274 /* texture objects */ //GL_EXT_texture_object
275 #define pglGenTextures glGenTextures
276 #define pglDeleteTextures glDeleteTextures
277 #define pglBindTexture glBindTexture
278 /* texture mapping */ //GL_EXT_copy_texture
279 #define pglCopyTexImage2D glCopyTexImage2D
280 #define pglCopyTexSubImage2D glCopyTexSubImage2D
281 
282 #else //!STATIC_OPENGL
283 
284 /* 1.0 functions */
285 /* Miscellaneous */
286 typedef void (APIENTRY * PFNglClearColor) (GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha);
287 static PFNglClearColor pglClearColor;
288 typedef void (APIENTRY * PFNglColorMask) (GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha);
289 static PFNglColorMask pglColorMask;
290 typedef void (APIENTRY * PFNglAlphaFunc) (GLenum func, GLclampf ref);
291 static PFNglAlphaFunc pglAlphaFunc;
292 typedef void (APIENTRY * PFNglBlendFunc) (GLenum sfactor, GLenum dfactor);
293 static PFNglBlendFunc pglBlendFunc;
294 typedef void (APIENTRY * PFNglCullFace) (GLenum mode);
295 static PFNglCullFace pglCullFace;
296 typedef void (APIENTRY * PFNglPolygonOffset) (GLfloat factor, GLfloat units);
297 static PFNglPolygonOffset pglPolygonOffset;
298 typedef void (APIENTRY * PFNglScissor) (GLint x, GLint y, GLsizei width, GLsizei height);
299 static PFNglScissor pglScissor;
300 typedef void (APIENTRY * PFNglEnable) (GLenum cap);
301 static PFNglEnable pglEnable;
302 typedef void (APIENTRY * PFNglDisable) (GLenum cap);
303 static PFNglDisable pglDisable;
304 typedef void (APIENTRY * PFNglGetFloatv) (GLenum pname, GLfloat *params);
305 static PFNglGetFloatv pglGetFloatv;
306 
307 /* Depth Buffer */
308 typedef void (APIENTRY * PFNglClearDepth) (GLclampd depth);
309 static PFNglClearDepth pglClearDepth;
310 typedef void (APIENTRY * PFNglDepthFunc) (GLenum func);
311 static PFNglDepthFunc pglDepthFunc;
312 typedef void (APIENTRY * PFNglDepthMask) (GLboolean flag);
313 static PFNglDepthMask pglDepthMask;
314 typedef void (APIENTRY * PFNglDepthRange) (GLclampd near_val, GLclampd far_val);
315 static PFNglDepthRange pglDepthRange;
316 
317 /* Transformation */
318 typedef void (APIENTRY * PFNglMatrixMode) (GLenum mode);
319 static PFNglMatrixMode pglMatrixMode;
320 typedef void (APIENTRY * PFNglViewport) (GLint x, GLint y, GLsizei width, GLsizei height);
321 static PFNglViewport pglViewport;
322 typedef void (APIENTRY * PFNglPushMatrix) (void);
323 static PFNglPushMatrix pglPushMatrix;
324 typedef void (APIENTRY * PFNglPopMatrix) (void);
325 static PFNglPopMatrix pglPopMatrix;
326 typedef void (APIENTRY * PFNglLoadIdentity) (void);
327 static PFNglLoadIdentity pglLoadIdentity;
328 typedef void (APIENTRY * PFNglMultMatrixf) (const GLfloat *m);
329 static PFNglMultMatrixf pglMultMatrixf;
330 typedef void (APIENTRY * PFNglRotatef) (GLfloat angle, GLfloat x, GLfloat y, GLfloat z);
331 static PFNglRotatef pglRotatef;
332 typedef void (APIENTRY * PFNglScalef) (GLfloat x, GLfloat y, GLfloat z);
333 static PFNglScalef pglScalef;
334 typedef void (APIENTRY * PFNglTranslatef) (GLfloat x, GLfloat y, GLfloat z);
335 static PFNglTranslatef pglTranslatef;
336 
337 /* Drawing Functions */
338 typedef void (APIENTRY * PFNglColor4ubv) (const GLubyte *v);
339 static PFNglColor4ubv pglColor4ubv;
340 typedef void (APIENTRY * PFNglVertexPointer) (GLint size, GLenum type, GLsizei stride, const GLvoid *pointer);
341 static PFNglVertexPointer pglVertexPointer;
342 typedef void (APIENTRY * PFNglNormalPointer) (GLenum type, GLsizei stride, const GLvoid *pointer);
343 static PFNglNormalPointer pglNormalPointer;
344 typedef void (APIENTRY * PFNglTexCoordPointer) (GLint size, GLenum type, GLsizei stride, const GLvoid *pointer);
345 static PFNglTexCoordPointer pglTexCoordPointer;
346 typedef void (APIENTRY * PFNglColorPointer) (GLint size, GLenum type, GLsizei stride, const GLvoid *pointer);
347 static PFNglColorPointer pglColorPointer;
348 typedef void (APIENTRY * PFNglDrawArrays) (GLenum mode, GLint first, GLsizei count);
349 static PFNglDrawArrays pglDrawArrays;
350 typedef void (APIENTRY * PFNglDrawElements) (GLenum mode, GLsizei count, GLenum type, const GLvoid *indices);
351 static PFNglDrawElements pglDrawElements;
352 typedef void (APIENTRY * PFNglEnableClientState) (GLenum cap);
353 static PFNglEnableClientState pglEnableClientState;
354 typedef void (APIENTRY * PFNglDisableClientState) (GLenum cap);
355 static PFNglDisableClientState pglDisableClientState;
356 
357 /* Lighting */
358 typedef void (APIENTRY * PFNglShadeModel) (GLenum mode);
359 static PFNglShadeModel pglShadeModel;
360 typedef void (APIENTRY * PFNglLightfv) (GLenum light, GLenum pname, GLfloat *params);
361 static PFNglLightfv pglLightfv;
362 typedef void (APIENTRY * PFNglLightModelfv) (GLenum pname, GLfloat *params);
363 static PFNglLightModelfv pglLightModelfv;
364 typedef void (APIENTRY * PFNglMaterialfv) (GLint face, GLenum pname, GLfloat *params);
365 static PFNglMaterialfv pglMaterialfv;
366 typedef void (APIENTRY * PFNglMateriali) (GLint face, GLenum pname, GLint param);
367 static PFNglMateriali pglMateriali;
368 
369 /* Raster functions */
370 typedef void (APIENTRY * PFNglPixelStorei) (GLenum pname, GLint param);
371 static PFNglPixelStorei pglPixelStorei;
372 typedef void (APIENTRY  * PFNglReadPixels) (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid *pixels);
373 static PFNglReadPixels pglReadPixels;
374 
375 /* Texture mapping */
376 typedef void (APIENTRY * PFNglTexEnvi) (GLenum target, GLenum pname, GLint param);
377 static PFNglTexEnvi pglTexEnvi;
378 typedef void (APIENTRY * PFNglTexParameteri) (GLenum target, GLenum pname, GLint param);
379 static PFNglTexParameteri pglTexParameteri;
380 typedef void (APIENTRY * PFNglTexImage2D) (GLenum target, GLint level, GLint internalFormat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid *pixels);
381 static PFNglTexImage2D pglTexImage2D;
382 typedef void (APIENTRY * PFNglTexSubImage2D) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels);
383 static PFNglTexSubImage2D pglTexSubImage2D;
384 
385 /* 1.1 functions */
386 /* texture objects */ //GL_EXT_texture_object
387 typedef void (APIENTRY * PFNglGenTextures) (GLsizei n, const GLuint *textures);
388 static PFNglGenTextures pglGenTextures;
389 typedef void (APIENTRY * PFNglDeleteTextures) (GLsizei n, const GLuint *textures);
390 static PFNglDeleteTextures pglDeleteTextures;
391 typedef void (APIENTRY * PFNglBindTexture) (GLenum target, GLuint texture);
392 static PFNglBindTexture pglBindTexture;
393 /* texture mapping */ //GL_EXT_copy_texture
394 typedef void (APIENTRY * PFNglCopyTexImage2D) (GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border);
395 static PFNglCopyTexImage2D pglCopyTexImage2D;
396 typedef void (APIENTRY * PFNglCopyTexSubImage2D) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height);
397 static PFNglCopyTexSubImage2D pglCopyTexSubImage2D;
398 #endif
399 /* GLU functions */
400 typedef GLint (APIENTRY * PFNgluBuild2DMipmaps) (GLenum target, GLint internalFormat, GLsizei width, GLsizei height, GLenum format, GLenum type, const void *data);
401 static PFNgluBuild2DMipmaps pgluBuild2DMipmaps;
402 
403 /* 1.3 functions for multitexturing */
404 typedef void (APIENTRY *PFNglActiveTexture) (GLenum);
405 static PFNglActiveTexture pglActiveTexture;
406 typedef void (APIENTRY *PFNglMultiTexCoord2f) (GLenum, GLfloat, GLfloat);
407 static PFNglMultiTexCoord2f pglMultiTexCoord2f;
408 typedef void (APIENTRY *PFNglMultiTexCoord2fv) (GLenum target, const GLfloat *v);
409 static PFNglMultiTexCoord2fv pglMultiTexCoord2fv;
410 typedef void (APIENTRY *PFNglClientActiveTexture) (GLenum);
411 static PFNglClientActiveTexture pglClientActiveTexture;
412 
413 /* 1.5 functions for buffers */
414 typedef void (APIENTRY * PFNglGenBuffers) (GLsizei n, GLuint *buffers);
415 static PFNglGenBuffers pglGenBuffers;
416 typedef void (APIENTRY * PFNglBindBuffer) (GLenum target, GLuint buffer);
417 static PFNglBindBuffer pglBindBuffer;
418 typedef void (APIENTRY * PFNglBufferData) (GLenum target, GLsizei size, const GLvoid *data, GLenum usage);
419 static PFNglBufferData pglBufferData;
420 typedef void (APIENTRY * PFNglDeleteBuffers) (GLsizei n, const GLuint *buffers);
421 static PFNglDeleteBuffers pglDeleteBuffers;
422 
423 /* 2.0 functions */
424 typedef void (APIENTRY * PFNglBlendEquation) (GLenum mode);
425 static PFNglBlendEquation pglBlendEquation;
426 
427 
428 /* 1.2 Parms */
429 /* GL_CLAMP_TO_EDGE_EXT */
430 #ifndef GL_CLAMP_TO_EDGE
431 #define GL_CLAMP_TO_EDGE 0x812F
432 #endif
433 #ifndef GL_TEXTURE_MIN_LOD
434 #define GL_TEXTURE_MIN_LOD 0x813A
435 #endif
436 #ifndef GL_TEXTURE_MAX_LOD
437 #define GL_TEXTURE_MAX_LOD 0x813B
438 #endif
439 
440 /* 1.3 GL_TEXTUREi */
441 #ifndef GL_TEXTURE0
442 #define GL_TEXTURE0 0x84C0
443 #endif
444 #ifndef GL_TEXTURE1
445 #define GL_TEXTURE1 0x84C1
446 #endif
447 
448 /* 1.5 Parms */
449 #ifndef GL_ARRAY_BUFFER
450 #define GL_ARRAY_BUFFER 0x8892
451 #endif
452 #ifndef GL_STATIC_DRAW
453 #define GL_STATIC_DRAW 0x88E4
454 #endif
455 
SetupGLfunc(void)456 boolean SetupGLfunc(void)
457 {
458 #ifndef STATIC_OPENGL
459 #define GETOPENGLFUNC(func, proc) \
460 	func = GetGLFunc(#proc); \
461 	if (!func) \
462 	{ \
463 		GL_MSG_Warning("failed to get OpenGL function: %s", #proc); \
464 	} \
465 
466 	GETOPENGLFUNC(pglClearColor, glClearColor)
467 
468 	GETOPENGLFUNC(pglClear, glClear)
469 	GETOPENGLFUNC(pglColorMask, glColorMask)
470 	GETOPENGLFUNC(pglAlphaFunc, glAlphaFunc)
471 	GETOPENGLFUNC(pglBlendFunc, glBlendFunc)
472 	GETOPENGLFUNC(pglCullFace, glCullFace)
473 	GETOPENGLFUNC(pglPolygonOffset, glPolygonOffset)
474 	GETOPENGLFUNC(pglScissor, glScissor)
475 	GETOPENGLFUNC(pglEnable, glEnable)
476 	GETOPENGLFUNC(pglDisable, glDisable)
477 	GETOPENGLFUNC(pglGetFloatv, glGetFloatv)
478 	GETOPENGLFUNC(pglGetIntegerv, glGetIntegerv)
479 	GETOPENGLFUNC(pglGetString, glGetString)
480 
481 	GETOPENGLFUNC(pglClearDepth, glClearDepth)
482 	GETOPENGLFUNC(pglDepthFunc, glDepthFunc)
483 	GETOPENGLFUNC(pglDepthMask, glDepthMask)
484 	GETOPENGLFUNC(pglDepthRange, glDepthRange)
485 
486 	GETOPENGLFUNC(pglMatrixMode, glMatrixMode)
487 	GETOPENGLFUNC(pglViewport, glViewport)
488 	GETOPENGLFUNC(pglPushMatrix, glPushMatrix)
489 	GETOPENGLFUNC(pglPopMatrix, glPopMatrix)
490 	GETOPENGLFUNC(pglLoadIdentity, glLoadIdentity)
491 	GETOPENGLFUNC(pglMultMatrixf, glMultMatrixf)
492 	GETOPENGLFUNC(pglRotatef, glRotatef)
493 	GETOPENGLFUNC(pglScalef, glScalef)
494 	GETOPENGLFUNC(pglTranslatef, glTranslatef)
495 
496 	GETOPENGLFUNC(pglColor4ubv, glColor4ubv)
497 
498 	GETOPENGLFUNC(pglVertexPointer, glVertexPointer)
499 	GETOPENGLFUNC(pglNormalPointer, glNormalPointer)
500 	GETOPENGLFUNC(pglTexCoordPointer, glTexCoordPointer)
501 	GETOPENGLFUNC(pglColorPointer, glColorPointer)
502 	GETOPENGLFUNC(pglDrawArrays, glDrawArrays)
503 	GETOPENGLFUNC(pglDrawElements, glDrawElements)
504 	GETOPENGLFUNC(pglEnableClientState, glEnableClientState)
505 	GETOPENGLFUNC(pglDisableClientState, glDisableClientState)
506 
507 	GETOPENGLFUNC(pglShadeModel, glShadeModel)
508 	GETOPENGLFUNC(pglLightfv, glLightfv)
509 	GETOPENGLFUNC(pglLightModelfv, glLightModelfv)
510 	GETOPENGLFUNC(pglMaterialfv, glMaterialfv)
511 	GETOPENGLFUNC(pglMateriali, glMateriali)
512 
513 	GETOPENGLFUNC(pglPixelStorei, glPixelStorei)
514 	GETOPENGLFUNC(pglReadPixels, glReadPixels)
515 
516 	GETOPENGLFUNC(pglTexEnvi, glTexEnvi)
517 	GETOPENGLFUNC(pglTexParameteri, glTexParameteri)
518 	GETOPENGLFUNC(pglTexImage2D, glTexImage2D)
519 	GETOPENGLFUNC(pglTexSubImage2D, glTexSubImage2D)
520 
521 	GETOPENGLFUNC(pglGenTextures, glGenTextures)
522 	GETOPENGLFUNC(pglDeleteTextures, glDeleteTextures)
523 	GETOPENGLFUNC(pglBindTexture, glBindTexture)
524 
525 	GETOPENGLFUNC(pglCopyTexImage2D, glCopyTexImage2D)
526 	GETOPENGLFUNC(pglCopyTexSubImage2D, glCopyTexSubImage2D)
527 
528 #undef GETOPENGLFUNC
529 
530 #endif
531 	return true;
532 }
533 
534 static boolean gl_shadersenabled = false;
535 static hwdshaderoption_t gl_allowshaders = HWD_SHADEROPTION_OFF;
536 
537 #ifdef GL_SHADERS
538 typedef GLuint 	(APIENTRY *PFNglCreateShader)		(GLenum);
539 typedef void 	(APIENTRY *PFNglShaderSource)		(GLuint, GLsizei, const GLchar**, GLint*);
540 typedef void 	(APIENTRY *PFNglCompileShader)		(GLuint);
541 typedef void 	(APIENTRY *PFNglGetShaderiv)		(GLuint, GLenum, GLint*);
542 typedef void 	(APIENTRY *PFNglGetShaderInfoLog)	(GLuint, GLsizei, GLsizei*, GLchar*);
543 typedef void 	(APIENTRY *PFNglDeleteShader)		(GLuint);
544 typedef GLuint 	(APIENTRY *PFNglCreateProgram)		(void);
545 typedef void  	(APIENTRY *PFNglDeleteProgram)		(GLuint);
546 typedef void 	(APIENTRY *PFNglAttachShader)		(GLuint, GLuint);
547 typedef void 	(APIENTRY *PFNglLinkProgram)		(GLuint);
548 typedef void 	(APIENTRY *PFNglGetProgramiv)		(GLuint, GLenum, GLint*);
549 typedef void 	(APIENTRY *PFNglUseProgram)			(GLuint);
550 typedef void 	(APIENTRY *PFNglUniform1i)			(GLint, GLint);
551 typedef void 	(APIENTRY *PFNglUniform1f)			(GLint, GLfloat);
552 typedef void 	(APIENTRY *PFNglUniform2f)			(GLint, GLfloat, GLfloat);
553 typedef void 	(APIENTRY *PFNglUniform3f)			(GLint, GLfloat, GLfloat, GLfloat);
554 typedef void 	(APIENTRY *PFNglUniform4f)			(GLint, GLfloat, GLfloat, GLfloat, GLfloat);
555 typedef void 	(APIENTRY *PFNglUniform1fv)			(GLint, GLsizei, const GLfloat*);
556 typedef void 	(APIENTRY *PFNglUniform2fv)			(GLint, GLsizei, const GLfloat*);
557 typedef void 	(APIENTRY *PFNglUniform3fv)			(GLint, GLsizei, const GLfloat*);
558 typedef GLint 	(APIENTRY *PFNglGetUniformLocation)	(GLuint, const GLchar*);
559 
560 static PFNglCreateShader pglCreateShader;
561 static PFNglShaderSource pglShaderSource;
562 static PFNglCompileShader pglCompileShader;
563 static PFNglGetShaderiv pglGetShaderiv;
564 static PFNglGetShaderInfoLog pglGetShaderInfoLog;
565 static PFNglDeleteShader pglDeleteShader;
566 static PFNglCreateProgram pglCreateProgram;
567 static PFNglDeleteProgram pglDeleteProgram;
568 static PFNglAttachShader pglAttachShader;
569 static PFNglLinkProgram pglLinkProgram;
570 static PFNglGetProgramiv pglGetProgramiv;
571 static PFNglUseProgram pglUseProgram;
572 static PFNglUniform1i pglUniform1i;
573 static PFNglUniform1f pglUniform1f;
574 static PFNglUniform2f pglUniform2f;
575 static PFNglUniform3f pglUniform3f;
576 static PFNglUniform4f pglUniform4f;
577 static PFNglUniform1fv pglUniform1fv;
578 static PFNglUniform2fv pglUniform2fv;
579 static PFNglUniform3fv pglUniform3fv;
580 static PFNglGetUniformLocation pglGetUniformLocation;
581 
582 // 13062019
583 typedef enum
584 {
585 	// lighting
586 	gluniform_poly_color,
587 	gluniform_tint_color,
588 	gluniform_fade_color,
589 	gluniform_lighting,
590 	gluniform_fade_start,
591 	gluniform_fade_end,
592 
593 	// misc. (custom shaders)
594 	gluniform_leveltime,
595 
596 	gluniform_max,
597 } gluniform_t;
598 
599 typedef struct gl_shader_s
600 {
601 	GLuint program;
602 	GLint uniforms[gluniform_max+1];
603 	boolean custom;
604 } gl_shader_t;
605 
606 static gl_shader_t gl_shaders[HWR_MAXSHADERS];
607 static gl_shader_t gl_usershaders[HWR_MAXSHADERS];
608 static shadersource_t gl_customshaders[HWR_MAXSHADERS];
609 
610 // 09102020
611 typedef struct gl_shaderstate_s
612 {
613 	gl_shader_t *current;
614 	GLuint type;
615 	GLuint program;
616 	boolean changed;
617 } gl_shaderstate_t;
618 static gl_shaderstate_t gl_shaderstate;
619 
620 // Shader info
621 static INT32 shader_leveltime = 0;
622 
623 // Lactozilla: Shader functions
624 static boolean Shader_CompileProgram(gl_shader_t *shader, GLint i, const GLchar *vert_shader, const GLchar *frag_shader);
625 static void Shader_CompileError(const char *message, GLuint program, INT32 shadernum);
626 static void Shader_SetUniforms(FSurfaceInfo *Surface, GLRGBAFloat *poly, GLRGBAFloat *tint, GLRGBAFloat *fade);
627 
628 static GLRGBAFloat shader_defaultcolor = {1.0f, 1.0f, 1.0f, 1.0f};
629 
630 // ================
631 //  Vertex shaders
632 // ================
633 
634 //
635 // Generic vertex shader
636 //
637 
638 #define GLSL_DEFAULT_VERTEX_SHADER \
639 	"void main()\n" \
640 	"{\n" \
641 		"gl_Position = gl_ProjectionMatrix * gl_ModelViewMatrix * gl_Vertex;\n" \
642 		"gl_FrontColor = gl_Color;\n" \
643 		"gl_TexCoord[0].xy = gl_MultiTexCoord0.xy;\n" \
644 		"gl_ClipVertex = gl_ModelViewMatrix * gl_Vertex;\n" \
645 	"}\0"
646 
647 // replicates the way fixed function lighting is used by the model lighting option,
648 // stores the lighting result to gl_Color
649 // (ambient lighting of 0.75 and diffuse lighting from above)
650 #define GLSL_MODEL_LIGHTING_VERTEX_SHADER \
651 	"void main()\n" \
652 	"{\n" \
653 		"float nDotVP = dot(gl_Normal, vec3(0, 1, 0));\n" \
654 		"float light = 0.75 + max(nDotVP, 0.0);\n" \
655 		"gl_Position = gl_ProjectionMatrix * gl_ModelViewMatrix * gl_Vertex;\n" \
656 		"gl_FrontColor = vec4(light, light, light, 1.0);\n" \
657 		"gl_TexCoord[0].xy = gl_MultiTexCoord0.xy;\n" \
658 		"gl_ClipVertex = gl_ModelViewMatrix * gl_Vertex;\n" \
659 	"}\0"
660 
661 // ==================
662 //  Fragment shaders
663 // ==================
664 
665 //
666 // Generic fragment shader
667 //
668 
669 #define GLSL_DEFAULT_FRAGMENT_SHADER \
670 	"uniform sampler2D tex;\n" \
671 	"uniform vec4 poly_color;\n" \
672 	"void main(void) {\n" \
673 		"gl_FragColor = texture2D(tex, gl_TexCoord[0].st) * poly_color;\n" \
674 	"}\0"
675 
676 //
677 // Software fragment shader
678 //
679 
680 #define GLSL_DOOM_COLORMAP \
681 	"float R_DoomColormap(float light, float z)\n" \
682 	"{\n" \
683 		"float lightnum = clamp(light / 17.0, 0.0, 15.0);\n" \
684 		"float lightz = clamp(z / 16.0, 0.0, 127.0);\n" \
685 		"float startmap = (15.0 - lightnum) * 4.0;\n" \
686 		"float scale = 160.0 / (lightz + 1.0);\n" \
687 		"return startmap - scale * 0.5;\n" \
688 	"}\n"
689 
690 #define GLSL_DOOM_LIGHT_EQUATION \
691 	"float R_DoomLightingEquation(float light)\n" \
692 	"{\n" \
693 		"float z = gl_FragCoord.z / gl_FragCoord.w;\n" \
694 		"float colormap = floor(R_DoomColormap(light, z)) + 0.5;\n" \
695 		"return clamp(colormap, 0.0, 31.0) / 32.0;\n" \
696 	"}\n"
697 
698 #define GLSL_SOFTWARE_TINT_EQUATION \
699 	"if (tint_color.a > 0.0) {\n" \
700 		"float color_bright = sqrt((base_color.r * base_color.r) + (base_color.g * base_color.g) + (base_color.b * base_color.b));\n" \
701 		"float strength = sqrt(9.0 * tint_color.a);\n" \
702 		"final_color.r = clamp((color_bright * (tint_color.r * strength)) + (base_color.r * (1.0 - strength)), 0.0, 1.0);\n" \
703 		"final_color.g = clamp((color_bright * (tint_color.g * strength)) + (base_color.g * (1.0 - strength)), 0.0, 1.0);\n" \
704 		"final_color.b = clamp((color_bright * (tint_color.b * strength)) + (base_color.b * (1.0 - strength)), 0.0, 1.0);\n" \
705 	"}\n"
706 
707 #define GLSL_SOFTWARE_FADE_EQUATION \
708 	"float darkness = R_DoomLightingEquation(lighting);\n" \
709 	"if (fade_start != 0.0 || fade_end != 31.0) {\n" \
710 		"float fs = fade_start / 31.0;\n" \
711 		"float fe = fade_end / 31.0;\n" \
712 		"float fd = fe - fs;\n" \
713 		"darkness = clamp((darkness - fs) * (1.0 / fd), 0.0, 1.0);\n" \
714 	"}\n" \
715 	"final_color = mix(final_color, fade_color, darkness);\n"
716 
717 #define GLSL_SOFTWARE_FRAGMENT_SHADER \
718 	"uniform sampler2D tex;\n" \
719 	"uniform vec4 poly_color;\n" \
720 	"uniform vec4 tint_color;\n" \
721 	"uniform vec4 fade_color;\n" \
722 	"uniform float lighting;\n" \
723 	"uniform float fade_start;\n" \
724 	"uniform float fade_end;\n" \
725 	GLSL_DOOM_COLORMAP \
726 	GLSL_DOOM_LIGHT_EQUATION \
727 	"void main(void) {\n" \
728 		"vec4 texel = texture2D(tex, gl_TexCoord[0].st);\n" \
729 		"vec4 base_color = texel * poly_color;\n" \
730 		"vec4 final_color = base_color;\n" \
731 		GLSL_SOFTWARE_TINT_EQUATION \
732 		GLSL_SOFTWARE_FADE_EQUATION \
733 		"final_color.a = texel.a * poly_color.a;\n" \
734 		"gl_FragColor = final_color;\n" \
735 	"}\0"
736 
737 // same as above but multiplies results with the lighting value from the
738 // accompanying vertex shader (stored in gl_Color)
739 #define GLSL_SOFTWARE_MODEL_LIGHTING_FRAGMENT_SHADER \
740 	"uniform sampler2D tex;\n" \
741 	"uniform vec4 poly_color;\n" \
742 	"uniform vec4 tint_color;\n" \
743 	"uniform vec4 fade_color;\n" \
744 	"uniform float lighting;\n" \
745 	"uniform float fade_start;\n" \
746 	"uniform float fade_end;\n" \
747 	GLSL_DOOM_COLORMAP \
748 	GLSL_DOOM_LIGHT_EQUATION \
749 	"void main(void) {\n" \
750 		"vec4 texel = texture2D(tex, gl_TexCoord[0].st);\n" \
751 		"vec4 base_color = texel * poly_color;\n" \
752 		"vec4 final_color = base_color;\n" \
753 		GLSL_SOFTWARE_TINT_EQUATION \
754 		GLSL_SOFTWARE_FADE_EQUATION \
755 		"final_color *= gl_Color;\n" \
756 		"final_color.a = texel.a * poly_color.a;\n" \
757 		"gl_FragColor = final_color;\n" \
758 	"}\0"
759 
760 //
761 // Water surface shader
762 //
763 // Mostly guesstimated, rather than the rest being built off Software science.
764 // Still needs to distort things underneath/around the water...
765 //
766 
767 #define GLSL_WATER_FRAGMENT_SHADER \
768 	"uniform sampler2D tex;\n" \
769 	"uniform vec4 poly_color;\n" \
770 	"uniform vec4 tint_color;\n" \
771 	"uniform vec4 fade_color;\n" \
772 	"uniform float lighting;\n" \
773 	"uniform float fade_start;\n" \
774 	"uniform float fade_end;\n" \
775 	"uniform float leveltime;\n" \
776 	"const float freq = 0.025;\n" \
777 	"const float amp = 0.025;\n" \
778 	"const float speed = 2.0;\n" \
779 	"const float pi = 3.14159;\n" \
780 	GLSL_DOOM_COLORMAP \
781 	GLSL_DOOM_LIGHT_EQUATION \
782 	"void main(void) {\n" \
783 		"float z = (gl_FragCoord.z / gl_FragCoord.w) / 2.0;\n" \
784 		"float a = -pi * (z * freq) + (leveltime * speed);\n" \
785 		"float sdistort = sin(a) * amp;\n" \
786 		"float cdistort = cos(a) * amp;\n" \
787 		"vec4 texel = texture2D(tex, vec2(gl_TexCoord[0].s - sdistort, gl_TexCoord[0].t - cdistort));\n" \
788 		"vec4 base_color = texel * poly_color;\n" \
789 		"vec4 final_color = base_color;\n" \
790 		GLSL_SOFTWARE_TINT_EQUATION \
791 		GLSL_SOFTWARE_FADE_EQUATION \
792 		"final_color.a = texel.a * poly_color.a;\n" \
793 		"gl_FragColor = final_color;\n" \
794 	"}\0"
795 
796 //
797 // Fog block shader
798 //
799 // Alpha of the planes themselves are still slightly off -- see HWR_FogBlockAlpha
800 //
801 
802 #define GLSL_FOG_FRAGMENT_SHADER \
803 	"uniform vec4 tint_color;\n" \
804 	"uniform vec4 fade_color;\n" \
805 	"uniform float lighting;\n" \
806 	"uniform float fade_start;\n" \
807 	"uniform float fade_end;\n" \
808 	GLSL_DOOM_COLORMAP \
809 	GLSL_DOOM_LIGHT_EQUATION \
810 	"void main(void) {\n" \
811 		"vec4 base_color = gl_Color;\n" \
812 		"vec4 final_color = base_color;\n" \
813 		GLSL_SOFTWARE_TINT_EQUATION \
814 		GLSL_SOFTWARE_FADE_EQUATION \
815 		"gl_FragColor = final_color;\n" \
816 	"}\0"
817 
818 //
819 // Sky fragment shader
820 // Modulates poly_color with gl_Color
821 //
822 #define GLSL_SKY_FRAGMENT_SHADER \
823 	"uniform sampler2D tex;\n" \
824 	"uniform vec4 poly_color;\n" \
825 	"void main(void) {\n" \
826 		"gl_FragColor = texture2D(tex, gl_TexCoord[0].st) * gl_Color * poly_color;\n" \
827 	"}\0"
828 
829 // ================
830 //  Shader sources
831 // ================
832 
833 static struct {
834 	const char *vertex;
835 	const char *fragment;
836 } const gl_shadersources[] = {
837 	// Default shader
838 	{GLSL_DEFAULT_VERTEX_SHADER, GLSL_DEFAULT_FRAGMENT_SHADER},
839 
840 	// Floor shader
841 	{GLSL_DEFAULT_VERTEX_SHADER, GLSL_SOFTWARE_FRAGMENT_SHADER},
842 
843 	// Wall shader
844 	{GLSL_DEFAULT_VERTEX_SHADER, GLSL_SOFTWARE_FRAGMENT_SHADER},
845 
846 	// Sprite shader
847 	{GLSL_DEFAULT_VERTEX_SHADER, GLSL_SOFTWARE_FRAGMENT_SHADER},
848 
849 	// Model shader
850 	{GLSL_DEFAULT_VERTEX_SHADER, GLSL_SOFTWARE_FRAGMENT_SHADER},
851 
852 	// Model shader + diffuse lighting from above
853 	{GLSL_MODEL_LIGHTING_VERTEX_SHADER, GLSL_SOFTWARE_MODEL_LIGHTING_FRAGMENT_SHADER},
854 
855 	// Water shader
856 	{GLSL_DEFAULT_VERTEX_SHADER, GLSL_WATER_FRAGMENT_SHADER},
857 
858 	// Fog shader
859 	{GLSL_DEFAULT_VERTEX_SHADER, GLSL_FOG_FRAGMENT_SHADER},
860 
861 	// Sky shader
862 	{GLSL_DEFAULT_VERTEX_SHADER, GLSL_SKY_FRAGMENT_SHADER},
863 
864 	{NULL, NULL},
865 };
866 
867 #endif	// GL_SHADERS
868 
SetupGLFunc4(void)869 void SetupGLFunc4(void)
870 {
871 	pglActiveTexture = GetGLFunc("glActiveTexture");
872 	pglMultiTexCoord2f = GetGLFunc("glMultiTexCoord2f");
873 	pglClientActiveTexture = GetGLFunc("glClientActiveTexture");
874 	pglMultiTexCoord2fv = GetGLFunc("glMultiTexCoord2fv");
875 
876 	/* 1.5 funcs */
877 	pglGenBuffers = GetGLFunc("glGenBuffers");
878 	pglBindBuffer = GetGLFunc("glBindBuffer");
879 	pglBufferData = GetGLFunc("glBufferData");
880 	pglDeleteBuffers = GetGLFunc("glDeleteBuffers");
881 
882 	/* 2.0 funcs */
883 	pglBlendEquation = GetGLFunc("glBlendEquation");
884 
885 #ifdef GL_SHADERS
886 	pglCreateShader = GetGLFunc("glCreateShader");
887 	pglShaderSource = GetGLFunc("glShaderSource");
888 	pglCompileShader = GetGLFunc("glCompileShader");
889 	pglGetShaderiv = GetGLFunc("glGetShaderiv");
890 	pglGetShaderInfoLog = GetGLFunc("glGetShaderInfoLog");
891 	pglDeleteShader = GetGLFunc("glDeleteShader");
892 	pglCreateProgram = GetGLFunc("glCreateProgram");
893 	pglDeleteProgram = GetGLFunc("glDeleteProgram");
894 	pglAttachShader = GetGLFunc("glAttachShader");
895 	pglLinkProgram = GetGLFunc("glLinkProgram");
896 	pglGetProgramiv = GetGLFunc("glGetProgramiv");
897 	pglUseProgram = GetGLFunc("glUseProgram");
898 	pglUniform1i = GetGLFunc("glUniform1i");
899 	pglUniform1f = GetGLFunc("glUniform1f");
900 	pglUniform2f = GetGLFunc("glUniform2f");
901 	pglUniform3f = GetGLFunc("glUniform3f");
902 	pglUniform4f = GetGLFunc("glUniform4f");
903 	pglUniform1fv = GetGLFunc("glUniform1fv");
904 	pglUniform2fv = GetGLFunc("glUniform2fv");
905 	pglUniform3fv = GetGLFunc("glUniform3fv");
906 	pglGetUniformLocation = GetGLFunc("glGetUniformLocation");
907 #endif
908 
909 	// GLU
910 	pgluBuild2DMipmaps = GetGLFunc("gluBuild2DMipmaps");
911 }
912 
HWRAPI(CompileShaders)913 EXPORT boolean HWRAPI(CompileShaders) (void)
914 {
915 #ifdef GL_SHADERS
916 	GLint i;
917 
918 	if (!pglUseProgram)
919 		return false;
920 
921 	gl_customshaders[SHADER_DEFAULT].vertex = NULL;
922 	gl_customshaders[SHADER_DEFAULT].fragment = NULL;
923 
924 	for (i = 0; gl_shadersources[i].vertex && gl_shadersources[i].fragment; i++)
925 	{
926 		gl_shader_t *shader, *usershader;
927 		const GLchar *vert_shader = gl_shadersources[i].vertex;
928 		const GLchar *frag_shader = gl_shadersources[i].fragment;
929 
930 		if (i >= HWR_MAXSHADERS)
931 			break;
932 
933 		shader = &gl_shaders[i];
934 		usershader = &gl_usershaders[i];
935 
936 		if (shader->program)
937 			pglDeleteProgram(shader->program);
938 		if (usershader->program)
939 			pglDeleteProgram(usershader->program);
940 
941 		shader->program = 0;
942 		usershader->program = 0;
943 
944 		if (!Shader_CompileProgram(shader, i, vert_shader, frag_shader))
945 			shader->program = 0;
946 
947 		// Compile custom shader
948 		if ((i == SHADER_DEFAULT) || !(gl_customshaders[i].vertex || gl_customshaders[i].fragment))
949 			continue;
950 
951 		// 18032019
952 		if (gl_customshaders[i].vertex)
953 			vert_shader = gl_customshaders[i].vertex;
954 		if (gl_customshaders[i].fragment)
955 			frag_shader = gl_customshaders[i].fragment;
956 
957 		if (!Shader_CompileProgram(usershader, i, vert_shader, frag_shader))
958 		{
959 			GL_MSG_Warning("CompileShaders: Could not compile custom shader program for %s\n", HWR_GetShaderName(i));
960 			usershader->program = 0;
961 		}
962 	}
963 
964 	return true;
965 #else
966 	return false;
967 #endif
968 }
969 
970 //
971 // Shader info
972 // Those are given to the uniforms.
973 //
974 
HWRAPI(SetShaderInfo)975 EXPORT void HWRAPI(SetShaderInfo) (hwdshaderinfo_t info, INT32 value)
976 {
977 #ifdef GL_SHADERS
978 	switch (info)
979 	{
980 		case HWD_SHADERINFO_LEVELTIME:
981 			shader_leveltime = value;
982 			break;
983 		default:
984 			break;
985 	}
986 #else
987 	(void)info;
988 	(void)value;
989 #endif
990 }
991 
992 //
993 // Custom shader loading
994 //
HWRAPI(LoadCustomShader)995 EXPORT void HWRAPI(LoadCustomShader) (int number, char *code, size_t size, boolean isfragment)
996 {
997 #ifdef GL_SHADERS
998 	shadersource_t *shader;
999 
1000 	if (!pglUseProgram)
1001 		return;
1002 
1003 	if (number < 1 || number > HWR_MAXSHADERS)
1004 		I_Error("LoadCustomShader: cannot load shader %d (min 1, max %d)", number, HWR_MAXSHADERS);
1005 	else if (code == NULL)
1006 		I_Error("LoadCustomShader: empty shader");
1007 
1008 	shader = &gl_customshaders[number];
1009 
1010 #define COPYSHADER(source) { \
1011 	if (shader->source) \
1012 		free(shader->source); \
1013 	shader->source = malloc(size+1); \
1014 	strncpy(shader->source, code, size); \
1015 	shader->source[size] = 0; \
1016 	}
1017 
1018 	if (isfragment)
1019 		COPYSHADER(fragment)
1020 	else
1021 		COPYSHADER(vertex)
1022 
1023 #else
1024 	(void)number;
1025 	(void)shader;
1026 	(void)size;
1027 	(void)fragment;
1028 #endif
1029 }
1030 
HWRAPI(SetShader)1031 EXPORT void HWRAPI(SetShader) (int type)
1032 {
1033 #ifdef GL_SHADERS
1034 	if (gl_allowshaders != HWD_SHADEROPTION_OFF)
1035 	{
1036 		gl_shader_t *shader = gl_shaderstate.current;
1037 
1038 		// If using model lighting, set the appropriate shader.
1039 		// However don't override a custom shader.
1040 		if (type == SHADER_MODEL && model_lighting
1041 		&& !(gl_shaders[SHADER_MODEL].custom && !gl_shaders[SHADER_MODEL_LIGHTING].custom))
1042 			type = SHADER_MODEL_LIGHTING;
1043 
1044 		if ((shader == NULL) || (GLuint)type != gl_shaderstate.type)
1045 		{
1046 			gl_shader_t *baseshader = &gl_shaders[type];
1047 			gl_shader_t *usershader = &gl_usershaders[type];
1048 
1049 			if (usershader->program)
1050 				shader = (gl_allowshaders == HWD_SHADEROPTION_NOCUSTOM) ? baseshader : usershader;
1051 			else
1052 				shader = baseshader;
1053 
1054 			gl_shaderstate.current = shader;
1055 			gl_shaderstate.type = type;
1056 			gl_shaderstate.changed = true;
1057 		}
1058 
1059 		if (gl_shaderstate.program != shader->program)
1060 		{
1061 			gl_shaderstate.program = shader->program;
1062 			gl_shaderstate.changed = true;
1063 		}
1064 
1065 		gl_shadersenabled = (shader->program != 0);
1066 		return;
1067 	}
1068 #else
1069 	(void)type;
1070 #endif
1071 	gl_shadersenabled = false;
1072 }
1073 
HWRAPI(UnSetShader)1074 EXPORT void HWRAPI(UnSetShader) (void)
1075 {
1076 #ifdef GL_SHADERS
1077 	gl_shaderstate.current = NULL;
1078 	gl_shaderstate.type = 0;
1079 	gl_shaderstate.program = 0;
1080 
1081 	if (pglUseProgram)
1082 		pglUseProgram(0);
1083 #endif
1084 
1085 	gl_shadersenabled = false;
1086 }
1087 
HWRAPI(CleanShaders)1088 EXPORT void HWRAPI(CleanShaders) (void)
1089 {
1090 	INT32 i;
1091 
1092 	for (i = 1; i < HWR_MAXSHADERS; i++)
1093 	{
1094 		shadersource_t *shader = &gl_customshaders[i];
1095 
1096 		if (shader->vertex)
1097 			free(shader->vertex);
1098 
1099 		if (shader->fragment)
1100 			free(shader->fragment);
1101 
1102 		shader->vertex = NULL;
1103 		shader->fragment = NULL;
1104 	}
1105 }
1106 
1107 // -----------------+
1108 // SetNoTexture     : Disable texture
1109 // -----------------+
SetNoTexture(void)1110 static void SetNoTexture(void)
1111 {
1112 	// Disable texture.
1113 	if (tex_downloaded != NOTEXTURE_NUM)
1114 	{
1115 		if (NOTEXTURE_NUM == 0)
1116 			pglGenTextures(1, &NOTEXTURE_NUM);
1117 		pglBindTexture(GL_TEXTURE_2D, NOTEXTURE_NUM);
1118 		tex_downloaded = NOTEXTURE_NUM;
1119 	}
1120 }
1121 
GLPerspective(GLfloat fovy,GLfloat aspect)1122 static void GLPerspective(GLfloat fovy, GLfloat aspect)
1123 {
1124 	GLfloat m[4][4] =
1125 	{
1126 		{ 1.0f, 0.0f, 0.0f, 0.0f},
1127 		{ 0.0f, 1.0f, 0.0f, 0.0f},
1128 		{ 0.0f, 0.0f, 1.0f,-1.0f},
1129 		{ 0.0f, 0.0f, 0.0f, 0.0f},
1130 	};
1131 	const GLfloat zNear = NEAR_CLIPPING_PLANE;
1132 	const GLfloat zFar = FAR_CLIPPING_PLANE;
1133 	const GLfloat radians = (GLfloat)(fovy / 2.0f * M_PIl / 180.0f);
1134 	const GLfloat sine = sin(radians);
1135 	const GLfloat deltaZ = zFar - zNear;
1136 	GLfloat cotangent;
1137 
1138 	if ((fabsf((float)deltaZ) < 1.0E-36f) || fpclassify(sine) == FP_ZERO || fpclassify(aspect) == FP_ZERO)
1139 	{
1140 		return;
1141 	}
1142 	cotangent = cosf(radians) / sine;
1143 
1144 	m[0][0] = cotangent / aspect;
1145 	m[1][1] = cotangent;
1146 	m[2][2] = -(zFar + zNear) / deltaZ;
1147 	m[3][2] = -2.0f * zNear * zFar / deltaZ;
1148 
1149 	pglMultMatrixf(&m[0][0]);
1150 }
1151 
GLProject(GLfloat objX,GLfloat objY,GLfloat objZ,GLfloat * winX,GLfloat * winY,GLfloat * winZ)1152 static void GLProject(GLfloat objX, GLfloat objY, GLfloat objZ,
1153                       GLfloat* winX, GLfloat* winY, GLfloat* winZ)
1154 {
1155 	GLfloat in[4], out[4];
1156 	int i;
1157 
1158 	for (i=0; i<4; i++)
1159 	{
1160 		out[i] =
1161 			objX * modelMatrix[0*4+i] +
1162 			objY * modelMatrix[1*4+i] +
1163 			objZ * modelMatrix[2*4+i] +
1164 			modelMatrix[3*4+i];
1165 	}
1166 	for (i=0; i<4; i++)
1167 	{
1168 		in[i] =
1169 			out[0] * projMatrix[0*4+i] +
1170 			out[1] * projMatrix[1*4+i] +
1171 			out[2] * projMatrix[2*4+i] +
1172 			out[3] * projMatrix[3*4+i];
1173 	}
1174 	if (fpclassify(in[3]) == FP_ZERO) return;
1175 	in[0] /= in[3];
1176 	in[1] /= in[3];
1177 	in[2] /= in[3];
1178 	/* Map x, y and z to range 0-1 */
1179 	in[0] = in[0] * 0.5f + 0.5f;
1180 	in[1] = in[1] * 0.5f + 0.5f;
1181 	in[2] = in[2] * 0.5f + 0.5f;
1182 
1183 	/* Map x,y to viewport */
1184 	in[0] = in[0] * viewport[2] + viewport[0];
1185 	in[1] = in[1] * viewport[3] + viewport[1];
1186 
1187 	*winX=in[0];
1188 	*winY=in[1];
1189 	*winZ=in[2];
1190 }
1191 
1192 // -----------------+
1193 // SetModelView     :
1194 // -----------------+
SetModelView(GLint w,GLint h)1195 void SetModelView(GLint w, GLint h)
1196 {
1197 //	GL_DBG_Printf("SetModelView(): %dx%d\n", (int)w, (int)h);
1198 
1199 	// The screen textures need to be flushed if the width or height change so that they be remade for the correct size
1200 	if (screen_width != w || screen_height != h)
1201 		FlushScreenTextures();
1202 
1203 	screen_width = w;
1204 	screen_height = h;
1205 
1206 	pglViewport(0, 0, w, h);
1207 
1208 	pglMatrixMode(GL_PROJECTION);
1209 	pglLoadIdentity();
1210 
1211 	pglMatrixMode(GL_MODELVIEW);
1212 	pglLoadIdentity();
1213 
1214 	GLPerspective(fov, ASPECT_RATIO);
1215 	//pglScalef(1.0f, 320.0f/200.0f, 1.0f);  // gl_scalefrustum (ORIGINAL_ASPECT)
1216 
1217 	// added for new coronas' code (without depth buffer)
1218 	pglGetIntegerv(GL_VIEWPORT, viewport);
1219 	pglGetFloatv(GL_PROJECTION_MATRIX, projMatrix);
1220 }
1221 
1222 
1223 // -----------------+
1224 // SetStates        : Set permanent states
1225 // -----------------+
SetStates(void)1226 void SetStates(void)
1227 {
1228 #ifdef GL_LIGHT_MODEL_AMBIENT
1229 	GLfloat LightDiffuse[] = {1.0f, 1.0f, 1.0f, 1.0f};
1230 #endif
1231 
1232 //	GL_DBG_Printf("SetStates()\n");
1233 
1234 	// Hurdler: not necessary, is it?
1235 	pglShadeModel(GL_SMOOTH);      // iterate vertice colors
1236 	//pglShadeModel(GL_FLAT);
1237 
1238 	pglEnable(GL_TEXTURE_2D);      // two-dimensional texturing
1239 
1240 	pglTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
1241 
1242 	pglEnable(GL_ALPHA_TEST);
1243 	pglAlphaFunc(GL_NOTEQUAL, 0.0f);
1244 
1245 	//pglBlendFunc(GL_ONE, GL_ZERO); // copy pixel to frame buffer (opaque)
1246 	pglEnable(GL_BLEND);           // enable color blending
1247 
1248 	pglColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
1249 
1250 	//pglDisable(GL_DITHER);         // faB: ??? (undocumented in OpenGL 1.1)
1251 	                              // Hurdler: yes, it is!
1252 	pglEnable(GL_DEPTH_TEST);    // check the depth buffer
1253 	pglDepthMask(GL_TRUE);             // enable writing to depth buffer
1254 	pglClearDepth(1.0f);
1255 	pglDepthRange(0.0f, 1.0f);
1256 	pglDepthFunc(GL_LEQUAL);
1257 
1258 	// this set CurrentPolyFlags to the actual configuration
1259 	CurrentPolyFlags = 0xffffffff;
1260 	SetBlend(0);
1261 
1262 	tex_downloaded = 0;
1263 	SetNoTexture();
1264 
1265 	pglPolygonOffset(-1.0f, -1.0f);
1266 
1267 	//pglEnable(GL_CULL_FACE);
1268 	//pglCullFace(GL_FRONT);
1269 
1270 	pglDisable(GL_FOG);
1271 
1272 	// Lighting for models
1273 #ifdef GL_LIGHT_MODEL_AMBIENT
1274 	pglLightModelfv(GL_LIGHT_MODEL_AMBIENT, LightDiffuse);
1275 	pglEnable(GL_LIGHT0);
1276 #endif
1277 
1278 	// bp : when no t&l :)
1279 	pglLoadIdentity();
1280 	pglScalef(1.0f, 1.0f, -1.0f);
1281 	pglGetFloatv(GL_MODELVIEW_MATRIX, modelMatrix); // added for new coronas' code (without depth buffer)
1282 }
1283 
1284 
1285 // -----------------+
1286 // DeleteTexture    : Deletes a texture from the GPU and frees its data
1287 // -----------------+
HWRAPI(DeleteTexture)1288 EXPORT void HWRAPI(DeleteTexture) (GLMipmap_t *pTexInfo)
1289 {
1290 	FTextureInfo *head = TexCacheHead;
1291 
1292 	if (!pTexInfo)
1293 		return;
1294 	else if (pTexInfo->downloaded)
1295 		pglDeleteTextures(1, (GLuint *)&pTexInfo->downloaded);
1296 
1297 	while (head)
1298 	{
1299 		if (head->downloaded == pTexInfo->downloaded)
1300 		{
1301 			if (head->next)
1302 				head->next->prev = head->prev;
1303 			else // no next -> tail is being deleted -> update TexCacheTail
1304 				TexCacheTail = head->prev;
1305 			if (head->prev)
1306 				head->prev->next = head->next;
1307 			else // no prev -> head is being deleted -> update TexCacheHead
1308 				TexCacheHead = head->next;
1309 			free(head);
1310 			break;
1311 		}
1312 
1313 		head = head->next;
1314 	}
1315 
1316 	pTexInfo->downloaded = 0;
1317 }
1318 
1319 
1320 // -----------------+
1321 // Flush            : flush OpenGL textures
1322 //                  : Clear list of downloaded mipmaps
1323 // -----------------+
Flush(void)1324 void Flush(void)
1325 {
1326 	//GL_DBG_Printf ("HWR_Flush()\n");
1327 
1328 	while (TexCacheHead)
1329 	{
1330 		FTextureInfo *pTexInfo = TexCacheHead;
1331 		GLMipmap_t *texture = pTexInfo->texture;
1332 
1333 		if (pTexInfo->downloaded)
1334 		{
1335 			pglDeleteTextures(1, (GLuint *)&pTexInfo->downloaded);
1336 			pTexInfo->downloaded = 0;
1337 		}
1338 
1339 		if (texture)
1340 			texture->downloaded = 0;
1341 
1342 		TexCacheHead = pTexInfo->next;
1343 		free(pTexInfo);
1344 	}
1345 
1346 	TexCacheTail = TexCacheHead = NULL; //Hurdler: well, TexCacheHead is already NULL
1347 	tex_downloaded = 0;
1348 }
1349 
1350 
1351 // -----------------+
1352 // isExtAvailable   : Look if an OpenGL extension is available
1353 // Returns          : true if extension available
1354 // -----------------+
isExtAvailable(const char * extension,const GLubyte * start)1355 INT32 isExtAvailable(const char *extension, const GLubyte *start)
1356 {
1357 	GLubyte         *where, *terminator;
1358 
1359 	if (!extension || !start) return 0;
1360 	where = (GLubyte *) strchr(extension, ' ');
1361 	if (where || *extension == '\0')
1362 		return 0;
1363 
1364 	for (;;)
1365 	{
1366 		where = (GLubyte *) strstr((const char *) start, extension);
1367 		if (!where)
1368 			break;
1369 		terminator = where + strlen(extension);
1370 		if (where == start || *(where - 1) == ' ')
1371 			if (*terminator == ' ' || *terminator == '\0')
1372 				return 1;
1373 		start = terminator;
1374 	}
1375 	return 0;
1376 }
1377 
1378 
1379 // -----------------+
1380 // Init             : Initialise the OpenGL interface API
1381 // Returns          :
1382 // -----------------+
HWRAPI(Init)1383 EXPORT boolean HWRAPI(Init) (void)
1384 {
1385 	return LoadGL();
1386 }
1387 
1388 
1389 // -----------------+
1390 // ClearMipMapCache : Flush OpenGL textures from memory
1391 // -----------------+
HWRAPI(ClearMipMapCache)1392 EXPORT void HWRAPI(ClearMipMapCache) (void)
1393 {
1394 	// GL_DBG_Printf ("HWR_Flush(exe)\n");
1395 	Flush();
1396 }
1397 
1398 
1399 // -----------------+
1400 // ReadRect         : Read a rectangle region of the truecolor framebuffer
1401 //                  : store pixels as 16bit 565 RGB
1402 // Returns          : 16bit 565 RGB pixel array stored in dst_data
1403 // -----------------+
HWRAPI(ReadRect)1404 EXPORT void HWRAPI(ReadRect) (INT32 x, INT32 y, INT32 width, INT32 height,
1405                                 INT32 dst_stride, UINT16 * dst_data)
1406 {
1407 	INT32 i;
1408 	// GL_DBG_Printf ("ReadRect()\n");
1409 	if (dst_stride == width*3)
1410 	{
1411 		GLubyte*top = (GLvoid*)dst_data, *bottom = top + dst_stride * (height - 1);
1412 		GLubyte *row = malloc(dst_stride);
1413 		if (!row) return;
1414 		pglPixelStorei(GL_PACK_ALIGNMENT, 1);
1415 		pglReadPixels(x, y, width, height, GL_RGB, GL_UNSIGNED_BYTE, dst_data);
1416 		pglPixelStorei(GL_UNPACK_ALIGNMENT, 1);
1417 		for(i = 0; i < height/2; i++)
1418 		{
1419 			memcpy(row, top, dst_stride);
1420 			memcpy(top, bottom, dst_stride);
1421 			memcpy(bottom, row, dst_stride);
1422 			top += dst_stride;
1423 			bottom -= dst_stride;
1424 		}
1425 		free(row);
1426 	}
1427 	else
1428 	{
1429 		INT32 j;
1430 		GLubyte *image = malloc(width*height*3*sizeof (*image));
1431 		if (!image) return;
1432 		pglPixelStorei(GL_PACK_ALIGNMENT, 1);
1433 		pglReadPixels(x, y, width, height, GL_RGB, GL_UNSIGNED_BYTE, image);
1434 		pglPixelStorei(GL_UNPACK_ALIGNMENT, 1);
1435 		for (i = height-1; i >= 0; i--)
1436 		{
1437 			for (j = 0; j < width; j++)
1438 			{
1439 				dst_data[(height-1-i)*width+j] =
1440 				(UINT16)(
1441 				                 ((image[(i*width+j)*3]>>3)<<11) |
1442 				                 ((image[(i*width+j)*3+1]>>2)<<5) |
1443 				                 ((image[(i*width+j)*3+2]>>3)));
1444 			}
1445 		}
1446 		free(image);
1447 	}
1448 }
1449 
1450 
1451 // -----------------+
1452 // GClipRect        : Defines the 2D hardware clipping window
1453 // -----------------+
HWRAPI(GClipRect)1454 EXPORT void HWRAPI(GClipRect) (INT32 minx, INT32 miny, INT32 maxx, INT32 maxy, float nearclip)
1455 {
1456 	// GL_DBG_Printf ("GClipRect(%d, %d, %d, %d)\n", minx, miny, maxx, maxy);
1457 
1458 	pglViewport(minx, screen_height-maxy, maxx-minx, maxy-miny);
1459 	NEAR_CLIPPING_PLANE = nearclip;
1460 
1461 	//pglScissor(minx, screen_height-maxy, maxx-minx, maxy-miny);
1462 	pglMatrixMode(GL_PROJECTION);
1463 	pglLoadIdentity();
1464 	GLPerspective(fov, ASPECT_RATIO);
1465 	pglMatrixMode(GL_MODELVIEW);
1466 
1467 	// added for new coronas' code (without depth buffer)
1468 	pglGetIntegerv(GL_VIEWPORT, viewport);
1469 	pglGetFloatv(GL_PROJECTION_MATRIX, projMatrix);
1470 }
1471 
1472 
1473 // -----------------+
1474 // ClearBuffer      : Clear the color/alpha/depth buffer(s)
1475 // -----------------+
HWRAPI(ClearBuffer)1476 EXPORT void HWRAPI(ClearBuffer) (FBOOLEAN ColorMask,
1477                                     FBOOLEAN DepthMask,
1478                                     FRGBAFloat * ClearColor)
1479 {
1480 	// GL_DBG_Printf ("ClearBuffer(%d)\n", alpha);
1481 	GLbitfield ClearMask = 0;
1482 
1483 	if (ColorMask)
1484 	{
1485 		if (ClearColor)
1486 			pglClearColor(ClearColor->red,
1487 			              ClearColor->green,
1488 			              ClearColor->blue,
1489 			              ClearColor->alpha);
1490 		ClearMask |= GL_COLOR_BUFFER_BIT;
1491 	}
1492 	if (DepthMask)
1493 	{
1494 		pglClearDepth(1.0f);     //Hurdler: all that are permanen states
1495 		pglDepthRange(0.0f, 1.0f);
1496 		pglDepthFunc(GL_LEQUAL);
1497 		ClearMask |= GL_DEPTH_BUFFER_BIT;
1498 	}
1499 
1500 	SetBlend(DepthMask ? PF_Occlude | CurrentPolyFlags : CurrentPolyFlags&~PF_Occlude);
1501 
1502 	pglClear(ClearMask);
1503 	pglEnableClientState(GL_VERTEX_ARRAY); // We always use this one
1504 	pglEnableClientState(GL_TEXTURE_COORD_ARRAY); // And mostly this one, too
1505 }
1506 
1507 
1508 // -----------------+
1509 // HWRAPI Draw2DLine: Render a 2D line
1510 // -----------------+
HWRAPI(Draw2DLine)1511 EXPORT void HWRAPI(Draw2DLine) (F2DCoord * v1,
1512                                    F2DCoord * v2,
1513                                    RGBA_t Color)
1514 {
1515 	// GL_DBG_Printf ("DrawLine() (%f %f %f) %d\n", v1->x, -v1->y, -v1->z, v1->argb);
1516 	GLfloat p[12];
1517 	GLfloat dx, dy;
1518 	GLfloat angle;
1519 
1520 	// BP: we should reflect the new state in our variable
1521 	//SetBlend(PF_Modulated|PF_NoTexture);
1522 
1523 	pglDisable(GL_TEXTURE_2D);
1524 
1525 	// This is the preferred, 'modern' way of rendering lines -- creating a polygon.
1526 	if (fabsf(v2->x - v1->x) > FLT_EPSILON)
1527 		angle = (float)atan((v2->y-v1->y)/(v2->x-v1->x));
1528 	else
1529 		angle = (float)N_PI_DEMI;
1530 	dx = (float)sin(angle) / (float)screen_width;
1531 	dy = (float)cos(angle) / (float)screen_height;
1532 
1533 	p[0] = v1->x - dx;  p[1] = -(v1->y + dy); p[2] = 1;
1534 	p[3] = v2->x - dx;  p[4] = -(v2->y + dy); p[5] = 1;
1535 	p[6] = v2->x + dx;  p[7] = -(v2->y - dy); p[8] = 1;
1536 	p[9] = v1->x + dx;  p[10] = -(v1->y - dy); p[11] = 1;
1537 
1538 	pglDisableClientState(GL_TEXTURE_COORD_ARRAY);
1539 	pglColor4ubv((GLubyte*)&Color.s);
1540 	pglVertexPointer(3, GL_FLOAT, 0, p);
1541 	pglDrawArrays(GL_TRIANGLE_FAN, 0, 4);
1542 
1543 	pglEnableClientState(GL_TEXTURE_COORD_ARRAY);
1544 	pglEnable(GL_TEXTURE_2D);
1545 }
1546 
1547 
1548 // -----------------+
1549 // SetBlend         : Set render mode
1550 // -----------------+
1551 // PF_Masked - we could use an ALPHA_TEST of GL_EQUAL, and alpha ref of 0,
1552 //             is it faster when pixels are discarded ?
1553 
Clamp2D(GLenum pname)1554 static void Clamp2D(GLenum pname)
1555 {
1556 	pglTexParameteri(GL_TEXTURE_2D, pname, GL_CLAMP); // fallback clamp
1557 	pglTexParameteri(GL_TEXTURE_2D, pname, GL_CLAMP_TO_EDGE);
1558 }
1559 
SetBlendEquation(GLenum mode)1560 static void SetBlendEquation(GLenum mode)
1561 {
1562 	if (pglBlendEquation)
1563 		pglBlendEquation(mode);
1564 }
1565 
SetBlendMode(FBITFIELD flags)1566 static void SetBlendMode(FBITFIELD flags)
1567 {
1568 	// Set blending function
1569 	switch (flags)
1570 	{
1571 		case PF_Translucent & PF_Blending:
1572 			pglBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // alpha = level of transparency
1573 			break;
1574 		case PF_Masked & PF_Blending:
1575 			// Hurdler: does that mean lighting is only made by alpha src?
1576 			// it sounds ok, but not for polygonsmooth
1577 			pglBlendFunc(GL_SRC_ALPHA, GL_ZERO);                // 0 alpha = holes in texture
1578 			break;
1579 		case PF_Additive & PF_Blending:
1580 		case PF_Subtractive & PF_Blending:
1581 		case PF_ReverseSubtract & PF_Blending:
1582 			pglBlendFunc(GL_SRC_ALPHA, GL_ONE); // src * alpha + dest
1583 			break;
1584 		case PF_Environment & PF_Blending:
1585 			pglBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
1586 			break;
1587 		case PF_Multiplicative & PF_Blending:
1588 			pglBlendFunc(GL_DST_COLOR, GL_ZERO);
1589 			break;
1590 		case PF_Fog & PF_Fog:
1591 			// Sryder: Fog
1592 			// multiplies input colour by input alpha, and destination colour by input colour, then adds them
1593 			pglBlendFunc(GL_SRC_ALPHA, GL_SRC_COLOR);
1594 			break;
1595 		default: // must be 0, otherwise it's an error
1596 			// No blending
1597 			pglBlendFunc(GL_ONE, GL_ZERO);   // the same as no blending
1598 			break;
1599 	}
1600 
1601 	// Set blending equation
1602 	switch (flags)
1603 	{
1604 		case PF_Subtractive & PF_Blending:
1605 			SetBlendEquation(GL_FUNC_SUBTRACT);
1606 			break;
1607 		case PF_ReverseSubtract & PF_Blending:
1608 			// good for shadow
1609 			// not really but what else ?
1610 			SetBlendEquation(GL_FUNC_REVERSE_SUBTRACT);
1611 			break;
1612 		default:
1613 			SetBlendEquation(GL_FUNC_ADD);
1614 			break;
1615 	}
1616 
1617 	// Alpha test
1618 	switch (flags)
1619 	{
1620 		case PF_Masked & PF_Blending:
1621 			pglAlphaFunc(GL_GREATER, 0.5f);
1622 			break;
1623 		case PF_Translucent & PF_Blending:
1624 		case PF_Additive & PF_Blending:
1625 		case PF_Subtractive & PF_Blending:
1626 		case PF_ReverseSubtract & PF_Blending:
1627 		case PF_Environment & PF_Blending:
1628 		case PF_Multiplicative & PF_Blending:
1629 			pglAlphaFunc(GL_NOTEQUAL, 0.0f);
1630 			break;
1631 		case PF_Fog & PF_Fog:
1632 			pglAlphaFunc(GL_ALWAYS, 0.0f); // Don't discard zero alpha fragments
1633 			break;
1634 		default:
1635 			pglAlphaFunc(GL_GREATER, 0.5f);
1636 			break;
1637 	}
1638 }
1639 
HWRAPI(SetBlend)1640 EXPORT void HWRAPI(SetBlend) (FBITFIELD PolyFlags)
1641 {
1642 	FBITFIELD Xor;
1643 	Xor = CurrentPolyFlags^PolyFlags;
1644 	if (Xor & (PF_Blending|PF_RemoveYWrap|PF_ForceWrapX|PF_ForceWrapY|PF_Occlude|PF_NoTexture|PF_Modulated|PF_NoDepthTest|PF_Decal|PF_Invisible))
1645 	{
1646 		if (Xor & PF_Blending) // if blending mode must be changed
1647 			SetBlendMode(PolyFlags & PF_Blending);
1648 
1649 		if (Xor & PF_NoAlphaTest)
1650 		{
1651 			if (PolyFlags & PF_NoAlphaTest)
1652 				pglDisable(GL_ALPHA_TEST);
1653 			else
1654 				pglEnable(GL_ALPHA_TEST);      // discard 0 alpha pixels (holes in texture)
1655 		}
1656 
1657 		if (Xor & PF_Decal)
1658 		{
1659 			if (PolyFlags & PF_Decal)
1660 				pglEnable(GL_POLYGON_OFFSET_FILL);
1661 			else
1662 				pglDisable(GL_POLYGON_OFFSET_FILL);
1663 		}
1664 
1665 		if (Xor & PF_NoDepthTest)
1666 		{
1667 			if (PolyFlags & PF_NoDepthTest)
1668 				pglDepthFunc(GL_ALWAYS); //pglDisable(GL_DEPTH_TEST);
1669 			else
1670 				pglDepthFunc(GL_LEQUAL); //pglEnable(GL_DEPTH_TEST);
1671 		}
1672 
1673 		if (Xor & PF_RemoveYWrap)
1674 		{
1675 			if (PolyFlags & PF_RemoveYWrap)
1676 				Clamp2D(GL_TEXTURE_WRAP_T);
1677 		}
1678 
1679 		if (Xor & PF_ForceWrapX)
1680 		{
1681 			if (PolyFlags & PF_ForceWrapX)
1682 				pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
1683 		}
1684 
1685 		if (Xor & PF_ForceWrapY)
1686 		{
1687 			if (PolyFlags & PF_ForceWrapY)
1688 				pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
1689 		}
1690 
1691 		if (Xor & PF_Modulated)
1692 		{
1693 #if defined (__unix__) || defined (UNIXCOMMON)
1694 			if (oglflags & GLF_NOTEXENV)
1695 			{
1696 				if (!(PolyFlags & PF_Modulated))
1697 					pglColor4ubv(white);
1698 			}
1699 			else
1700 #endif
1701 			if (PolyFlags & PF_Modulated)
1702 			{   // mix texture colour with Surface->PolyColor
1703 				pglTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
1704 			}
1705 			else
1706 			{   // colour from texture is unchanged before blending
1707 				pglTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
1708 			}
1709 		}
1710 
1711 		if (Xor & PF_Occlude) // depth test but (no) depth write
1712 		{
1713 			if (PolyFlags&PF_Occlude)
1714 			{
1715 				pglDepthMask(1);
1716 			}
1717 			else
1718 				pglDepthMask(0);
1719 		}
1720 		////Hurdler: not used if we don't define POLYSKY
1721 		if (Xor & PF_Invisible)
1722 		{
1723 			if (PolyFlags&PF_Invisible)
1724 				pglBlendFunc(GL_ZERO, GL_ONE);         // transparent blending
1725 			else
1726 			{   // big hack: (TODO: manage that better)
1727 				// we test only for PF_Masked because PF_Invisible is only used
1728 				// (for now) with it (yeah, that's crappy, sorry)
1729 				if ((PolyFlags&PF_Blending)==PF_Masked)
1730 					pglBlendFunc(GL_SRC_ALPHA, GL_ZERO);
1731 			}
1732 		}
1733 		if (PolyFlags & PF_NoTexture)
1734 		{
1735 			SetNoTexture();
1736 		}
1737 	}
1738 	CurrentPolyFlags = PolyFlags;
1739 }
1740 
1741 // -----------------+
1742 // UpdateTexture    : Updates the texture data.
1743 // -----------------+
HWRAPI(UpdateTexture)1744 EXPORT void HWRAPI(UpdateTexture) (GLMipmap_t *pTexInfo)
1745 {
1746 	// Download a mipmap
1747 	boolean updatemipmap = true;
1748 	static RGBA_t   tex[2048*2048];
1749 	const GLvoid   *ptex = tex;
1750 	INT32             w, h;
1751 	GLuint texnum = 0;
1752 
1753 	if (!pTexInfo->downloaded)
1754 	{
1755 		pglGenTextures(1, &texnum);
1756 		pTexInfo->downloaded = texnum;
1757 		updatemipmap = false;
1758 	}
1759 	else
1760 		texnum = pTexInfo->downloaded;
1761 
1762 	//GL_DBG_Printf ("DownloadMipmap %d %x\n",(INT32)texnum,pTexInfo->data);
1763 
1764 	w = pTexInfo->width;
1765 	h = pTexInfo->height;
1766 
1767 	if ((pTexInfo->format == GL_TEXFMT_P_8) ||
1768 		(pTexInfo->format == GL_TEXFMT_AP_88))
1769 	{
1770 		const GLubyte *pImgData = (const GLubyte *)pTexInfo->data;
1771 		INT32 i, j;
1772 
1773 		for (j = 0; j < h; j++)
1774 		{
1775 			for (i = 0; i < w; i++)
1776 			{
1777 				if ((*pImgData == HWR_PATCHES_CHROMAKEY_COLORINDEX) &&
1778 					(pTexInfo->flags & TF_CHROMAKEYED))
1779 				{
1780 					tex[w*j+i].s.red   = 0;
1781 					tex[w*j+i].s.green = 0;
1782 					tex[w*j+i].s.blue  = 0;
1783 					tex[w*j+i].s.alpha = 0;
1784 					pTexInfo->flags |= TF_TRANSPARENT; // there is a hole in it
1785 				}
1786 				else
1787 				{
1788 					tex[w*j+i].s.red   = myPaletteData[*pImgData].s.red;
1789 					tex[w*j+i].s.green = myPaletteData[*pImgData].s.green;
1790 					tex[w*j+i].s.blue  = myPaletteData[*pImgData].s.blue;
1791 					tex[w*j+i].s.alpha = myPaletteData[*pImgData].s.alpha;
1792 				}
1793 
1794 				pImgData++;
1795 
1796 				if (pTexInfo->format == GL_TEXFMT_AP_88)
1797 				{
1798 					if (!(pTexInfo->flags & TF_CHROMAKEYED))
1799 						tex[w*j+i].s.alpha = *pImgData;
1800 					pImgData++;
1801 				}
1802 
1803 			}
1804 		}
1805 	}
1806 	else if (pTexInfo->format == GL_TEXFMT_RGBA)
1807 	{
1808 		// corona test : passed as ARGB 8888, which is not in glide formats
1809 		// Hurdler: not used for coronas anymore, just for dynamic lighting
1810 		ptex = pTexInfo->data;
1811 	}
1812 	else if (pTexInfo->format == GL_TEXFMT_ALPHA_INTENSITY_88)
1813 	{
1814 		const GLubyte *pImgData = (const GLubyte *)pTexInfo->data;
1815 		INT32 i, j;
1816 
1817 		for (j = 0; j < h; j++)
1818 		{
1819 			for (i = 0; i < w; i++)
1820 			{
1821 				tex[w*j+i].s.red   = *pImgData;
1822 				tex[w*j+i].s.green = *pImgData;
1823 				tex[w*j+i].s.blue  = *pImgData;
1824 				pImgData++;
1825 				tex[w*j+i].s.alpha = *pImgData;
1826 				pImgData++;
1827 			}
1828 		}
1829 	}
1830 	else if (pTexInfo->format == GL_TEXFMT_ALPHA_8) // Used for fade masks
1831 	{
1832 		const GLubyte *pImgData = (const GLubyte *)pTexInfo->data;
1833 		INT32 i, j;
1834 
1835 		for (j = 0; j < h; j++)
1836 		{
1837 			for (i = 0; i < w; i++)
1838 			{
1839 				tex[w*j+i].s.red   = 255; // 255 because the fade mask is modulated with the screen texture, so alpha affects it while the colours don't
1840 				tex[w*j+i].s.green = 255;
1841 				tex[w*j+i].s.blue  = 255;
1842 				tex[w*j+i].s.alpha = *pImgData;
1843 				pImgData++;
1844 			}
1845 		}
1846 	}
1847 	else
1848 		GL_MSG_Warning ("SetTexture(bad format) %ld\n", pTexInfo->format);
1849 
1850 	// the texture number was already generated by pglGenTextures
1851 	pglBindTexture(GL_TEXTURE_2D, texnum);
1852 	tex_downloaded = texnum;
1853 
1854 	// disable texture filtering on any texture that has holes so there's no dumb borders or blending issues
1855 	if (pTexInfo->flags & TF_TRANSPARENT)
1856 	{
1857 		pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1858 		pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1859 	}
1860 	else
1861 	{
1862 		pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, mag_filter);
1863 		pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, min_filter);
1864 	}
1865 
1866 	if (pTexInfo->format == GL_TEXFMT_ALPHA_INTENSITY_88)
1867 	{
1868 		//pglTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, ptex);
1869 		if (MipMap)
1870 		{
1871 			pgluBuild2DMipmaps(GL_TEXTURE_2D, GL_LUMINANCE_ALPHA, w, h, GL_RGBA, GL_UNSIGNED_BYTE, ptex);
1872 			pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_LOD, 0);
1873 			if (pTexInfo->flags & TF_TRANSPARENT)
1874 				pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LOD, 0); // No mippmaps on transparent stuff
1875 			else
1876 				pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LOD, 4);
1877 			//pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_LINEAR_MIPMAP_LINEAR);
1878 		}
1879 		else
1880 		{
1881 			if (updatemipmap)
1882 				pglTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, w, h, GL_RGBA, GL_UNSIGNED_BYTE, ptex);
1883 			else
1884 				pglTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE_ALPHA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, ptex);
1885 		}
1886 	}
1887 	else if (pTexInfo->format == GL_TEXFMT_ALPHA_8)
1888 	{
1889 		//pglTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, ptex);
1890 		if (MipMap)
1891 		{
1892 			pgluBuild2DMipmaps(GL_TEXTURE_2D, GL_ALPHA, w, h, GL_RGBA, GL_UNSIGNED_BYTE, ptex);
1893 			pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_LOD, 0);
1894 			if (pTexInfo->flags & TF_TRANSPARENT)
1895 				pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LOD, 0); // No mippmaps on transparent stuff
1896 			else
1897 				pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LOD, 4);
1898 			//pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_LINEAR_MIPMAP_LINEAR);
1899 		}
1900 		else
1901 		{
1902 			if (updatemipmap)
1903 				pglTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, w, h, GL_RGBA, GL_UNSIGNED_BYTE, ptex);
1904 			else
1905 				pglTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, ptex);
1906 		}
1907 	}
1908 	else
1909 	{
1910 		if (MipMap)
1911 		{
1912 			pgluBuild2DMipmaps(GL_TEXTURE_2D, textureformatGL, w, h, GL_RGBA, GL_UNSIGNED_BYTE, ptex);
1913 			// Control the mipmap level of detail
1914 			pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_LOD, 0); // the lower the number, the higer the detail
1915 			if (pTexInfo->flags & TF_TRANSPARENT)
1916 				pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LOD, 0); // No mippmaps on transparent stuff
1917 			else
1918 				pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LOD, 5);
1919 		}
1920 		else
1921 		{
1922 			if (updatemipmap)
1923 				pglTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, w, h, GL_RGBA, GL_UNSIGNED_BYTE, ptex);
1924 			else
1925 				pglTexImage2D(GL_TEXTURE_2D, 0, textureformatGL, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, ptex);
1926 		}
1927 	}
1928 
1929 	if (pTexInfo->flags & TF_WRAPX)
1930 		pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
1931 	else
1932 		Clamp2D(GL_TEXTURE_WRAP_S);
1933 
1934 	if (pTexInfo->flags & TF_WRAPY)
1935 		pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
1936 	else
1937 		Clamp2D(GL_TEXTURE_WRAP_T);
1938 
1939 	if (maximumAnisotropy)
1940 		pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, anisotropic_filter);
1941 }
1942 
1943 // -----------------+
1944 // SetTexture       : The mipmap becomes the current texture source
1945 // -----------------+
HWRAPI(SetTexture)1946 EXPORT void HWRAPI(SetTexture) (GLMipmap_t *pTexInfo)
1947 {
1948 	if (!pTexInfo)
1949 	{
1950 		SetNoTexture();
1951 		return;
1952 	}
1953 	else if (pTexInfo->downloaded)
1954 	{
1955 		if (pTexInfo->downloaded != tex_downloaded)
1956 		{
1957 			pglBindTexture(GL_TEXTURE_2D, pTexInfo->downloaded);
1958 			tex_downloaded = pTexInfo->downloaded;
1959 		}
1960 	}
1961 	else
1962 	{
1963 		FTextureInfo *newTex = calloc(1, sizeof (*newTex));
1964 
1965 		UpdateTexture(pTexInfo);
1966 
1967 		newTex->texture = pTexInfo;
1968 		newTex->downloaded = (UINT32)pTexInfo->downloaded;
1969 		newTex->width = (UINT32)pTexInfo->width;
1970 		newTex->height = (UINT32)pTexInfo->height;
1971 		newTex->format = (UINT32)pTexInfo->format;
1972 
1973 		// insertion at the tail
1974 		if (TexCacheTail)
1975 		{
1976 			newTex->prev = TexCacheTail;
1977 			TexCacheTail->next = newTex;
1978 			TexCacheTail = newTex;
1979 		}
1980 		else // initialization of the linked list
1981 			TexCacheTail = TexCacheHead = newTex;
1982 	}
1983 }
1984 
Shader_SetUniforms(FSurfaceInfo * Surface,GLRGBAFloat * poly,GLRGBAFloat * tint,GLRGBAFloat * fade)1985 static void Shader_SetUniforms(FSurfaceInfo *Surface, GLRGBAFloat *poly, GLRGBAFloat *tint, GLRGBAFloat *fade)
1986 {
1987 #ifdef GL_SHADERS
1988 	gl_shader_t *shader = gl_shaderstate.current;
1989 
1990 	if (gl_shadersenabled && (shader != NULL) && pglUseProgram)
1991 	{
1992 		if (!shader->program)
1993 		{
1994 			pglUseProgram(0);
1995 			return;
1996 		}
1997 
1998 		if (gl_shaderstate.changed)
1999 		{
2000 			pglUseProgram(shader->program);
2001 			gl_shaderstate.changed = false;
2002 		}
2003 
2004 		// Color uniforms can be left NULL and will be set to white (1.0f, 1.0f, 1.0f, 1.0f)
2005 		if (poly == NULL)
2006 			poly = &shader_defaultcolor;
2007 		if (tint == NULL)
2008 			tint = &shader_defaultcolor;
2009 		if (fade == NULL)
2010 			fade = &shader_defaultcolor;
2011 
2012 		#define UNIFORM_1(uniform, a, function) \
2013 			if (uniform != -1) \
2014 				function (uniform, a);
2015 
2016 		#define UNIFORM_2(uniform, a, b, function) \
2017 			if (uniform != -1) \
2018 				function (uniform, a, b);
2019 
2020 		#define UNIFORM_3(uniform, a, b, c, function) \
2021 			if (uniform != -1) \
2022 				function (uniform, a, b, c);
2023 
2024 		#define UNIFORM_4(uniform, a, b, c, d, function) \
2025 			if (uniform != -1) \
2026 				function (uniform, a, b, c, d);
2027 
2028 		// polygon
2029 		UNIFORM_4(shader->uniforms[gluniform_poly_color], poly->red, poly->green, poly->blue, poly->alpha, pglUniform4f);
2030 		UNIFORM_4(shader->uniforms[gluniform_tint_color], tint->red, tint->green, tint->blue, tint->alpha, pglUniform4f);
2031 		UNIFORM_4(shader->uniforms[gluniform_fade_color], fade->red, fade->green, fade->blue, fade->alpha, pglUniform4f);
2032 
2033 		if (Surface != NULL)
2034 		{
2035 			UNIFORM_1(shader->uniforms[gluniform_lighting], Surface->LightInfo.light_level, pglUniform1f);
2036 			UNIFORM_1(shader->uniforms[gluniform_fade_start], Surface->LightInfo.fade_start, pglUniform1f);
2037 			UNIFORM_1(shader->uniforms[gluniform_fade_end], Surface->LightInfo.fade_end, pglUniform1f);
2038 		}
2039 
2040 		UNIFORM_1(shader->uniforms[gluniform_leveltime], ((float)shader_leveltime) / TICRATE, pglUniform1f);
2041 
2042 		#undef UNIFORM_1
2043 		#undef UNIFORM_2
2044 		#undef UNIFORM_3
2045 		#undef UNIFORM_4
2046 	}
2047 #else
2048 	(void)Surface;
2049 	(void)poly;
2050 	(void)tint;
2051 	(void)fade;
2052 #endif
2053 }
2054 
Shader_CompileProgram(gl_shader_t * shader,GLint i,const GLchar * vert_shader,const GLchar * frag_shader)2055 static boolean Shader_CompileProgram(gl_shader_t *shader, GLint i, const GLchar *vert_shader, const GLchar *frag_shader)
2056 {
2057 	GLuint gl_vertShader, gl_fragShader;
2058 	GLint result;
2059 
2060 	//
2061 	// Load and compile vertex shader
2062 	//
2063 	gl_vertShader = pglCreateShader(GL_VERTEX_SHADER);
2064 	if (!gl_vertShader)
2065 	{
2066 		GL_MSG_Error("Shader_CompileProgram: Error creating vertex shader %s\n", HWR_GetShaderName(i));
2067 		return false;
2068 	}
2069 
2070 	pglShaderSource(gl_vertShader, 1, &vert_shader, NULL);
2071 	pglCompileShader(gl_vertShader);
2072 
2073 	// check for compile errors
2074 	pglGetShaderiv(gl_vertShader, GL_COMPILE_STATUS, &result);
2075 	if (result == GL_FALSE)
2076 	{
2077 		Shader_CompileError("Error compiling vertex shader", gl_vertShader, i);
2078 		pglDeleteShader(gl_vertShader);
2079 		return false;
2080 	}
2081 
2082 	//
2083 	// Load and compile fragment shader
2084 	//
2085 	gl_fragShader = pglCreateShader(GL_FRAGMENT_SHADER);
2086 	if (!gl_fragShader)
2087 	{
2088 		GL_MSG_Error("Shader_CompileProgram: Error creating fragment shader %s\n", HWR_GetShaderName(i));
2089 		pglDeleteShader(gl_vertShader);
2090 		pglDeleteShader(gl_fragShader);
2091 		return false;
2092 	}
2093 
2094 	pglShaderSource(gl_fragShader, 1, &frag_shader, NULL);
2095 	pglCompileShader(gl_fragShader);
2096 
2097 	// check for compile errors
2098 	pglGetShaderiv(gl_fragShader, GL_COMPILE_STATUS, &result);
2099 	if (result == GL_FALSE)
2100 	{
2101 		Shader_CompileError("Error compiling fragment shader", gl_fragShader, i);
2102 		pglDeleteShader(gl_vertShader);
2103 		pglDeleteShader(gl_fragShader);
2104 		return false;
2105 	}
2106 
2107 	shader->program = pglCreateProgram();
2108 	pglAttachShader(shader->program, gl_vertShader);
2109 	pglAttachShader(shader->program, gl_fragShader);
2110 	pglLinkProgram(shader->program);
2111 
2112 	// check link status
2113 	pglGetProgramiv(shader->program, GL_LINK_STATUS, &result);
2114 
2115 	// delete the shader objects
2116 	pglDeleteShader(gl_vertShader);
2117 	pglDeleteShader(gl_fragShader);
2118 
2119 	// couldn't link?
2120 	if (result != GL_TRUE)
2121 	{
2122 		GL_MSG_Error("Shader_CompileProgram: Error linking shader program %s\n", HWR_GetShaderName(i));
2123 		pglDeleteProgram(shader->program);
2124 		return false;
2125 	}
2126 
2127 	// 13062019
2128 #define GETUNI(uniform) pglGetUniformLocation(shader->program, uniform);
2129 
2130 	// lighting
2131 	shader->uniforms[gluniform_poly_color] = GETUNI("poly_color");
2132 	shader->uniforms[gluniform_tint_color] = GETUNI("tint_color");
2133 	shader->uniforms[gluniform_fade_color] = GETUNI("fade_color");
2134 	shader->uniforms[gluniform_lighting] = GETUNI("lighting");
2135 	shader->uniforms[gluniform_fade_start] = GETUNI("fade_start");
2136 	shader->uniforms[gluniform_fade_end] = GETUNI("fade_end");
2137 
2138 	// misc. (custom shaders)
2139 	shader->uniforms[gluniform_leveltime] = GETUNI("leveltime");
2140 
2141 #undef GETUNI
2142 
2143 	return true;
2144 }
2145 
Shader_CompileError(const char * message,GLuint program,INT32 shadernum)2146 static void Shader_CompileError(const char *message, GLuint program, INT32 shadernum)
2147 {
2148 	GLchar *infoLog = NULL;
2149 	GLint logLength;
2150 
2151 	pglGetShaderiv(program, GL_INFO_LOG_LENGTH, &logLength);
2152 
2153 	if (logLength)
2154 	{
2155 		infoLog = malloc(logLength);
2156 		pglGetShaderInfoLog(program, logLength, NULL, infoLog);
2157 	}
2158 
2159 	GL_MSG_Error("Shader_CompileProgram: %s (%s)\n%s", message, HWR_GetShaderName(shadernum), (infoLog ? infoLog : ""));
2160 
2161 	if (infoLog)
2162 		free(infoLog);
2163 }
2164 
2165 // code that is common between DrawPolygon and DrawIndexedTriangles
2166 // the corona thing is there too, i have no idea if that stuff works with DrawIndexedTriangles and batching
PreparePolygon(FSurfaceInfo * pSurf,FOutVector * pOutVerts,FBITFIELD PolyFlags)2167 static void PreparePolygon(FSurfaceInfo *pSurf, FOutVector *pOutVerts, FBITFIELD PolyFlags)
2168 {
2169 	static GLRGBAFloat poly = {0,0,0,0};
2170 	static GLRGBAFloat tint = {0,0,0,0};
2171 	static GLRGBAFloat fade = {0,0,0,0};
2172 
2173 	if ((PolyFlags & PF_Corona) && (oglflags & GLF_NOZBUFREAD))
2174 		PolyFlags &= ~(PF_NoDepthTest|PF_Corona);
2175 
2176 	SetBlend(PolyFlags);    //TODO: inline (#pragma..)
2177 
2178 	if (pSurf)
2179 	{
2180 		// If modulated, mix the surface colour to the texture
2181 		if (CurrentPolyFlags & PF_Modulated)
2182 			pglColor4ubv((GLubyte*)&pSurf->PolyColor.s);
2183 
2184 		// If the surface is either modulated or colormapped, or both
2185 		if (CurrentPolyFlags & (PF_Modulated | PF_ColorMapped))
2186 		{
2187 			poly.red   = byte2float[pSurf->PolyColor.s.red];
2188 			poly.green = byte2float[pSurf->PolyColor.s.green];
2189 			poly.blue  = byte2float[pSurf->PolyColor.s.blue];
2190 			poly.alpha = byte2float[pSurf->PolyColor.s.alpha];
2191 		}
2192 
2193 		// Only if the surface is colormapped
2194 		if (CurrentPolyFlags & PF_ColorMapped)
2195 		{
2196 			tint.red   = byte2float[pSurf->TintColor.s.red];
2197 			tint.green = byte2float[pSurf->TintColor.s.green];
2198 			tint.blue  = byte2float[pSurf->TintColor.s.blue];
2199 			tint.alpha = byte2float[pSurf->TintColor.s.alpha];
2200 
2201 			fade.red   = byte2float[pSurf->FadeColor.s.red];
2202 			fade.green = byte2float[pSurf->FadeColor.s.green];
2203 			fade.blue  = byte2float[pSurf->FadeColor.s.blue];
2204 			fade.alpha = byte2float[pSurf->FadeColor.s.alpha];
2205 		}
2206 	}
2207 
2208 	// this test is added for new coronas' code (without depth buffer)
2209 	// I think I should do a separate function for drawing coronas, so it will be a little faster
2210 	if (PolyFlags & PF_Corona) // check to see if we need to draw the corona
2211 	{
2212 		FUINT i;
2213 		FUINT j;
2214 
2215 		//rem: all 8 (or 8.0f) values are hard coded: it can be changed to a higher value
2216 		GLfloat     buf[8][8];
2217 		GLfloat    cx, cy, cz;
2218 		GLfloat    px = 0.0f, py = 0.0f, pz = -1.0f;
2219 		GLfloat     scalef = 0.0f;
2220 
2221 		GLubyte c[4];
2222 
2223 		float alpha;
2224 
2225 		cx = (pOutVerts[0].x + pOutVerts[2].x) / 2.0f; // we should change the coronas' ...
2226 		cy = (pOutVerts[0].y + pOutVerts[2].y) / 2.0f; // ... code so its only done once.
2227 		cz = pOutVerts[0].z;
2228 
2229 		// I dont know if this is slow or not
2230 		GLProject(cx, cy, cz, &px, &py, &pz);
2231 		//GL_DBG_Printf("Projection: (%f, %f, %f)\n", px, py, pz);
2232 
2233 		if ((pz <  0.0l) ||
2234 			(px < -8.0l) ||
2235 			(py < viewport[1]-8.0l) ||
2236 			(px > viewport[2]+8.0l) ||
2237 			(py > viewport[1]+viewport[3]+8.0l))
2238 			return;
2239 
2240 		// the damned slow glReadPixels functions :(
2241 		pglReadPixels((INT32)px-4, (INT32)py, 8, 8, GL_DEPTH_COMPONENT, GL_FLOAT, buf);
2242 		//GL_DBG_Printf("DepthBuffer: %f %f\n", buf[0][0], buf[3][3]);
2243 
2244 		for (i = 0; i < 8; i++)
2245 			for (j = 0; j < 8; j++)
2246 				scalef += (pz > buf[i][j]+0.00005f) ? 0 : 1;
2247 
2248 		// quick test for screen border (not 100% correct, but looks ok)
2249 		if (px < 4) scalef -= (GLfloat)(8*(4-px));
2250 		if (py < viewport[1]+4) scalef -= (GLfloat)(8*(viewport[1]+4-py));
2251 		if (px > viewport[2]-4) scalef -= (GLfloat)(8*(4-(viewport[2]-px)));
2252 		if (py > viewport[1]+viewport[3]-4) scalef -= (GLfloat)(8*(4-(viewport[1]+viewport[3]-py)));
2253 
2254 		scalef /= 64;
2255 		//GL_DBG_Printf("Scale factor: %f\n", scalef);
2256 
2257 		if (scalef < 0.05f)
2258 			return;
2259 
2260 		// GLubyte c[4];
2261 		c[0] = pSurf->PolyColor.s.red;
2262 		c[1] = pSurf->PolyColor.s.green;
2263 		c[2] = pSurf->PolyColor.s.blue;
2264 
2265 		alpha = byte2float[pSurf->PolyColor.s.alpha];
2266 		alpha *= scalef; // change the alpha value (it seems better than changing the size of the corona)
2267 		c[3] = (unsigned char)(alpha * 255);
2268 		pglColor4ubv(c);
2269 	}
2270 
2271 	Shader_SetUniforms(pSurf, &poly, &tint, &fade);
2272 }
2273 
2274 // -----------------+
2275 // DrawPolygon      : Render a polygon, set the texture, set render mode
2276 // -----------------+
HWRAPI(DrawPolygon)2277 EXPORT void HWRAPI(DrawPolygon) (FSurfaceInfo *pSurf, FOutVector *pOutVerts, FUINT iNumPts, FBITFIELD PolyFlags)
2278 {
2279 	PreparePolygon(pSurf, pOutVerts, PolyFlags);
2280 
2281 	pglVertexPointer(3, GL_FLOAT, sizeof(FOutVector), &pOutVerts[0].x);
2282 	pglTexCoordPointer(2, GL_FLOAT, sizeof(FOutVector), &pOutVerts[0].s);
2283 	pglDrawArrays(GL_TRIANGLE_FAN, 0, iNumPts);
2284 
2285 	if (PolyFlags & PF_RemoveYWrap)
2286 		pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
2287 
2288 	if (PolyFlags & PF_ForceWrapX)
2289 		Clamp2D(GL_TEXTURE_WRAP_S);
2290 
2291 	if (PolyFlags & PF_ForceWrapY)
2292 		Clamp2D(GL_TEXTURE_WRAP_T);
2293 }
2294 
HWRAPI(DrawIndexedTriangles)2295 EXPORT void HWRAPI(DrawIndexedTriangles) (FSurfaceInfo *pSurf, FOutVector *pOutVerts, FUINT iNumPts, FBITFIELD PolyFlags, UINT32 *IndexArray)
2296 {
2297 	PreparePolygon(pSurf, pOutVerts, PolyFlags);
2298 
2299 	pglVertexPointer(3, GL_FLOAT, sizeof(FOutVector), &pOutVerts[0].x);
2300 	pglTexCoordPointer(2, GL_FLOAT, sizeof(FOutVector), &pOutVerts[0].s);
2301 	pglDrawElements(GL_TRIANGLES, iNumPts, GL_UNSIGNED_INT, IndexArray);
2302 
2303 	// the DrawPolygon variant of this has some code about polyflags and wrapping here but havent noticed any problems from omitting it?
2304 }
2305 
2306 static const boolean gl_ext_arb_vertex_buffer_object = true;
2307 
2308 #define NULL_VBO_VERTEX ((gl_skyvertex_t*)NULL)
2309 #define sky_vbo_x (gl_ext_arb_vertex_buffer_object ? &NULL_VBO_VERTEX->x : &sky->data[0].x)
2310 #define sky_vbo_u (gl_ext_arb_vertex_buffer_object ? &NULL_VBO_VERTEX->u : &sky->data[0].u)
2311 #define sky_vbo_r (gl_ext_arb_vertex_buffer_object ? &NULL_VBO_VERTEX->r : &sky->data[0].r)
2312 
HWRAPI(RenderSkyDome)2313 EXPORT void HWRAPI(RenderSkyDome) (gl_sky_t *sky)
2314 {
2315 	int i, j;
2316 
2317 	Shader_SetUniforms(NULL, NULL, NULL, NULL);
2318 
2319 	// Build the sky dome! Yes!
2320 	if (sky->rebuild)
2321 	{
2322 		// delete VBO when already exists
2323 		if (gl_ext_arb_vertex_buffer_object)
2324 		{
2325 			if (sky->vbo)
2326 				pglDeleteBuffers(1, &sky->vbo);
2327 		}
2328 
2329 		if (gl_ext_arb_vertex_buffer_object)
2330 		{
2331 			// generate a new VBO and get the associated ID
2332 			pglGenBuffers(1, &sky->vbo);
2333 
2334 			// bind VBO in order to use
2335 			pglBindBuffer(GL_ARRAY_BUFFER, sky->vbo);
2336 
2337 			// upload data to VBO
2338 			pglBufferData(GL_ARRAY_BUFFER, sky->vertex_count * sizeof(sky->data[0]), sky->data, GL_STATIC_DRAW);
2339 		}
2340 
2341 		sky->rebuild = false;
2342 	}
2343 
2344 	// bind VBO in order to use
2345 	if (gl_ext_arb_vertex_buffer_object)
2346 		pglBindBuffer(GL_ARRAY_BUFFER, sky->vbo);
2347 
2348 	// activate and specify pointers to arrays
2349 	pglVertexPointer(3, GL_FLOAT, sizeof(sky->data[0]), sky_vbo_x);
2350 	pglTexCoordPointer(2, GL_FLOAT, sizeof(sky->data[0]), sky_vbo_u);
2351 	pglColorPointer(4, GL_UNSIGNED_BYTE, sizeof(sky->data[0]), sky_vbo_r);
2352 
2353 	// activate color arrays
2354 	pglEnableClientState(GL_COLOR_ARRAY);
2355 
2356 	// set transforms
2357 	pglScalef(1.0f, (float)sky->height / 200.0f, 1.0f);
2358 	pglRotatef(270.0f, 0.0f, 1.0f, 0.0f);
2359 
2360 	for (j = 0; j < 2; j++)
2361 	{
2362 		for (i = 0; i < sky->loopcount; i++)
2363 		{
2364 			gl_skyloopdef_t *loop = &sky->loops[i];
2365 			unsigned int mode = 0;
2366 
2367 			if (j == 0 ? loop->use_texture : !loop->use_texture)
2368 				continue;
2369 
2370 			switch (loop->mode)
2371 			{
2372 				case HWD_SKYLOOP_FAN:
2373 					mode = GL_TRIANGLE_FAN;
2374 					break;
2375 				case HWD_SKYLOOP_STRIP:
2376 					mode = GL_TRIANGLE_STRIP;
2377 					break;
2378 				default:
2379 					continue;
2380 			}
2381 
2382 			pglDrawArrays(mode, loop->vertexindex, loop->vertexcount);
2383 		}
2384 	}
2385 
2386 	pglScalef(1.0f, 1.0f, 1.0f);
2387 	pglColor4ubv(white);
2388 
2389 	// bind with 0, so, switch back to normal pointer operation
2390 	if (gl_ext_arb_vertex_buffer_object)
2391 		pglBindBuffer(GL_ARRAY_BUFFER, 0);
2392 
2393 	// deactivate color array
2394 	pglDisableClientState(GL_COLOR_ARRAY);
2395 }
2396 
2397 // ==========================================================================
2398 //
2399 // ==========================================================================
HWRAPI(SetSpecialState)2400 EXPORT void HWRAPI(SetSpecialState) (hwdspecialstate_t IdState, INT32 Value)
2401 {
2402 	switch (IdState)
2403 	{
2404 		case HWD_SET_MODEL_LIGHTING:
2405 			model_lighting = Value;
2406 			break;
2407 
2408 		case HWD_SET_SHADERS:
2409 			gl_allowshaders = (hwdshaderoption_t)Value;
2410 			break;
2411 
2412 		case HWD_SET_TEXTUREFILTERMODE:
2413 			switch (Value)
2414 			{
2415 				case HWD_SET_TEXTUREFILTER_TRILINEAR:
2416 					min_filter = GL_LINEAR_MIPMAP_LINEAR;
2417 					mag_filter = GL_LINEAR;
2418 					MipMap = GL_TRUE;
2419 					break;
2420 				case HWD_SET_TEXTUREFILTER_BILINEAR:
2421 					min_filter = mag_filter = GL_LINEAR;
2422 					MipMap = GL_FALSE;
2423 					break;
2424 				case HWD_SET_TEXTUREFILTER_POINTSAMPLED:
2425 					min_filter = mag_filter = GL_NEAREST;
2426 					MipMap = GL_FALSE;
2427 					break;
2428 				case HWD_SET_TEXTUREFILTER_MIXED1:
2429 					min_filter = GL_NEAREST;
2430 					mag_filter = GL_LINEAR;
2431 					MipMap = GL_FALSE;
2432 					break;
2433 				case HWD_SET_TEXTUREFILTER_MIXED2:
2434 					min_filter = GL_LINEAR;
2435 					mag_filter = GL_NEAREST;
2436 					MipMap = GL_FALSE;
2437 					break;
2438 				case HWD_SET_TEXTUREFILTER_MIXED3:
2439 					min_filter = GL_LINEAR_MIPMAP_LINEAR;
2440 					mag_filter = GL_NEAREST;
2441 					MipMap = GL_TRUE;
2442 					break;
2443 				default:
2444 					mag_filter = GL_LINEAR;
2445 					min_filter = GL_NEAREST;
2446 			}
2447 			if (!pgluBuild2DMipmaps)
2448 			{
2449 				MipMap = GL_FALSE;
2450 				min_filter = GL_LINEAR;
2451 			}
2452 			Flush(); //??? if we want to change filter mode by texture, remove this
2453 			break;
2454 
2455 		case HWD_SET_TEXTUREANISOTROPICMODE:
2456 			anisotropic_filter = min(Value,maximumAnisotropy);
2457 			if (maximumAnisotropy)
2458 				Flush(); //??? if we want to change filter mode by texture, remove this
2459 			break;
2460 
2461 		default:
2462 			break;
2463 	}
2464 }
2465 
2466 static float *vertBuffer = NULL;
2467 static float *normBuffer = NULL;
2468 static size_t lerpBufferSize = 0;
2469 static short *vertTinyBuffer = NULL;
2470 static char *normTinyBuffer = NULL;
2471 static size_t lerpTinyBufferSize = 0;
2472 
2473 // Static temporary buffer for doing frame interpolation
2474 // 'size' is the vertex size
AllocLerpBuffer(size_t size)2475 static void AllocLerpBuffer(size_t size)
2476 {
2477 	if (lerpBufferSize >= size)
2478 		return;
2479 
2480 	if (vertBuffer != NULL)
2481 		free(vertBuffer);
2482 
2483 	if (normBuffer != NULL)
2484 		free(normBuffer);
2485 
2486 	lerpBufferSize = size;
2487 	vertBuffer = malloc(lerpBufferSize);
2488 	normBuffer = malloc(lerpBufferSize);
2489 }
2490 
2491 // Static temporary buffer for doing frame interpolation
2492 // 'size' is the vertex size
AllocLerpTinyBuffer(size_t size)2493 static void AllocLerpTinyBuffer(size_t size)
2494 {
2495 	if (lerpTinyBufferSize >= size)
2496 		return;
2497 
2498 	if (vertTinyBuffer != NULL)
2499 		free(vertTinyBuffer);
2500 
2501 	if (normTinyBuffer != NULL)
2502 		free(normTinyBuffer);
2503 
2504 	lerpTinyBufferSize = size;
2505 	vertTinyBuffer = malloc(lerpTinyBufferSize);
2506 	normTinyBuffer = malloc(lerpTinyBufferSize / 2);
2507 }
2508 
2509 #ifndef GL_STATIC_DRAW
2510 #define GL_STATIC_DRAW 0x88E4
2511 #endif
2512 
2513 #ifndef GL_ARRAY_BUFFER
2514 #define GL_ARRAY_BUFFER 0x8892
2515 #endif
2516 
CreateModelVBO(mesh_t * mesh,mdlframe_t * frame)2517 static void CreateModelVBO(mesh_t *mesh, mdlframe_t *frame)
2518 {
2519 	int bufferSize = sizeof(vbo64_t)*mesh->numTriangles * 3;
2520 	vbo64_t *buffer = (vbo64_t*)malloc(bufferSize);
2521 	vbo64_t *bufPtr = buffer;
2522 
2523 	float *vertPtr = frame->vertices;
2524 	float *normPtr = frame->normals;
2525 	float *tanPtr = frame->tangents;
2526 	float *uvPtr = mesh->uvs;
2527 	float *lightPtr = mesh->lightuvs;
2528 	char *colorPtr = frame->colors;
2529 
2530 	int i;
2531 	for (i = 0; i < mesh->numTriangles * 3; i++)
2532 	{
2533 		bufPtr->x = *vertPtr++;
2534 		bufPtr->y = *vertPtr++;
2535 		bufPtr->z = *vertPtr++;
2536 
2537 		bufPtr->nx = *normPtr++;
2538 		bufPtr->ny = *normPtr++;
2539 		bufPtr->nz = *normPtr++;
2540 
2541 		bufPtr->s0 = *uvPtr++;
2542 		bufPtr->t0 = *uvPtr++;
2543 
2544 		if (tanPtr != NULL)
2545 		{
2546 			bufPtr->tan0 = *tanPtr++;
2547 			bufPtr->tan1 = *tanPtr++;
2548 			bufPtr->tan2 = *tanPtr++;
2549 		}
2550 
2551 		if (lightPtr != NULL)
2552 		{
2553 			bufPtr->s1 = *lightPtr++;
2554 			bufPtr->t1 = *lightPtr++;
2555 		}
2556 
2557 		if (colorPtr)
2558 		{
2559 			bufPtr->r = *colorPtr++;
2560 			bufPtr->g = *colorPtr++;
2561 			bufPtr->b = *colorPtr++;
2562 			bufPtr->a = *colorPtr++;
2563 		}
2564 		else
2565 		{
2566 			bufPtr->r = 255;
2567 			bufPtr->g = 255;
2568 			bufPtr->b = 255;
2569 			bufPtr->a = 255;
2570 		}
2571 
2572 		bufPtr++;
2573 	}
2574 
2575 	pglGenBuffers(1, &frame->vboID);
2576 	pglBindBuffer(GL_ARRAY_BUFFER, frame->vboID);
2577 	pglBufferData(GL_ARRAY_BUFFER, bufferSize, buffer, GL_STATIC_DRAW);
2578 	free(buffer);
2579 
2580 	// Don't leave the array buffer bound to the model,
2581 	// since this is called mid-frame
2582 	pglBindBuffer(GL_ARRAY_BUFFER, 0);
2583 }
2584 
CreateModelVBOTiny(mesh_t * mesh,tinyframe_t * frame)2585 static void CreateModelVBOTiny(mesh_t *mesh, tinyframe_t *frame)
2586 {
2587 	int bufferSize = sizeof(vbotiny_t)*mesh->numTriangles * 3;
2588 	vbotiny_t *buffer = (vbotiny_t*)malloc(bufferSize);
2589 	vbotiny_t *bufPtr = buffer;
2590 
2591 	short *vertPtr = frame->vertices;
2592 	char *normPtr = frame->normals;
2593 	float *uvPtr = mesh->uvs;
2594 	char *tanPtr = frame->tangents;
2595 
2596 	int i;
2597 	for (i = 0; i < mesh->numVertices; i++)
2598 	{
2599 		bufPtr->x = *vertPtr++;
2600 		bufPtr->y = *vertPtr++;
2601 		bufPtr->z = *vertPtr++;
2602 
2603 		bufPtr->nx = *normPtr++;
2604 		bufPtr->ny = *normPtr++;
2605 		bufPtr->nz = *normPtr++;
2606 
2607 		bufPtr->s0 = *uvPtr++;
2608 		bufPtr->t0 = *uvPtr++;
2609 
2610 		if (tanPtr)
2611 		{
2612 			bufPtr->tanx = *tanPtr++;
2613 			bufPtr->tany = *tanPtr++;
2614 			bufPtr->tanz = *tanPtr++;
2615 		}
2616 
2617 		bufPtr++;
2618 	}
2619 
2620 	pglGenBuffers(1, &frame->vboID);
2621 	pglBindBuffer(GL_ARRAY_BUFFER, frame->vboID);
2622 	pglBufferData(GL_ARRAY_BUFFER, bufferSize, buffer, GL_STATIC_DRAW);
2623 	free(buffer);
2624 
2625 	// Don't leave the array buffer bound to the model,
2626 	// since this is called mid-frame
2627 	pglBindBuffer(GL_ARRAY_BUFFER, 0);
2628 }
2629 
HWRAPI(CreateModelVBOs)2630 EXPORT void HWRAPI(CreateModelVBOs) (model_t *model)
2631 {
2632 	int i;
2633 	for (i = 0; i < model->numMeshes; i++)
2634 	{
2635 		mesh_t *mesh = &model->meshes[i];
2636 
2637 		if (mesh->frames)
2638 		{
2639 			int j;
2640 			for (j = 0; j < model->meshes[i].numFrames; j++)
2641 			{
2642 				mdlframe_t *frame = &mesh->frames[j];
2643 				if (frame->vboID)
2644 					pglDeleteBuffers(1, &frame->vboID);
2645 				frame->vboID = 0;
2646 				CreateModelVBO(mesh, frame);
2647 			}
2648 		}
2649 		else if (mesh->tinyframes)
2650 		{
2651 			int j;
2652 			for (j = 0; j < model->meshes[i].numFrames; j++)
2653 			{
2654 				tinyframe_t *frame = &mesh->tinyframes[j];
2655 				if (frame->vboID)
2656 					pglDeleteBuffers(1, &frame->vboID);
2657 				frame->vboID = 0;
2658 				CreateModelVBOTiny(mesh, frame);
2659 			}
2660 		}
2661 	}
2662 }
2663 
2664 #define BUFFER_OFFSET(i) ((void*)(i))
2665 
DrawModelEx(model_t * model,INT32 frameIndex,INT32 duration,INT32 tics,INT32 nextFrameIndex,FTransform * pos,float scale,UINT8 flipped,UINT8 hflipped,FSurfaceInfo * Surface)2666 static void DrawModelEx(model_t *model, INT32 frameIndex, INT32 duration, INT32 tics, INT32 nextFrameIndex, FTransform *pos, float scale, UINT8 flipped, UINT8 hflipped, FSurfaceInfo *Surface)
2667 {
2668 	static GLRGBAFloat poly = {0,0,0,0};
2669 	static GLRGBAFloat tint = {0,0,0,0};
2670 	static GLRGBAFloat fade = {0,0,0,0};
2671 
2672 	float pol = 0.0f;
2673 	float scalex, scaley, scalez;
2674 
2675 	boolean useTinyFrames;
2676 
2677 	boolean useVBO = true;
2678 
2679 	FBITFIELD flags;
2680 	int i;
2681 
2682 	// Because otherwise, scaling the screen negatively vertically breaks the lighting
2683 	GLfloat LightPos[] = {0.0f, 1.0f, 0.0f, 0.0f};
2684 #ifdef GL_LIGHT_MODEL_AMBIENT
2685 	GLfloat ambient[4];
2686 	GLfloat diffuse[4];
2687 #endif
2688 
2689 	// Affect input model scaling
2690 	scale *= 0.5f;
2691 	scalex = scale;
2692 	scaley = scale;
2693 	scalez = scale;
2694 
2695 	if (duration != 0 && duration != -1 && tics != -1) // don't interpolate if instantaneous or infinite in length
2696 	{
2697 		UINT32 newtime = (duration - tics); // + 1;
2698 
2699 		pol = (newtime)/(float)duration;
2700 
2701 		if (pol > 1.0f)
2702 			pol = 1.0f;
2703 
2704 		if (pol < 0.0f)
2705 			pol = 0.0f;
2706 	}
2707 
2708 	poly.red    = byte2float[Surface->PolyColor.s.red];
2709 	poly.green  = byte2float[Surface->PolyColor.s.green];
2710 	poly.blue   = byte2float[Surface->PolyColor.s.blue];
2711 	poly.alpha  = byte2float[Surface->PolyColor.s.alpha];
2712 
2713 #ifdef GL_LIGHT_MODEL_AMBIENT
2714 	if (model_lighting)
2715 	{
2716 		if (!gl_shadersenabled)
2717 		{
2718 			ambient[0] = poly.red;
2719 			ambient[1] = poly.green;
2720 			ambient[2] = poly.blue;
2721 			ambient[3] = poly.alpha;
2722 
2723 			diffuse[0] = poly.red;
2724 			diffuse[1] = poly.green;
2725 			diffuse[2] = poly.blue;
2726 			diffuse[3] = poly.alpha;
2727 
2728 			if (ambient[0] > 0.75f)
2729 				ambient[0] = 0.75f;
2730 			if (ambient[1] > 0.75f)
2731 				ambient[1] = 0.75f;
2732 			if (ambient[2] > 0.75f)
2733 				ambient[2] = 0.75f;
2734 
2735 			pglLightfv(GL_LIGHT0, GL_POSITION, LightPos);
2736 
2737 			pglEnable(GL_LIGHTING);
2738 			pglMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, ambient);
2739 			pglMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, diffuse);
2740 		}
2741 		pglShadeModel(GL_SMOOTH);
2742 	}
2743 #endif
2744 	else
2745 		pglColor4ubv((GLubyte*)&Surface->PolyColor.s);
2746 
2747 	tint.red   = byte2float[Surface->TintColor.s.red];
2748 	tint.green = byte2float[Surface->TintColor.s.green];
2749 	tint.blue  = byte2float[Surface->TintColor.s.blue];
2750 	tint.alpha = byte2float[Surface->TintColor.s.alpha];
2751 
2752 	fade.red   = byte2float[Surface->FadeColor.s.red];
2753 	fade.green = byte2float[Surface->FadeColor.s.green];
2754 	fade.blue  = byte2float[Surface->FadeColor.s.blue];
2755 	fade.alpha = byte2float[Surface->FadeColor.s.alpha];
2756 
2757 	flags = (Surface->PolyFlags | PF_Modulated);
2758 	if (Surface->PolyFlags & (PF_Additive|PF_Subtractive|PF_ReverseSubtract|PF_Multiplicative))
2759 		flags |= PF_Occlude;
2760 	else if (Surface->PolyColor.s.alpha == 0xFF)
2761 		flags |= (PF_Occlude | PF_Masked);
2762 
2763 	SetBlend(flags);
2764 	Shader_SetUniforms(Surface, &poly, &tint, &fade);
2765 
2766 	pglEnable(GL_CULL_FACE);
2767 	pglEnable(GL_NORMALIZE);
2768 
2769 #ifdef USE_FTRANSFORM_MIRROR
2770 	// flipped is if the object is vertically flipped
2771 	// hflipped is if the object is horizontally flipped
2772 	// pos->flip is if the screen is flipped vertically
2773 	// pos->mirror is if the screen is flipped horizontally
2774 	// XOR all the flips together to figure out what culling to use!
2775 	{
2776 		boolean reversecull = (flipped ^ hflipped ^ pos->flip ^ pos->mirror);
2777 		if (reversecull)
2778 			pglCullFace(GL_FRONT);
2779 		else
2780 			pglCullFace(GL_BACK);
2781 	}
2782 #else
2783 	// pos->flip is if the screen is flipped too
2784 	if (flipped ^ hflipped ^ pos->flip) // If one or three of these are active, but not two, invert the model's culling
2785 	{
2786 		pglCullFace(GL_FRONT);
2787 	}
2788 	else
2789 	{
2790 		pglCullFace(GL_BACK);
2791 	}
2792 #endif
2793 
2794 	pglPushMatrix(); // should be the same as glLoadIdentity
2795 	//Hurdler: now it seems to work
2796 	pglTranslatef(pos->x, pos->z, pos->y);
2797 	if (flipped)
2798 		scaley = -scaley;
2799 	if (hflipped)
2800 		scalez = -scalez;
2801 
2802 #ifdef USE_FTRANSFORM_ANGLEZ
2803 	pglRotatef(pos->anglez, 0.0f, 0.0f, -1.0f); // rotate by slope from Kart
2804 #endif
2805 	pglRotatef(pos->angley, 0.0f, -1.0f, 0.0f);
2806 	pglRotatef(pos->anglex, 1.0f, 0.0f, 0.0f);
2807 
2808 	if (pos->roll)
2809 	{
2810 		float roll = (1.0f * pos->rollflip);
2811 		pglTranslatef(pos->centerx, pos->centery, 0);
2812 		if (pos->rotaxis == 2) // Z
2813 			pglRotatef(pos->rollangle, 0.0f, 0.0f, roll);
2814 		else if (pos->rotaxis == 1) // Y
2815 			pglRotatef(pos->rollangle, 0.0f, roll, 0.0f);
2816 		else // X
2817 			pglRotatef(pos->rollangle, roll, 0.0f, 0.0f);
2818 		pglTranslatef(-pos->centerx, -pos->centery, 0);
2819 	}
2820 
2821 	pglScalef(scalex, scaley, scalez);
2822 
2823 	useTinyFrames = model->meshes[0].tinyframes != NULL;
2824 
2825 	if (useTinyFrames)
2826 		pglScalef(1 / 64.0f, 1 / 64.0f, 1 / 64.0f);
2827 
2828 	// Don't use the VBO if it does not have the correct texture coordinates.
2829 	// (Can happen when model uses a sprite as a texture and the sprite changes)
2830 	// Comparing floats with the != operator here should be okay because they
2831 	// are just copies of glpatches' max_s and max_t values.
2832 	// Instead of the != operator, memcmp is used to avoid a compiler warning.
2833 	if (memcmp(&(model->vbo_max_s), &(model->max_s), sizeof(model->max_s)) != 0 ||
2834 		memcmp(&(model->vbo_max_t), &(model->max_t), sizeof(model->max_t)) != 0)
2835 		useVBO = false;
2836 
2837 	pglEnableClientState(GL_NORMAL_ARRAY);
2838 
2839 	for (i = 0; i < model->numMeshes; i++)
2840 	{
2841 		mesh_t *mesh = &model->meshes[i];
2842 
2843 		if (useTinyFrames)
2844 		{
2845 			tinyframe_t *frame = &mesh->tinyframes[frameIndex % mesh->numFrames];
2846 			tinyframe_t *nextframe = NULL;
2847 
2848 			if (nextFrameIndex != -1)
2849 				nextframe = &mesh->tinyframes[nextFrameIndex % mesh->numFrames];
2850 
2851 			if (!nextframe || fpclassify(pol) == FP_ZERO)
2852 			{
2853 				if (useVBO)
2854 				{
2855 					pglBindBuffer(GL_ARRAY_BUFFER, frame->vboID);
2856 					pglVertexPointer(3, GL_SHORT, sizeof(vbotiny_t), BUFFER_OFFSET(0));
2857 					pglNormalPointer(GL_BYTE, sizeof(vbotiny_t), BUFFER_OFFSET(sizeof(short)*3));
2858 					pglTexCoordPointer(2, GL_FLOAT, sizeof(vbotiny_t), BUFFER_OFFSET(sizeof(short) * 3 + sizeof(char) * 6));
2859 
2860 					pglDrawElements(GL_TRIANGLES, mesh->numTriangles * 3, GL_UNSIGNED_SHORT, mesh->indices);
2861 					pglBindBuffer(GL_ARRAY_BUFFER, 0);
2862 				}
2863 				else
2864 				{
2865 					pglVertexPointer(3, GL_SHORT, 0, frame->vertices);
2866 					pglNormalPointer(GL_BYTE, 0, frame->normals);
2867 					pglTexCoordPointer(2, GL_FLOAT, 0, mesh->uvs);
2868 					pglDrawElements(GL_TRIANGLES, mesh->numTriangles * 3, GL_UNSIGNED_SHORT, mesh->indices);
2869 				}
2870 			}
2871 			else
2872 			{
2873 				short *vertPtr;
2874 				char *normPtr;
2875 				int j = 0;
2876 
2877 				// Dangit, I soooo want to do this in a GLSL shader...
2878 				AllocLerpTinyBuffer(mesh->numVertices * sizeof(short) * 3);
2879 				vertPtr = vertTinyBuffer;
2880 				normPtr = normTinyBuffer;
2881 
2882 				for (j = 0; j < mesh->numVertices * 3; j++)
2883 				{
2884 					// Interpolate
2885 					*vertPtr++ = (short)(frame->vertices[j] + (pol * (nextframe->vertices[j] - frame->vertices[j])));
2886 					*normPtr++ = (char)(frame->normals[j] + (pol * (nextframe->normals[j] - frame->normals[j])));
2887 				}
2888 
2889 				pglVertexPointer(3, GL_SHORT, 0, vertTinyBuffer);
2890 				pglNormalPointer(GL_BYTE, 0, normTinyBuffer);
2891 				pglTexCoordPointer(2, GL_FLOAT, 0, mesh->uvs);
2892 				pglDrawElements(GL_TRIANGLES, mesh->numTriangles * 3, GL_UNSIGNED_SHORT, mesh->indices);
2893 			}
2894 		}
2895 		else
2896 		{
2897 			mdlframe_t *frame = &mesh->frames[frameIndex % mesh->numFrames];
2898 			mdlframe_t *nextframe = NULL;
2899 
2900 			if (nextFrameIndex != -1)
2901 				nextframe = &mesh->frames[nextFrameIndex % mesh->numFrames];
2902 
2903 			if (!nextframe || fpclassify(pol) == FP_ZERO)
2904 			{
2905 				if (useVBO)
2906 				{
2907 					pglBindBuffer(GL_ARRAY_BUFFER, frame->vboID);
2908 					pglVertexPointer(3, GL_FLOAT, sizeof(vbo64_t), BUFFER_OFFSET(0));
2909 					pglNormalPointer(GL_FLOAT, sizeof(vbo64_t), BUFFER_OFFSET(sizeof(float) * 3));
2910 					pglTexCoordPointer(2, GL_FLOAT, sizeof(vbo64_t), BUFFER_OFFSET(sizeof(float) * 6));
2911 
2912 					pglDrawArrays(GL_TRIANGLES, 0, mesh->numTriangles * 3);
2913 					// No tinyframes, no mesh indices
2914 					//pglDrawElements(GL_TRIANGLES, mesh->numTriangles * 3, GL_UNSIGNED_SHORT, mesh->indices);
2915 					pglBindBuffer(GL_ARRAY_BUFFER, 0);
2916 				}
2917 				else
2918 				{
2919 					pglVertexPointer(3, GL_FLOAT, 0, frame->vertices);
2920 					pglNormalPointer(GL_FLOAT, 0, frame->normals);
2921 					pglTexCoordPointer(2, GL_FLOAT, 0, mesh->uvs);
2922 					pglDrawArrays(GL_TRIANGLES, 0, mesh->numTriangles * 3);
2923 				}
2924 			}
2925 			else
2926 			{
2927 				float *vertPtr;
2928 				float *normPtr;
2929 				int j = 0;
2930 
2931 				// Dangit, I soooo want to do this in a GLSL shader...
2932 				AllocLerpBuffer(mesh->numVertices * sizeof(float) * 3);
2933 				vertPtr = vertBuffer;
2934 				normPtr = normBuffer;
2935 				//int j = 0;
2936 
2937 				for (j = 0; j < mesh->numVertices * 3; j++)
2938 				{
2939 					// Interpolate
2940 					*vertPtr++ = frame->vertices[j] + (pol * (nextframe->vertices[j] - frame->vertices[j]));
2941 					*normPtr++ = frame->normals[j] + (pol * (nextframe->normals[j] - frame->normals[j]));
2942 				}
2943 
2944 				pglVertexPointer(3, GL_FLOAT, 0, vertBuffer);
2945 				pglNormalPointer(GL_FLOAT, 0, normBuffer);
2946 				pglTexCoordPointer(2, GL_FLOAT, 0, mesh->uvs);
2947 				pglDrawArrays(GL_TRIANGLES, 0, mesh->numVertices);
2948 			}
2949 		}
2950 	}
2951 
2952 	pglDisableClientState(GL_NORMAL_ARRAY);
2953 
2954 	pglPopMatrix(); // should be the same as glLoadIdentity
2955 	pglDisable(GL_CULL_FACE);
2956 	pglDisable(GL_NORMALIZE);
2957 
2958 #ifdef GL_LIGHT_MODEL_AMBIENT
2959 	if (model_lighting)
2960 	{
2961 		if (!gl_shadersenabled)
2962 			pglDisable(GL_LIGHTING);
2963 		pglShadeModel(GL_FLAT);
2964 	}
2965 #endif
2966 }
2967 
2968 // -----------------+
2969 // HWRAPI DrawModel : Draw a model
2970 // -----------------+
HWRAPI(DrawModel)2971 EXPORT void HWRAPI(DrawModel) (model_t *model, INT32 frameIndex, INT32 duration, INT32 tics, INT32 nextFrameIndex, FTransform *pos, float scale, UINT8 flipped, UINT8 hflipped, FSurfaceInfo *Surface)
2972 {
2973 	DrawModelEx(model, frameIndex, duration, tics, nextFrameIndex, pos, scale, flipped, hflipped, Surface);
2974 }
2975 
2976 // -----------------+
2977 // SetTransform     :
2978 // -----------------+
HWRAPI(SetTransform)2979 EXPORT void HWRAPI(SetTransform) (FTransform *stransform)
2980 {
2981 	static boolean special_splitscreen;
2982 	boolean shearing = false;
2983 	float used_fov;
2984 
2985 	pglLoadIdentity();
2986 
2987 	if (stransform)
2988 	{
2989 		used_fov = stransform->fovxangle;
2990 #ifdef USE_FTRANSFORM_MIRROR
2991 		// mirroring from Kart
2992 		if (stransform->mirror)
2993 			pglScalef(-stransform->scalex, stransform->scaley, -stransform->scalez);
2994 		else
2995 #endif
2996 		if (stransform->flip)
2997 			pglScalef(stransform->scalex, -stransform->scaley, -stransform->scalez);
2998 		else
2999 			pglScalef(stransform->scalex, stransform->scaley, -stransform->scalez);
3000 
3001 		if (stransform->roll)
3002 			pglRotatef(stransform->rollangle, 0.0f, 0.0f, 1.0f);
3003 		pglRotatef(stransform->anglex       , 1.0f, 0.0f, 0.0f);
3004 		pglRotatef(stransform->angley+270.0f, 0.0f, 1.0f, 0.0f);
3005 		pglTranslatef(-stransform->x, -stransform->z, -stransform->y);
3006 
3007 		special_splitscreen = stransform->splitscreen;
3008 		shearing = stransform->shearing;
3009 	}
3010 	else
3011 	{
3012 		used_fov = fov;
3013 		pglScalef(1.0f, 1.0f, -1.0f);
3014 	}
3015 
3016 	pglMatrixMode(GL_PROJECTION);
3017 	pglLoadIdentity();
3018 
3019 	// Simulate Software's y-shearing
3020 	// https://zdoom.org/wiki/Y-shearing
3021 	if (shearing)
3022 	{
3023 		float fdy = stransform->viewaiming * 2;
3024 		if (stransform->flip)
3025 			fdy *= -1.0f;
3026 		pglTranslatef(0.0f, -fdy/BASEVIDHEIGHT, 0.0f);
3027 	}
3028 
3029 	if (special_splitscreen)
3030 	{
3031 		used_fov = atan(tan(used_fov*M_PI/360)*0.8)*360/M_PI;
3032 		GLPerspective(used_fov, 2*ASPECT_RATIO);
3033 	}
3034 	else
3035 		GLPerspective(used_fov, ASPECT_RATIO);
3036 
3037 	pglGetFloatv(GL_PROJECTION_MATRIX, projMatrix); // added for new coronas' code (without depth buffer)
3038 	pglMatrixMode(GL_MODELVIEW);
3039 
3040 	pglGetFloatv(GL_MODELVIEW_MATRIX, modelMatrix); // added for new coronas' code (without depth buffer)
3041 
3042 }
3043 
HWRAPI(GetTextureUsed)3044 EXPORT INT32  HWRAPI(GetTextureUsed) (void)
3045 {
3046 	FTextureInfo *tmp = TexCacheHead;
3047 	INT32 res = 0;
3048 
3049 	while (tmp)
3050 	{
3051 		// Figure out the correct bytes-per-pixel for this texture
3052 		// I don't know which one the game actually _uses_ but this
3053 		// follows format2bpp in hw_cache.c
3054 		int bpp = 1;
3055 		int format = tmp->format;
3056 		if (format == GL_TEXFMT_RGBA)
3057 			bpp = 4;
3058 		else if (format == GL_TEXFMT_ALPHA_INTENSITY_88 || format == GL_TEXFMT_AP_88)
3059 			bpp = 2;
3060 
3061 		// Add it up!
3062 		res += tmp->height*tmp->width*bpp;
3063 		tmp = tmp->next;
3064 	}
3065 
3066 	return res;
3067 }
3068 
HWRAPI(PostImgRedraw)3069 EXPORT void HWRAPI(PostImgRedraw) (float points[SCREENVERTS][SCREENVERTS][2])
3070 {
3071 	INT32 x, y;
3072 	float float_x, float_y, float_nextx, float_nexty;
3073 	float xfix, yfix;
3074 	INT32 texsize = 2048;
3075 
3076 	const float blackBack[16] =
3077 	{
3078 		-16.0f, -16.0f, 6.0f,
3079 		-16.0f, 16.0f, 6.0f,
3080 		16.0f, 16.0f, 6.0f,
3081 		16.0f, -16.0f, 6.0f
3082 	};
3083 
3084 	// Use a power of two texture, dammit
3085 	if(screen_width <= 1024)
3086 		texsize = 1024;
3087 	if(screen_width <= 512)
3088 		texsize = 512;
3089 
3090 	// X/Y stretch fix for all resolutions(!)
3091 	xfix = (float)(texsize)/((float)((screen_width)/(float)(SCREENVERTS-1)));
3092 	yfix = (float)(texsize)/((float)((screen_height)/(float)(SCREENVERTS-1)));
3093 
3094 	pglDisable(GL_DEPTH_TEST);
3095 	pglDisable(GL_BLEND);
3096 
3097 	// const float blackBack[16]
3098 
3099 	// Draw a black square behind the screen texture,
3100 	// so nothing shows through the edges
3101 	pglColor4ubv(white);
3102 
3103 	pglVertexPointer(3, GL_FLOAT, 0, blackBack);
3104 	pglDrawArrays(GL_TRIANGLE_FAN, 0, 4);
3105 
3106 	pglEnableClientState(GL_TEXTURE_COORD_ARRAY);
3107 	for(x=0;x<SCREENVERTS-1;x++)
3108 	{
3109 		for(y=0;y<SCREENVERTS-1;y++)
3110 		{
3111 			float stCoords[8];
3112 			float vertCoords[12];
3113 
3114 			// Used for texture coordinates
3115 			// Annoying magic numbers to scale the square texture to
3116 			// a non-square screen..
3117 			float_x = (float)(x/(xfix));
3118 			float_y = (float)(y/(yfix));
3119 			float_nextx = (float)(x+1)/(xfix);
3120 			float_nexty = (float)(y+1)/(yfix);
3121 
3122 			// float stCoords[8];
3123 			stCoords[0] = float_x;
3124 			stCoords[1] = float_y;
3125 			stCoords[2] = float_x;
3126 			stCoords[3] = float_nexty;
3127 			stCoords[4] = float_nextx;
3128 			stCoords[5] = float_nexty;
3129 			stCoords[6] = float_nextx;
3130 			stCoords[7] = float_y;
3131 
3132 			pglTexCoordPointer(2, GL_FLOAT, 0, stCoords);
3133 
3134 			// float vertCoords[12];
3135 			vertCoords[0] = points[x][y][0];
3136 			vertCoords[1] = points[x][y][1];
3137 			vertCoords[2] = 4.4f;
3138 			vertCoords[3] = points[x][y + 1][0];
3139 			vertCoords[4] = points[x][y + 1][1];
3140 			vertCoords[5] = 4.4f;
3141 			vertCoords[6] = points[x + 1][y + 1][0];
3142 			vertCoords[7] = points[x + 1][y + 1][1];
3143 			vertCoords[8] = 4.4f;
3144 			vertCoords[9] = points[x + 1][y][0];
3145 			vertCoords[10] = points[x + 1][y][1];
3146 			vertCoords[11] = 4.4f;
3147 
3148 			pglVertexPointer(3, GL_FLOAT, 0, vertCoords);
3149 
3150 			pglDrawArrays(GL_TRIANGLE_FAN, 0, 4);
3151 		}
3152 	}
3153 
3154 	pglEnable(GL_DEPTH_TEST);
3155 	pglEnable(GL_BLEND);
3156 }
3157 
3158 // Sryder:	This needs to be called whenever the screen changes resolution in order to reset the screen textures to use
3159 //			a new size
HWRAPI(FlushScreenTextures)3160 EXPORT void HWRAPI(FlushScreenTextures) (void)
3161 {
3162 	pglDeleteTextures(1, &screentexture);
3163 	pglDeleteTextures(1, &startScreenWipe);
3164 	pglDeleteTextures(1, &endScreenWipe);
3165 	pglDeleteTextures(1, &finalScreenTexture);
3166 	screentexture = 0;
3167 	startScreenWipe = 0;
3168 	endScreenWipe = 0;
3169 	finalScreenTexture = 0;
3170 }
3171 
3172 // Create Screen to fade from
HWRAPI(StartScreenWipe)3173 EXPORT void HWRAPI(StartScreenWipe) (void)
3174 {
3175 	INT32 texsize = 2048;
3176 	boolean firstTime = (startScreenWipe == 0);
3177 
3178 	// Use a power of two texture, dammit
3179 	if(screen_width <= 512)
3180 		texsize = 512;
3181 	else if(screen_width <= 1024)
3182 		texsize = 1024;
3183 
3184 	// Create screen texture
3185 	if (firstTime)
3186 		pglGenTextures(1, &startScreenWipe);
3187 	pglBindTexture(GL_TEXTURE_2D, startScreenWipe);
3188 
3189 	if (firstTime)
3190 	{
3191 		pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3192 		pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3193 		Clamp2D(GL_TEXTURE_WRAP_S);
3194 		Clamp2D(GL_TEXTURE_WRAP_T);
3195 		pglCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 0, 0, texsize, texsize, 0);
3196 	}
3197 	else
3198 		pglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, texsize, texsize);
3199 
3200 	tex_downloaded = startScreenWipe;
3201 }
3202 
3203 // Create Screen to fade to
HWRAPI(EndScreenWipe)3204 EXPORT void HWRAPI(EndScreenWipe)(void)
3205 {
3206 	INT32 texsize = 2048;
3207 	boolean firstTime = (endScreenWipe == 0);
3208 
3209 	// Use a power of two texture, dammit
3210 	if(screen_width <= 512)
3211 		texsize = 512;
3212 	else if(screen_width <= 1024)
3213 		texsize = 1024;
3214 
3215 	// Create screen texture
3216 	if (firstTime)
3217 		pglGenTextures(1, &endScreenWipe);
3218 	pglBindTexture(GL_TEXTURE_2D, endScreenWipe);
3219 
3220 	if (firstTime)
3221 	{
3222 		pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3223 		pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3224 		Clamp2D(GL_TEXTURE_WRAP_S);
3225 		Clamp2D(GL_TEXTURE_WRAP_T);
3226 		pglCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 0, 0, texsize, texsize, 0);
3227 	}
3228 	else
3229 		pglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, texsize, texsize);
3230 
3231 	tex_downloaded = endScreenWipe;
3232 }
3233 
3234 
3235 // Draw the last scene under the intermission
HWRAPI(DrawIntermissionBG)3236 EXPORT void HWRAPI(DrawIntermissionBG)(void)
3237 {
3238 	float xfix, yfix;
3239 	INT32 texsize = 2048;
3240 
3241 	const float screenVerts[12] =
3242 	{
3243 		-1.0f, -1.0f, 1.0f,
3244 		-1.0f, 1.0f, 1.0f,
3245 		1.0f, 1.0f, 1.0f,
3246 		1.0f, -1.0f, 1.0f
3247 	};
3248 
3249 	float fix[8];
3250 
3251 	if(screen_width <= 1024)
3252 		texsize = 1024;
3253 	if(screen_width <= 512)
3254 		texsize = 512;
3255 
3256 	xfix = 1/((float)(texsize)/((float)((screen_width))));
3257 	yfix = 1/((float)(texsize)/((float)((screen_height))));
3258 
3259 	// const float screenVerts[12]
3260 
3261 	// float fix[8];
3262 	fix[0] = 0.0f;
3263 	fix[1] = 0.0f;
3264 	fix[2] = 0.0f;
3265 	fix[3] = yfix;
3266 	fix[4] = xfix;
3267 	fix[5] = yfix;
3268 	fix[6] = xfix;
3269 	fix[7] = 0.0f;
3270 
3271 	pglClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
3272 
3273 	pglBindTexture(GL_TEXTURE_2D, screentexture);
3274 	pglColor4ubv(white);
3275 
3276 	pglTexCoordPointer(2, GL_FLOAT, 0, fix);
3277 	pglVertexPointer(3, GL_FLOAT, 0, screenVerts);
3278 	pglDrawArrays(GL_TRIANGLE_FAN, 0, 4);
3279 
3280 	tex_downloaded = screentexture;
3281 }
3282 
3283 // Do screen fades!
HWRAPI(DoScreenWipe)3284 EXPORT void HWRAPI(DoScreenWipe)(void)
3285 {
3286 	INT32 texsize = 2048;
3287 	float xfix, yfix;
3288 
3289 	INT32 fademaskdownloaded = tex_downloaded; // the fade mask that has been set
3290 
3291 	const float screenVerts[12] =
3292 	{
3293 		-1.0f, -1.0f, 1.0f,
3294 		-1.0f, 1.0f, 1.0f,
3295 		1.0f, 1.0f, 1.0f,
3296 		1.0f, -1.0f, 1.0f
3297 	};
3298 
3299 	float fix[8];
3300 
3301 	const float defaultST[8] =
3302 	{
3303 		0.0f, 1.0f,
3304 		0.0f, 0.0f,
3305 		1.0f, 0.0f,
3306 		1.0f, 1.0f
3307 	};
3308 
3309 	// Use a power of two texture, dammit
3310 	if(screen_width <= 1024)
3311 		texsize = 1024;
3312 	if(screen_width <= 512)
3313 		texsize = 512;
3314 
3315 	xfix = 1/((float)(texsize)/((float)((screen_width))));
3316 	yfix = 1/((float)(texsize)/((float)((screen_height))));
3317 
3318 	// const float screenVerts[12]
3319 
3320 	// float fix[8];
3321 	fix[0] = 0.0f;
3322 	fix[1] = 0.0f;
3323 	fix[2] = 0.0f;
3324 	fix[3] = yfix;
3325 	fix[4] = xfix;
3326 	fix[5] = yfix;
3327 	fix[6] = xfix;
3328 	fix[7] = 0.0f;
3329 
3330 	pglClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
3331 
3332 	SetBlend(PF_Modulated|PF_NoDepthTest);
3333 	pglEnable(GL_TEXTURE_2D);
3334 
3335 	// Draw the original screen
3336 	pglBindTexture(GL_TEXTURE_2D, startScreenWipe);
3337 	pglColor4ubv(white);
3338 	pglTexCoordPointer(2, GL_FLOAT, 0, fix);
3339 	pglVertexPointer(3, GL_FLOAT, 0, screenVerts);
3340 	pglDrawArrays(GL_TRIANGLE_FAN, 0, 4);
3341 
3342 	SetBlend(PF_Modulated|PF_Translucent|PF_NoDepthTest);
3343 
3344 	// Draw the end screen that fades in
3345 	pglActiveTexture(GL_TEXTURE0);
3346 	pglEnable(GL_TEXTURE_2D);
3347 	pglBindTexture(GL_TEXTURE_2D, endScreenWipe);
3348 	pglTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
3349 
3350 	pglActiveTexture(GL_TEXTURE1);
3351 	pglEnable(GL_TEXTURE_2D);
3352 	pglBindTexture(GL_TEXTURE_2D, fademaskdownloaded);
3353 
3354 	pglTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
3355 
3356 	// const float defaultST[8]
3357 
3358 	pglClientActiveTexture(GL_TEXTURE0);
3359 	pglTexCoordPointer(2, GL_FLOAT, 0, fix);
3360 	pglVertexPointer(3, GL_FLOAT, 0, screenVerts);
3361 	pglClientActiveTexture(GL_TEXTURE1);
3362 	pglEnableClientState(GL_TEXTURE_COORD_ARRAY);
3363 	pglTexCoordPointer(2, GL_FLOAT, 0, defaultST);
3364 	pglDrawArrays(GL_TRIANGLE_FAN, 0, 4);
3365 
3366 	pglDisable(GL_TEXTURE_2D); // disable the texture in the 2nd texture unit
3367 	pglDisableClientState(GL_TEXTURE_COORD_ARRAY);
3368 
3369 	pglActiveTexture(GL_TEXTURE0);
3370 	pglClientActiveTexture(GL_TEXTURE0);
3371 	tex_downloaded = endScreenWipe;
3372 }
3373 
3374 // Create a texture from the screen.
HWRAPI(MakeScreenTexture)3375 EXPORT void HWRAPI(MakeScreenTexture) (void)
3376 {
3377 	INT32 texsize = 2048;
3378 	boolean firstTime = (screentexture == 0);
3379 
3380 	// Use a power of two texture, dammit
3381 	if(screen_width <= 512)
3382 		texsize = 512;
3383 	else if(screen_width <= 1024)
3384 		texsize = 1024;
3385 
3386 	// Create screen texture
3387 	if (firstTime)
3388 		pglGenTextures(1, &screentexture);
3389 	pglBindTexture(GL_TEXTURE_2D, screentexture);
3390 
3391 	if (firstTime)
3392 	{
3393 		pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3394 		pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3395 		Clamp2D(GL_TEXTURE_WRAP_S);
3396 		Clamp2D(GL_TEXTURE_WRAP_T);
3397 		pglCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 0, 0, texsize, texsize, 0);
3398 	}
3399 	else
3400 		pglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, texsize, texsize);
3401 
3402 	tex_downloaded = screentexture;
3403 }
3404 
HWRAPI(MakeScreenFinalTexture)3405 EXPORT void HWRAPI(MakeScreenFinalTexture) (void)
3406 {
3407 	INT32 texsize = 2048;
3408 	boolean firstTime = (finalScreenTexture == 0);
3409 
3410 	// Use a power of two texture, dammit
3411 	if(screen_width <= 512)
3412 		texsize = 512;
3413 	else if(screen_width <= 1024)
3414 		texsize = 1024;
3415 
3416 	// Create screen texture
3417 	if (firstTime)
3418 		pglGenTextures(1, &finalScreenTexture);
3419 	pglBindTexture(GL_TEXTURE_2D, finalScreenTexture);
3420 
3421 	if (firstTime)
3422 	{
3423 		pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3424 		pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3425 		Clamp2D(GL_TEXTURE_WRAP_S);
3426 		Clamp2D(GL_TEXTURE_WRAP_T);
3427 		pglCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 0, 0, texsize, texsize, 0);
3428 	}
3429 	else
3430 		pglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, texsize, texsize);
3431 
3432 	tex_downloaded = finalScreenTexture;
3433 }
3434 
HWRAPI(DrawScreenFinalTexture)3435 EXPORT void HWRAPI(DrawScreenFinalTexture)(int width, int height)
3436 {
3437 	float xfix, yfix;
3438 	float origaspect, newaspect;
3439 	float xoff = 1, yoff = 1; // xoffset and yoffset for the polygon to have black bars around the screen
3440 	FRGBAFloat clearColour;
3441 	INT32 texsize = 2048;
3442 
3443 	float off[12];
3444 	float fix[8];
3445 
3446 	if(screen_width <= 1024)
3447 		texsize = 1024;
3448 	if(screen_width <= 512)
3449 		texsize = 512;
3450 
3451 	xfix = 1/((float)(texsize)/((float)((screen_width))));
3452 	yfix = 1/((float)(texsize)/((float)((screen_height))));
3453 
3454 	origaspect = (float)screen_width / screen_height;
3455 	newaspect = (float)width / height;
3456 	if (origaspect < newaspect)
3457 	{
3458 		xoff = origaspect / newaspect;
3459 		yoff = 1;
3460 	}
3461 	else if (origaspect > newaspect)
3462 	{
3463 		xoff = 1;
3464 		yoff = newaspect / origaspect;
3465 	}
3466 
3467 	// float off[12];
3468 	off[0] = -xoff;
3469 	off[1] = -yoff;
3470 	off[2] = 1.0f;
3471 	off[3] = -xoff;
3472 	off[4] = yoff;
3473 	off[5] = 1.0f;
3474 	off[6] = xoff;
3475 	off[7] = yoff;
3476 	off[8] = 1.0f;
3477 	off[9] = xoff;
3478 	off[10] = -yoff;
3479 	off[11] = 1.0f;
3480 
3481 	// float fix[8];
3482 	fix[0] = 0.0f;
3483 	fix[1] = 0.0f;
3484 	fix[2] = 0.0f;
3485 	fix[3] = yfix;
3486 	fix[4] = xfix;
3487 	fix[5] = yfix;
3488 	fix[6] = xfix;
3489 	fix[7] = 0.0f;
3490 
3491 	pglViewport(0, 0, width, height);
3492 
3493 	clearColour.red = clearColour.green = clearColour.blue = 0;
3494 	clearColour.alpha = 1;
3495 	ClearBuffer(true, false, &clearColour);
3496 	pglBindTexture(GL_TEXTURE_2D, finalScreenTexture);
3497 
3498 	pglColor4ubv(white);
3499 
3500 	pglTexCoordPointer(2, GL_FLOAT, 0, fix);
3501 	pglVertexPointer(3, GL_FLOAT, 0, off);
3502 
3503 	pglDrawArrays(GL_TRIANGLE_FAN, 0, 4);
3504 	tex_downloaded = finalScreenTexture;
3505 }
3506 
3507 #endif //HWRENDER
3508