How can I give the skybox a blur effect like blender? - c++

I am studying OpenGL at Learn-OpenGL.
Here I learned about skybox and framebuffer.
So I can see that I can blur the skybox by capturing it in the framebuffer.
I want to see a screen like this image:
But, when rendering with this framebuffer, the object is overwritten and only the skybox is visible.
this is my code:
glEnable(GL_DEPTH_TEST);
glEnable(GL_BLEND);
glBindFramebuffer(GL_FRAMEBUFFER, skybox_framebuffer->get_fbo());
{
// skybox capture
glViewport(0, 0, skybox_framebuffer->get_width(), skybox_framebuffer->get_height());
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
skybox.draw(camera, projection);
}
glBindFramebuffer(GL_FRAMEBUFFER, 0);
{
glViewport(0, 0, g_window.get_width(), g_window.get_height());
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
skybox_framebuffer->draw();
draw_model(ourModel, ourShader, view, projection);
}
Even changing the drawing order gave the same result:
.
And, if I draw the SKYBOX directly instead of the framebuffer, I get this result:
.
Solution1
I think the solution is to use the stencil buffer.
my solution code:
glBindFramebuffer(GL_FRAMEBUFFER, 0);
{
glViewport(0, 0, g_window.get_width(), g_window.get_height());
glEnable(GL_DEPTH_TEST);
glEnable(GL_STENCIL_TEST);
glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
// draw model
glStencilFunc(GL_ALWAYS, 1, 0xFF);
glStencilMask(0xFF);
draw_model(ourModel, ourShader, view, projection);
// draw skybox framebuffer
glStencilFunc(GL_NOTEQUAL, 1, 0xFF);
glStencilMask(0x00); // disable writing to the stencil buffer
glDisable(GL_DEPTH_TEST);
skybox_framebuffer->draw();
glStencilMask(0xFF);
glStencilFunc(GL_ALWAYS, 1, 0xFF);
glEnable(GL_DEPTH_TEST);
}
and my solution result:
Solution2
using glDepthMask
This shows the same screen as solution1 without the stencil buffer.
glBindFramebuffer(GL_FRAMEBUFFER, 0);
{
glViewport(0, 0, g_window.get_width(), g_window.get_height());
glEnable(GL_DEPTH_TEST);
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glDepthMask(GL_FALSE);
skybox_framebuffer->draw();
glDepthMask(GL_TRUE);
draw_model(ourModel, ourShader, view, projection);
}
question
I could implement it like this,
Is there any way to blur the skybox without using the framebuffer, other than using a blurred image?

Related

Using glTexImage2D to render to texture, blank result. (Dreamcast GLdc)

I am trying to create a quick render to texture example using GLdc, a OpenGL implementation for the Sega Dreamcast. I have verified that both my Texture and Framebuffer Object are complete, yet the texture resulting from the framebuffer only has 1 white dot in it.
First, I generate an empty texture and prepare it to be written to.
func genTextures(){
glGenTextures(1, &renderedTexture[0]);
glBindTexture(GL_TEXTURE_2D, renderedTexture[0]);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR); // scale linearly when image smaller than texture
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 128, 128, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
}
Next, I generate an FBO and bind the new texture we just created to it.
func genFBO() {
glGenFramebuffersEXT(1, &fbo);
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo);
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,
GL_TEXTURE_2D, renderedTexture[0], 0);
}
At this point the FBO and the Texture should both be considered complete. The main loop is structured something like this:
int main(int argc, char **argv)
{
glKosInit();
InitGL(640, 480);
ReSizeGLScene(640, 480);
genTextures();
genFBO();
while(1) {
if(check_start())
break;
// I checked here for FBO and Texture completeness, both return True.
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo); // bind to the FBO
DrawGLScene(); // Draw our cube to the FBO
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); // back to default
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
ReSizeGLScene(640,480);
DrawGLUI(); //Draw the quad with the framebuffers texture
}
return 0;
}
Here are the two functions that draw geometry:
void DrawGLScene()
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);// Clear The Screen And The Depth Buffer
glLoadIdentity(); // Reset The View
glTranslatef(0.0f,0.0f,-5.0f); // move 5 units into the screen.
glRotatef(xrot,1.0f,0.0f,0.0f); // Rotate On The X Axis
glRotatef(yrot,0.0f,1.0f,0.0f); // Rotate On The Y Axis
glRotatef(zrot,0.0f,0.0f,1.0f); // Rotate On The Z Axis
glBindTexture(GL_TEXTURE_2D, texture[0]); // choose the texture to use.
glBegin(GL_QUADS); // begin drawing a cube
// Draw my textured cube, works fine.
glEnd(); // done with the polygon.
xrot+=1.5f; // X Axis Rotation
yrot+=1.5f; // Y Axis Rotation
zrot+=1.5f; // Z Axis Rotation
glKosSwapBuffers();
}
void DrawGLUI(){
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glClearColor(0.0f, 0.0f, 0.0f, 0.0f); // This Will Clear The Background Color To Black
glClearDepth(1.0); // Enables Clearing Of The Depth Buffer
glLoadIdentity();
glMatrixMode(GL_PROJECTION);
glDisable(GL_DEPTH_TEST);
glEnable(GL_TEXTURE_2D);
glLoadIdentity();
glBindTexture(GL_TEXTURE_2D, renderedTexture[0]);
glBegin(GL_QUADS);
//glColor3f(1.0f, 0.0f, 0.0);
glTexCoord2f(0.0, 0.0); glVertex2f(0.0, 0.0);
glTexCoord2f(1.0, 0.0); glVertex2f(1.0, 0.0);
glTexCoord2f(1.0, 1.0); glVertex2f(1.0, 1.0);
glTexCoord2f(0.0, 1.0); glVertex2f(0.0, 1.0);
glEnd();
glEnable(GL_DEPTH_TEST);
ReSizeGLScene(640,480);
glFlush();
}
The result is
Where I would like to have the cube rendered to a texture then that texture applied to the quad in the upper right corner...
The size of the viewport must be adjusted to the size of the framebuffer with glViewport when the framebuffer is switched:
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo);
glViewport(0, 0, 128, 128);
// [...]
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
glViewport(0, 0, 640, 480);
// [...]

Rendering a second pass yields a different result

Currently I'm trying to render multiple passes with different shaders in a simple OpenGL application. Here's my (simplified) code:
void InitScene()
{
glViewport(0, 0, mWindowWidth, mWindowHeight);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0, mWindowWidth, mWindowHeight, 0, -1, 1);
mFramebufferName = CreateFrameBuffer(mWindowWidth, mWindowHeight);
}
void DrawScene()
{
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
if(drawDirectlyToScreen)
{
// This works fine, image will fill the whole screen
// Directly draw to the screen
DrawFullScreenQuad();
}
else
{
// This does not work. The image from the first pass will only be a small quadrat
// Draw to frame buffer instead of screen
glBindFramebuffer(GL_FRAMEBUFFER, mFramebufferName);
DrawFullScreenQuad();
glBindFramebuffer(GL_FRAMEBUFFER, 0);
// Get ready for second pass
BindFrameBufferTextureAndActivateAnotherShader();
// Now draw to the screen
DrawFullScreenQuad();
}
glPopMatrix();
}
void DrawFullScreenQuad()
{
glBegin(GL_QUADS);
glTexCoord2f(0.0f, 1.0f); glVertex3f(0.0f, mWindowHeight, 0.0f);
glTexCoord2f(1.0f, 1.0f); glVertex3f(mWindowWidth, mWindowHeight, 0.0f);
glTexCoord2f(1.0f, 0.0f); glVertex3f(mWindowWidth, 0.0f, 0.0f);
glTexCoord2f(0.0f, 0.0f); glVertex3f(0.0f, 0.0f, 0.0f);
glEnd();
}
void CreateFrameBuffer(int width, int height)
{
// Generate and bind the frame buffer
mFramebufferName = 0;
glGenFramebuffers(1, &mFramebufferName);
glBindFramebuffer(GL_FRAMEBUFFER, mFramebufferName);
// Create and bind the render texture
glGenTextures(1, &mSecondPassRenderTexture);
glBindTexture(GL_TEXTURE_2D, mSecondPassRenderTexture);
// Give an empty image to OpenGL ( the last "0" )
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
// Set "mSecondPassRenderTexture" as colour attachement #0
glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, mSecondPassRenderTexture, 0);
// Set the list of draw buffers.
GLenum DrawBuffers[1] = { GL_COLOR_ATTACHMENT0 };
glDrawBuffers(1, DrawBuffers); // "1" is the size of DrawBuffers
}
When rendering only one pass everything is fine. The image covers the whole screen. When rendering with two passes, the resulting image will only cover a small square area in the top left corner of the screen (see the attached images).
The problem seems to come from the first pass. The texture created in that pass is already wrong (i.e. the image is only in the corner, the rest of the texture is black). The second pass then works correctly (i.e. the broken texture is drawn correctly to the whole screen).
So my question is: why does my call to DrawFullScreenQuad() yield different results when
Rendering to the screen directly
Rendering to a frame buffer (which has the same size as the window)

Object leaves a trail on alpha background

What is a standard reason for this behavior? I have 2 the same buffers with 2 textures of mesh with premultiplied alpha and alpha background: in the first I have object on background, but the second leaves object trail behind itself when I move it on this alpha background. I can't realise why! FBO's are similar.
Thanks!
My mistake was I forgot to bind FBO before clearing:
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glBindFramebuffer(GL_FRAMEBUFFER, FBO);
glBindFramebuffer(GL_FRAMEBUFFER, 0); // WRONG!
glBindFramebuffer(GL_FRAMEBUFFER, FBO);
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
glBindFramebuffer(GL_FRAMEBUFFER, 0); // RIGHT!

OpenGL Rendering to Multiple Textures, results are white

I've begun switching my rendering code to support shaders, and that all works fine when rendering to the back buffer. So now I'm working towards rendering to FBOs, but all I get are white textures for both the color and normals.
Here is my FBO creation code:
void RenderTarget_GL::CreateFBO (void)
{
// if the machine supports the GL FBO extension
if (s_supportfbo)
{
// Create FBO
glGenFramebuffersEXT(1, &m_fbo);
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_fbo);
// Create default texture buffer
char *buffer = new char [static_cast<int>(g_window->GetWidth() * m_screenWidth) * static_cast<int>(g_window->GetHeight() * m_screenHeight) * 4];
std::memset(buffer, 0, static_cast<int>(g_window->GetWidth() * m_screenWidth) * static_cast<int>(g_window->GetHeight() * m_screenHeight) * 4);
// Create Render Texture
glGenTextures(1, &m_rendertexture);
glBindTexture(GL_TEXTURE_2D, m_rendertexture);
glTexImage2D(GL_TEXTURE_2D, 0, 4, static_cast<int>(g_window->GetWidth() * m_screenWidth), static_cast<int>(g_window->GetHeight() * m_screenHeight), 0, GL_RGBA, GL_UNSIGNED_BYTE, buffer);
// Bind Render Texture to FBO
glBindTexture(GL_TEXTURE_2D, 0);
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, m_rendertexture, 0);
// Create Normal Texture if this FBO will be rendering normals
if (m_hasnormal)
{
glGenTextures(1, &m_normaltexture);
glTexImage2D(GL_TEXTURE_2D, 0, 4, static_cast<int>(g_window->GetWidth() * m_screenWidth), static_cast<int>(g_window->GetHeight() * m_screenHeight), 0, GL_RGBA, GL_UNSIGNED_BYTE, buffer);
// Bind Normal Texture to FBO
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT1_EXT, GL_TEXTURE_2D, m_normaltexture, 0);
}
// UnBind FBO and cleanup default buffer
delete [] buffer;
Clear();
}
}
And the code I use to set the current render target:
void RenderTarget_GL::Set (void)
{
if (s_supportfbo && g_glgraphics->GetShaderEnabled())
{
static const GLenum buffer1[] = {GL_COLOR_ATTACHMENT0_EXT};
static const GLenum buffer2[] = {GL_COLOR_ATTACHMENT0_EXT, GL_COLOR_ATTACHMENT1_EXT};
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_fbo);
if (m_hasnormal)
glDrawBuffers(2, buffer2);
else
glDrawBuffers(1, buffer1);
}
}
And finally, my actual drawing code:
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
// Setup the camera transformation
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
if (m_camera)
m_camera->GLMatrix();
else
m_defaultCam.GLMatrix();
// Setup Render Target
if (m_shaderenabled)
{
glPushAttrib(GL_VIEWPORT_BIT);
glViewport(0,0,g_window->GetWidth(),g_window->GetHeight());
m_initialpass->Set();
}
// Draw All Objects with their per-object shaders
// Clear render target and shader bindings
if (m_shaderenabled)
{
glPopAttrib();
RenderTarget_GL::Clear();
Shader_GL::ClearShaderBinding();
}
glPopMatrix();
glMatrixMode(GL_PROJECTION);
glPushMatrix();
glLoadIdentity();
// Draw Scene
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, m_initialpass->GetColorTexture());
glBegin(GL_QUADS);
glTexCoord2f(0.0f, 0.0f);
glVertex3f(-1.0f, -1.0f, 0.0f);
glTexCoord2f(1.0f, 0.0f);
glVertex3f(1.0f, -1.0f, 0.0f);
glTexCoord2f(1.0f, 1.0f);
glVertex3f(1.0f, 1.0f, 0.0f);
glTexCoord2f(0.0f, 1.0f);
glVertex3f(-1.0f, 1.0f, 0.0f);
glEnd();
Texture_GL::ClearTextureBinding();
glPopMatrix();
// Swap Buffers
GL_TEXTURE_MIN_FILTER is GL_NEAREST_MIPMAP_LINEAR by default. Supply mipmaps or switch to GL_LINEAR or GL_NEAREST.
The OpenGL Wiki has more.

Shadow volumes - final stage

I continue to work on shadow volumes in OpenGL, after finishing with volume itself, i need to draw a shadow using stencil buffer, and thats where i'm stuck :) I rendered this scene: http://prntscr.com/17lyr
As you see, sphere represents light source, and one mushroom has its volume drawn directly to the screen, and one hasnt(i expect to see shadow instead). They are absolutely equal, made be translating one model some units on the X axis. Here is the code im working with:
void Display(){
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
glLoadIdentity();
glLightfv(GL_LIGHT1,GL_POSITION,light_position[0]);
cam.SetPrespective();
DrawDebugObject(true);
glTranslatef(15,0,0);
DrawDebugObject(false);
glFinish();
glutSwapBuffers();
}
void DrawDebugObject(bool draw_sil){
glPushMatrix();
glTranslatef(light_position[1][0],light_position[1][1],light_position[1][2]);
glColor3ub(255,255,0);
gluSphere(gluNewQuadric(),0.5,10,10);
glPopMatrix();
glDisable(GL_LIGHTING);
glBegin(GL_QUADS);
glColor3f(1,1,1);
glVertex3f(-100,0,-100);
glVertex3f(-100,0,100);
glVertex3f(100,0,100);
glVertex3f(100,0,-100);
glEnd();
glEnable(GL_LIGHTING);
pModel->draw();
if(draw_sil)
pModel->markSilouette(light_position[1]);
castShadow(pModel,light_position[1]);
}
void castShadow(Model* model,float* lp){
glDisable(GL_LIGHTING);
glDepthMask(GL_FALSE);
glDepthFunc(GL_LEQUAL);
pModel->markVisible(lp);
glEnable(GL_STENCIL_TEST);
glColorMask(0, 0, 0, 0);
glStencilFunc(GL_ALWAYS, 1, 0xffffffff);
// first pass, stencil operation decreases stencil value
glFrontFace(GL_CCW);
glStencilOp(GL_KEEP, GL_KEEP, GL_INCR);
pModel->markSilouette(lp);
// second pass, stencil operation increases stencil value
glFrontFace(GL_CW);
glStencilOp(GL_KEEP, GL_KEEP, GL_DECR);
pModel->markSilouette(lp);
glFrontFace(GL_CCW);
glColorMask(1, 1, 1, 1);
//draw a shadowing rectangle covering the entire screen
glColor4f(1.0f, 0.0f, 0.0f, 0.4f);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glStencilFunc(GL_NOTEQUAL, 0, 0xffffffff);
glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
glPushMatrix();
glLoadIdentity();
glBegin(GL_QUADS);
glVertex3f(-0.1f, 0.1f,-0.10f);
glVertex3f(-0.1f,-0.1f,-0.10f);
glVertex3f( 0.1f, 0.1f,-0.10f);
glVertex3f( 0.1f,-0.1f,-0.10f);
glEnd();
glPopMatrix();
glDisable(GL_BLEND);
glDepthFunc(GL_LEQUAL);
glDepthMask(GL_TRUE);
glEnable(GL_LIGHTING);
glDisable(GL_STENCIL_TEST);
}
Here is my GL initialization function:
void InitGL(){
glEnable(GL_NORMALIZE);
glEnable(GL_LIGHTING);
glEnable(GL_TEXTURE_2D);
glShadeModel(GL_SMOOTH);
glClearDepth(1.0f); // Depth Buffer Setup
glClearStencil(0); // Stencil Buffer Setup
glEnable(GL_DEPTH_TEST); // Enables Depth Testing
glDepthFunc(GL_LEQUAL); // The Type Of Depth Testing To Do
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); // Really Nice Perspective Calculations
glHint(GL_LINE_SMOOTH_HINT, GL_NICEST);
glHint(GL_POLYGON_SMOOTH_HINT, GL_NICEST);
glHint(GL_FOG_HINT, GL_NICEST);
...nothing important after that
And in my main function:
glutInit(&argc,argv);
glutInitDisplayMode(GLUT_RGB|GLUT_DEPTH|GLUT_DOUBLE|GLUT_STENCIL|GLUT_ACCUM);
glutInitWindowSize(Width,Height);
glutCreateWindow("Spheres");
glutDisplayFunc(Display);
glutReshapeFunc(Reshape);
glutKeyboardFunc(Keyboard);
glutKeyboardUpFunc(KeyboardUp);
glutTimerFunc(TIMEOUT,Timer,TIMEOUT);
glutPassiveMotionFunc(MouseMove);
Is everything ok with my code? Because i dont see shadow and dont even know how to check if stencil values are set correctly.
There is no way to check stencils afaik. I am going to assume you are using depth fail. I recommend using glStencilOpSeperate like so.
glClear(GL_STENCIL_BUFFER_BIT);
glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
glEnable(GL_STENCIL_TEST);
glEnable(GL_POLYGON_OFFSET_FILL);
glDisable(GL_CULL_FACE);
glStencilFunc(GL_ALWAYS, 0x00, 0xFF);
glStencilOpSeparate(GL_FRONT, GL_KEEP, GL_INCR_WRAP, GL_KEEP);
glStencilOpSeparate(GL_BACK, GL_KEEP, GL_DECR_WRAP, GL_KEEP);
glPolygonOffset(0.0f, 5.0f);
glDepthFunc(GL_LESS);
Then when you draw the actual geometry make sure you are replacing stencil values like so:
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
glEnable(GL_CULL_FACE);
glDisable(GL_POLYGON_OFFSET_FILL);
glCullFace(GL_BACK);
glDepthFunc(GL_GEQUAL);
glStencilFunc(GL_EQUAL, 0x00, 0xFF);
glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE);