My problem is that after having set up a frame buffer object with a single colour texture attached to the GL_COLOR_ATTACHMENT0 point and rendering a number of objects to this texture when I then go to draw this to the screen I get a completely white texture.
Now I know the drawing code is correct as I can draw to the back buffer just fine, it's simply when the frame buffer becomes involved that the problem occurs. The drawing code uses a very basic shader that textures a quad.
My code is below:
// Create the FBO
glGenFramebuffers(1, &m_gbufferFBO);
glBindFramebuffer(GL_FRAMEBUFFER, m_gbufferFBO);
// Create a colour texture for use in the fbo
glGenTextures(1, &m_colourBuffer);
glBindTexture(GL_TEXTURE_2D, m_colourBuffer);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, m_width, m_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_colourBuffer, 0);
// check if the frame buffer was successfully created
CheckFrameBufferErrors();
CheckGLErrors();
// Begin rendering with the frame buffer
glBindFramebuffer(GL_FRAMEBUFFER, m_gbufferFBO);
glPushAttrib(GL_VIEWPORT_BIT | GL_COLOR_BUFFER_BIT);
// Set the viewport to match the width and height of our FBO
glViewport(0, 0, m_width, m_height);
glDrawBuffer(GL_COLOR_ATTACHMENT0);
// Clear buffer to whatever the clear colour is set to
glClearColor(m_clearColour.GetR(), m_clearColour.GetG(), m_clearColour.GetB(), m_clearColour.GetA());
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT );
Game::GetInstance().GetCamera()->ApplyViewTransform();
// RENDERING OF OBJECTS
glPopAttrib();
glBindFramebuffer(GL_FRAMEBUFFER, 0);
Then the buffer's colour texture is rendered to the screen using the fixed function pipeline.
glDisable(GL_DEPTH_TEST);
glDisable(GL_BLEND);
glActiveTexture(GL_TEXTURE0);
glEnable(GL_TEXTURE_2D);
// Render the colour buffer to screen
glBindTexture(GL_TEXTURE_2D, m_colourBuffer);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glBegin(GL_QUADS);
glTexCoord2f(0.f, 0.f); glVertex3f(0.f, 0.f, 0.f);
glTexCoord2f(1.f, 0.f); glVertex3f(m_width, 0.f, 0.f);
glTexCoord2f(1.f, 1.f); glVertex3f(m_width, m_height, 0.f);
glTexCoord2f(0.f, 1.f); glVertex3f(0.f, m_height, 0.f);
glEnd();
Any ideas on what I could be doing wrong here?
The FBO attached texture must not be bound, when the FBO is bound. A texture can never be a data source and sink at the same time.
For all texturing units and targets to which the texture has been bound you must bind another or no texture before binding the FBO as render destination.
Related
So, i have this assignment about double pass rendering to compute shadows and I am trying to store the depth value of each of the objects of a scene and rendering them as a texture in another object.
I am using OpenGL, I don't really know where the error could be, but when analyzing a capture with RenderDoc, it says that the FBO (FrameBufferObject) is unused and also interprets what should be my 1st pass, a depth only pass, as a color pass.
/*-This is how I create the FBO and the texture to render the depth-*/
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LESS);
// Create texture for Depth image (first pass)
glGenTextures(1, &depthTexture);
glBindTexture(GL_TEXTURE_2D, depthTexture);
// Give pixel data to opengl
glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, 1024, 1024, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, nullptr);
// WITH PCF for anti-aliasing shadow edges
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
glGenFramebuffers(1, &FBO);
glBindFramebuffer(GL_FRAMEBUFFER, FBO);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D,
depthTexture, 0);
glDrawBuffer(GL_NONE);
glReadBuffer(GL_NONE);
glBindFramebuffer(GL_FRAMEBUFFER, 0);
/*---------------------------END------------------------------------*/
/*---This is how I render all the objects (1st and second pass)-----*/
glViewport(0, 0, 1024, 1024);
glClearColor(0.3f, 0.3f, 0.3f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
cube.FirstPass(light.getPos());
plane.FirstPass(light.getPos());
cone1.FirstPass(light.getPos());
cone2.FirstPass(light.getPos());
glFlush();
glFinish();
glViewport(0, 0, WIDTH, HEIGHT);
glClearColor(0.3f, 0.3f, 0.3f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
cube.display(&cam, light.getPos());
plane.display(&cam, light.getPos());
viewport.display(&cam, light.getPos());
cone1.display(&cam, light.getPos());
cone2.display(&cam, light.getPos());
/*---------------------------END------------------------------------*/
/*---------This is how I do First Pass---------*/
//Here goes first pass
glBindFramebuffer(GL_FRAMEBUFFER, sceneManager.getFBO());
glClear(GL_DEPTH_BUFFER_BIT);
glUseProgram(DepthPass.shader);
glm::mat4 mtx = glm::perspective(glm::radians(60.0f), 1024.0f / 1024.0f, 5.0f, 40.0f);
DepthPass.setMat("M", mtx * glm::lookAt(glm::vec3(lightPos.x, lightPos.y, lightPos.z), glm::vec3(0.0, 0.0, 0.0), glm::vec3(0.0, 1.0, 0.0)) *
getModelToWorld());
glBindVertexArray(vao);
// Draw
glDrawArrays(GL_TRIANGLES, 0, ModelVertices.size());
glBindFramebuffer(GL_FRAMEBUFFER, 0);
/*---------------------------END------------------------------------*/
/*--This is what I pass to the shader that shows the depth texture--*/
DepthPass.setFloat("near", 5.0f);
DepthPass.setFloat("far", 40.0);
DepthPass.setInt("IsViewport", 1);
glActiveTexture(GL_TEXTURE0);
//GetDepthTexture() returns a handle of the texture created before
glBindTexture(GL_TEXTURE_2D, sceneManager.GetDepthTexture());
std::string textureName = "depthTexture";
DepthPass.setInt(textureName.c_str(), sceneManager.GetDepthTexture());
/*---------------------------END------------------------------------*/
I am trying to render a texture to a surface from a FBO but I am getting a repeat image effect like this: Repeating Image effect
I am not sure what is doing this. I am adapting the code from this tutorial: https://www.youtube.com/watch?v=21UsMuFTN0k which is in java to c++.
This is my code i use to setup to FBO:
GLuint frameBuffer;
glGenFramebuffers(1, &frameBuffer);
//generate name for frame buffer
glBindFramebuffer(GL_FRAMEBUFFER, frameBuffer);
//create the framebuffer
glDrawBuffer(GL_COLOR_ATTACHMENT0);
//indicate that we will always render to color attachment 0
//texture setup
GLuint texture;
glGenTextures(1, &texture);
glBindTexture(GL_TEXTURE_2D, texture);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 320, 180, 0, GL_RGB, GL_UNSIGNED_BYTE, 0);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,texture, 0);
//depth buffer setup
GLuint depthBuffer;
glGenRenderbuffers(1, &depthBuffer);
glBindRenderbuffer(GL_RENDERBUFFER, depthBuffer);
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, 320, 180);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depthBuffer);
This section is used to render:
//water is two triangle joined together
Water test(texture);
render->addWater(&test);
while (!glfwWindowShouldClose(window))
{
// Set frame time
GLfloat currentFrame = (float)glfwGetTime();
deltaTime = currentFrame - lastFrame;
lastFrame = currentFrame;
glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
gameController->update(deltaTime);
glBindTexture(GL_TEXTURE_2D, 0);//To make sure the texture isn't bound
glBindFramebuffer(GL_FRAMEBUFFER, frameBuffer);
glViewport(0, 0, 320, 180);
render->renderScene();
glBindFramebuffer(GL_FRAMEBUFFER, 0);
glViewport(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT);
render->renderScene();
render->renderWater();
glfwSwapBuffers(window);
}
If there is any other code that is needed, let me know.
The "repeat image" effect is caused, because you don't clear the framebuffer (color attachment texture and render buffer for the depth).
It is not sufficient to clear the drawing buffer. You have to clar the color plane and the depth buffer of the framebuffer too.
Bind the framebuffer, set the clear color (background of the texture) and clear the frame buffer. This causes that the each texel of the texture object is set to the color which you specify by glClearColor right before and the render buffer object (depthBuffer) is cleared (set to 1.0 - default value see glClearDepth).
glBindFramebuffer(GL_FRAMEBUFFER, frameBuffer);
glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
After rendering to the texture, set the default framebuffer for rendering, set the background color and clear the buffer:
glBindFramebuffer(GL_FRAMEBUFFER, 0);
glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
I am trying to do OpenGL GLSL based shadow mapping. The trouble is that after I have finished rendering the shadow map, I am rendering the map to the screen to test whether the rendering works correctly or not i.e I am simply using the newly generated texture as a texture which I am mapping on to the screen. The expected result is that I will see the new texture. But instead, what i am seeing is a white area with the texture drawn but extremely faint. That is, if I tilt the screen at a certain angle only then I can see the faint outlines of the shadow map.
Can anyone tell me if I am doing anything wrong?
Here is relevant parts of my code :
void Init_FBO()
{
//glActiveTexture(GL_TEXTURE3);
GLfloat border[] = {1.0f, 0.0f, 0.0f, 0.0f};
glGenTextures(1, &depthTex);
glBindTexture(GL_TEXTURE_2D, depthTex);
glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT24,900,900, 0, GL_DEPTH_COMPONENT, GL_FLOAT, NULL);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, border);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_REF_TO_TEXTURE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC, GL_LESS);
glBindTexture(GL_TEXTURE_2D,0);
glGenFramebuffers(1, &shadowFBO);
glBindFramebuffer(GL_FRAMEBUFFER, shadowFBO);
glDrawBuffer(GL_NONE);
glReadBuffer(GL_NONE);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, depthTex, 0);
glBindFramebuffer(GL_FRAMEBUFFER, 0); // go back to the default framebuffer
// check FBO status
GLenum FBOstatus = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER);
if(FBOstatus != GL_FRAMEBUFFER_COMPLETE)
{
printf("GL_FRAMEBUFFER_COMPLETE failed, CANNOT use FBO\n");
}
else
{
printf("Frame Buffer Done Succesfully\n");
}
}
void generateShadowTex()
{
//Calculate final ligting properties
glm::vec4 a_f=light_ambient*mat_ambient;
glm::vec4 d_f=light_diffuse*mat_diffuse;
glm::vec4 s_f=light_specular*mat_specular;
int counter=0;
glEnable(GL_DEPTH_TEST); // need depth test to correctly draw 3D objects
glClearColor(0,0,0,1);
//glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
glClear(GL_DEPTH_BUFFER_BIT);
glCullFace(GL_FRONT);
if(wframe)
glPolygonMode(GL_FRONT_AND_BACK,GL_LINE);
else
glPolygonMode(GL_FRONT_AND_BACK,GL_FILL);
glUseProgram(programObject);
//Draw the stuff using Light Position as camera
//glutSwapBuffers();
glActiveTexture(GL_TEXTURE3);
glBindTexture(GL_TEXTURE_2D,depthTex);
glUseProgram(0);
}
void generateScene()
{
//Calculate final ligting properties
glm::vec4 a_f=light_ambient*mat_ambient;
glm::vec4 d_f=light_diffuse*mat_diffuse;
glm::vec4 s_f=light_specular*mat_specular;
int counter=0;
glEnable(GL_DEPTH_TEST); // need depth test to correctly draw 3D objects
glClearColor(0,0,0,1);
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
//Draw the stuff using camera as camera position
}
glutSwapBuffers();
glUseProgram(0);
}
void display()
{
glBindFramebuffer(GL_FRAMEBUFFER, shadowFBO);
generateShadowTex();
glBindFramebuffer(GL_FRAMEBUFFER, 0);
generateScene();
}
your depth texture is looking normally, depth covers range from near to far clip planes, you can set some reasonable clipping planes using glFrustumf(...)
I have been trying to render a teapot to a FBO and then use the subsequent texture as a texture map. nothing seems to come up, so I was wondering what I was doing wrong. Below is the main loop:
//switch to fbo
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
gluLookAt(0.0,0.0,5.0,
0.0,0.0,-1.0,
0.0f,1.0f,0.0f);
glLightfv(GL_LIGHT0, GL_POSITION, lpos);
glRotatef(a,0,1,1);
glutSolidTeapot(1);
//switch to main
glBindFramebuffer(GL_FRAMEBUFFER, 0);
glLoadIdentity();
gluLookAt(0.0,0.0,5.0,
0.0,0.0,-1.0,
0.0f,1.0f,0.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glBindTexture(GL_TEXTURE_2D, img);
//draw cube
glColor4f(1, 1, 1, 1);
glBegin(GL_TRIANGLES);
// front faces
glNormal3f(0,0,1);
// face v0-v1-v2
glTexCoord2f(1,1); glVertex3f(1,1,1);
glTexCoord2f(0,1); glVertex3f(-1,1,1);
glTexCoord2f(0,0); glVertex3f(-1,-1,1);
...draws cube
I have tried using the glFramebufferStatus and it has returned "success"
glGenTextures(1, &img);
glBindTexture(GL_TEXTURE_2D, img);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 512, 512, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
glGenFramebuffers(1,&fbo);
glBindFramebuffer(GL_FRAMEBUFFER,fbo);
glGenRenderbuffers(1, &depthbuffer);
glBindRenderbuffer(GL_RENDERBUFFER, depthbuffer);
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, 512, 512);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depthbuffer);
glGenTextures(1, &img);
glBindTexture(GL_TEXTURE_2D, img);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 512, 512, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, img, 0);
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
if (status==GL_FRAMEBUFFER_COMPLETE) {
printf("success\n");
}
However, all I get is the cube with no texture mapping.
There are two possible errors here:
Rendering into the FBO fails. To check if this is the case, clear the FBO with a distinct background color (e.g. pink) and see if the texture is affected (by reading it back to the CPU, for example). You should also make sure that your transformation matrices and the viewport (glViewport) are correct.
Texture mapping fails. Make sure that you've got everything set up for texture mapping and test texture mapping with a static texture first.
What about glEnable ( GL_TEXTURE_2D ) ?
I want to draw edges of an object with hidden edges removed. The idea I want to apply is to render the object's faces first to the depth buffer, then in a second pass drawing the edges with depth testing enabled.
Since not all triangle edges should be visible, the edges are stored separately (simple example: in a cube, the diagonal edges should not be visible, although they are there since a quad is rendered as two triangles). The faces are therefore drawn using GL_TRIANGLES, the edges are drawn uing GL_LINES with a separate vertex buffer.
The problem is that hidden edges are partly shown with this setup, and that visible edges are partly hidden. How can I achieve a proper result?
without depth testing:
with depth testing:
faces which are rendered to depth buffer:
I use a framebuffer with an attached color and depth buffer to draw my object.
// Color buffer setup.
glBindTexture(GL_TEXTURE_2D, objectEdges);
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_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 640, 360, 0, GL_RGBA, GL_UNSIGNED_BYTE, nil);
// Depth buffer setup.
glBindRenderbuffer(GL_RENDERBUFFER, objectFaces);
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, 640, 360);
// Framebuffer setup.
glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
GL_TEXTURE_2D, objectEdges, 0);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
GL_RENDERBUFFER, objectFaces);
assert(glCheckFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE);
assert(glGetError() == GL_NO_ERROR);
This setup works without any problems. I draw my object as following:
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LEQUAL);
glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
glDepthMask(GL_TRUE);
glBindVertexArrayOES(vertexArray_faces);
glDrawArrays(GL_TRIANGLES, 0, vertexCount_faces);
glBindVertexArrayOES(0);
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
glDepthMask(GL_FALSE);
glBindVertexArrayOES(vertexArray_edges);
glDrawArrays(GL_LINES, 0, vertexCount_edges);
glBindVertexArrayOES(0);
glDisable(GL_DEPTH_TEST);
The used shader is just a standard model-view-projection vertex shader, and a fragment shader which outputs white for all fragments.
GLKMatrix4 projectionMatrix =
GLKMatrix4MakePerspective(
GLKMathDegreesToRadians(65.0f), 640.0 / 360.0f, 0.01f, 10.0f);
GLKMatrix4 modelViewMatrix =
GLKMatrix4MakeLookAt(0.2f, 0.4f, 0.2f, 0.2f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f);
You're running into the issue that depth values are calculated for lines slightly differently than for filled primitives. The very thing you try to do is one of the reasons for the existance of the so called "polygon offest". The whole thing is described in the official programming guide in the appendix: "Hidden-Line Removal"