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