1 /*
2 * Copyright (C) 1997-2001 Id Software, Inc.
3 *
4 * This program is free software; you can redistribute it and/or modify it under
5 * the terms of the GNU General Public License as published by the Free
6 * Software Foundation; either version 2 of the License, or (at your option)
7 * any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE.
12 *
13 * See the GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License along with
16 * this program; if not, write to the Free Software Foundation, Inc., 59
17 * Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18 */
19
20 #include "gl_local.h"
21
22 int r_numflares;
23 flare_t *r_flares[MAX_FLARES];
24
25 void
R_RenderFlares(void)26 R_RenderFlares(void)
27 {
28 int i;
29
30 if (gl_flares->value == 0)
31 return;
32
33 qglDepthMask(0);
34 qglDisable(GL_TEXTURE_2D);
35 qglShadeModel(GL_SMOOTH);
36 qglEnable(GL_BLEND);
37
38 /* Fog bug fix by Kirk Barnes. */
39 qglBlendFunc(GL_SRC_ALPHA, GL_ONE);
40
41 for (i = 0; i < r_numflares; i++)
42 if (ri.CL_IsVisible(r_origin, r_flares[i]->origin))
43 R_RenderFlare(r_flares[i]);
44
45 qglColor3f(1, 1, 1);
46 qglDisable(GL_BLEND);
47 qglEnable(GL_TEXTURE_2D);
48 qglBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
49 qglDepthMask(1);
50 }
51
52 void
R_RenderFlare(flare_t * light)53 R_RenderFlare(flare_t *light)
54 {
55 char pathname[MAX_QPATH]; /* Flare image path. */
56 int size; /* Flare size. */
57 int style; /* Flare style. */
58 float dist; /* Distance to flare. */
59 image_t *flare; /* Flare image. */
60 vec3_t color; /* Flare color. */
61 vec3_t vec; /* Vector distance to flare. */
62 vec3_t point; /* For flare coordinates. */
63
64 /* Check for flare style override. */
65 if (gl_flare_force_style->value > 0 &&
66 gl_flare_force_style->value <= FLARE_STYLES)
67 style = gl_flare_force_style->value;
68 else
69 style = light->style;
70
71 /* Check if style is valid. */
72 if (style > 0 && style <= FLARE_STYLES)
73 Com_sprintf(pathname, sizeof(pathname),
74 "gfx/flare%d.png", style);
75 else
76 ri.Sys_Error(ERR_DROP,
77 "R_RenderFlare: invalid flare style: %d", style);
78
79 flare = GL_FindImage(pathname, it_sprite);
80
81 if (flare == NULL)
82 flare = r_notexture;
83
84 /* Check for flare size override. */
85 if (gl_flare_force_size->value != 0)
86 size = gl_flare_force_size->value;
87 else
88 size = light->size * gl_flare_scale->value;
89
90 /* Adjust flare intensity. */
91 VectorScale(light->color, gl_flare_intensity->value, color);
92
93 /* Calculate size based on distance. */
94 VectorSubtract(light->origin, r_origin, vec);
95 dist = VectorLength(vec) * (size * 0.01);
96
97 /* Limit flare size. */
98 if (gl_flare_maxdist->value != 0)
99 if (dist > gl_flare_maxdist->value)
100 dist = gl_flare_maxdist->value;
101
102 qglDisable(GL_DEPTH_TEST);
103 qglEnable(GL_TEXTURE_2D);
104 qglColor4f(color[0] / 2, color[1] / 2, color[2] / 2, 1);
105 GL_Bind(flare->texnum);
106
107 GL_TexEnv(GL_MODULATE);
108
109 qglBegin(GL_QUADS);
110
111 #if 0
112 /* Shorter, but expensive (needs more calculations). */
113 for (i = 0; i < 2; i++)
114 for (i ? (j = 0) : (j = 1);
115 i ? (j < 2) : (j >= 0);
116 i ? (j++) : (j--)) {
117 qglTexCoord2f(i, j);
118 VectorMA(light->origin, i ? (1 + dist) : (-1 - dist),
119 vup, point);
120 VectorMA(point, j ? (1 + dist) : (-1 - dist),
121 vright, point);
122 qglVertex3fv(point);
123 }
124 #endif
125
126 qglTexCoord2f(0, 1);
127 VectorMA(light->origin, -1-dist, vup, point);
128 VectorMA(point, 1+dist, vright, point);
129 qglVertex3fv(point);
130
131 qglTexCoord2f(0, 0);
132 VectorMA(light->origin, -1-dist, vup, point);
133 VectorMA(point, -1-dist, vright, point);
134 qglVertex3fv (point);
135
136 qglTexCoord2f(1, 0);
137 VectorMA(light->origin, 1+dist, vup, point);
138 VectorMA(point, -1-dist, vright, point);
139 qglVertex3fv(point);
140
141 qglTexCoord2f(1, 1);
142 VectorMA(light->origin, 1+dist, vup, point);
143 VectorMA(point, 1+dist, vright, point);
144 qglVertex3fv(point);
145
146 qglEnd();
147
148 GL_TexEnv(GL_REPLACE);
149 qglEnable(GL_DEPTH_TEST);
150 qglDisable(GL_TEXTURE_2D);
151 qglColor3f(0, 0, 0);
152 }
153
154 void
GL_AddFlareSurface(msurface_t * surf)155 GL_AddFlareSurface(msurface_t * surf)
156 {
157 int intens; /* Light intensity. */
158 flare_t *light; /* New flare. */
159 vec3_t origin; /* Center of surface. */
160 vec3_t color; /* Flare color. */
161 vec3_t normal; /* Normal vector. */
162
163 /* Check for free flares. */
164 if (r_numflares >= MAX_FLARES)
165 return;
166
167 /* Initialization. */
168 VectorClear(origin);
169 VectorSet(color, 1.0, 1.0, 1.0);
170
171 intens = surf->texinfo->value;
172
173 /* Skip very small or null lights. */
174 if (intens <= 1000) {
175 ri.Con_Printf(PRINT_DEVELOPER,
176 "Skipped flare surface with intensity of %d.\n", intens);
177 return;
178 }
179
180 /* Create new flare. */
181 light = Hunk_Alloc(sizeof(flare_t));
182 r_flares[r_numflares++] = light;
183
184 VectorCopy(surf->center, origin);
185
186 #if 0
187 /* Calculate color average of light surface texture. */
188 GL_Bind(surf->texinfo->image->texnum);
189 width = surf->texinfo->image->upload_width;
190 height = surf->texinfo->image->upload_height;
191
192 buffer = malloc(width * height * 3);
193 qglGetTexImage(GL_TEXTURE_2D, 0, GL_RGB, GL_UNSIGNED_BYTE, buffer);
194 VectorClear(rgbSum);
195
196 for (i = 0, p = buffer; i < width * height; i++, p += 3)
197 rgbSum[i % 3] += (float)p[i % 3] * (1.0 / 255);
198
199 free(buffer);
200
201 VectorScale(rgbSum, 1.0 / (width*height), color);
202 VectorCopy(color, light->color);
203 #else
204 if (surf->wallLight != NULL)
205 VectorCopy(surf->wallLight->color, light->color);
206 else
207 VectorSet(light->color, 1.0, 1.0, 1.0);
208 #endif
209
210 /* Move flare 2 units far from the surface. */
211 if (surf->flags & SURF_PLANEBACK)
212 VectorNegate(surf->plane->normal, normal);
213 else
214 VectorCopy(surf->plane->normal, normal);
215
216 VectorMA(origin, 2, normal, origin);
217 VectorCopy(origin, light->origin);
218
219 light->style = r_numflares % FLARE_STYLES + 1; /* Pseudo-random. */
220 light->size = intens / 1000;
221
222 ri.Con_Printf(PRINT_DEVELOPER, "Added flare on light surface %d: "
223 "size = %d, style = %d, red = %f, green = %f, blue = %f,"
224 "x = %f, y = %f, z = %f.\n", r_numflares, light->size,
225 light->style, light->color[0], light->color[1], light->color[2],
226 light->origin[0], light->origin[1], light->origin[2]);
227 }
228