1 /*
2 Copyright (C) 2007, 2010 - Bit-Blot
3
4 This file is part of Aquaria.
5
6 Aquaria is free software; you can redistribute it and/or
7 modify it under the terms of the GNU General Public License
8 as published by the Free Software Foundation; either version 2
9 of the License, or (at your option) any later version.
10
11 This program 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.
14
15 See the GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 */
21 #include "AfterEffect.h"
22 //#include "math.h"
23
24 #include <assert.h>
25
Effect()26 Effect::Effect()
27 {
28 done = false;
29 rate = 1;
30 }
31
AfterEffectManager(int xDivs,int yDivs)32 AfterEffectManager::AfterEffectManager(int xDivs, int yDivs)
33 {
34 active = false;
35 numEffects = 0;
36 bRenderGridPoints = true;
37 shaderPipeline.resize(10, 0);
38
39 screenWidth = core->getWindowWidth();
40 screenHeight = core->getWindowHeight();
41
42 this->xDivs = 0;
43 this->yDivs = 0;
44
45 drawGrid = 0;
46
47 this->xDivs = xDivs;
48 this->yDivs = yDivs;
49
50 reloadDevice();
51
52 if (xDivs != 0 && yDivs != 0)
53 {
54 drawGrid = new Vector * [xDivs];
55 for (int i = 0; i < xDivs; i++)
56 {
57 drawGrid[i] = new Vector [yDivs];
58 }
59 }
60
61 loadShaders();
62 }
63
loadShaders()64 void AfterEffectManager::loadShaders()
65 {
66 deleteShaders();
67
68 // ...Load shaders here...
69 }
70
~AfterEffectManager()71 AfterEffectManager::~AfterEffectManager()
72 {
73 if (drawGrid)
74 {
75 int i;
76 for (i = 0; i < xDivs; i++)
77 {
78 delete[] drawGrid[i];
79 }
80 delete[] drawGrid;
81 }
82 deleteEffects();
83 deleteShaders();
84 }
85
deleteEffects()86 void AfterEffectManager::deleteEffects()
87 {
88 for (int i = 0; i < effects.size(); i++)
89 {
90 if (effects[i])
91 {
92 delete effects[i];
93 }
94 }
95 effects.clear();
96 numEffects=0;
97 while (!openSpots.empty())
98 openSpots.pop();
99 }
100
deleteShaders()101 void AfterEffectManager::deleteShaders()
102 {
103 for(size_t i = 0; i < shaderPipeline.size(); ++i)
104 shaderPipeline[i] = 0;
105
106 for(size_t i = 0; i < loadedShaders.size(); ++i)
107 {
108 if(loadedShaders[i])
109 {
110 delete loadedShaders[i];
111 loadedShaders[i] = 0;
112 }
113 }
114 }
115
unloadShaders()116 void AfterEffectManager::unloadShaders()
117 {
118 for(size_t i = 0; i < loadedShaders.size(); ++i)
119 if(loadedShaders[i])
120 loadedShaders[i]->unload();
121 }
122
clear()123 void AfterEffectManager::clear()
124 {
125 deleteEffects();
126 resetGrid();
127 }
128
update(float dt)129 void AfterEffectManager::update(float dt)
130 {
131 if (core->particlesPaused) return;
132
133 resetGrid();
134
135 if (core->frameBuffer.isInited())
136 active = true;
137 else
138 active = false;
139
140 for (int i = 0; i < effects.size(); i++)
141 {
142 Effect *e = effects[i];
143 if (e)
144 {
145 active = true;
146 e->update(dt, drawGrid, xDivs, yDivs);
147 if (e->done)
148 {
149 numEffects--;
150 destroyEffect(i);
151 }
152 }
153 }
154 }
155
156
resetGrid()157 void AfterEffectManager::resetGrid()
158 {
159 for (int i = 0; i < xDivs; i++)
160 {
161 for (int j = 0; j < yDivs; j++)
162 {
163 drawGrid[i][j].x = i/(float)(xDivs-1);
164 drawGrid[i][j].y = j/(float)(yDivs-1);
165 }
166 }
167 }
168
destroyEffect(int id)169 void AfterEffectManager::destroyEffect(int id)
170 {
171 delete effects[id];
172 effects[id] = 0;
173 openSpots.push(id);
174 }
175
render()176 void AfterEffectManager::render()
177 {
178 assert(core->frameBuffer.isInited());
179
180 #ifdef BBGE_BUILD_OPENGL
181 glPushMatrix();
182
183 glDisable (GL_ALPHA_TEST);
184 glDisable(GL_BLEND);
185
186 core->frameBuffer.endCapture();
187 glTranslatef(core->cameraPos.x, core->cameraPos.y, 0);
188 glScalef(core->invGlobalScale, core->invGlobalScale,0);
189
190 glColor4f(1,1,1,1);
191 renderGrid();
192 //renderGridPoints();
193 glPopMatrix();
194 #endif
195 }
196
renderGrid()197 void AfterEffectManager::renderGrid()
198 {
199 #ifdef BBGE_BUILD_OPENGL
200
201 int firstShader = -1;
202 int lastShader = -1;
203 Shader *activeShader = 0;
204 for (size_t i = 0; i < shaderPipeline.size(); ++i)
205 {
206 if(shaderPipeline[i] && shaderPipeline[i]->isLoaded())
207 {
208 if(firstShader < 0)
209 {
210 firstShader = i;
211 activeShader = shaderPipeline[i];
212 }
213 lastShader = i;
214 }
215 }
216
217 screenWidth = core->getWindowWidth();
218 screenHeight = core->getWindowHeight();
219
220 float percentX, percentY;
221 percentX = (float)screenWidth/(float)textureWidth;
222 percentY = (float)screenHeight/(float)textureHeight;
223
224 int vw = core->getVirtualWidth();
225 int vh = core->getVirtualHeight();
226 int offx = -core->getVirtualOffX();
227 int offy = -core->getVirtualOffY();
228
229 core->frameBuffer.bindTexture();
230
231 if(activeShader)
232 {
233 activeShader->bind();
234 activeShader->setInt("tex", 0);
235
236 if(firstShader != lastShader)
237 backupBuffer.startCapture();
238 }
239
240 //float div = xDivs;
241 for (int i = 0; i < (xDivs-1); i++)
242 {
243 for (int j = 0; j < (yDivs-1); j++)
244 {
245 glBegin(GL_QUADS);
246 //glColor3f(i/div, i/div, i/div);
247 glTexCoord2f(i/(float)(xDivs-1)*percentX, 1*percentY-(j)/(float)(yDivs-1)*percentY);
248 //glMultiTexCoord2fARB(GL_TEXTURE0_ARB,i/(float)(xDivs-1)*percentX, 1*percentY-(j)/(float)(yDivs-1)*percentY);
249 //glMultiTexCoord2fARB(GL_TEXTURE1_ARB,0,0);
250 glVertex2f(offx + vw*drawGrid[i][j].x, offy + vh*drawGrid[i][j].y);
251 glTexCoord2f(i/(float)(xDivs-1)*percentX, 1*percentY-(j+1)/(float)(yDivs-1)*percentY);
252 //glMultiTexCoord2fARB(GL_TEXTURE0_ARB,i/(float)(xDivs-1)*percentX, 1*percentY-(j+1)/(float)(yDivs-1)*percentY);
253 //glMultiTexCoord2fARB(GL_TEXTURE1_ARB,0,(float)(screenHeight/(yDivs-1))/16);
254 glVertex2f(offx + vw*drawGrid[i][j+1].x, offy + vh*drawGrid[i][j+1].y);
255 glTexCoord2f((i+1)/(float)(xDivs-1)*percentX, 1*percentY-(j+1)/(float)(yDivs-1)*percentY);
256 //glMultiTexCoord2fARB(GL_TEXTURE0_ARB,(i+1)/(float)(xDivs-1)*percentX, 1*percentY-(j+1)/(float)(yDivs-1)*percentY);
257 //glMultiTexCoord2fARB(GL_TEXTURE1_ARB,(float)(screenWidth/(xDivs-1))/16,(float)(screenHeight/(yDivs-1))/16);
258 glVertex2f(offx + vw*drawGrid[i+1][j+1].x, offy + vh*drawGrid[i+1][j+1].y);
259 glTexCoord2f((i+1)/(float)(xDivs-1)*percentX, 1*percentY-(j)/(float)(yDivs-1)*percentY);
260 //glMultiTexCoord2fARB(GL_TEXTURE0_ARB,(i+1)/(float)(xDivs-1)*percentX, 1*percentY-(j)/(float)(yDivs-1)*percentY);
261 //glMultiTexCoord2fARB(GL_TEXTURE1_ARB,(float)(screenWidth/(xDivs-1))/16,0);
262 glVertex2f(offx + vw*drawGrid[i+1][j].x, offy + vh*drawGrid[i+1][j].y);
263 glEnd();
264 }
265 }
266
267 if (activeShader)
268 activeShader->unbind();
269
270 float width2 = float(vw)/2;
271 float height2 = float(vh)/2;
272
273
274 if(firstShader != lastShader)
275 {
276 // From here on: secondary shader passes.
277 // We just outputted to the backup buffer...
278 FrameBuffer *fbIn = &core->frameBuffer;
279 FrameBuffer *fbOut = &backupBuffer;
280
281
282 for(int i = firstShader + 1; i <= lastShader; ++i)
283 {
284 activeShader = shaderPipeline[i];
285 if(!(activeShader && activeShader->isLoaded()))
286 continue;
287
288 // Swap and exchange framebuffers. The old output buffer serves as texture input for the other one
289 fbOut->endCapture();
290 std::swap(fbIn, fbOut);
291 fbIn->bindTexture();
292
293 // If this is the last pass, do not render to a frame buffer again
294 if(i != lastShader)
295 fbOut->startCapture();
296
297 activeShader->bind();
298 activeShader->setInt("tex", 0);
299
300 // note that offx, offy are negative here!
301 glBegin(GL_QUADS);
302 glTexCoord2d(0.0f, 0.0f);
303 glVertex3f(offx, vh+offy, 0.0f);
304 glTexCoord2d(percentX, 0.0f);
305 glVertex3f( vw+offx, vh+offy, 0.0f);
306 glTexCoord2d(percentX, percentY);
307 glVertex3f( vw+offx, offy, 0.0f);
308 glTexCoord2d(0.0f, percentY);
309 glVertex3f(offx, offy, 0.0f);
310 glEnd();
311
312 activeShader->unbind();
313 }
314 }
315
316
317 // uncomment to render grid points
318 /*
319 glBindTexture(GL_TEXTURE_2D, 0);
320 glPointSize(2);
321 glColor4f(1, 0, 0, 0.5);
322 for (int i = 0; i < (xDivs-1); i++)
323 {
324 for (int j = 0; j < (yDivs-1); j++)
325 {
326 glBegin(GL_POINTS);
327 //glColor3f(i/div, i/div, i/div);
328 glTexCoord2f(i/(float)(xDivs-1)*percentX, 1*percentY-(j)/(float)(yDivs-1)*percentY);
329 //glMultiTexCoord2fARB(GL_TEXTURE0_ARB,i/(float)(xDivs-1)*percentX, 1*percentY-(j)/(float)(yDivs-1)*percentY);
330 //glMultiTexCoord2fARB(GL_TEXTURE1_ARB,0,0);
331 glVertex2f(800*drawGrid[i][j].x, 600*drawGrid[i][j].y);
332 glTexCoord2f(i/(float)(xDivs-1)*percentX, 1*percentY-(j+1)/(float)(yDivs-1)*percentY);
333 //glMultiTexCoord2fARB(GL_TEXTURE0_ARB,i/(float)(xDivs-1)*percentX, 1*percentY-(j+1)/(float)(yDivs-1)*percentY);
334 //glMultiTexCoord2fARB(GL_TEXTURE1_ARB,0,(float)(screenHeight/(yDivs-1))/16);
335 glVertex2f(800*drawGrid[i][j+1].x, 600*drawGrid[i][j+1].y);
336 glTexCoord2f((i+1)/(float)(xDivs-1)*percentX, 1*percentY-(j+1)/(float)(yDivs-1)*percentY);
337 //glMultiTexCoord2fARB(GL_TEXTURE0_ARB,(i+1)/(float)(xDivs-1)*percentX, 1*percentY-(j+1)/(float)(yDivs-1)*percentY);
338 //glMultiTexCoord2fARB(GL_TEXTURE1_ARB,(float)(screenWidth/(xDivs-1))/16,(float)(screenHeight/(yDivs-1))/16);
339 glVertex2f(800*drawGrid[i+1][j+1].x, 600*drawGrid[i+1][j+1].y);
340 glTexCoord2f((i+1)/(float)(xDivs-1)*percentX, 1*percentY-(j)/(float)(yDivs-1)*percentY);
341 //glMultiTexCoord2fARB(GL_TEXTURE0_ARB,(i+1)/(float)(xDivs-1)*percentX, 1*percentY-(j)/(float)(yDivs-1)*percentY);
342 //glMultiTexCoord2fARB(GL_TEXTURE1_ARB,(float)(screenWidth/(xDivs-1))/16,0);
343 glVertex2f(800*drawGrid[i+1][j].x, 600*drawGrid[i+1][j].y);
344 glEnd();
345 }
346 }
347 */
348
349 //glDisable(GL_TEXTURE_2D);
350 RenderObject::lastTextureApplied = 0;
351 glBindTexture(GL_TEXTURE_2D, 0);
352
353 //bwShader.unbind();
354 //glActiveTextureARB(GL_TEXTURE0_ARB);
355 //glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
356 //if (bRenderGridPoints)
357 // renderGridPoints();
358 #endif
359 }
360
renderGridPoints()361 void AfterEffectManager::renderGridPoints()
362 {
363 #ifdef BBGE_BUILD_OPENGL
364 glColor4f(0.0f,0.0f,0.0f,1.0f);
365 for (int i = 0; i < (xDivs); i++)
366 {
367 for (int j = 0; j < (yDivs); j++)
368 {
369 glBegin(GL_QUADS);
370 glVertex2f(screenWidth*drawGrid[i][j].x-3, screenHeight*drawGrid[i][j].y-3);
371 glVertex2f(screenWidth*drawGrid[i][j].x-3, screenHeight*drawGrid[i][j].y+3);
372 glVertex2f(screenWidth*drawGrid[i][j].x+3, screenHeight*drawGrid[i][j].y+3);
373 glVertex2f(screenWidth*drawGrid[i][j].x+3, screenHeight*drawGrid[i][j].y-3);
374 glEnd();
375 }
376 }
377 #endif
378 }
379
unloadDevice()380 void AfterEffectManager::unloadDevice()
381 {
382 backupBuffer.unloadDevice();
383 unloadShaders();
384 }
385
reloadDevice()386 void AfterEffectManager::reloadDevice()
387 {
388 screenWidth = core->getWindowWidth();
389 screenHeight = core->getWindowHeight();
390
391 if (core->frameBuffer.isInited())
392 {
393 textureWidth = core->frameBuffer.getWidth();
394 textureHeight = core->frameBuffer.getHeight();
395 }
396 else
397 {
398 textureWidth = screenWidth;
399 sizePowerOf2Texture(textureWidth);
400 textureHeight = screenHeight;
401 sizePowerOf2Texture(textureHeight);
402 }
403
404 if(backupBuffer.isInited())
405 backupBuffer.reloadDevice();
406 else
407 backupBuffer.init(-1, -1, true);
408
409 for (size_t i = 0; i < loadedShaders.size(); ++i)
410 {
411 if (Shader *sh = loadedShaders[i])
412 {
413 sh->reload();
414 if (!sh->isLoaded())
415 {
416 debugLog("AfterEffect::reloadDevice(): Failed to reload shader");
417 delete sh;
418 loadedShaders[i] = 0;
419 for(size_t j = 0; j < shaderPipeline.size(); ++j)
420 if(sh == shaderPipeline[j])
421 shaderPipeline[j] = 0;
422 }
423 }
424 }
425 }
426
addEffect(Effect * e)427 void AfterEffectManager::addEffect(Effect *e)
428 {
429
430 if (!openSpots.empty())
431 {
432 int i = openSpots.front();
433 openSpots.pop();
434 effects[i] = e;
435 }
436 else
437 {
438 effects.push_back(e);
439 }
440 numEffects++;
441 //float lowest = 9999;
442 Vector base(0,0,0);
443 //Vector *newPos = &base;
444 //Vector *v;
445 e->position.x /= screenWidth;
446 //e->position.x *= xDivs;
447 e->position.y /= screenHeight;
448 //e->position.y *= yDivs;
449
450 /*
451 for (int x = 1; x < xDivs-1; x++)
452 {
453 for (int y = 1; y < yDivs-1; y++)
454 {
455 v = &drawGrid[x][y];
456 float dist = (v->x - e->position.x)*(v->x - e->position.x)+(v->y - e->position.y)*(v->y - e->position.y);
457 if (dist < lowest)
458 {
459 lowest = dist;
460 newPos = &drawGrid[x][y];
461 }
462 }
463 }
464 e->position = Vector(newPos->x, newPos->y, newPos->z);
465 */
466
467 }
468
469
update(float dt,Vector ** drawGrid,int xDivs,int yDivs)470 void ShockEffect::update(float dt, Vector ** drawGrid, int xDivs, int yDivs)
471 {
472 dt *= timeMultiplier;
473 Effect::update(dt, drawGrid, xDivs, yDivs);
474 //GLdouble sx, sy,sz;
475 /*
476 gluProject(position.x,position.y,position.z,
477 nCameraPointer->modelMatrix,nCameraPointer->projMatrix,nCameraPointer->viewport,
478 &sx,&sy,&sz); // Find out where the light is on the screen.
479 centerPoint.Set(sx/(float)nCameraPointer->viewport[2],1-sy/(float)nCameraPointer->viewport[3],sz);
480
481 */
482 centerPoint = position;
483 centerPoint -= ((core->screenCenter-originalCenter)*core->globalScale.x)/core->width;
484 //centerPoint = position/xDivs;
485 //centerPoint = drawGrid[xDivs/2][yDivs/2];
486 float xDist,yDist,tDist;
487
488
489 amplitude-=dt*rate;
490 currentDistance+=dt*frequency;
491
492
493 //float distFromCamp =(core->cameraPos - position).getLength2D();//v3dDist(nCameraPointer->pos, position);
494 //if (distFromCamp < 4)
495 float distFromCamp = 4;
496
497 float adjWaveLength = waveLength/distFromCamp;
498 float adjAmplitude = amplitude/distFromCamp;
499
500 if (amplitude < 0)
501 done=true;
502
503 for (int i = 1; i < (xDivs-1); i++)
504 {
505 for (int j = 1; j < (yDivs-1); j++)
506 {
507 /*
508 Vector p = getNearestPointOnLine(centerPoint, centerPoint + Vector(-200, -200), Vector(drawGrid[i][j].x*core->width, drawGrid[i][j].y*core->height));
509
510 p.x /= core->width;
511 p.y /= core->height;
512 */
513
514 xDist = (centerPoint.x - drawGrid[i][j].x)/.75;
515 yDist = centerPoint.y - drawGrid[i][j].y;
516
517 /*
518 xDist = (p.x - drawGrid[i][j].x)/.75;
519 yDist = p.y - drawGrid[i][j].y;
520 */
521
522 //xDist = 1;
523 //yDist = 2;
524 tDist = sqrtf(xDist*xDist+yDist*yDist);
525
526 //drawGrid[i][j].x += (rand()%100)/10000.0f;
527 //drawGrid[i][j].y += (rand()%100)/10000.0f;
528
529
530 if (tDist < currentDistance*adjWaveLength)
531 {
532 //drawGrid[i][j].x += rand()%50;
533 //drawGrid[i][j].y += rand()%50;
534 drawGrid[i][j].x += adjAmplitude*sinf(-tDist/adjWaveLength+currentDistance)*.75f;
535 drawGrid[i][j].y += adjAmplitude*cosf(-tDist/adjWaveLength+currentDistance);
536 }
537 }
538 }
539 }
540
541
RippleEffect()542 RippleEffect::RippleEffect() : Effect()
543 {
544 time = 0;
545 }
546
update(float dt,Vector ** drawGrid,int xDivs,int yDivs)547 void RippleEffect::update(float dt, Vector ** drawGrid, int xDivs, int yDivs)
548 {
549 /*
550 // whole screen roll
551 time += dt;
552 float amp = 0.01;
553 for (int i = 0; i < (xDivs-1); i++)
554 {
555 for (int j = 0; j < (yDivs-1); j++)
556 {
557 float offset = +i/float(xDivs) +j/float(xDivs);
558 //drawGrid[i][j].x += sinf(time+offset)*amp;
559 drawGrid[i][j].y += cosf((time+offset)*2.5f)*amp;
560 }
561 }
562 */
563 time += dt*0.5f;
564 float amp = 0.002;
565 for (int i = 0; i < (xDivs-1); i++)
566 {
567 for (int j = 0; j < (yDivs-1); j++)
568 {
569 float offset = i/float(xDivs) + (core->screenCenter.x/float(core->width)/2) +j/float(xDivs) + (core->screenCenter.y/float(core->height)/2);
570 //drawGrid[i][j].x += sinf(time+offset)*amp;
571 drawGrid[i][j].x += sinf((time+offset)*7.5f)*(amp*0.5f);
572 drawGrid[i][j].y += cosf((time+offset)*7.5f)*amp;
573 }
574 }
575 }
576
loadShaderFile(const char * vert,const char * frag)577 int AfterEffectManager::loadShaderFile(const char *vert, const char *frag)
578 {
579 Shader *sh = new Shader();
580 sh->load(vert, frag);
581 if(!sh->isLoaded())
582 {
583 delete sh;
584 return 0;
585 }
586 return _insertShader(sh);
587 }
588
loadShaderSrc(const char * vert,const char * frag)589 int AfterEffectManager::loadShaderSrc(const char *vert, const char *frag)
590 {
591 Shader *sh = new Shader();
592 sh->loadSrc(vert, frag);
593 if(!sh->isLoaded())
594 {
595 delete sh;
596 return 0;
597 }
598 return _insertShader(sh);
599 }
600
getShaderPtr(int handle)601 Shader *AfterEffectManager::getShaderPtr(int handle)
602 {
603 size_t idx = handle - 1;
604 return idx < loadedShaders.size() ? loadedShaders[idx] : 0;
605 }
606
setShaderPipelineSize(size_t size)607 void AfterEffectManager::setShaderPipelineSize(size_t size)
608 {
609 shaderPipeline.resize(size, 0);
610 }
611
setShaderPipelinePos(int handle,size_t pos)612 bool AfterEffectManager::setShaderPipelinePos(int handle, size_t pos)
613 {
614 if(pos < shaderPipeline.size())
615 {
616 shaderPipeline[pos] = getShaderPtr(handle);
617 return true;
618 }
619 return false;
620 }
621
622 // returns handle (= index + 1)
_insertShader(Shader * sh)623 int AfterEffectManager::_insertShader(Shader *sh)
624 {
625 for(size_t i = 0; i < loadedShaders.size(); ++i)
626 {
627 if(!loadedShaders[i])
628 {
629 loadedShaders[i] = sh;
630 return i+1;
631 }
632 }
633 loadedShaders.push_back(sh);
634 return loadedShaders.size();
635 }
636
deleteShader(int handle)637 void AfterEffectManager::deleteShader(int handle)
638 {
639 Shader *sh = getShaderPtr(handle);
640 if(!sh)
641 return;
642
643 for(size_t i = 0; i < shaderPipeline.size(); ++i)
644 if(shaderPipeline[i] == sh)
645 shaderPipeline[i] = 0;
646
647 size_t idx = handle - 1;
648 loadedShaders[idx] = 0;
649 delete sh;
650 }
651
652