PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : OpenGL/GLSL Blur-Shader und FBO


Gast
2012-01-15, 22:04:59
Abend,

ich bin gerade dabei einen simplen Blur-Shader zu erstellen, der einfach nur auf die gesamte Szene einen Gaußian-Blur anwendet. So weit bin ich bis jetzt:
Die Szene wird zunächst in ein FrameBufferObject (FBO) gerendert. Die Textur des FBOs wird dann auf ein Quad gelegt, das so groß ist wie der gesamte Bildschirm. Auf das texturierte Quad wird ein Gauß-Filter angewendet, jedoch bisher nur in vertikaler Richtung - also ein klassicher Postprocessing-Blur.

Was fehlt:
Der Blur auch in horizontaler Richtung. Dazu würde ich jetzt wie folgt vorgehen:
1. Die Szene wird in das erste FrameBufferObject gerendert.
2. Die Textur des ersten FBOs lege ich dann auf ein Quad und wende den vertikalen Blur-Shader darauf an. (ALSO BISHER SO WIE OBEN BESCHRIEBEN)
Die ganze Szene wird in ein zweites FBO gerendert.
3. Die Textur des zweiten FBOs wird auf ein neues Quad gebunden und dieses Quad wird dann ohne FBO gerendert und auf das Quad wiederum der horizontale Blur angewendet.

Jedoch bleibt die Szene bzw das zweite Quad einfach nur schwarz, auch ohne zweiten Blur. Also müsste irgendwas mit dem zweiten FBO nicht hinhaun. Ich bin leider relativ neu im Umgang mit FBOs und weiß deshalb nichtmal ob man zwei FBOs einsetzen kann...

Weiß jemand Rat?

Ganon
2012-01-15, 22:17:08
Ich hatte das auch mal so gemacht, wie du das da beschrieben hast und es funktionierte. Du musst halt bei OpenGL recht genau aufpassen in welcher Reihenfolge du was machst und was du wo aktivierst und deaktivierst.

Aber vllt. gibt es da auch noch eine schnellere Variante, weil ich erinnere mich noch, dass das Ergebnis nicht gerade schnell war.

Gast
2012-01-15, 22:25:10
Schnelligkeit ist mir erstmal egal, es muss nur funktionieren. ;) Könntest du bitte eventuell Mal schnell über den Code meiner display-Methode schaun:


// FIRST: RENDER TEAPOT IN FBO1
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo.getFboID()); // Bind frame buffer for rendering
// Push glEnable, glViewport and glLight states to store the original values and restore them after rendering to the fbo
glPushAttrib(GL_VIEWPORT_BIT | GL_ENABLE_BIT | GL_LIGHTING_BIT);

glViewport(0, 0, windowWidth, windowHeight); // Set the size of the frame buffer view port


// proceed as in the display method
glClearColor (1.0f, 0.0f, 0.0f, 0.0f); // Set the clear colour
glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Clear the depth and colour buffers

glLoadIdentity(); // Reset the modelview matrix
// render teapot
renderTeapot();


// restore previouse state after rendering to the buffer is finished
glPopAttrib(); // Restore glEnable and glViewport states
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); // Unbind our texture



// create quad for binding the fbo to it
//renderFboQuad();
/* */

// SECOND: BIND FBO1-TEXTURE ON QUAD AN APPLY SHADER ON QUAD + RENDER QUAD IN FBO2
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo2.getFboID()); // Bind frame buffer for rendering
// Push glEnable, glViewport and glLight states to store the original values and restore them after rendering to the fbo
glPushAttrib(GL_VIEWPORT_BIT | GL_ENABLE_BIT | GL_LIGHTING_BIT);

glViewport(0, 0, windowWidth, windowHeight); // Set the size of the frame buffer view port

// proceed as in the display method
glClearColor (0.0f, 1.0f, 0.0f, 0.0f); // Set the clear colour
glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Clear the depth and colour buffers

glLoadIdentity(); // Reset the modelview matrix



// binding the shader to the quad
bloom.bind();
// set glsl-uniform parameters
// set the sigma of the gauss function defining the blur-intensity
GLint sigma = glGetUniformLocation(bloom.getID(), "sigma");
glUniform2f(sigma, blurIntensity / windowWidth, 0.0);
// set the source texture that will be blurred
GLint sourceTexture = glGetUniformLocation(bloom.getID(), "sourceTexture");
glUniform1i(sourceTexture, 0);


glBindTexture(GL_TEXTURE_2D, fbo.getFboTextureID()); // bind frame buffer texture before attaching it to the quad


glBegin(GL_QUADS);

glTexCoord2f(0.0f, 0.0f);
glVertex3f(-1.0f, -1.0f, 0.0f); // The bottom left corner

glTexCoord2f(0.0f, 1.0f);
glVertex3f(-1.0f, 1.0f, 0.0f); // The top left corner

glTexCoord2f(1.0f, 1.0f);
glVertex3f(1.0f, 1.0f, 0.0f); // The top right corner

glTexCoord2f(1.0f, 0.0f);
glVertex3f(1.0f, -1.0f, 0.0f); // The bottom right corner

glEnd();

// unbind the frame buffer texture after attaching it to the quad
glBindTexture(GL_TEXTURE_2D, 0);

// unbind shader after applying it to the quad
bloom.unbind();


// restore previouse state after rendering to the buffer is finished
glPopAttrib(); // Restore glEnable and glViewport states
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); // Unbind our texture

/* */

// THIRD: BIND TEXTURE ON NEW QUAD. OUTPUT THIS QUAD
glClearColor (0.5, 0.5, 0.5, 1.0);
glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // clear the color buffer

glLoadIdentity(); // Load the Identity Matrix to reset our drawing locations
gluLookAt (0.0, 0.0, 2.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);

//renderFboQuad();

glBindTexture(GL_TEXTURE_2D, fbo2.getFboTextureID()); // bind frame buffer texture before attaching it to the quad


glBegin(GL_QUADS);

glTexCoord2f(0.0f, 0.0f);
glVertex3f(-1.0f, -1.0f, 0.0f); // The bottom left corner

glTexCoord2f(0.0f, 1.0f);
glVertex3f(-1.0f, 1.0f, 0.0f); // The top left corner

glTexCoord2f(1.0f, 1.0f);
glVertex3f(1.0f, 1.0f, 0.0f); // The top right corner

glTexCoord2f(1.0f, 0.0f);
glVertex3f(1.0f, -1.0f, 0.0f); // The bottom right corner

glEnd();

// unbind the frame buffer texture after attaching it to the quad
glBindTexture(GL_TEXTURE_2D, 0);


glutSwapBuffers();

Gast
2012-01-15, 22:48:43
Ok, habs gelöst. Du hattest recht, ich hab nicht gut genug aufgepasst wo ich wann was setze:
gluLookAt war vor dem binden des ersten Quads falsch! Hier der richtige Code, bereits mit integriertem horizontalem Blur und sehr dirty Code:


// FIRST: RENDER TEAPOT IN FBO1
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo.getFboID()); // Bind frame buffer for rendering
// Push glEnable, glViewport and glLight states to store the original values and restore them after rendering to the fbo
glPushAttrib(GL_VIEWPORT_BIT | GL_ENABLE_BIT | GL_LIGHTING_BIT);

glViewport(0, 0, windowWidth, windowHeight); // Set the size of the frame buffer view port


// proceed as in the display method
glClearColor (1.0f, 0.0f, 0.0f, 0.0f); // Set the clear colour
glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Clear the depth and colour buffers

glLoadIdentity(); // Reset the modelview matrix
// render teapot
renderTeapot();


// restore previouse state after rendering to the buffer is finished
glPopAttrib(); // Restore glEnable and glViewport states
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); // Unbind our texture



// create quad for binding the fbo to it
//renderFboQuad();
/* */

// SECOND: BIND FBO1-TEXTURE ON QUAD AN APPLY SHADER ON QUAD + RENDER QUAD IN FBO2
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo2.getFboID()); // Bind frame buffer for rendering
// Push glEnable, glViewport and glLight states to store the original values and restore them after rendering to the fbo
glPushAttrib(GL_VIEWPORT_BIT | GL_ENABLE_BIT | GL_LIGHTING_BIT);

glViewport(0, 0, windowWidth, windowHeight); // Set the size of the frame buffer view port

// proceed as in the display method
glClearColor (0.5, 0.5, 0.5, 1.0);
glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // clear the color buffer

glLoadIdentity(); // Load the Identity Matrix to reset our drawing locations
gluLookAt (0.0, 0.0, 2.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);



// binding the shader to the quad
bloom.bind();
// set glsl-uniform parameters
// set the sigma of the gauss function defining the blur-intensity
GLint sigma = glGetUniformLocation(bloom.getID(), "sigma");
glUniform2f(sigma, blurIntensity / windowWidth, 0.0);
// set the source texture that will be blurred
GLint sourceTexture = glGetUniformLocation(bloom.getID(), "sourceTexture");
glUniform1i(sourceTexture, 0);


glBindTexture(GL_TEXTURE_2D, fbo.getFboTextureID()); // bind frame buffer texture before attaching it to the quad


glBegin(GL_QUADS);

glTexCoord2f(0.0f, 0.0f);
glVertex3f(-1.0f, -1.0f, 0.0f); // The bottom left corner

glTexCoord2f(0.0f, 1.0f);
glVertex3f(-1.0f, 1.0f, 0.0f); // The top left corner

glTexCoord2f(1.0f, 1.0f);
glVertex3f(1.0f, 1.0f, 0.0f); // The top right corner

glTexCoord2f(1.0f, 0.0f);
glVertex3f(1.0f, -1.0f, 0.0f); // The bottom right corner

glEnd();

// unbind the frame buffer texture after attaching it to the quad
glBindTexture(GL_TEXTURE_2D, 0);

// unbind shader after applying it to the quad
bloom.unbind();


// restore previouse state after rendering to the buffer is finished
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); // Unbind our texture

/* */

// THIRD: BIND TEXTURE ON NEW QUAD. OUTPUT THIS QUAD


//renderFboQuad();
// binding the shader to the quad
bloom.bind();
// set glsl-uniform parameters
// set the sigma of the gauss function defining the blur-intensity
sigma = glGetUniformLocation(bloom.getID(), "sigma");
glUniform2f(sigma, 0.0, blurIntensity / windowHeight);
// set the source texture that will be blurred
sourceTexture = glGetUniformLocation(bloom.getID(), "sourceTexture");
glUniform1i(sourceTexture, 0);

glBindTexture(GL_TEXTURE_2D, fbo2.getFboTextureID()); // bind frame buffer texture before attaching it to the quad
glClearColor (0.5, 0.5, 0.5, 1.0);
glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // clear the color buffer

glLoadIdentity(); // Load the Identity Matrix to reset our drawing locations
gluLookAt (0.0, 0.0, 2.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);

glBegin(GL_QUADS);

glTexCoord2f(0.0f, 0.0f);
glVertex3f(-1.0f, -1.0f, 0.0f); // The bottom left corner

glTexCoord2f(0.0f, 1.0f);
glVertex3f(-1.0f, 1.0f, 0.0f); // The top left corner

glTexCoord2f(1.0f, 1.0f);
glVertex3f(1.0f, 1.0f, 0.0f); // The top right corner

glTexCoord2f(1.0f, 0.0f);
glVertex3f(1.0f, -1.0f, 0.0f); // The bottom right corner

glEnd();

// unbind the frame buffer texture after attaching it to the quad
glBindTexture(GL_TEXTURE_2D, 0);

// unbind shader after applying it to the quad
bloom.unbind();

glutSwapBuffers();



ABER MEINE NÄCHSTE FRAGE:
Wie kann ich nun nur einzelne Objekte blurren? Also zb, dass nur der helle Hintergrund ein Objekt überstrahlt - siehe:
http://666kb.com/i/c0f10jlezp1gu247r.jpg

SaschaW
2012-01-16, 09:58:29
Mit einem separaten Blurpass. Du renderst dort dann halt nur die Teile bunt/hell die auch überstrahlen können, also in dem geposteten Bild würde nur der Hintergrund farbig im Blurpass gerendert, alle anderen Objekte die nicht überstrahlen dann komplett schwarz, ohne Texturen etc. Kann man ja heutzutage schön über einen Shader regeln der dann mit passender Flag nur schwarz rendert und ansonsten normal.