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