1 /* Emacs style mode select -*- C++ -*-
2 *-----------------------------------------------------------------------------
3 *
4 *
5 * PrBoom: a Doom port merged with LxDoom and LSDLDoom
6 * based on BOOM, a modified and improved DOOM engine
7 * Copyright (C) 1999 by
8 * id Software, Chi Hoang, Lee Killough, Jim Flynn, Rand Phares, Ty Halderman
9 * Copyright (C) 1999-2000 by
10 * Jess Haas, Nicolas Kalkhof, Colin Phipps, Florian Schulze
11 * Copyright 2005, 2006 by
12 * Florian Schulze, Colin Phipps, Neil Stevens, Andrey Budko
13 *
14 * This program is free software; you can redistribute it and/or
15 * modify it under the terms of the GNU General Public License
16 * as published by the Free Software Foundation; either version 2
17 * of the License, or (at your option) any later version.
18 *
19 * This program is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU General Public License for more details.
23 *
24 * You should have received a copy of the GNU General Public License
25 * along with this program; if not, write to the Free Software
26 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
27 * 02111-1307, USA.
28 *
29 * DESCRIPTION:
30 *
31 *---------------------------------------------------------------------
32 */
33
34 #ifdef HAVE_CONFIG_H
35 #include "config.h"
36 #endif
37
38 #include <SDL.h>
39
40 #include <math.h>
41
42 #include "doomstat.h"
43 #include "lprintf.h"
44 #include "v_video.h"
45 #include "r_main.h"
46 #include "gl_intern.h"
47 #include "e6y.h"
48
49 gl_lightmode_t gl_lightmode;
50 const char *gl_lightmodes[] = {"glboom", "gzdoom", "fog based"};
51 int gl_light_ambient;
52 int gl_rellight;
53
54 int gl_fog;
55 int gl_use_fog;
56 int gl_fog_color;
57
58 int gl_fogenabled;
59 int gl_distfog = 70;
60 float gl_CurrentFogDensity = -1.0f;
61 float distfogtable[3][256];
62
63 typedef void (*gld_InitLightTable_f)(void);
64
65 typedef struct
66 {
67 int use_hwgamma;
68 int rellight;
69 gld_InitLightTable_f Init;
70 gld_CalcLightLevel_f GetLight;
71 gld_Calc2DLightLevel_f Get2DLight;
72 gld_CalcFogDensity_f GetFog;
73 } GLLight;
74
75 static float lighttable_glboom[5][256];
76 static float lighttable_gzdoom[256];
77 static float lighttable_fogbased[256];
78
79 gld_Calc2DLightLevel_f gld_Calc2DLightLevel;
80
81 static void gld_InitLightTable_glboom(void);
82 static void gld_InitLightTable_gzdoom(void);
83 static void gld_InitLightTable_fogbased(void);
84
85 static float gld_CalcLightLevel_glboom(int lightlevel);
86 static float gld_CalcLightLevel_gzdoom(int lightlevel);
87 static float gld_CalcLightLevel_fogbased(int lightlevel);
88
89 static float gld_CalcFogDensity_glboom(sector_t *sector, int lightlevel, GLDrawItemType type);
90 static float gld_CalcFogDensity_gzdoom(sector_t *sector, int lightlevel, GLDrawItemType type);
91 static float gld_CalcFogDensity_fogbased(sector_t *sector, int lightlevel, GLDrawItemType type);
92
93 static GLLight gld_light[gl_lightmode_last] = {
94 //gl_lightmode_glboom
95 {false, 16,
96 gld_InitLightTable_glboom,
97 gld_CalcLightLevel_glboom, gld_CalcLightLevel_glboom,
98 gld_CalcFogDensity_glboom},
99
100 //gl_lightmode_gzdoom
101 {true, 8,
102 gld_InitLightTable_gzdoom,
103 gld_CalcLightLevel_gzdoom, gld_CalcLightLevel_gzdoom,
104 gld_CalcFogDensity_gzdoom},
105
106 //gl_lightmode_fogbased
107 {true, 8,
108 gld_InitLightTable_fogbased,
109 gld_CalcLightLevel_fogbased, gld_CalcLightLevel_gzdoom,
110 gld_CalcFogDensity_fogbased},
111 };
112
113 int gl_hardware_gamma = false;
114 gld_CalcLightLevel_f gld_CalcLightLevel = gld_CalcLightLevel_glboom;
115 gld_CalcFogDensity_f gld_CalcFogDensity = gld_CalcFogDensity_glboom;
116
M_ChangeLightMode(void)117 void M_ChangeLightMode(void)
118 {
119 if (gl_compatibility && gl_lightmode == gl_lightmode_fogbased)
120 {
121
122 gl_lightmode = gl_lightmode_glboom;
123 lprintf(LO_INFO, "M_ChangeLightMode: \"Fog Based\" sector light mode is not allowed in gl_compatibility mode\n");
124 }
125
126 gl_hardware_gamma = gld_light[gl_lightmode].use_hwgamma;
127 gl_rellight = gld_light[gl_lightmode].rellight;
128 gld_CalcLightLevel = gld_light[gl_lightmode].GetLight;
129 gld_Calc2DLightLevel = gld_light[gl_lightmode].Get2DLight;
130 gld_CalcFogDensity = gld_light[gl_lightmode].GetFog;
131
132 if (gld_light[gl_lightmode].use_hwgamma)
133 {
134 gld_SetGammaRamp(useglgamma);
135 }
136 else
137 {
138 gld_SetGammaRamp(-1);
139 gld_FlushTextures();
140 }
141 }
142
gld_InitLightTable(void)143 void gld_InitLightTable(void)
144 {
145 int i;
146
147 for (i = 0; i < gl_lightmode_last; i++)
148 {
149 gld_light[i].Init();
150 }
151 }
152
153 /*
154 * lookuptable for lightvalues
155 * calculated as follow:
156 * floatlight=(1.0-exp((light^3)*gamma)) / (1.0-exp(1.0*gamma));
157 * gamma=-0,2;-2,0;-4,0;-6,0;-8,0
158 * light=0,0 .. 1,0
159 */
gld_InitLightTable_glboom(void)160 static void gld_InitLightTable_glboom(void)
161 {
162 int i, g;
163 float gamma[5] = {-0.2f, -2.0f, -4.0f, -6.0f, -8.0f};
164
165 for (g = 0; g < 5; g++)
166 {
167 for (i = 0; i < 256; i++)
168 {
169 lighttable_glboom[g][i] = (float)((1.0f - exp(pow(i / 255.0f, 3) * gamma[g])) / (1.0f - exp(1.0f * gamma[g])));
170 }
171 }
172 }
173
gld_InitLightTable_gzdoom(void)174 static void gld_InitLightTable_gzdoom(void)
175 {
176 int i;
177 float light;
178
179 for (i = 0; i < 256; i++)
180 {
181 if (i < 192)
182 light = (192.0f - (192 - i) * 1.95f);
183 else
184 light = (float)i;
185
186 if (light < gl_light_ambient)
187 light = (float)gl_light_ambient;
188
189 lighttable_gzdoom[i] = light / 255.0f;
190 }
191
192 lighttable_gzdoom[0] = 0.0f;
193 }
194
gld_InitLightTable_fogbased(void)195 static void gld_InitLightTable_fogbased(void)
196 {
197 int i;
198 float light;
199
200 for (i = 0; i < 256; i++)
201 {
202 if (i < 192)
203 light = (float)255;
204 else
205 light = (float)i;
206
207 lighttable_fogbased[i] = light / 255.0f;
208 }
209 }
210
gld_CalcLightLevel_glboom(int lightlevel)211 static float gld_CalcLightLevel_glboom(int lightlevel)
212 {
213 return lighttable_glboom[usegamma][BETWEEN(0, 255, lightlevel)];
214 }
215
gld_CalcLightLevel_gzdoom(int lightlevel)216 static float gld_CalcLightLevel_gzdoom(int lightlevel)
217 {
218 return lighttable_gzdoom[BETWEEN(0, 255, lightlevel)];
219 }
220
gld_CalcLightLevel_fogbased(int lightlevel)221 static float gld_CalcLightLevel_fogbased(int lightlevel)
222 {
223 if (players[displayplayer].fixedcolormap)
224 return lighttable_gzdoom[BETWEEN(0, 255, lightlevel)];
225 else
226 {
227 if (extralight)
228 return lighttable_fogbased[255];
229 else
230 return lighttable_fogbased[BETWEEN(0, 255, lightlevel)];
231 }
232 }
233
gld_StaticLightAlpha(float light,float alpha)234 void gld_StaticLightAlpha(float light, float alpha)
235 {
236 player_t *player;
237 player = &players[displayplayer];
238
239 if (!player->fixedcolormap)
240 {
241 glColor4f(light, light, light, alpha);
242 }
243 else
244 {
245 if (!(invul_method & INVUL_BW))
246 {
247 glColor4f(1.0f, 1.0f, 1.0f, alpha);
248 }
249 else
250 {
251 #ifdef USE_FBO_TECHNIQUE
252 if (SceneInTexture)
253 {
254 if (gl_invul_bw_method == 0)
255 glColor4f(0.5f, 0.5f, 0.5f, alpha);
256 else
257 glColor4f(1.0f, 1.0f, 1.0f, alpha);
258 }
259 else
260 #endif
261 {
262 glColor4f(bw_red, bw_green, bw_blue, alpha);
263 }
264 }
265 }
266 }
267
M_ChangeAllowFog(void)268 void M_ChangeAllowFog(void)
269 {
270 int i;
271 GLfloat FogColor[4] = { 0.0f, 0.0f, 0.0f, 0.0f };
272
273 FogColor[0] = ((float)((gl_fog_color >> 16) & 0xff)) / 255.0f;
274 FogColor[1] = ((float)((gl_fog_color >> 8) & 0xff)) / 255.0f;
275 FogColor[2] = ((float)((gl_fog_color >> 0) & 0xff)) / 255.0f;
276 FogColor[3] = 0.0f;
277
278 glFogi (GL_FOG_MODE, GL_EXP);
279 glFogfv(GL_FOG_COLOR, FogColor);
280 glHint (GL_FOG_HINT, GL_NICEST);
281
282 gl_CurrentFogDensity = -1;
283
284 gl_EnableFog(true);
285 gl_EnableFog(false);
286
287 for (i = 0; i < 256; i++)
288 {
289 if (i < 164)
290 {
291 distfogtable[0][i] = (float)((gl_distfog >> 1) + (gl_distfog) * (164 - i) / 164);
292 }
293 else if (i < 230)
294 {
295 distfogtable[0][i] = (float)((gl_distfog >> 1) - (gl_distfog >> 1) * (i - 164) / (230 - 164));
296 }
297 else
298 {
299 distfogtable[0][i] = 0.0f;
300 }
301
302 if (i < 128)
303 {
304 distfogtable[1][i] = 6.0f + (gl_distfog >> 1) + (gl_distfog) * (128 - i) / 48;
305 }
306 else if (i < 216)
307 {
308 distfogtable[1][i] = (216.0f - i) / ((216.0f - 128.0f)) * gl_distfog / 10;
309 }
310 else
311 {
312 distfogtable[1][i] = 0.0f;
313 }
314
315 if (i <= 128)
316 {
317 distfogtable[2][i] = (float)(1<<16) / (float)pow(1.46f, ((float)i / 8.0f));
318 if (distfogtable[2][i] > 2048)
319 distfogtable[2][i] = 2048;
320 }
321 else if (i < 192)
322 {
323 distfogtable[2][i] = (float)(1<<13) / (float)pow(1.30f, ((float)i / 8.0f));
324 }
325 else if (i < 216)
326 {
327 distfogtable[2][i] = (216.0f - i) / ((216.0f - 128.0f)) * gl_distfog / 10;
328 }
329 else
330 {
331 distfogtable[2][i] = 0.0f;
332 }
333 }
334 }
335
gld_CalcFogDensity_glboom(sector_t * sector,int lightlevel,GLDrawItemType type)336 static float gld_CalcFogDensity_glboom(sector_t *sector, int lightlevel, GLDrawItemType type)
337 {
338 return 0;
339 }
340
gld_CalcFogDensity_gzdoom(sector_t * sector,int lightlevel,GLDrawItemType type)341 static float gld_CalcFogDensity_gzdoom(sector_t *sector, int lightlevel, GLDrawItemType type)
342 {
343 if ((!gl_use_fog) ||
344 (sector && (sector->ceilingpic == skyflatnum || sector->floorpic == skyflatnum)))
345 {
346 return 0;
347 }
348 else
349 {
350 return distfogtable[1][BETWEEN(0, 255, lightlevel)];
351 }
352 }
353
gld_CalcFogDensity_fogbased(sector_t * sector,int lightlevel,GLDrawItemType type)354 static float gld_CalcFogDensity_fogbased(sector_t *sector, int lightlevel, GLDrawItemType type)
355 {
356 if (players[displayplayer].fixedcolormap)
357 {
358 return 0;
359 }
360 else
361 {
362 float fog = distfogtable[2][BETWEEN(0, 255, lightlevel)];
363
364 if (extralight)
365 {
366 if (extralight == 1)
367 fog -= fog / 3.0f;
368 else
369 fog -= fog / 2.0f;
370 }
371
372 if (type == GLDIT_CEILING || type == GLDIT_FLOOR || type == GLDIT_FWALL)
373 {
374 return fog * 2;
375 }
376 else
377 {
378 return fog;
379 }
380 }
381 }
382
gld_SetFog(float fogdensity)383 void gld_SetFog(float fogdensity)
384 {
385 if (fogdensity)
386 {
387 gl_EnableFog(true);
388 if (fogdensity != gl_CurrentFogDensity)
389 {
390 glFogf(GL_FOG_DENSITY, fogdensity / 512.0f);
391 gl_CurrentFogDensity = fogdensity;
392 }
393 }
394 else
395 {
396 gl_EnableFog(false);
397 gl_CurrentFogDensity = -1.0f;
398 }
399 }
400
gl_EnableFog(int on)401 void gl_EnableFog(int on)
402 {
403 if (on)
404 {
405 if (!gl_fogenabled)
406 glEnable(GL_FOG);
407 }
408 else
409 {
410 if (gl_fogenabled)
411 glDisable(GL_FOG);
412 }
413 gl_fogenabled=on;
414 }
415