Im trying to attach multiple targets to a framebuffer object. I have the following problem:
There is no error, when using float texture attachments and a depth attachment.
There is also no error, when using float texture attachments and integer texture attachments. Although these combinations work, I cant use float, integer and depth attachments at the same time. This results in a GL_FRAMEBUFFER_UNSUPPORTED
status.
this is my code:
//working:
Framebuffer fb = Framebuffer(
1280,720,
{
//AttachmentInfo(GL_DEPTH_COMPONENT16,GL_DEPTH_ATTACHMENT),
AttachmentInfo(GL_RG32F,GL_COLOR_ATTACHMENT0),
AttachmentInfo(GL_RGB16UI,GL_COLOR_ATTACHMENT1),
AttachmentInfo(GL_RGB32F,GL_COLOR_ATTACHMENT2),
AttachmentInfo(GL_RGB32F,GL_COLOR_ATTACHMENT3),
AttachmentInfo(GL_RGBA16F,GL_COLOR_ATTACHMENT4),
AttachmentInfo(GL_RGB32F,GL_COLOR_ATTACHMENT5),
AttachmentInfo(GL_RGB32F,GL_COLOR_ATTACHMENT6),
}
);
//working:
Framebuffer fb = Framebuffer(
1280,720,
{
AttachmentInfo(GL_DEPTH_COMPONENT16,GL_DEPTH_ATTACHMENT),
AttachmentInfo(GL_RG32F,GL_COLOR_ATTACHMENT0),
//AttachmentInfo(GL_RGB16UI,GL_COLOR_ATTACHMENT1),
AttachmentInfo(GL_RGB32F,GL_COLOR_ATTACHMENT2),
AttachmentInfo(GL_RGB32F,GL_COLOR_ATTACHMENT3),
AttachmentInfo(GL_RGBA16F,GL_COLOR_ATTACHMENT4),
AttachmentInfo(GL_RGB32F,GL_COLOR_ATTACHMENT5),
AttachmentInfo(GL_RGB32F,GL_COLOR_ATTACHMENT6),
}
);
//NOT working:
Framebuffer fb = Framebuffer(
1280,720,
{
AttachmentInfo(GL_DEPTH_COMPONENT16,GL_DEPTH_ATTACHMENT),
AttachmentInfo(GL_RG32F,GL_COLOR_ATTACHMENT0),
AttachmentInfo(GL_RGB16UI,GL_COLOR_ATTACHMENT1),
AttachmentInfo(GL_RGB32F,GL_COLOR_ATTACHMENT2),
AttachmentInfo(GL_RGB32F,GL_COLOR_ATTACHMENT3),
AttachmentInfo(GL_RGBA16F,GL_COLOR_ATTACHMENT4),
AttachmentInfo(GL_RGB32F,GL_COLOR_ATTACHMENT5),
AttachmentInfo(GL_RGB32F,GL_COLOR_ATTACHMENT6),
}
);
Note: I only get this error when using my NVidia GTX 970 graphics card. On a bit older ATI card no error occured.
I use glbinding
to call glGetError
after every gl*
function call, so I know, that no other error occured.
this is my constructor code for the Framebuffer
object:
Framebuffer::Framebuffer(uint width,uint height,initializer_list<AttachmentInfo> attachments)
:width(width),height(height)
{
glGenFramebuffers(1,&fbID);
glBindFramebuffer(GL_FRAMEBUFFER,fbID);
if(std::none_of(attachments.begin(),attachments.end(),[](const AttachmentInfo& a){
return a.attachment == GL_DEPTH_ATTACHMENT;
})){
//depth test needs either a depth renderbuffer or depth attachment.
unsigned int rboID=0;
glGenRenderbuffers(1, &rboID);
glBindRenderbuffer(GL_RENDERBUFFER, rboID);
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, width, height);
glBindRenderbuffer(GL_RENDERBUFFER, 0);
glFramebufferRenderbuffer(GL_FRAMEBUFFER,GL_DEPTH_ATTACHMENT,GL_RENDERBUFFER,rboID);
}
vector<GLenum> buffers;
glActiveTexture(GL_TEXTURE0);
for(AttachmentInfo attachment:attachments){
GLuint tID;
glGenTextures(1, &tID);
glBindTexture(GL_TEXTURE_2D,tID);
GLint param;
glGetInternalformativ(GL_TEXTURE_2D, attachment.internalFormat, GL_FRAMEBUFFER_RENDERABLE, 1, ¶m);
if(param != GL_FULL_SUPPORT){
_log(WARNING,"Internal format " << attachment.internalFormat << " support is " << GLenum(param) << ".");
}
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GLint(GL_LINEAR));
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GLint(GL_LINEAR));
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GLint(GL_CLAMP_TO_EDGE));
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GLint(GL_CLAMP_TO_EDGE));
if(attachment.attachment == GL_DEPTH_ATTACHMENT){
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GLint(GL_COMPARE_REF_TO_TEXTURE));
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC, GLint(GL_LESS));
}
glTexStorage2D(GL_TEXTURE_2D,1,attachment.internalFormat,width,height);
glFramebufferTexture(GL_FRAMEBUFFER, attachment.attachment, tID, 0);
if(Tools::startsWith(glbinding::Meta::getString(attachment.attachment),"GL_COLOR_ATTACHMENT")){
buffers.push_back(attachment.attachment);
}
texMap[attachment.attachment]=new Texture(tID,GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D,0);
}
if(buffers.empty()){
buffers.push_back(GL_NONE);
}
glDrawBuffers(buffers.size(),buffers.data());
GLenum error=glCheckFramebufferStatus(GL_FRAMEBUFFER);
if(error != GL_FRAMEBUFFER_COMPLETE){
_log(ERROR,"Framebuffer error: " << error);
}
unbind();
}
Im really out of ideas what I can do to make it work...
Your OpenGL implementation tells you, that the configuration you choose is not supported. You have to accept that. The OpenGL specification does not require that particular combination of formats to be supported by all implementation, so if you want to program to be portable and robust, if you get a GL_FRAMEBUFFER_UNSUPPORTED error you'll have to gradually step down your format requirements until a workable combination is found.
A very good hint on what's supported is enumerating all the FBConfigs supported for creating a OpenGL context; usually this is a subset of the permissible FBO configurations.