1 /*
2  * Copyright (C) 2002  Terence M. Welsh
3  * Ported to Linux by Tugrul Galatali <tugrul@galatali.com>
4  *
5  * Skyrocket is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License version 2 as
7  * published by the Free Software Foundation.
8  *
9  * Skyrocket is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
17  */
18 
19 #include <GL/gl.h>
20 #include <GL/glu.h>
21 
22 #include "skyrocket_flare.h"
23 
24 #define FLARESIZE 128
25 
26 #define max(x, y) ((x > y) ? x : y)
27 
28 unsigned int flarelist[4];
29 
30 extern int xsize, ysize;
31 extern float aspectRatio;
32 
33 // Generate textures for lens flares
34 // then applies textures to geometry in display lists
initFlares()35 void initFlares ()
36 {
37 	int i, j;
38 	float x, y;
39 	float temp;
40 	unsigned char flare[FLARESIZE][FLARESIZE][4];
41 	unsigned int flaretex[4];
42 
43 	glGenTextures (4, flaretex);
44 
45 	// First flare:  basic sphere
46 	for (i = 0; i < FLARESIZE; i++) {
47 		for (j = 0; j < FLARESIZE; j++) {
48 			flare[i][j][0] = 255;
49 			flare[i][j][1] = 255;
50 			flare[i][j][2] = 255;
51 			x = float (i - FLARESIZE / 2) / float (FLARESIZE / 2);
52 			y = float (j - FLARESIZE / 2) / float (FLARESIZE / 2);
53 
54 			temp = 1.0f - ((x * x) + (y * y));
55 			if (temp > 1.0f)
56 				temp = 1.0f;
57 			if (temp < 0.0f)
58 				temp = 0.0f;
59 			flare[i][j][3] = char (255.0f * temp * temp);
60 		}
61 	}
62 	glBindTexture (GL_TEXTURE_2D, flaretex[0]);
63 	//glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
64 	glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
65 	glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
66 	glTexImage2D (GL_TEXTURE_2D, 0, 4, FLARESIZE, FLARESIZE, 0, GL_RGBA, GL_UNSIGNED_BYTE, flare);
67 
68 	// Second flare:  flattened sphere
69 	for (i = 0; i < FLARESIZE; i++) {
70 		for (j = 0; j < FLARESIZE; j++) {
71 			flare[i][j][0] = 255;
72 			flare[i][j][1] = 255;
73 			flare[i][j][2] = 255;
74 			x = float (i - FLARESIZE / 2) / float (FLARESIZE / 2);
75 			y = float (j - FLARESIZE / 2) / float (FLARESIZE / 2);
76 
77 			temp = 2.5f * (1.0f - ((x * x) + (y * y)));
78 			if (temp > 1.0f)
79 				temp = 1.0f;
80 			if (temp < 0.0f)
81 				temp = 0.0f;
82 			//temp = temp * temp * temp * temp;
83 			flare[i][j][3] = char (255.0f * temp);
84 		}
85 	}
86 	glBindTexture (GL_TEXTURE_2D, flaretex[1]);
87 	//glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
88 	glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
89 	glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
90 	glTexImage2D (GL_TEXTURE_2D, 0, 4, FLARESIZE, FLARESIZE, 0, GL_RGBA, GL_UNSIGNED_BYTE, flare);
91 
92 	// Third flare:  torus
93 	for (i = 0; i < FLARESIZE; i++) {
94 		for (j = 0; j < FLARESIZE; j++) {
95 			flare[i][j][0] = 255;
96 			flare[i][j][1] = 255;
97 			flare[i][j][2] = 255;
98 			x = float (i - FLARESIZE / 2) / float (FLARESIZE / 2);
99 			y = float (j - FLARESIZE / 2) / float (FLARESIZE / 2);
100 
101 			temp = 4.0f * ((x * x) + (y * y)) * (1.0f - ((x * x) + (y * y)));
102 			if (temp > 1.0f)
103 				temp = 1.0f;
104 			if (temp < 0.0f)
105 				temp = 0.0f;
106 			temp = temp * temp * temp * temp;
107 			flare[i][j][3] = char (255.0f * temp);
108 		}
109 	}
110 	glBindTexture (GL_TEXTURE_2D, flaretex[2]);
111 	//glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
112 	glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
113 	glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
114 	glTexImage2D (GL_TEXTURE_2D, 0, 4, FLARESIZE, FLARESIZE, 0, GL_RGBA, GL_UNSIGNED_BYTE, flare);
115 
116 	// Fourth flare:  kick-ass flare
117 	for (i = 0; i < FLARESIZE; i++) {
118 		for (j = 0; j < FLARESIZE; j++) {
119 			x = float (i - FLARESIZE / 2) / float (FLARESIZE / 2);
120 
121 			if (x < 0.0f)
122 				x = -x;
123 			y = float (j - FLARESIZE / 2) / float (FLARESIZE / 2);
124 
125 			if (y < 0.0f)
126 				y = -y;
127 			flare[i][j][0] = 255;
128 			flare[i][j][1] = 255;
129 			temp = 0.14f * (1.0f - max (x, y)) / max ((x * y), 0.05f);
130 			if (temp > 1.0f)
131 				temp = 1.0f;
132 			if (temp < 0.0f)
133 				temp = 0.0f;
134 			flare[i][j][2] = char (255.0f * temp);
135 
136 			temp = 0.1f * (1.0f - max (x, y)) / max ((x * y), 0.1f);
137 			if (temp > 1.0f)
138 				temp = 1.0f;
139 			if (temp < 0.0f)
140 				temp = 0.0f;
141 			flare[i][j][3] = char (255.0f * temp);
142 		}
143 	}
144 	glBindTexture (GL_TEXTURE_2D, flaretex[3]);
145 	//glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
146 	glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
147 	glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
148 	glTexImage2D (GL_TEXTURE_2D, 0, 4, FLARESIZE, FLARESIZE, 0, GL_RGBA, GL_UNSIGNED_BYTE, flare);
149 
150 	// Build display lists
151 	flarelist[0] = glGenLists (4);
152 	flarelist[1] = flarelist[0] + 1;
153 	flarelist[2] = flarelist[0] + 2;
154 	flarelist[3] = flarelist[0] + 3;
155 	for (i = 0; i < 4; i++) {
156 		glNewList (flarelist[i], GL_COMPILE);
157 		glBindTexture (GL_TEXTURE_2D, flaretex[i]);
158 		glBegin (GL_TRIANGLE_STRIP);
159 		glTexCoord2f (0.0f, 0.0f);
160 		glVertex3f (-0.5f, -0.5f, 0.0f);
161 		glTexCoord2f (1.0f, 0.0f);
162 		glVertex3f (0.5f, -0.5f, 0.0f);
163 		glTexCoord2f (0.0f, 1.0f);
164 		glVertex3f (-0.5f, 0.5f, 0.0f);
165 		glTexCoord2f (1.0f, 1.0f);
166 		glVertex3f (0.5f, 0.5f, 0.0f);
167 		glEnd ();
168 		glEndList ();
169 	}
170 }
171 
cleanupFlares()172 void cleanupFlares ()
173 {
174 	glDeleteLists (flarelist[0], 4);
175 }
176 
177 // Draw a flare at a specified (x,y) location on the screen
178 // Screen corners are at (0,0) and (1,1)
179 // alpha = 0.0 for lowest intensity; alpha = 1.0 for highest intensity
flare(float x,float y,float red,float green,float blue,float alpha)180 void flare (float x, float y, float red, float green, float blue, float alpha)
181 {
182 	float dx, dy;
183 	float fadewidth, temp;
184 
185 	glBlendFunc (GL_SRC_ALPHA, GL_ONE);
186 	glEnable (GL_BLEND);
187 
188 	// Fade alpha if source is off edge of screen
189 	fadewidth = float (xsize) / 10.0f;
190 
191 	if (y < 0) {
192 		temp = fadewidth + y;
193 		if (temp < 0.0f)
194 			return;
195 		alpha *= temp / fadewidth;
196 	}
197 	if (y > ysize) {
198 		temp = fadewidth - y + ysize;
199 		if (temp < 0.0f)
200 			return;
201 		alpha *= temp / fadewidth;
202 	}
203 	if (x < 0) {
204 		temp = fadewidth + x;
205 		if (temp < 0.0f)
206 			return;
207 		alpha *= temp / fadewidth;
208 	}
209 	if (x > xsize) {
210 		temp = fadewidth - x + xsize;
211 		if (temp < 0.0f)
212 			return;
213 		alpha *= temp / fadewidth;
214 	}
215 	// Find lens flare vector
216 	// This vector runs from the light source through the screen's center
217 	dx = 0.5f * aspectRatio - x;
218 	dy = 0.5f - y;
219 
220 	// Setup projection matrix
221 	glMatrixMode (GL_PROJECTION);
222 	glPushMatrix ();
223 	glLoadIdentity ();
224 	gluOrtho2D (0, aspectRatio, 0, 1.0f);
225 
226 	// Draw stuff
227 	glMatrixMode (GL_MODELVIEW);
228 	glPushMatrix ();
229 
230 	glLoadIdentity ();
231 	glTranslatef (x + dx * 0.05f, y + dy * 0.05f, 0.0f);
232 	glScalef (0.065f, 0.065f, 0.065f);
233 	glColor4f (red, green, blue, alpha * 0.4f);
234 	glCallList (flarelist[2]);
235 
236 	glLoadIdentity ();
237 	glTranslatef (x + dx * 0.15f, y + dy * 0.15f, 0.0f);
238 	glScalef (0.04f, 0.04f, 0.04f);
239 	glColor4f (red * 0.9f, green * 0.9f, blue, alpha * 0.9f);
240 	glCallList (flarelist[1]);
241 
242 	glLoadIdentity ();
243 	glTranslatef (x + dx * 0.25f, y + dy * 0.25f, 0.0f);
244 	glScalef (0.06f, 0.06f, 0.06f);
245 	glColor4f (red * 0.8f, green * 0.8f, blue, alpha * 0.9f);
246 	glCallList (flarelist[1]);
247 
248 	glLoadIdentity ();
249 	glTranslatef (x + dx * 0.35f, y + dy * 0.35f, 0.0f);
250 	glScalef (0.08f, 0.08f, 0.08f);
251 	glColor4f (red * 0.7f, green * 0.7f, blue, alpha * 0.9f);
252 	glCallList (flarelist[1]);
253 
254 	glLoadIdentity ();
255 	glTranslatef (x + dx * 1.25f, y + dy * 1.25f, 0.0f);
256 	glScalef (0.05f, 0.05f, 0.05f);
257 	glColor4f (red, green * 0.6f, blue * 0.6f, alpha * 0.9f);
258 	glCallList (flarelist[1]);
259 
260 	glLoadIdentity ();
261 	glTranslatef (x + dx * 1.65f, y + dy * 1.65f, 0.0f);
262 	glRotatef (x, 0, 0, 1);
263 	glScalef (0.3f, 0.3f, 0.3f);
264 	glColor4f (red, green, blue, alpha);
265 	glCallList (flarelist[3]);
266 
267 	glLoadIdentity ();
268 	glTranslatef (x + dx * 1.85f, y + dy * 1.85f, 0.0f);
269 	glScalef (0.04f, 0.04f, 0.04f);
270 	glColor4f (red, green * 0.6f, blue * 0.6f, alpha * 0.9f);
271 	glCallList (flarelist[1]);
272 
273 	glLoadIdentity ();
274 	glTranslatef (x + dx * 2.2f, y + dy * 2.2f, 0.0f);
275 	glScalef (0.3f, 0.3f, 0.3f);
276 	glColor4f (red, green, blue, alpha * 0.7f);
277 	glCallList (flarelist[1]);
278 
279 	glLoadIdentity ();
280 	glTranslatef (x + dx * 2.5f, y + dy * 2.5f, 0.0f);
281 	glScalef (0.6f, 0.6f, 0.6f);
282 	glColor4f (red, green, blue, alpha * 0.8f);
283 	glCallList (flarelist[3]);
284 
285 	glPopMatrix ();
286 
287 	// Unsetup projection matrix
288 	glMatrixMode (GL_PROJECTION);
289 	glPopMatrix ();
290 	glMatrixMode (GL_MODELVIEW);
291 }
292 
293 // super bright elongated glow for sucker, shockwave, stretcher, and bigmama
superFlare(float x,float y,float red,float green,float blue,float alpha)294 void superFlare (float x, float y, float red, float green, float blue, float alpha)
295 {
296 	float fadewidth, temp;
297 
298 	glBlendFunc (GL_SRC_ALPHA, GL_ONE);
299 	glEnable (GL_BLEND);
300 
301 	// Fade alpha if source is off edge of screen
302 	fadewidth = float (xsize) / 10.0f;
303 
304 	if (y < 0) {
305 		temp = fadewidth + y;
306 		if (temp < 0.0f)
307 			return;
308 		alpha *= temp / fadewidth;
309 	}
310 	if (y > ysize) {
311 		temp = fadewidth - y + ysize;
312 		if (temp < 0.0f)
313 			return;
314 		alpha *= temp / fadewidth;
315 	}
316 	if (x < 0) {
317 		temp = fadewidth + x;
318 		if (temp < 0.0f)
319 			return;
320 		alpha *= temp / fadewidth;
321 	}
322 	if (x > xsize) {
323 		temp = fadewidth - x + xsize;
324 		if (temp < 0.0f)
325 			return;
326 		alpha *= temp / fadewidth;
327 	}
328 	// Setup projection matrix
329 	glMatrixMode (GL_PROJECTION);
330 	glPushMatrix ();
331 	glLoadIdentity ();
332 	gluOrtho2D (0, aspectRatio, 0, 1.0f);
333 
334 	// Draw stuff
335 	glMatrixMode (GL_MODELVIEW);
336 	glPushMatrix ();
337 
338 	glLoadIdentity ();
339 	glTranslatef (x, y, 0.0f);
340 	glScalef (2.0f * alpha, 0.08f, 0.0f);
341 	glColor4f (red, green, blue, alpha);
342 	glCallList (flarelist[0]);
343 
344 	glLoadIdentity ();
345 	glTranslatef (x, y, 0.0f);
346 	glScalef (0.4f, 0.35f * alpha + 0.05f, 1.0f);
347 	glColor4f (red, green, blue, alpha * 0.4f);
348 	glCallList (flarelist[2]);
349 
350 	glPopMatrix ();
351 
352 	// Unsetup projection matrix
353 	glMatrixMode (GL_PROJECTION);
354 	glPopMatrix ();
355 	glMatrixMode (GL_MODELVIEW);
356 }
357