1 //----------------------------------------------------------------------------
2 // EDGE OpenGL Rendering (Main Stuff)
3 //----------------------------------------------------------------------------
4 //
5 // Copyright (c) 1999-2009 The EDGE Team.
6 //
7 // This program is free software; you can redistribute it and/or
8 // modify it under the terms of the GNU General Public License
9 // as published by the Free Software Foundation; either version 2
10 // of the License, or (at your option) any later version.
11 //
12 // This program is distributed in the hope that it will be useful,
13 // but WITHOUT ANY WARRANTY; without even the implied warranty of
14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 // GNU General Public License for more details.
16 //
17 //----------------------------------------------------------------------------
18
19 #include "i_defs.h"
20 #include "i_defs_gl.h"
21
22 #include "g_game.h"
23 #include "r_misc.h"
24 #include "r_gldefs.h"
25 #include "r_units.h"
26 #include "r_colormap.h"
27 #include "r_draw.h"
28 #include "r_modes.h"
29 #include "r_image.h"
30
31 #define DEBUG 0
32
33 // implementation limits
34
35 int glmax_lights;
36 int glmax_clip_planes;
37 int glmax_tex_size;
38 int glmax_tex_units;
39
40 cvar_c r_aspect;
41
42 cvar_c r_nearclip;
43 cvar_c r_farclip;
44
45
46 typedef enum
47 {
48 PFT_LIGHTING = (1 << 0),
49 PFT_COLOR_MAT = (1 << 1),
50 PFT_SKY = (1 << 2),
51 PFT_MULTI_TEX = (1 << 3),
52 }
53 problematic_feature_e;
54
55 typedef struct
56 {
57 // these are substrings that may be matched anywhere
58 const char *renderer;
59 const char *vendor;
60 const char *version;
61
62 // problematic features to force on or off (bitmasks)
63 int disable;
64 int enable;
65 }
66 driver_bug_t;
67
68 static const driver_bug_t driver_bugs[] =
69 {
70 { "Radeon", NULL, NULL, PFT_LIGHTING | PFT_COLOR_MAT, 0 },
71 { "RADEON", NULL, NULL, PFT_LIGHTING | PFT_COLOR_MAT, 0 },
72
73 // { "R200", NULL, "Mesa 6.4", PFT_VERTEX_ARRAY, 0 },
74 // { "R200", NULL, "Mesa 6.5", PFT_VERTEX_ARRAY, 0 },
75 // { "Intel", NULL, "Mesa 6.5", PFT_VERTEX_ARRAY, 0 },
76
77 { "TNT2", NULL, NULL, PFT_COLOR_MAT, 0 },
78
79 { "Velocity", NULL, NULL, PFT_COLOR_MAT | PFT_SKY, 0 },
80 { "Voodoo3", NULL, NULL, PFT_SKY | PFT_MULTI_TEX, 0 },
81 };
82
83 #define NUM_DRIVER_BUGS (sizeof(driver_bugs) / sizeof(driver_bug_t))
84
85
86
87 //
88 // RGL_SetupMatrices2D
89 //
90 // Setup the GL matrices for drawing 2D stuff.
91 //
RGL_SetupMatrices2D(void)92 void RGL_SetupMatrices2D(void)
93 {
94 glViewport(0, 0, SCREENWIDTH, SCREENHEIGHT);
95
96 glMatrixMode(GL_PROJECTION);
97 glLoadIdentity();
98 glOrtho(0.0f, (float)SCREENWIDTH,
99 0.0f, (float)SCREENHEIGHT, -1.0f, 1.0f);
100
101 glMatrixMode(GL_MODELVIEW);
102 glLoadIdentity();
103
104 // turn off lighting stuff
105 glDisable(GL_LIGHTING);
106 glDisable(GL_COLOR_MATERIAL);
107
108 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
109 }
110
111
112 //
113 // RGL_SetupMatrices3D
114 //
115 // Setup the GL matrices for drawing 3D stuff.
116 //
RGL_SetupMatrices3D(void)117 void RGL_SetupMatrices3D(void)
118 {
119 GLfloat ambient[4] = { 1.0f, 1.0f, 1.0f, 1.0f };
120
121 glViewport(viewwindow_x, viewwindow_y, viewwindow_w, viewwindow_h);
122
123 // calculate perspective matrix
124
125 glMatrixMode(GL_PROJECTION);
126
127 glLoadIdentity();
128
129 glFrustum(-view_x_slope * r_nearclip.f, view_x_slope * r_nearclip.f,
130 -view_y_slope * r_nearclip.f, view_y_slope * r_nearclip.f,
131 r_nearclip.f, r_farclip.f);
132
133 // calculate look-at matrix
134
135 glMatrixMode(GL_MODELVIEW);
136
137 glLoadIdentity();
138 glRotatef(270.0f - ANG_2_FLOAT(viewvertangle), 1.0f, 0.0f, 0.0f);
139 glRotatef(90.0f - ANG_2_FLOAT(viewangle), 0.0f, 0.0f, 1.0f);
140 glTranslatef(-viewx, -viewy, -viewz);
141
142 // turn on lighting. Some drivers (e.g. TNT2) don't work properly
143 // without it.
144 if (r_colorlighting.d)
145 {
146 glEnable(GL_LIGHTING);
147 glLightModelfv(GL_LIGHT_MODEL_AMBIENT, ambient);
148 }
149 else
150 glDisable(GL_LIGHTING);
151
152 if (r_colormaterial.d)
153 {
154 glEnable(GL_COLOR_MATERIAL);
155 glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE);
156 }
157 else
158 glDisable(GL_COLOR_MATERIAL);
159
160 /* glBlendFunc(GL_SRC_ALPHA, GL_ONE); // Additive lighting */
161 }
162
SafeStr(const void * s)163 static inline const char *SafeStr(const void *s)
164 {
165 return s ? (const char *)s : "";
166 }
167
168 //
169 // RGL_CheckExtensions
170 //
171 // Based on code by Bruce Lewis.
172 //
RGL_CheckExtensions(void)173 void RGL_CheckExtensions(void)
174 {
175 GLenum err = glewInit();
176
177 if (err != GLEW_OK)
178 I_Error("Unable to initialise GLEW: %s\n",
179 glewGetErrorString(err));
180
181 // -ACB- 2004/08/11 Made local: these are not yet used elsewhere
182 std::string glstr_version (SafeStr(glGetString(GL_VERSION)));
183 std::string glstr_renderer(SafeStr(glGetString(GL_RENDERER)));
184 std::string glstr_vendor (SafeStr(glGetString(GL_VENDOR)));
185
186 I_Printf("OpenGL: Version: %s\n", glstr_version.c_str());
187 I_Printf("OpenGL: Renderer: %s\n", glstr_renderer.c_str());
188 I_Printf("OpenGL: Vendor: %s\n", glstr_vendor.c_str());
189 I_Printf("OpenGL: GLEW version: %s\n", glewGetString(GLEW_VERSION));
190
191 #if 0 // FIXME: this crashes (buffer overflow?)
192 I_Printf("OpenGL: EXTENSIONS: %s\n", glGetString(GL_EXTENSIONS));
193 #endif
194
195 // Check for a windows software renderer
196 if (stricmp(glstr_vendor.c_str(), "Microsoft Corporation") == 0)
197 {
198 if (stricmp(glstr_renderer.c_str(), "GDI Generic") == 0)
199 {
200 I_Error("OpenGL: SOFTWARE Renderer!\n");
201 }
202 }
203
204 // Check for various extensions
205
206 if (GLEW_VERSION_1_3 || GLEW_ARB_multitexture)
207 { /* OK */ }
208 else
209 I_Error("OpenGL driver does not support Multitexturing.\n");
210
211 if (GLEW_VERSION_1_3 ||
212 GLEW_ARB_texture_env_combine ||
213 GLEW_EXT_texture_env_combine)
214 { /* OK */ }
215 else
216 {
217 I_Warning("OpenGL driver does not support COMBINE.\n");
218 r_dumbcombine = 1;
219 }
220
221 if (GLEW_VERSION_1_2 ||
222 GLEW_EXT_texture_edge_clamp ||
223 GLEW_SGIS_texture_edge_clamp)
224 { /* OK */ }
225 else
226 {
227 I_Warning("OpenGL driver does not support Edge-Clamp.\n");
228 r_dumbclamp = 1;
229 }
230
231
232 // --- Detect buggy drivers, enable workarounds ---
233
234 for (int j = 0; j < (int)NUM_DRIVER_BUGS; j++)
235 {
236 const driver_bug_t *bug = &driver_bugs[j];
237
238 if (bug->renderer && !strstr(glstr_renderer.c_str(), bug->renderer))
239 continue;
240
241 if (bug->vendor && !strstr(glstr_vendor.c_str(), bug->vendor))
242 continue;
243
244 if (bug->version && !strstr(glstr_version.c_str(), bug->version))
245 continue;
246
247 I_Printf("OpenGL: Enabling workarounds for %s.\n",
248 bug->renderer ? bug->renderer :
249 bug->vendor ? bug->vendor : "the Axis of Evil");
250
251 if (bug->disable & PFT_LIGHTING) r_colorlighting = 0;
252 if (bug->disable & PFT_COLOR_MAT) r_colormaterial = 0;
253 if (bug->disable & PFT_SKY) r_dumbsky = 1;
254 if (bug->disable & PFT_MULTI_TEX) r_dumbmulti = 1;
255
256 if (bug->enable & PFT_LIGHTING) r_colorlighting = 1;
257 if (bug->enable & PFT_COLOR_MAT) r_colormaterial = 1;
258 if (bug->enable & PFT_SKY) r_dumbsky = 0;
259 if (bug->enable & PFT_MULTI_TEX) r_dumbmulti = 0;
260 }
261 }
262
263 //
264 // RGL_SoftInit
265 //
266 // All the stuff that can be re-initialised multiple times.
267 //
RGL_SoftInit(void)268 void RGL_SoftInit(void)
269 {
270 glDisable(GL_FOG);
271 glDisable(GL_BLEND);
272 glDisable(GL_LIGHTING);
273 glDisable(GL_CULL_FACE);
274 glDisable(GL_DEPTH_TEST);
275 glDisable(GL_SCISSOR_TEST);
276 glDisable(GL_STENCIL_TEST);
277
278 glDisable(GL_LINE_SMOOTH);
279 glDisable(GL_POLYGON_SMOOTH);
280
281 if (var_dithering)
282 glEnable(GL_DITHER);
283 else
284 glDisable(GL_DITHER);
285
286 glEnable(GL_NORMALIZE);
287
288 glShadeModel(GL_SMOOTH);
289 glDepthFunc(GL_LEQUAL);
290 glAlphaFunc(GL_GREATER, 0);
291
292 glFrontFace(GL_CW);
293 glCullFace(GL_BACK);
294 glDisable(GL_CULL_FACE);
295
296 glHint(GL_FOG_HINT, GL_NICEST);
297 glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
298 }
299
300 //
301 // RGL_Init
302 //
RGL_Init(void)303 void RGL_Init(void)
304 {
305 I_Printf("OpenGL: Initialising...\n");
306
307 RGL_CheckExtensions();
308
309
310 // read implementation limits
311 {
312 GLint max_lights;
313 GLint max_clip_planes;
314 GLint max_tex_size;
315 GLint max_tex_units;
316
317 glGetIntegerv(GL_MAX_LIGHTS, &max_lights);
318 glGetIntegerv(GL_MAX_CLIP_PLANES, &max_clip_planes);
319 glGetIntegerv(GL_MAX_TEXTURE_SIZE, &max_tex_size);
320 glGetIntegerv(GL_MAX_TEXTURE_UNITS, &max_tex_units);
321
322 glmax_lights = max_lights;
323 glmax_clip_planes = max_clip_planes;
324 glmax_tex_size = max_tex_size;
325 glmax_tex_units = max_tex_units;
326 }
327
328 I_Printf("OpenGL: Lights: %d Clips: %d Tex: %d Units: %d\n",
329 glmax_lights, glmax_clip_planes, glmax_tex_size, glmax_tex_units);
330
331 RGL_SoftInit();
332
333 R2_InitUtil();
334
335 // initialise unit system
336 RGL_InitUnits();
337
338 RGL_SetupMatrices2D();
339 }
340
341
342 //--- editor settings ---
343 // vi:ts=4:sw=4:noexpandtab
344