I am doing this from a tutorial and i have exactly the code from the tutorial. But for some reason is not working. So i debugged and i saw that it had a 36060 error also know as GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER as far as i know and i don't really understand why. I searched for answers and everybody said about glReadBuffer(GL_NONE); But even with that i get the same error.
bool ShadowMapFBO::Init(unsigned int WindowWidth, unsigned int WindowHeight)
{
// Create the FBO
glGenFramebuffers(1, &m_fbo);
// Create the depth buffer
glGenTextures(1, &m_shadowMap);
glBindTexture(GL_TEXTURE_2D, m_shadowMap);
glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, WindowWidth, WindowHeight, 0, GL_DEPTH_COMPONENT, GL_FLOAT, NULL);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, m_fbo);
glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, m_shadowMap, 0);
// Disable writes to the color buffer
glDrawBuffer(GL_NONE);
glReadBuffer(GL_NONE);
GLenum Status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
if (Status != GL_FRAMEBUFFER_COMPLETE) {
printf("FB error, status: 0x%x\n", Status);
return false;
}
return true;
}
EDIT: seems like glReadBuffer doesn't work at all and I don't know why. I tried glGetError and i got no error
I solved the problem. Seems like I had to add glBindFramebuffer(GL_READ_FRAMEBUFFER, m_fbo);
Seems like if you don't need it if you have a nvidia video card. I had a intel integrated video card and that's why it didn't worked.
Related
I render the color (GL_COLOR_ATTACHMENT0) and depth (GL_DEPTH_ATTACHMENT) of my scene into a FBO, which works fine on PC with OpenGL 4+.
But on my Smartphone with OpenGL ES 3.1+ I always get for the depth via glCheckFramebufferStatus(GL_FRAMEBUFFER) the status = 36054.
glGenTextures(1, &m_textCol);
glBindTexture(GL_TEXTURE_2D, m_textCol);
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, wth, hgt, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
glBindTexture(GL_TEXTURE_2D, 0);
glGenTextures(1, &m_textDepth);
glBindTexture(GL_TEXTURE_2D, m_textDepth);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
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_DEPTH_COMPONENT, wth, hgt, 0, GL_DEPTH_COMPONENT, GL_FLOAT, NULL);
glBindTexture(GL_TEXTURE_2D, 0);
GLuint framebuffer;
glGenFramebuffers(1, &framebuffer);
glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_textCol, 0);
GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER); always 36053 -> ok
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, m_textDepth, 0);
status = glCheckFramebufferStatus(GL_FRAMEBUFFER); // always 36054 -> not ok
I tried it also with
glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, wth, hgt, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, NULL);
but no change.
Has maybe someone an idea what I'm doing wrong? Thanks.
Status 36054 is GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT.
If we look at Section 9.4 of the OpenGL ES3.1 specification, it lists the following valid internalFormat values for depth attachments:
DEPTH_COMPONENT16
DEPTH_COMPONENT24
DEPTH_COMPONENT32F
DEPTH24_STENCIL8
DEPTH32F_STENCIL8
Note that the last two also contain a stencil part. You can use these for the depth component and ignore the stencil attachment if you do not need it. Especially DEPTH24_STENCIL8 has a good chance of being widely supported.
I'm trying to have a FBO with separate depth and stencil buffers.
I know that NVidia GPU's historically only supported packed depth/stencil.
However I stumbled on the ARB_texture_stencil8 extension and wonder how to use it against a FBO.
This code gives gl error 1159 on glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT, GL_TEXTURE_2D, fboStencilTexture, 0):
static GLuint fboId, rboDepth, rboStencil, TEXTURE_WIDTH, TEXTURE_HEIGHT;
if (!fboColorTexture) {
fboDepthTexture = fboId = rboDepth = rboStencil = TEXTURE_WIDTH = TEXTURE_HEIGHT = 0; // vid restart?
glGenTextures(1, &fboColorTexture);
glBindTexture(GL_TEXTURE_2D, fboColorTexture);
qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
}
if (!fboDepthTexture) {
glGenTextures(1, &fboDepthTexture);
glBindTexture(GL_TEXTURE_2D, fboDepthTexture);
qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
}
if (!fboStencilTexture) {
glGenTextures(1, &fboStencilTexture);
glBindTexture(GL_TEXTURE_2D, fboStencilTexture);
qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
}
GLuint curWidth = r_virtualResolution.GetFloat() * glConfig.vidWidth, curHeight = r_virtualResolution.GetFloat() * glConfig.vidHeight;
if (curWidth != TEXTURE_WIDTH || curHeight != TEXTURE_HEIGHT) {
TEXTURE_WIDTH = curWidth;
TEXTURE_HEIGHT = curHeight;
glBindTexture(GL_TEXTURE_2D, fboColorTexture);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB5_A1, TEXTURE_WIDTH, TEXTURE_HEIGHT, 0, GL_BGRA, GL_UNSIGNED_BYTE, NULL); //NULL means reserve texture memory, but texels are undefined
glBindTexture(GL_TEXTURE_2D, fboDepthTexture);
glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT16, TEXTURE_WIDTH, TEXTURE_HEIGHT, 0, GL_DEPTH_COMPONENT, GL_FLOAT, 0);
glBindTexture(GL_TEXTURE_2D, fboStencilTexture);
glTexImage2D(GL_TEXTURE_2D, 0, GL_STENCIL_INDEX8, TEXTURE_WIDTH, TEXTURE_HEIGHT, 0, GL_STENCIL_INDEX, GL_FLOAT, 0);
}
//-------------------------
if (!fboId) {
// create a framebuffer object, you need to delete them when program exits.
glGenFramebuffersEXT(1, &fboId);
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fboId);
// attach a texture to FBO color attachement point
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, fboColorTexture, 0);
// attach a renderbuffer to depth attachment point
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_TEXTURE_2D, fboDepthTexture, 0);
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT, GL_TEXTURE_2D, fboStencilTexture, 0);
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
}
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fboId);
The purpose of ARB_texture_stencil8 is to permit you to use stencil-only formats as textures. That is, reading from them in shaders.
This does not mean that you can separate your stencil and depth buffers. The idea behind stencil-8 textures is that you would generate their data by either copying the stencil portion of a depth/stencil texture, or you would render without a depth buffer entirely.
So you cannot use this extension to guarantee that you can render to separate depth and stencil images. That's still hardware dependent.
Also, if you're going to use new features like ARB_texture_stencil8, you shouldn't be combining them with old EXT_framebuffer_object APIs. So stop using glFramebufferTexture2DEXT and start using glFramebufferTexture.
I am trying to implement shadow mapping with the tutorial here, however when I try to use this code to attach a Framebuffer to a texture it fails. My OpenGL context is 3.1 and I believe i have an Intel 3000 series graphics card. The code fails at 2 points. The first failure is at glFramebufferTexture2D, which gives error code 1282 (Not sure what enumeration that corresponds too). I believe this error is causing the assert assi later in the code to fail. I have tried code from similar questions but they do not seem to work in this case.
glGenFramebuffers(1, &MObject::fbo);
glGenTextures(1, &MObject::shadowMap);
glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, windowWidth, windowHeight, 0, GL_DEPTH_COMPONENT, GL_FLOAT, NULL);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
glBindFramebuffer(GL_FRAMEBUFFER, MObject::fbo);
glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, MObject::shadowMap, 0);
GLenum err = glGetError(); // Error code: 1282
glDrawBuffer(GL_NONE);
glReadBuffer(GL_NONE);
GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
assi(status == GL_FRAMEBUFFER_COMPLETE, "FBO error!"); // Expression is false, abort called.
Yea so I forgot glBindTexture. I hate myself. Thank you Hectigo!
I'm working on opengl 2.1 and opengl es 2.0. I want to implement Depth-of-field effect for whole scene. I know how to do this for single model with shader, but this would require all models to have shader with same code. Is there a way to retrieve final scene depth and color buffer and store them into textures so I could use them again with DOF shader? Or is it a bad idea?
[EDIT]
Finally got it working.
The initialization code looks like this:
glGenFramebuffers(1, &frameBuffer_);
glGenTextures(1, &colorBuffer_);
glGenTextures(1, &depthBuffer_);
//glGenRenderbuffers(1, &depthBuffer_);
glBindFramebuffer(GL_FRAMEBUFFER, frameBuffer_);
glBindTexture(GL_TEXTURE_2D, colorBuffer_);
glTexImage2D(
GL_TEXTURE_2D,
0,
GL_RGBA,
width,
height,
0,
GL_RGBA,
GL_UNSIGNED_BYTE,
NULL);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glFramebufferTexture2D(
GL_FRAMEBUFFER,
GL_COLOR_ATTACHMENT0,
GL_TEXTURE_2D, colorBuffer_, 0);
glBindTexture(GL_TEXTURE_2D, depthBuffer_);
glTexImage2D(
GL_TEXTURE_2D,
0,
GL_DEPTH24_STENCIL8,
width,
height,
0,
GL_DEPTH_STENCIL,
GL_UNSIGNED_INT_24_8,
NULL);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glFramebufferTexture2D(
GL_FRAMEBUFFER,
GL_DEPTH_ATTACHMENT,
GL_TEXTURE_2D, depthBuffer_, 0);
//glBindRenderbuffer(GL_RENDERBUFFER, depthBuffer_);
//glRenderbufferStorage(
// GL_RENDERBUFFER,
// GL_DEPTH_COMPONENT24,
// width,
// height);
//glFramebufferRenderbuffer(
// GL_FRAMEBUFFER,
// GL_DEPTH_ATTACHMENT,
// GL_RENDERBUFFER, depthBuffer_);
GLenum status;
status = glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER);
switch(status) {
case GL_FRAMEBUFFER_COMPLETE:
// Success.
break;
case GL_FRAMEBUFFER_UNSUPPORTED:
LOGE("Frame buffer format not supported.");
break;
default:
LOGE("Framebuffer Error.");
}
And later when rendering first call:
glBindFramebuffer(GL_FRAMEBUFFER, frameBuffer_);
Render scene, then call:
glBindFramebuffer(GL_FRAMEBUFFER, 0);
And now anything can be rendered here using depthBuffer_ or colorBuffer_ as OpengGL texture handles.
Use a framebuffer object. They're part of OpenGL-ES-2 and are available as (well supported) extension to OpenGL-2.1.
See
https://github.com/datenwolf/codesamples/tree/master/samples/OpenGL/minimalfbo
for a minimal working example using extensions on desktop OpenGL-2.x
EDIT: SOLVED
I encountered a problem while attempting to render into a texture. I create a framebuffer object like this:
glGenTextures(1, &renderFBOtex);
glBindTexture(GL_TEXTURE_2D, renderFBOtex);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
glBindTexture(GL_TEXTURE_2D, 0);
glGenRenderbuffers(1, &renderFBOrender);
glBindRenderbuffer(GL_RENDERBUFFER, renderFBOrender);
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, width, height);
glBindRenderbuffer(GL_RENDERBUFFER, 0);
glGenFramebuffers(1, &renderFBO);
glBindFramebuffer(GL_FRAMEBUFFER, renderFBO);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, renderFBOtex, 0);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, renderFBOrender);
GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
glBindFramebuffer(GL_FRAMEBUFFER, 0);
But the return value of glCheckFrambufferStatus is always GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT.
The problem seems to be with the texture, as it is the same without the Renderbuffer attachment. Drawing into the Framebuffer itself shouldn't be a problem.
Could someone please point out what am I missing here?
Build texture mipmaps before attaching it on the color buffer.
The routine dedicated to this task is glGenerateMipmap.
Another suggestion would be to play with the texture internal format. You are not specifying a sized internal format. Since one of reason of the error is that the texture doesn't have a supported color-renderable internal format, you could give a try.
Problem was in another part of the program. It was a very stupid mistake, which led to use of wrongly initialized values for width and height of the texture. They were both set to 0, hence the incomplete attachment error.
Try this:
glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, renderFBOtex, 0);
^^^^
Technically they should make no difference, but some drivers may had this bug.