1 ////////////////////////////////////////////////////////////////////////////////
2 //    Scorched3D (c) 2000-2011
3 //
4 //    This file is part of Scorched3D.
5 //
6 //    Scorched3D is free software; you can redistribute it and/or modify
7 //    it under the terms of the GNU General Public License as published by
8 //    the Free Software Foundation; either version 2 of the License, or
9 //    (at your option) any later version.
10 //
11 //    Scorched3D is distributed in the hope that it will be useful,
12 //    but WITHOUT ANY WARRANTY; without even the implied warranty of
13 //    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 //    GNU General Public License for more details.
15 //
16 //    You should have received a copy of the GNU General Public License along
17 //    with this program; if not, write to the Free Software Foundation, Inc.,
18 //    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19 ////////////////////////////////////////////////////////////////////////////////
20 
21 #include <math.h>
22 #include <GLEXT/GLState.h>
23 #include <GLEXT/GLCamera.h>
24 #include <image/ImageLuminanceFactory.h>
25 #include <GLEXT/GLLenseFlare.h>
26 #include <GLEXT/GLCameraFrustum.h>
27 #include <common/Defines.h>
28 #include <lang/LangResource.h>
29 
30 GLLenseFlare *GLLenseFlare::instance_ = 0;
31 
instance()32 GLLenseFlare *GLLenseFlare::instance()
33 {
34 	if (!instance_)
35 	{
36 		instance_ = new GLLenseFlare;
37 	}
38 
39 	return instance_;
40 }
41 
GLLenseFlare()42 GLLenseFlare::GLLenseFlare() : shineTic_(0)
43 {
44 
45 }
46 
~GLLenseFlare()47 GLLenseFlare::~GLLenseFlare()
48 {
49 
50 }
51 
setFlare(int index,int type,float scale,float loc,Vector & color1,Vector & color2,Vector & color3,Vector & color4,float colorScale)52 void GLLenseFlare::setFlare(int index, int type, float scale, float loc,
53 							Vector &color1, Vector &color2, Vector &color3, Vector &color4,
54 							float colorScale)
55 {
56 	if (index > 2) loc *= 500;
57 
58 	flare_[index].type = type;
59 	flare_[index].loc = loc;
60 	flare_[index].scale = scale;
61 	flare_[index].color1 = color1 * colorScale;
62 	flare_[index].color2 = color2 * colorScale;
63 	flare_[index].color3 = color3 * colorScale;
64 	flare_[index].color4 = color4 * colorScale;
65 }
66 
init(ProgressCounter * counter)67 void GLLenseFlare::init(ProgressCounter *counter)
68 {
69 	if (counter) counter->setNewOp(LANG_RESOURCE("LENS_FLARES", "Lens Flares"));
70 
71 	Vector red1(1.0f, 0.0f, 0.0f);
72 	Vector green1(0.0f, 1.0f, 0.0f);
73 	Vector blue1(0.0f, 0.0f, 1.0f);
74 
75 	Vector red2(1.0f, 0.0f, 0.0f);
76 	Vector green2(0.5f, 1.0f, 0.0f);
77 	Vector blue2(0.5f, 0.0f, 1.0f);
78 
79 	Vector red3(1.0f, 0.5f, 0.0f);
80 	Vector green3(0.0f, 1.0f, 0.0f);
81 	Vector blue3(0.0f, 0.5f, 1.0f);
82 
83 	Vector red4(1.0f, 0.0f, 0.5f);
84 	Vector green4(0.0f, 1.0f, 0.5f);
85 	Vector blue4(0.0f, 0.0f, 1.0f);
86 
87 	setFlare(0, -1, 1.0f, 0.3f, blue1, blue2, blue3, blue4, 1.0f);
88 	setFlare(1, -1, 1.0f, 0.2f, green1, green2, green3, green4, 1.f);
89 	setFlare(2, -1, 1.0f, 0.25f, red1, red2, red3, red4, 1.0f);
90 
91 	/* Flares, ordered to eliminate redundant texture binds */
92 	setFlare(3, 1, 0.5f, 0.2f, red1, red2, red3, red4, 0.3f);
93 	setFlare(4, 2, 1.3f, 0.04f, red1, red2, red3, red4, 0.6f);
94 	setFlare(5, 3, 1.0f, 0.1f, red1, red2, red3, red4, 0.4f);
95 	setFlare(6, 3, 0.2f, 0.05f, red1, red2, red3, red4, 0.3f);
96 	setFlare(7, 0, 0.0f, 0.04f, red1, red2, red3, red4, 0.3f);
97 	setFlare(8, 5, -0.25f, 0.07f, red1, red2, red3, red4, 0.5f);
98 	setFlare(9, 5, -0.4f, 0.02f, red1, red2, red3, red4, 0.6f);
99 	setFlare(10, 5, -0.6f, 0.04f, red1, red2, red3, red4, 0.4f);
100 	setFlare(11, 5, -1.0f, 0.03f, red1, red2, red3, red4, 0.2f);
101 
102 	int i;
103 	for (i = 0; i < 10; i++)
104 	{
105 		if (counter) counter->setNewPercentage(float (i) / 16.0f * 100.0f);
106 
107 		Image bitmap = ImageLuminanceFactory::loadFromFile(S3D::getModFile(S3D::formatStringBuffer("data/textures/lensflare/shine%d.bw", i)));
108 		shines_[i].create(bitmap);
109 	}
110 
111 	for (i = 0; i < 6; i++)
112 	{
113 		if (counter) counter->setNewPercentage(float (i+10) / 16.0f * 100.0f);
114 
115 		Image bitmap = ImageLuminanceFactory::loadFromFile(S3D::getModFile(S3D::formatStringBuffer("data/textures/lensflare/flare%d.bw", i)));
116 		flares_[i].create(bitmap);
117 	}
118 }
119 
draw(Vector & flarePos,bool fullFlare,int colorNo,float size,float alpha)120 void GLLenseFlare::draw(Vector &flarePos,
121 	bool fullFlare, int colorNo,
122 	float size, float alpha)
123 {
124 	if (GLCameraFrustum::instance()->sphereInFrustum(flarePos, 5))
125 	{
126 		Vector &cameraPos = GLCamera::getCurrentCamera()->getCurrentPos();
127 		Vector &cameraAt = GLCamera::getCurrentCamera()->getLookAt();
128 
129 		Vector view_dir = flarePos - cameraPos;
130 		Vector centre = cameraPos + view_dir.Normalize() * 20.0f;
131 		Vector axis = (cameraAt - flarePos).Normalize();
132 
133 		Vector dx = axis.Normalize();
134 		Vector dy = (dx * view_dir).Normalize();
135 		dx = -(dy * view_dir).Normalize();
136 
137 		dx *= 2.0f * size;
138 		dy *= 2.0f * size;
139 
140 		glDepthMask(GL_FALSE);
141 		GLState currentState(GLState::BLEND_ON);
142 		glBlendFunc(GL_ONE, GL_ONE);
143 
144 		GLState *afterThreeState = 0;
145 		int endTexture = 12;
146 		if (!fullFlare) endTexture = 3;
147 		for (int i=0; i<endTexture; i++)
148 		{
149 			Vector sx = dx * flare_[i].scale;
150 			Vector sy = dy * flare_[i].scale;
151 			static Vector position;
152 
153 			switch(colorNo)
154 			{
155 				case 0: glColor4f(flare_[i].color1[0], flare_[i].color1[1], flare_[i].color1[2], alpha); break;
156 				case 1: glColor4f(flare_[i].color2[0], flare_[i].color2[1], flare_[i].color2[2], alpha); break;
157 				case 2: glColor4f(flare_[i].color3[0], flare_[i].color3[1], flare_[i].color3[2], alpha); break;
158 				case 3: glColor4f(flare_[i].color4[0], flare_[i].color4[1], flare_[i].color4[2], alpha); break;
159 			}
160 			if (flare_[i].type < 0)
161 			{
162 				shines_[shineTic_].draw();
163 				shineTic_ = (shineTic_ + 1) % 10;
164 
165 				position = flarePos + (axis * flare_[i].loc);
166 			}
167 			else
168 			{
169 				flares_[flare_[i].type].draw();
170 
171 				position = flarePos + (axis * flare_[i].loc);
172 			}
173 
174 			if (i==3) afterThreeState = new GLState(GLState::DEPTH_OFF);
175 
176 			glBegin(GL_QUADS);
177 
178 			static Vector tmp;
179 
180 			tmp = position + sx + sy;
181 			glTexCoord2f(0.0, 0.0);
182 			glVertex3fv(tmp);
183 
184 			tmp = (position - sx) + sy;
185 			glTexCoord2f(1.0, 0.0);
186 			glVertex3fv(tmp);
187 
188 			tmp = (position - sx) - sy;
189 			glTexCoord2f(1.0, 1.0);
190 			glVertex3fv(tmp);
191 
192 			tmp = (position + sx) - sy;
193 			glTexCoord2f(0.0, 1.0);
194 			glVertex3fv(tmp);
195 
196 			glEnd();
197 		}
198 
199 		glDepthMask(GL_TRUE);
200 		delete afterThreeState;
201 	}
202 	glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
203 }
204 
draw(Vector & flarePos,Vector & flareDir,int colorNo)205 void GLLenseFlare::draw(Vector &flarePos, Vector &flareDir, int colorNo)
206 {
207 	if (!GLCameraFrustum::instance()->sphereInFrustum(flarePos, 5))
208 	{
209 		return;
210 	}
211 
212 	Vector &cameraPos = GLCamera::getCurrentCamera()->getCurrentPos();
213 	Vector &cameraAt = GLCamera::getCurrentCamera()->getLookAt();
214 
215 	Vector flare_dir = flareDir;// .Normalize(); // Should already be normalized
216 	Vector view_dir = (flarePos - cameraPos).Normalize();
217 
218 	float dotP = (float) flare_dir.dotP(view_dir);
219 	if (dotP <= 0.2f) return;
220 
221 	Vector centre = cameraPos + view_dir * 20.0f;
222 	Vector axis = (cameraAt - flarePos).Normalize();
223 
224 	Vector dx = axis.Normalize();
225 	Vector dy = (dx * view_dir).Normalize();
226 	dx = -(dy * view_dir).Normalize();
227 
228 	dx *= 2.0f * (dotP - 0.2f);
229 	dy *= 2.0f * (dotP - 0.2f);
230 
231 	glDepthMask(GL_FALSE);
232 	GLState currentState(GLState::BLEND_ON | GLState::TEXTURE_ON);
233 	glBlendFunc(GL_ONE, GL_ONE);
234 
235 	for (int i=0; i<3; i++)
236 	{
237 		switch(colorNo)
238 		{
239 			case 0: glColor3fv(flare_[i].color1); break;
240 			case 1: glColor3fv(flare_[i].color2); break;
241 			case 2: glColor3fv(flare_[i].color3); break;
242 			case 3: glColor3fv(flare_[i].color4); break;
243 		}
244 
245 		shines_[shineTic_].draw();
246 		shineTic_ = (shineTic_ + 1) % 10;
247 
248 		Vector position = flarePos + (axis * flare_[i].loc);
249 		Vector sx = dx * flare_[i].scale;
250 		Vector sy = dy * flare_[i].scale;
251 
252 		glBegin(GL_QUADS);
253 			static Vector tmp;
254 			tmp = position + sx + sy;
255 			glTexCoord2f(0.0, 0.0);
256 			glVertex3fv(tmp);
257 
258 			tmp = (position - sx) + sy;
259 			glTexCoord2f(1.0, 0.0);
260 			glVertex3fv(tmp);
261 
262 			tmp = (position - sx) - sy;
263 			glTexCoord2f(1.0, 1.0);
264 			glVertex3fv(tmp);
265 
266 			tmp = (position + sx) - sy;
267 			glTexCoord2f(0.0, 1.0);
268 			glVertex3fv(tmp);
269 
270 		glEnd();
271 	}
272 	glDepthMask(GL_TRUE);
273 	glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
274 }
275