I fiddled with framebuffers and visualized the texture, and I was faced with the need to rekindle them. Again on some machines, I get GL_INVALID_OPERATION immediately after calling glBlitFramebuffer . Each texture attached to the framebuffer is configured in exactly the same way, all the same sizes and parameters. In addition, when I try to split one whole texture (previously successfully processed) into another framebuffer, only the “rectangle” of the destination for writing is smaller than the rectangle for reading (for example, when I want to split it to a quarter of the screen), it also throws GL_INVALID_OPERATION .
EDIT: In fact, it always throws an error whenever the rectangles are read and drawn to have a different size, so I can’t smooth out the texture of a different size or the same size, but the region “relate to” is of a different size ...?
Every time I turn on a manually created framebuffer, the status is checked through glCheckFramebufferStatus and it always returns GL_FRAMEBUFFER_COMPLETE .
-BIGGEST SNIP EVER-, see below for a shorter "source code", obviously a couple of C ++ errors and incomplete ones, but only for GL calls
An OpenGL error occurs when I call the last viewport method (Viewport :: blit) with the screen framebuffer as the target (by passing NULL). First, it sets the read buffer of its own framebuffer (drawing buffers are already configured), and then it calls RenderTarget :: blit, which calls glBlitFramebuffer . In the blit method, it binds both buffers, and you can see that it calls glCheckFramebufferStatus , which does not return an error.
I read this one over and over again, but I cannot find the error that causes it. When I blit the color buffer, I use GL_LINEAR , otherwise I use GL_NEAREST . All color buffers use GL_RGB32F as the internal format, and the depth buffer (which I never fill) uses GL_DEPTH_COMPONENT32F
EDIT, a shorter example, just took all the GL calls and populated the parameters that I used
glBindFramebuffer(GL_READ_FRAMEBUFFER, _GL_Framebuffer); glReadBuffer(GL_COLOR_ATTACHMENT0 + index); glBindFramebuffer(GL_READ_FRAMEBUFFER, 0); // OpenGL error check, does not return an error glBindFramebuffer(GL_READ_FRAMEBUFFER, _GL_Framebuffer); GLenum status = glCheckFramebufferStatus(GL_READ_FRAMEBUFFER); if(status != GL_FRAMEBUFFER_COMPLETE) { // Some error checking, fortunately status always turns out to be complete } glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); glBlitFramebuffer(0, 0, screenWidth, screenHeight, 0, 0, screenWidth, screenHeight, target, (target == GL_COLOR_BUFFER_BIT) ? GL_LINEAR : GL_NEAREST); // If the source/destination read/draw rectangles are different in size, GL_INVALID_OPERATION is cought here
And creating Framebuffer / Texture:
glGenFramebuffer(1, &_GL_Framebuffer); glGenTextures(1, &_GL_ZBuffer); glBindTexture(GL_TEXTURE_2D, _GL_ZBuffer); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0); glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT32F, screenWidth, screenHeight, 0, GL_DEPTH_COMPONENT, GL_FLOAT, 0); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glBindTexture(GL_TEXTURE_2D, 0); glBindFramebuffer(GL_FRAMEBUFFER, _GL_Framebuffer); glFramebufferTexture(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT + 0, _GL_ZBuffer, 0); glBindFramebuffer(GL_FRAMEBUFFER, 0); int writeIndices[BUFFER_COUNT]; for(unsigned int i = 0; i < BUFFER_COUNT; ++i) { writeIndices[i] = i; glGenTextures(1, &_GL_Texture); glBindTexture(GL_TEXTURE_2D, _GL_Texture); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB32F, screenWidth, screenHeight, 0, GL_RGB, GL_FLOAT, 0); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glBindTexture(GL_TEXTURE_2D, 0); glBindFramebuffer(GL_FRAMEBUFFER, _GL_Framebuffer); glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + i, _GL_Texture, 0); glBindFramebuffer(GL_FRAMEBUFFER, 0); // In the actual code each texture is obviously saved in an object } GLenum *enums = new GLenum[BUFFER_COUNT]; for(unsigned int i = 0; i < BUFFER_COUNT; ++i) { // Get index and validate int index = *(indices + i); // indices = writeIndices if(index < 0 || index >= maxAttachments) { delete[] enums; return false; } // Set index enums[i] = GL_COLOR_ATTACHMENT0 + index; } // Set indices glBindFramebuffer(GL_DRAW_FRAMEBUFFER, _GL_Framebuffer); glDrawBuffers(BUFFER_COUNT, enums); glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); delete[] enums; // OpenGL error check, no errors