Why am I getting a GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT here? - opengl

I have the following code. I'm trying to create a Multisample Framebuffer that has two color attachments and a depth-stencil attachment.
/* Generate Framebuffer and textures & renderbuffers */
glGenFramebuffers(1, &m_framebuffer);
glGenTextures(1, &m_fboColorAttachment);
glGenTextures(1, &m_fboAdditionalInfo);
glGenRenderbuffers(1,&m_fboRenderbufferDepthStencil);
glBindFramebuffer(GL_FRAMEBUFFER, m_framebuffer);
/* setup color output 0 */
glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, m_fboColorAttachment);
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);
glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 4, GL_RGBA8, renderDimensionsX, renderDimensionsY, GL_FALSE);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE, m_fboColorAttachment, 0);
glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, 0);
/* setup color output 1 */
glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, m_fboAdditionalInfo);
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);
glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 4, GL_R32UI, renderDimensionsX, renderDimensionsY, GL_FALSE);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D_MULTISAMPLE, m_fboAdditionalInfo, 0);
glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, 0);
/* setup depth and stencil */
glBindRenderbuffer(GL_RENDERBUFFER, m_fboRenderbufferDepthStencil);
glRenderbufferStorageMultisample(GL_RENDERBUFFER, 4, GL_DEPTH24_STENCIL8, renderDimensionsX, renderDimensionsY);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, m_fboRenderbufferDepthStencil);
auto status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
if(status != GL_FRAMEBUFFER_COMPLETE)
{
std::wstring statusStr = L"WTF error";
if(status == GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT)
statusStr = L"Attachment";
else if(status == GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT)
statusStr = L"Missing attachment";
else if(status == GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER)
statusStr = L"Draw buffer";
else if(status == GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER)
statusStr = L"Read buffer";
else if(status == GL_FRAMEBUFFER_UNSUPPORTED)
statusStr = L"Unsupported";
else if(status == GL_FRAMEBUFFER_UNDEFINED)
statusStr = L"Undefined";
else if(status == GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE)
statusStr = L"Multisample";
else if(status == GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS)
statusStr = L"Layer targets";
drawFuncLog << L"Framebuffer status: " << statusStr << L"\r\n";
}
glBindFramebuffer(GL_FRAMEBUFFER, 0);
I'm getting the GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT status returned. As near as I can tell, everything has been created as multisampled and the number of multisample levels matches across the attachments. Incomplete Attachment apparently means one of my attachments is incomplete, which I think is the depth-stencil renderbuffer.

See OpenGL 4.6 API Core Profile Specification; 9.4.2 Whole Framebuffer Completeness; page 326:
The framebuffer object bound to target is said to be framebuffer complete if all the following conditions are true:
......
The value of TEXTURE_FIXED_SAMPLE_LOCATIONS is the same for all attached textures; and, if the attached images are a mix of renderbuffers and textures, the value of TEXTURE_FIXED_SAMPLE_LOCATIONS must be TRUE for all attached textures.
This means you have to pass GL_TRUE, to the last parameter of glTexImage2DMultisample for both texture attachments, to solve the issue:
glTexImage2DMultisample(
GL_TEXTURE_2D_MULTISAMPLE, 4, GL_RGBA8, renderDimensionsX, renderDimensionsY, GL_TRUE);
glTexImage2DMultisample(
GL_TEXTURE_2D_MULTISAMPLE, 4, GL_R32UI, renderDimensionsX, renderDimensionsY, GL_TRUE);

Related

how to unbind glBindFramebuffer in c++ opengles ios

i am porting a program that run on windows and android to ios.
the following code works on both platform but on ios it stops rendering after that code is being executed, i suspect that the bind never gets unbinded, what is the proper way of doing it?
the objective of the code is to get the textures pixels.
this is the code:
void Texture::Bind()
{
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, mTextureID);
}
GLubyte* Texture::GetPixels()
{
Bind();
int data_size = mWidth * mHeight * 4;
GLubyte* pixels = new GLubyte[data_size];
#ifdef _WIN32
glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
#else
GLuint fbo;
glGenFramebuffers(1, &fbo);
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mTextureID, 0);
glReadPixels(0, 0, mWidth, mHeight, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
glBindFramebuffer(GL_FRAMEBUFFER, 0);
glDeleteFramebuffers(1, &fbo);
#endif
return pixels;
}
iOS does not work with default framebuffer indexed with 0. You need to bind the buffer you use as main. It depends on the tool you used but if you are using directly an UIView then you should find some code similar to the following:
- (instancetype)initWithView:(UIView *)view {
if((self = [super init])) {
{
GLuint bufferID = 0;
glGenFramebuffers(1, &bufferID);
glBindFramebuffer(GL_FRAMEBUFFER, bufferID);
self.frameBufferID = bufferID;
}
{
GLuint bufferID = 0;
glGenRenderbuffers(1, &bufferID);
glBindRenderbuffer(GL_RENDERBUFFER, bufferID);
view.layer.contentsScale = UIScreen.mainScreen.scale;
[[EAGLContext currentContext] renderbufferStorage:GL_RENDERBUFFER fromDrawable:(CAEAGLLayer *)view.layer];
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, bufferID);
self.colorBufferID = bufferID;
GLint width, height;
glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_WIDTH, &width);
glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_HEIGHT, &height);
self.bufferWidth = width;
self.bufferHeight = height;
}
}
return self;
}
You are looking for a call to renderbufferStorage:fromDrawable:. Near it a frame buffer should be created which is associated to this render buffer. The id of that frame buffer is what you need to bind.
So in the snipped above you would use self.frameBufferID.
As for the snippet I posted it is a part of a project which generates frame and render buffer from a given UIView. First it generates frame buffer and binds it. Next render buffer is created and bound. Render buffer is then setup through native iOS code with layer. We attach render buffer to frame buffer. At the end width and height are extracted.
Before drawing to this object the following bind method is called:
- (void)bind {
glBindFramebuffer(GL_FRAMEBUFFER, self.frameBufferID);
glBindRenderbuffer(GL_RENDERBUFFER, self.colorBufferID);
}

GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT from the shared second context

I need to share the color/depth/stencil buffers between two OpenGL contexts. 2D textures are attached to framebuffer object for the buffers. The code looks like below:
// === Start of context 1
//
Create _hDC1, _hRC1;
wglMakeCurrent(hDC1, hRC1);
glGenFramebuffers(1, &_FBO1);
glBindFramebuffer(GL_FRAMEBUFFER, _FBO1);
// color buffer
glGenTextures(1, &_color1);
glBindTexture(GL_TEXTURE2D, _color1);
glTexParameteri(GL_TEXTURE_2D, ..., ); // GL_TEXTURE_WRAP_S, ..., etc.
glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA16F, 512, 512);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, _color1, 0);
// depth buffer
glGenTextures(1, &_depth1);
glBindTexture(GL_TEXTURE2D, _depth1);
glTexParameteri(GL_TEXTURE_2D, ..., ); // GL_TEXTURE_WRAP_S, ..., etc.
glTexStorage2D(GL_TEXTURE_2D, 1, GL_DEPTH24_STENCIL8, 512, 512);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, _depth1, 0);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_TEXTURE_2D, _depth1, 0);
// check completeness
GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
assert(status == GL_FRAMEBUFFER_COMPLETE); // *pass fine here*
// detach _FBO1
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0, 0);
glReadBuffer(GL_NONE);
glDrawBuffer(GL_NONE);
//
// === End of context 1
// === Start of context 2
//
Create _hDC2, _hRC2; // pixel format is same as _hDC1
wglShareLists(_hRC2, hRC1); // share objects between _hRC1 and _hRC2
wglMakeCurrent(_hDC2, _hRC2);
// Create another frame buffer, since it is not sharable
glGenFramebuffers(1, &_FBO2);
glBindFramebuffer(GL_FRAMEBUFFER, _FBO2);
// Use the shared textures for color/depth/stencil buffers
glBindTexture(GL_TEXTURE2D, _color1);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, _color1, 0);
glBindTexture(GL_TEXTURE2D, _depth1);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, _depth1, 0);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_TEXTURE_2D, _depth1, 0);
// check completeness
GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
assert(status == GL_FRAMEBUFFER_COMPLETE); // *fail here, status is GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT*
//
// === End of context 2
The second completeness check always fails.
Tried move the second completeness check right after attaching the color buffer, and I got the same failure.
Also tried to unbind _color and _depth before creating the second context, but, it did not help.
glGetError() was put after each OpenGL call and no error was detected.
From https://www.khronos.org/opengles/sdk/docs/man/xhtml/glCheckFramebufferStatus.xml
Not all framebuffer attachment points are framebuffer attachment complete. This means that at least one attachment point with a renderbuffer or texture attached has its attached object no longer in existence or has an attached image with a width or height of zero, or the color attachment point has a non-color-renderable image attached, or the depth attachment point has a non-depth-renderable image attached, or the stencil attachment point has a non-stencil-renderable image attached.
Can not figure out what's get missed. Checked several posts online, but none of them is the same use case as mine.
Aha, I messed up with the arguments order when calling wglShareLists(), which should be:
wglShareLists(_hRC1, hRC2);
Everything works now. I should have put an error check around it.

How to egl offscreen render to an image on linux?

I'm trying to use egl to do offscreen rendering to an image.
my code doesn't generate any error. the egl part seems to be correct, the fbo is also complete. but when I read pixels using glReadPixels, I always get a black image (I cleared the entire scene with red, so the image should be red too).
I can't figure out what's wrong.
Also, I noticed that glRenderbufferStorage can only support 16bit color depth. GL_RGBA8 is consider an invalid parameter for this function. Isn't 16bit a bit low for serious opengl application?
My environment is Ubuntu 14.10 with mesa and intel graphics.
#include <QCoreApplication>
#include <QDebug>
#include <QImage>
#include <GLES2/gl2.h>
#include <EGL/egl.h>
int main(int argc, char *argv[])
{
#define CONTEXT_ES20
#ifdef CONTEXT_ES20
EGLint ai32ContextAttribs[] = { EGL_CONTEXT_CLIENT_VERSION, 2,
EGL_NONE };
#endif
// Step 1 - Get the default display.
EGLDisplay eglDisplay = eglGetDisplay((EGLNativeDisplayType)0);
// Step 2 - Initialize EGL.
eglInitialize(eglDisplay, 0, 0);
#ifdef CONTEXT_ES20
// Step 3 - Make OpenGL ES the current API.
eglBindAPI(EGL_OPENGL_ES_API);
// Step 4 - Specify the required configuration attributes.
EGLint pi32ConfigAttribs[5];
pi32ConfigAttribs[0] = EGL_SURFACE_TYPE;
pi32ConfigAttribs[1] = EGL_WINDOW_BIT;
pi32ConfigAttribs[2] = EGL_RENDERABLE_TYPE;
pi32ConfigAttribs[3] = EGL_OPENGL_ES2_BIT;
pi32ConfigAttribs[4] = EGL_NONE;
#else
EGLint pi32ConfigAttribs[3];
pi32ConfigAttribs[0] = EGL_SURFACE_TYPE;
pi32ConfigAttribs[1] = EGL_WINDOW_BIT;
pi32ConfigAttribs[2] = EGL_NONE;
#endif
// Step 5 - Find a config that matches all requirements.
int iConfigs;
EGLConfig eglConfig;
eglChooseConfig(eglDisplay, pi32ConfigAttribs, &eglConfig, 1,
&iConfigs);
if (iConfigs != 1) {
printf("Error: eglChooseConfig(): config not found.\n");
exit(-1);
}
// Step 6 - Create a surface to draw to.
EGLSurface eglSurface;
eglSurface = eglCreateWindowSurface(eglDisplay, eglConfig,
(EGLNativeWindowType)NULL, NULL);
// Step 7 - Create a context.
EGLContext eglContext;
#ifdef CONTEXT_ES20
eglContext = eglCreateContext(eglDisplay, eglConfig, NULL,
ai32ContextAttribs);
#else
eglContext = eglCreateContext(eglDisplay, eglConfig, NULL, NULL);
#endif
// Step 8 - Bind the context to the current thread
eglMakeCurrent(eglDisplay, eglSurface, eglSurface, eglContext);
GLuint fboId = 0;
GLuint renderBufferWidth = 1280;
GLuint renderBufferHeight = 720;
// create a framebuffer object
glGenFramebuffers(1, &fboId);
glBindFramebuffer(GL_FRAMEBUFFER, fboId);
// create a texture object
/* GLuint textureId;
glGenTextures(1, &textureId);
glBindTexture(GL_TEXTURE_2D, textureId);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
//GL_LINEAR_MIPMAP_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);
glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP_HINT, GL_TRUE); // automatic mipmap
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, renderBufferWidth, renderBufferHeight, 0,
GL_RGB, GL_UNSIGNED_BYTE, 0);
glBindTexture(GL_TEXTURE_2D, 0);
// attach the texture to FBO color attachment point
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
GL_TEXTURE_2D, textureId, 0);
*/
qDebug() << glGetError();
GLuint renderBuffer;
glGenRenderbuffers(1, &renderBuffer);
glBindRenderbuffer(GL_RENDERBUFFER, renderBuffer);
qDebug() << glGetError();
glRenderbufferStorage(GL_RENDERBUFFER,
GL_RGB565,
renderBufferWidth,
renderBufferHeight);
qDebug() << glGetError();
glFramebufferRenderbuffer(GL_FRAMEBUFFER,
GL_COLOR_ATTACHMENT0,
GL_RENDERBUFFER,
renderBuffer);
qDebug() << glGetError();
GLuint depthRenderbuffer;
glGenRenderbuffers(1, &depthRenderbuffer);
glBindRenderbuffer(GL_RENDERBUFFER, depthRenderbuffer);
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, renderBufferWidth, renderBufferHeight);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depthRenderbuffer);
// check FBO status
GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
if(status != GL_FRAMEBUFFER_COMPLETE) {
printf("Problem with OpenGL framebuffer after specifying color render buffer: \n%x\n", status);
} else {
printf("FBO creation succedded\n");
}
glClearColor(1.0,0.0,0.0,1.0);
glClear(GL_COLOR_BUFFER_BIT);
qDebug() << eglSwapBuffers( eglDisplay, eglSurface);
int size = 4 * renderBufferHeight * renderBufferWidth;
printf("print size");
printf("size %d", size);
qDebug() << size;
unsigned char *data2 = new unsigned char[size];
glReadPixels(0,0,renderBufferWidth,renderBufferHeight,GL_RGB, GL_RGB565, data2);
QImage image(data2, renderBufferWidth, renderBufferHeight,renderBufferWidth*2, QImage::Format_RGB16);
image.save("result.png");
qDebug() << "done";
QCoreApplication a(argc, argv);
return a.exec();
}
OpenGL ES 2.0 has a very limited number of formats/types that are supported for glReadPixels(). The ones you are trying to use are not guaranteed to be supported:
glReadPixels(0 ,0, renderBufferWidth, renderBufferHeight,
GL_RGB, GL_RGB565, data2);
Only two formats/types are supported:
GL_RGBA/GL_UNSIGNED_BYTE.
An implementation dependent combination.
The format and type of the implementation dependent combination can be queried with:
GLint format = 0, type = 0;
glGetIntegerv(GL_IMPLEMENTATION_COLOR_READ_FORMAT, &format);
glGetIntegerv(GL_IMPLEMENTATION_COLOR_READ_TYPE, &type);
This can give you one of the following combinations:
GL_RGB/GL_UNSIGNED_BYTE.
GL_RGB/GL_UNSIGNED_SHORT_5_6_5.
GL_RGBA/GL_UNSIGNED_SHORT_4_4_4_4.
GL_RGBA/GL_UNSIGNED_SHORT_5_5_5_1.
GL_ALPHA/GL_UNSIGNED_BYTE.
So the combination you tried to use could be supported by an implementation, if it returns the corresponding values from the glGetIntegerv() calls above. However, there was a subtle but important error in the arguments of your glReadPixels() call even if it is supported: GL_RGB565 is a value for a format, while the 6th argument is a type. The call would have to be:
glReadPixels(0 ,0, renderBufferWidth, renderBufferHeight,
GL_RGB, GL_UNSIGNED_SHORT_5_6_5, data2);

OpenGL glFramebufferRenderbuffer() get error: GL_INVALID_OPERATION, status: GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT

I'm trying to do texture rendering using cocos2d and openGL.
After I called
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, _depthRenderBufffer)
I checked the status, using:
GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
and turned out the status was GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT
I also checked the error using
GLenum error = glGetError();
and the result was GL_INVALID_OPERATION
According to the documentation the cause of GL_INVALID_OPERATION is because:
the default framebuffer object name 0 is bound.
or
if renderbuffer is neither 0 nor the name of an existing renderbuffer object
I checked the framebuffer and renderbuffer, neither of them are 0, but I am not sure wheather there is any other rederbuffer object has the same name.
Does any one know how to fix this issue?
The detailed code I was using:
.....
GLint oldRBO;
glGetIntegerv(GL_RENDERBUFFER_BINDING, &oldRBO);
// generate FBO
glGenFramebuffers(1, &_FBO);
glBindFramebuffer(GL_FRAMEBUFFER, _FBO);
// associate texture with FBO
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, _texture.name, 0);
if (depthStencilFormat != 0) {
glGenRenderbuffers(1, &_depthRenderBufffer);
glBindRenderbuffer(GL_RENDERBUFFER, _depthRenderBufffer);
glRenderbufferStorage(GL_RENDERBUFFER, depthStencilFormat, (GLsizei)powW, (GLsizei)powH);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, _depthRenderBufffer);
GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER); // the status here will result in GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT
GLenum error = glGetError (); // the error here will be GL_INVALID_OPERATION
// I checked the value of _FBO, which was 1, and the value of _depthRenderBufffer was 2
.....
}

Problems outputting gl_PrimitiveID to custom frame buffer object (FBO)

I have a very basic fragment shader which I want to output 'gl_PrimitiveID' to a fragment buffer object (FBO) which I have defined. Below is my fragment shader:
#version 150
uniform vec4 colorConst;
out vec4 fragColor;
out uvec4 triID;
void main(void)
{
fragColor = colorConst;
triID.r = uint(gl_PrimitiveID);
}
I setup my FBO like this:
GLuint renderbufId0;
GLuint renderbufId1;
GLuint depthbufId;
GLuint framebufId;
// generate render and frame buffer objects
glGenRenderbuffers( 1, &renderbufId0 );
glGenRenderbuffers( 1, &renderbufId1 );
glGenRenderbuffers( 1, &depthbufId );
glGenFramebuffers ( 1, &framebufId );
// setup first renderbuffer (fragColor)
glBindRenderbuffer(GL_RENDERBUFFER, renderbufId0);
glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA, gViewWidth, gViewHeight);
// setup second renderbuffer (triID)
glBindRenderbuffer(GL_RENDERBUFFER, renderbufId1);
glRenderbufferStorage(GL_RENDERBUFFER, GL_RGB32UI, gViewWidth, gViewHeight);
// setup depth buffer
glBindRenderbuffer(GL_RENDERBUFFER, depthbufId);
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT32, gViewWidth, gViewHeight);
// setup framebuffer
glBindFramebuffer(GL_FRAMEBUFFER, framebufId);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, renderbufId0);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_RENDERBUFFER, renderbufId1);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depthbufId );
// check if everything went well
GLenum stat = glCheckFramebufferStatus(GL_FRAMEBUFFER);
if(stat != GL_FRAMEBUFFER_COMPLETE) { exit(0); }
// setup color attachments
const GLenum att[] = {GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1};
glDrawBuffers(2, att);
// render mesh
RenderMyMesh()
// copy second color attachment (triID) to local buffer
glReadBuffer(GL_COLOR_ATTACHMENT1);
glReadPixels(0, 0, gViewWidth, gViewHeight, GL_RED, GL_UNSIGNED_INT, data);
For some reason glReadPixels gives me a 'GL_INVALID_OPERATION' error? However if i change the internal format of renderbufId1 from 'GL_RGB32UI' to 'GL_RGB' and I use 'GL_FLOAT' in glReadPixels instead of 'GL_UNSIGNED_INT' then everything works fine. Does anyone know why I am getting the 'GL_INVALID_OPERATION' error and how I can solve it?
Is there an alternative way of outputting 'gl_PrimitiveID'?
PS: The reason I want to output 'gl_PrimitiveID' like this is explained here: Picking triangles in OpenGL core profile when using glDrawElements
glReadPixels(0, 0, gViewWidth, gViewHeight, GL_RED, GL_UNSIGNED_INT, data);
As stated on the OpenGL Wiki, you need to use GL_RED_INTEGER when transferring true integer data. Otherwise, OpenGL will try to use floating-point conversion on it.
BTW, make sure you're using glBindFragDataLocation to set up which buffers those fragment shader outputs go to. Alternatively, you can set it up explicitly in the shader if you're using GLSL 3.30 or above.