Wymaga OpenGL, GLEW (do shaderow) i GLTools.
/* * BloomPostProcess.h * * Created on: 2011-06-27 * Author: myood */ /* * KNOWN BUGS: * * if new width while resizing is < 16, then GL_ERROR_INVALID_OPERATION occur */ #ifndef BLOOMPOSTPROCESS_H_ #define BLOOMPOSTPROCESS_H_ #include#include #include #include #include /* * Typical usage: * initialize once: * BloomPostProcess::getInstance()->init(); * * in resize screen handling: * BloomPostProcess::getInstance()->resize(); * * render loop: * { * BloomPostProcess::getInstance()->BeginRendering(); * * --do normal rendering-- * BloomPostProcess::getInstance()->BeginGlowParts(); * --do rendering-- * BloomPostProcess::getInstance()->PostProcess(); * BloomPostProcess::getInstance()->display(); * } * * cleanup: * BloomPostProcess::getInstance()->finalize(); * BloomPostProcess::getInstance()->destroy(); */ class BloomPostProcess { public: enum BLOOM_STATE { NONEXISTENT, //Before instatination or after destroy() call INSTANITED, //After getInstance() call INITIALIZED, //After init() or display() call RENDERED, //After BeginRendering() call PREPROCESSED, //After BeginGlowParts() call POSTPROCESSED, //After PostProcess() call FINALIZED, //After cleanup() or finalize() call DESTROYED //After destroy() call, next call will return NONEXISTENT }; bool debug; static BloomPostProcess* getInstance(); virtual ~BloomPostProcess(){}; inline static enum BLOOM_STATE getState(); /* * Initialize Bloom Post Process Effect */ GLenum init(int newScreenWidth, int newScreenHeight, int RENDER_STEPS=3); /* * Do clean up - free memory etc. * Both functions do exactly the same. */ GLenum finalize(); inline GLenum cleanup(); /* * Destroy post processing effect */ GLenum destroy(); /* * Resize handling */ GLenum resize(int new_width, int new_height); /* * Pre and post process glow, display effect on screen */ GLenum BeginRendering(); GLenum BeginGlowParts(); GLenum PostProcess(); GLenum Display(); /* * Resize screen function */ //todo /* * LOTS OF TO DO :) */ protected: BloomPostProcess(bool doWeDebug= true) { mp_state= NONEXISTENT; debug= doWeDebug; } private: static BloomPostProcess* mp_BloomPostProcess; BloomPostProcess( BloomPostProcess const& bps){} BloomPostProcess& operator=(BloomPostProcess const&){ return *this; } /* * CONFIGURATION */ static BLOOM_STATE mp_state; int mp_iScreenWidth; int mp_iScreenHeight; int mp_iPostRenderSteps; GLenum* mp_fboBuffs; GLenum* mp_fboWindowBuff; //todo --- ?resize? /* * SHADERS */ //This shader is used to downsampling textures GLint* mp_shScreenTextMVP; //This shader is used to find glowing parts, //but it is deprecated. // GLint* processGlowShader; //Blur scene horizontally GLint* mp_shBlurHori; //Blur scene verticaly GLint* mp_shBlurVerti; //This shader is used to create bloom effect - //it add all downsampled textures to the //normally rendered scene texture. GLint* mp_shPostProcess; /* * TEXTURES */ GLuint* mp_texRendering; GLuint* mp_texGlowParts; GLuint* mp_texDownsampled; GLuint* mp_texHoriBlur; GLuint* mp_texVertBlur; GLuint* mp_texGlowing; /* * FBOS */ GLuint* mp_fboRendering; GLuint* mp_fboGlowParts; GLuint* mp_fboDownsampled; GLuint* mp_fboHoriBlur; GLuint* mp_fboVertBlur; GLuint* mp_fboGlowing; /* * RBO */ GLuint* mp_rboRendering; /* * PROJECTION MATRICES AND SCREEN QUADS */ M3DMatrix44f* mp_OrthoMatrix; GLBatch* mp_ScreenQuad; /* * ACTIONS */ GLenum createAndBindFBO(int* ScreenWidth, int* ScreenHeight, GLuint* FBO, GLuint* Texture, GLuint* DepthBuffer= NULL); GLenum renderTextureOnWholeScreen(GLuint* textureID, GLint* shader, float v4color[4], int i= 0); }; #endif /* BLOOMPOSTPROCESS_H_ */
/*
* BloomPostProcess.cpp
*
* Created on: 2011-06-27
* Author: myood
*/
#include "BloomPostProcess.h"
// enum BLOOM_STATE {
// NONEXISTENT, //Before intatination or after destroy() call
// INSTANITED, //After getInstance() call
// INITIALIZED, //After init() call
// FINALIZED, //After cleanup() or finalize() call
// DESTROYED //After destroy() call, next call will return NONEXISTENT
// };
BloomPostProcess* BloomPostProcess::mp_BloomPostProcess= 0;
BloomPostProcess::BLOOM_STATE BloomPostProcess::mp_state= NONEXISTENT;
BloomPostProcess* BloomPostProcess::getInstance()
{
if ( !mp_BloomPostProcess )
{
mp_BloomPostProcess= new BloomPostProcess();
mp_state= INSTANITED;
}
return mp_BloomPostProcess;
}
BloomPostProcess::BLOOM_STATE BloomPostProcess::getState()
{
return mp_state;
}
//todo changable postrender steps
GLenum BloomPostProcess::init(int newScreenWidth, int newScreenHeight, int POSTRENDER_STEPS)
{
/*
* STATE CHECK
*/
if ( mp_state != INSTANITED )
{
if ( debug )
{
std::cerr << "BloomPostProcess::init() Invalid operation.\n"
<< "\tObject is in wrong state - it must be INSTANITED.\n"
<< "\tYou can get current state by calling getState(). \n"
<< "\tCall getInstance() first, or finalize() and destroy() in that order."
<< std::endl;
}
return GL_INVALID_OPERATION;
}
/*
* AVAILABLE TEXTURE UNITS CHECK
*/
GLint iMAX_TEXT_UNITS= 0;
glGetIntegerv(GL_MAX_TEXTURE_UNITS, &iMAX_TEXT_UNITS);
if ( iMAX_TEXT_UNITS < POSTRENDER_STEPS+1 )
{
std::cerr << "Error: Not enough available textures in multitexturing, required: "
<< POSTRENDER_STEPS+1 <<", implementation have: " << iMAX_TEXT_UNITS
<< std::endl;
return GL_OUT_OF_MEMORY;
}
else
std::cout << "OK: Enough available textures in multitexturing, required: 4, "
<< "implementation have: " << iMAX_TEXT_UNITS
<< std::endl;
if ( POSTRENDER_STEPS != 3 )
{
fprintf(stderr, "Error: Sorry, post render steps value must be 3, different render steps are not implemented yet." );
return GL_INVALID_VALUE;
}
/*
* CFG SAVE
*/
mp_iPostRenderSteps= POSTRENDER_STEPS;
mp_iScreenWidth= newScreenWidth;
mp_iScreenHeight= newScreenHeight;
/*
* FLAT SCREEN MVP ALLOCATION
*/
mp_OrthoMatrix= new M3DMatrix44f[mp_iPostRenderSteps];
mp_ScreenQuad= new GLBatch[mp_iPostRenderSteps];
/*
* TEXTURES VARS ALLOCATION
*/
//TODO
//FREE MEMORY IN FINALIZE
mp_texRendering= new GLuint;
mp_texGlowParts= new GLuint;
mp_texGlowing= new GLuint;
mp_texDownsampled= new GLuint[mp_iPostRenderSteps];
mp_texHoriBlur= new GLuint[mp_iPostRenderSteps];
mp_texVertBlur= new GLuint[mp_iPostRenderSteps];
/*
* FBO & RBO VARS ALLOC
*/
mp_fboRendering= new GLuint;
mp_fboGlowParts= new GLuint;
mp_fboDownsampled= new GLuint[mp_iPostRenderSteps];
mp_fboHoriBlur= new GLuint[mp_iPostRenderSteps];
mp_fboVertBlur= new GLuint[mp_iPostRenderSteps];
mp_fboGlowing= new GLuint;
mp_rboRendering= new GLuint;
/*
* ATTACHMENTS ALLOC AND SETUP
*/
mp_fboBuffs= new GLenum(GL_COLOR_ATTACHMENT0);
mp_fboWindowBuff= new GLenum(GL_BACK_LEFT);
/*
* SHADERS VARS ALLOC
*/
mp_shScreenTextMVP= new GLint;
mp_shBlurHori= new GLint;
mp_shBlurVerti= new GLint;
mp_shPostProcess= new GLint;
GLenum error;
if ( (error= createAndBindFBO(&mp_iScreenWidth,&mp_iScreenHeight,mp_fboRendering,mp_texRendering,mp_rboRendering)) != GL_NO_ERROR )
return error;
if ( (error= createAndBindFBO(&mp_iScreenWidth,&mp_iScreenHeight,mp_fboGlowParts,mp_texGlowParts)) != GL_NO_ERROR )
return error;
int l_screenWidth= mp_iScreenWidth >> 2;
int l_screenHeight= mp_iScreenHeight >> 2;
for ( int i= 0; i < mp_iPostRenderSteps; i++ )
{
gltGenerateOrtho2DMat(l_screenWidth, l_screenHeight, mp_OrthoMatrix[i], mp_ScreenQuad[i]);
if ( (error= createAndBindFBO(&l_screenWidth,&l_screenHeight,&mp_fboDownsampled[i],&mp_texDownsampled[i])) != GL_NO_ERROR )
return error;
if ( (error= createAndBindFBO(&l_screenWidth,&l_screenHeight,&mp_fboHoriBlur[i],&mp_texHoriBlur[i])) != GL_NO_ERROR )
return error;
if ( (error= createAndBindFBO(&l_screenWidth,&l_screenHeight,&mp_fboVertBlur[i],&mp_texVertBlur[i])) != GL_NO_ERROR )
return error;
l_screenWidth= l_screenWidth >> 1;
l_screenHeight= l_screenHeight >> 1;
}
//ladowanie shadera rysowania na ekranie
*mp_shScreenTextMVP = gltLoadShaderPairWithAttributes(
"shadery/textured.vp", "shadery/textured.fp", 2,
GLT_ATTRIBUTE_VERTEX, "vVertex", GLT_ATTRIBUTE_TEXTURE0, "vTexCoords");
//ladowanie shadera rozmycia horyzontalnego
*mp_shBlurHori = gltLoadShaderPairWithAttributes(
"shadery/blurh.vp", "shadery/blurh.fp", 2,
GLT_ATTRIBUTE_VERTEX, "vVertex", GLT_ATTRIBUTE_TEXTURE0, "vTexCoords");
//ladowanie shadera rozmycie pionowego
*mp_shBlurVerti = gltLoadShaderPairWithAttributes(
"shadery/blurv.vp", "shadery/blurv.fp", 2,
GLT_ATTRIBUTE_VERTEX, "vVertex", GLT_ATTRIBUTE_TEXTURE0, "vTexCoords");
//ladowanie shadera rozmycie pionowego
*mp_shPostProcess = gltLoadShaderPairWithAttributes(
"shadery/addition.vp", "shadery/addition.fp", 2,
GLT_ATTRIBUTE_VERTEX, "vVertex", GLT_ATTRIBUTE_TEXTURE0, "vTexCoords");
mp_state= INITIALIZED;
return GL_NO_ERROR;
}
GLenum BloomPostProcess::finalize()
{
if ( mp_state != INITIALIZED )
{
if ( debug )
{
std::cerr << "BloomPostProcess::finalize() Invalid operation.\n"
<< "\tObject is in wrong state - it must be INITIALIZED.\n"
<< "\tYou can get current state by calling getState(). \n"
<< "\tCall init() first."
<< std::endl;
}
return GL_INVALID_OPERATION;
}
// Cleanup textures
for ( int i= 0; i < mp_iPostRenderSteps; i++ )
{
//TODO I HOPE ITS CORRECT :)
glActiveTexture(GL_TEXTURE0 + i);
glBindTexture(GL_TEXTURE_2D, 0);
}
glDeleteTextures(1, mp_texRendering);
glDeleteTextures(1, mp_texGlowParts);
glDeleteTextures(1, mp_texGlowing);
glDeleteTextures(mp_iPostRenderSteps, mp_texDownsampled);
glDeleteTextures(mp_iPostRenderSteps, mp_texHoriBlur);
glDeleteTextures(mp_iPostRenderSteps, mp_texVertBlur);
// Cleanup FBOs
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
glDeleteFramebuffers(mp_iPostRenderSteps, mp_fboDownsampled);
glDeleteFramebuffers(mp_iPostRenderSteps, mp_fboHoriBlur);
glDeleteFramebuffers(mp_iPostRenderSteps, mp_fboVertBlur);
// Cleanup RBOs
glDeleteRenderbuffers(1, mp_rboRendering);
// Cleanup Progams
glUseProgram(0);
glDeleteProgram(*mp_shScreenTextMVP);
glDeleteProgram(*mp_shBlurHori);
glDeleteProgram(*mp_shBlurVerti);
glDeleteProgram(*mp_shPostProcess);
// Cleanup allocated memory
delete [] mp_OrthoMatrix;
delete [] mp_ScreenQuad;
delete mp_texRendering;
delete mp_texGlowParts;
delete mp_texGlowing;
delete [] mp_texDownsampled;
delete [] mp_texHoriBlur;
delete [] mp_texVertBlur;
delete mp_fboRendering;
delete mp_fboGlowParts;
delete [] mp_fboDownsampled;
delete [] mp_fboHoriBlur;
delete [] mp_fboVertBlur;
delete mp_fboGlowing;
delete mp_fboBuffs;
delete mp_fboWindowBuff;
delete mp_rboRendering;
delete mp_shScreenTextMVP;
delete mp_shBlurHori;
delete mp_shBlurVerti;
delete mp_shPostProcess;
mp_state= FINALIZED;
return GL_NO_ERROR;
}
GLenum BloomPostProcess::cleanup()
{
return finalize();
}
GLenum BloomPostProcess::destroy()
{
if ( mp_state != FINALIZED )
{
if ( debug )
{
std::cerr << "BloomPostProcess::destroy() Invalid operation.\n"
<< "\tObject is in wrong state - it must be FINALIZED.\n"
<< "\tYou can get current state by calling getState(). \n"
<< "\tCall finalize() first."
<< std::endl;
}
return GL_INVALID_OPERATION;
}
mp_state= DESTROYED;
delete mp_BloomPostProcess;
return GL_NO_ERROR;
}
GLenum BloomPostProcess::resize(int new_width, int new_height)
{
if ( mp_state != INITIALIZED )
{
if ( debug )
{
std::cerr << "BloomPostProcess::resize() Invalid operation.\n"
<< "\tObject is in wrong state - it must be INITIALIZED.\n"
<< "\tYou can get current state by calling getState(). \n"
<< "\tCall init() first."
<< std::endl;
}
return GL_INVALID_OPERATION;
}
if ( new_height < 16 )
new_height= 16;
if ( new_width < 16 )
new_height= 16;
//New sizes
mp_iScreenWidth= new_width;
mp_iScreenHeight= new_height;
//DELETE PREVIOUS FBOS TEXTURES
// Cleanup textures
for ( int i= 0; i < mp_iPostRenderSteps; i++ )
{
//TODO I HOPE ITS CORRECT :)
glActiveTexture(GL_TEXTURE0 + i);
glBindTexture(GL_TEXTURE_2D, 0);
}
glDeleteTextures(1, mp_texRendering);
glDeleteTextures(1, mp_texGlowParts);
glDeleteTextures(1, mp_texGlowing);
glDeleteTextures(mp_iPostRenderSteps, mp_texDownsampled);
glDeleteTextures(mp_iPostRenderSteps, mp_texHoriBlur);
glDeleteTextures(mp_iPostRenderSteps, mp_texVertBlur);
// Cleanup FBOs
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
glDeleteFramebuffers(mp_iPostRenderSteps, mp_fboDownsampled);
glDeleteFramebuffers(mp_iPostRenderSteps, mp_fboHoriBlur);
glDeleteFramebuffers(mp_iPostRenderSteps, mp_fboVertBlur);
// Cleanup RBOs
glDeleteRenderbuffers(1, mp_rboRendering);
//APPLY NEW SIZES
GLenum error;
if ( (error= createAndBindFBO(&mp_iScreenWidth,&mp_iScreenHeight,mp_fboRendering,mp_texRendering,mp_rboRendering)) != GL_NO_ERROR )
return error;
if ( (error= createAndBindFBO(&mp_iScreenWidth,&mp_iScreenHeight,mp_fboGlowParts,mp_texGlowParts)) != GL_NO_ERROR )
return error;
int l_screenWidth= mp_iScreenWidth >> 2;
int l_screenHeight= mp_iScreenHeight >> 2;
for ( int i= 0; i < mp_iPostRenderSteps; i++ )
{
gltGenerateOrtho2DMat(l_screenWidth, l_screenHeight, mp_OrthoMatrix[i], mp_ScreenQuad[i]);
if ( (error= createAndBindFBO(&l_screenWidth,&l_screenHeight,&mp_fboDownsampled[i],&mp_texDownsampled[i])) != GL_NO_ERROR )
return error;
if ( (error= createAndBindFBO(&l_screenWidth,&l_screenHeight,&mp_fboHoriBlur[i],&mp_texHoriBlur[i])) != GL_NO_ERROR )
return error;
if ( (error= createAndBindFBO(&l_screenWidth,&l_screenHeight,&mp_fboVertBlur[i],&mp_texVertBlur[i])) != GL_NO_ERROR )
return error;
l_screenWidth= l_screenWidth >> 1;
l_screenHeight= l_screenHeight >> 1;
}
return GL_NO_ERROR;
}
GLenum BloomPostProcess::BeginRendering()
{
if ( mp_state != INITIALIZED )
{
if ( debug )
{
std::cerr << "BloomPostProcess::BeginRendering() Invalid operation.\n"
<< "\tObject is in wrong state - it must be INITIALIZED.\n"
<< "\tYou can get current state by calling getState(). \n"
<< "\tCall init() first."
<< std::endl;
}
return GL_INVALID_OPERATION;
}
/*
* After calling this function you shall render your scene as usual
*/
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, *mp_fboRendering);
glDrawBuffers(1, mp_fboBuffs);
mp_state= RENDERED;
return GL_NO_ERROR;
}
GLenum BloomPostProcess::BeginGlowParts()
{
if ( mp_state != RENDERED )
{
if ( debug )
{
std::cerr << "BloomPostProcess::BeginGlowParts() Invalid operation.\n"
<< "\tObject is in wrong state - it must be RENDERED.\n"
<< "\tYou can get current state by calling getState(). \n"
<< "\tCall BeginRender() and render your scene first."
<< std::endl;
}
return GL_INVALID_OPERATION;
}
/*
* After calling this function you shall render ONLY glowing parts
* in way that you find appropriate
*/
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, *mp_fboGlowParts);
glDrawBuffers(1, mp_fboBuffs);
mp_state= PREPROCESSED;
return GL_NO_ERROR;
}
GLenum BloomPostProcess::PostProcess()
{
if ( mp_state != PREPROCESSED )
{
if ( debug )
{
std::cerr << "BloomPostProcess::PostProcess() Invalid operation.\n"
<< "\tObject is in wrong state - it must be PREPROCESSED.\n"
<< "\tYou can get current state by calling getState(). \n"
<< "\tCall BeginGlowParts() and render glow parts on your scene first."
<< std::endl;
}
return GL_INVALID_OPERATION;
}
//todo delete v4color
GLfloat v4color[]= {
1.0f, 1.0f, 1.0f, 1.0f
};
/*
* DOWNSAMPLING
*/
for ( int i= 0; i < mp_iPostRenderSteps; i++ )
{
glViewport(0,0, mp_iScreenWidth >> (i+2), mp_iScreenHeight >> (i+2));
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, mp_fboDownsampled[i]);
glDrawBuffers(1, mp_fboBuffs);
{
//rozmywanie w poziomie >>
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
{
renderTextureOnWholeScreen(mp_texGlowParts,mp_shScreenTextMVP,v4color,i);
}
}
}
/*
* BLURING HORIZONTALLY
*/
for ( int i= 0; i < mp_iPostRenderSteps; i++ )
{
glViewport(0,0, mp_iScreenWidth >> (i+2), mp_iScreenHeight >> (i+2));
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
//bufor do rozmywania w poziomie
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, mp_fboHoriBlur[i]);
glDrawBuffers(1, mp_fboBuffs);
{
//rozmywanie w poziomie >>
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
{
renderTextureOnWholeScreen(&mp_texDownsampled[i],mp_shBlurHori,v4color,i);
}
}
}
/*
* BLUR VERTICALLY
*/
for ( int i= 0; i < mp_iPostRenderSteps; i++ )
{
glViewport(0,0, mp_iScreenWidth >> (i+2), mp_iScreenHeight >> (i+2));
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
//bufor do rozmywania w poziomie
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, mp_fboVertBlur[i]);
glDrawBuffers(1, mp_fboBuffs);
{
//rozmywanie w poziomie >>
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
{
renderTextureOnWholeScreen(&mp_texHoriBlur[i],mp_shBlurVerti,v4color,i);
}
}
}
mp_state= POSTPROCESSED;
return GL_NO_ERROR;
}
GLenum BloomPostProcess::Display()
{
if ( mp_state != POSTPROCESSED )
{
if ( debug )
{
std::cerr << "BloomPostProcess::Display() Invalid operation.\n"
<< "\tObject is in wrong state - it must be POSTPROCESSED.\n"
<< "\tYou can get current state by calling getState(). \n"
<< "\tCall BeginGlowParts() and render your scene first."
<< std::endl;
}
return GL_INVALID_OPERATION;
}
GLfloat v4color[]= {
1.0f, 1.0f, 1.0f, 1.0f
};
glViewport(0,0,mp_iScreenWidth,mp_iScreenHeight);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
glDrawBuffers(1, mp_fboWindowBuff);
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
glUseProgram(*mp_shPostProcess);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, *mp_texRendering);
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, mp_texVertBlur[0]);
glActiveTexture(GL_TEXTURE2);
glBindTexture(GL_TEXTURE_2D, mp_texVertBlur[1]);
glActiveTexture(GL_TEXTURE3);
glBindTexture(GL_TEXTURE_2D, mp_texVertBlur[2]);
//Ustawiam zmienna uniform shadera wierzcholkow - macierz projekcji
GLint locMVP = glGetUniformLocation(*mp_shPostProcess, "mvpMatrix");
glUniformMatrix4fv(locMVP, 1, GL_FALSE, mp_OrthoMatrix[0]);
GLint locColor = glGetUniformLocation(*mp_shPostProcess, "v4color");
glUniform4fv(locColor,1,v4color);
GLint iTextureUniform = glGetUniformLocation(*mp_shPostProcess, "colorMap");
glUniform1i(iTextureUniform, 0);
iTextureUniform = glGetUniformLocation(*mp_shPostProcess, "colorMap0");
glUniform1i(iTextureUniform, 1);
//todo SHADER IS NOT COMPATIBLE WITH DIFFERENT POST RENDER STEPS
// if ( mp_iPostRenderSteps > 1 )
// {
iTextureUniform = glGetUniformLocation(*mp_shPostProcess, "colorMap1");
glUniform1i(iTextureUniform, 2);
// if ( mp_iPostRenderSteps > 2 )
// {
iTextureUniform = glGetUniformLocation(*mp_shPostProcess, "colorMap2");
glUniform1i(iTextureUniform, 3);
// }
// }
mp_ScreenQuad[0].Draw();
mp_state= INITIALIZED;
return GL_NO_ERROR;
}
GLenum BloomPostProcess::createAndBindFBO(int* ScreenWidth, int* ScreenHeight, GLuint* FBO, GLuint* Texture, GLuint* DepthBuffer)
{
if ( ScreenWidth == NULL || ScreenHeight == NULL || FBO == NULL || Texture == NULL )
{
std::cerr << "BloomPostProcess::createAndBindFBO:\n"
<< "\t One of the needed argument is null pointer."
<< std::endl;
return GL_INVALID_VALUE;
}
// Create and bind an FBO
glGenFramebuffers(1,FBO);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, *FBO);
// Create depth renderbuffer
if ( DepthBuffer != 0 )
{
glGenRenderbuffers(1, DepthBuffer);
glBindRenderbuffer(GL_RENDERBUFFER, *DepthBuffer);
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT32, *ScreenWidth, *ScreenHeight);
}
// Create the reflection texture
glGenTextures(1, Texture);
glBindTexture(GL_TEXTURE_2D, *Texture);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, *ScreenWidth, *ScreenHeight, 0, GL_RGBA, GL_FLOAT, NULL);
glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, *Texture, 0);
if ( DepthBuffer != 0 )
glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, *DepthBuffer);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
return gltCheckErrors();
}
GLenum BloomPostProcess::renderTextureOnWholeScreen(GLuint* textureID, GLint* shader, float v4color[4], int i)
{
glUseProgram(*shader);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, *textureID);
//Ustawiam zmienna uniform shadera fragmentow - texture
GLint iTextureUniform = glGetUniformLocation(*shader, "colorMap");
glUniform1i(iTextureUniform, 0);
//Ustawiam zmienna uniform shadera wierzcholkow - macierz projekcji
GLint locMVP = glGetUniformLocation(*shader, "mvpMatrix");
glUniformMatrix4fv(locMVP, 1, GL_FALSE, mp_OrthoMatrix[i]);
GLint locColor = glGetUniformLocation(*shader, "v4color");
glUniform4fv(locColor,1,v4color);
mp_ScreenQuad[i].Draw();
return GL_NO_ERROR;
}

