I am playing a bit with bit blitting in OpenGL. When I run the code looking like this:
GLuint fbo = CreateFBO(); // creates fbo and attaches a texture to it
glBindFramebuffer(GL_FRAMEBUFFER, 0);
GLfloat some_color[] = {0.8, 0.4, 0.6, 1.0};
glClearBufferfv(GL_COLOR, 0, some_color);
glBlitNamedFramebuffer(0, fbo, 0, 0, 100, 100, 0, 0, 100, 100, GL_COLOR_BUFFER_BIT, GL_NEAREST);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT |GL_STENCIL_BUFFER_BIT);
glBlitNamedFramebuffer(fbo, 0, 0, 0, 100, 100, 0, 0, 100, 100, GL_COLOR_BUFFER_BIT, GL_NEAREST);
It yields a black screen, that is, the screen was cleared, although it should have the color of some_color. But if I change the "named" function to the "unnamed" counterpart, then it works as intended. The new piece of code looks like:
GLuint fbo = CreateFBO(); // creates fbo and attaches a texture to it
glBindFramebuffer(GL_FRAMEBUFFER, 0);
GLfloat some_color[] = {0.8, 0.4, 0.6, 1.0};
glClearBufferfv(GL_COLOR, 0, some_color);
glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo_);
glBlitFramebuffer(0, 0, 100, 100, 0, 0, 100, 100, GL_COLOR_BUFFER_BIT, GL_NEAREST);
glBindFramebuffer(GL_FRAMEBUFFER, 0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT |GL_STENCIL_BUFFER_BIT);
glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo_);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
glBlitFramebuffer(0, 0, 100, 100, 0, 0, 100, 100, GL_COLOR_BUFFER_BIT, GL_NEAREST);
And executing this code, I get the expected result, namely the screen having the color of some_color. What am I doing wrong employing bit blitting? Or if I am using it correctly, why doesn't it work properly?
UPD: I mixed up blit functions in the second code sample.
It yields a black screen, that is, the screen was cleared, although it should have the color of some_color.
No it shouldn't. The first parameter to glBlitNamedFramebuffer is the read framebuffer. So your blit reads from the default framebuffer and writes to the FBO. You clear the screen. Then you reverse this operation. This copies from the FBO to the default framebuffer. Thus overwriting the clear.
Whatever it is you see on the screen, it should be anything but some_color.
Related
I want to dabble in some procedural textures in an OpenGL project, but nothing seems to work. All I need is to input the RGB and maybe A values into an empty texture, instead of loading it from a file. How do I do this, in actual, practical code?
Edit: There is no main code yet, because I have found nothing that works. The current best guess is this:
void GenerateTexture()
{
unsigned char image_data[16] = {0, 0, 150, 255, 125, 0, 0, 255, 0, 0, 150, 255, 125, 0, 0, 255};
glGenTextures(1, &tex_obj);
glBindTexture(GL_TEXTURE_2D, tex_obj);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, image_data);
}
... implemented like this:
glBegin (GL_QUADS);
if (*irrelevant for question*){
glTexCoord2f(0.0,1.0);
glVertex3f (-0.45-cam.pos.val[0], 0.45-cam.pos.val[1], 0.45-cam.pos.val[2]);
glTexCoord2f(0.0,0.0);
glVertex3f (-0.45-cam.pos.val[0], -0.45-cam.pos.val[1], 0.45-cam.pos.val[2]);
glTexCoord2f(1.0,0.0);
glVertex3f (0.45-cam.pos.val[0], -0.45-cam.pos.val[1], 0.45-cam.pos.val[2]);
glTexCoord2f(1.0,1.0);
glVertex3f (0.45-cam.pos.val[0], 0.45-cam.pos.val[1], 0.45-cam.pos.val[2]);
}
glEnd ();
... but as soon as it is run with more than a 1x1 texture, it just goes clean white.
Create an array of data and load it into a texture image:
uint8_t image_data[4] = {255, 0, 0, 255}; // red
GLuint tex_obj;
glGenTextures(1, &tex_obj);
glBindTexture(GL_TEXTURE_2D, tex_obj);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, image_data);
I am trying to implement MSAA together with HDR and Bloom. I want to blit a buffer object with two color attachments to another frame buffer with two color attachments also. I tried the following with no success
glBindFramebuffer(GL_READ_FRAMEBUFFER, msaaFrameBuffer);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, hdrFBO);
glReadBuffer(GL_COLOR_ATTACHMENT0);
glDrawBuffer(GL_COLOR_ATTACHMENT0);
glBlitFramebuffer(0, 0, renderWidth, renderHeight, 0, 0, renderWidth, renderHeight, GL_COLOR_BUFFER_BIT, GL_NEAREST);
glBindFramebuffer(GL_READ_FRAMEBUFFER, msaaFrameBuffer);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, hdrFBO);
glReadBuffer(GL_COLOR_ATTACHMENT1);
glDrawBuffer(GL_COLOR_ATTACHMENT1);
glBlitFramebuffer(0, 0, renderWidth, renderHeight, 0, 0, renderWidth, renderHeight, GL_COLOR_BUFFER_BIT, GL_NEAREST);
it just copies the first color attachment of the source frame buffer to both color attachments of the target frame buffer. What am I missing here?
I'm currently trying to test out rendering to a framebuffer for various uses, but whenever I have an object(say a square) at a certain y-value, it appears "stretched", and then past a certain y-value or a certain x-value it seems to "thin out" and disappears. I have determined the x and y-values that it disappears at, but the coordinates seem to not have any rhyme or reason.
When I remove the framebuffer binding and render directly to the screen it draws the square perfectly fine, no matter the x or y-value.
Drawing a basic square(using immediate mode to remove possible errors) with a wide x-value looks like this:
Code here:
Window window("Framebuffer Testing", 1600, 900); //1600x900 right now
int fbowidth = 800, fboheight = 600;
mat4 ortho = mat4::orthographic(0, width, 0, height, -1.0f, 1.0f);
//trimmed out some code from shader creation that is bugless and unneccessary to include
Shader shader("basic"); shader.setUniform("pr_matrix", ortho);
Shader drawFromFBO("fbotest"); shader.setUniform("pr_matrix", ortho);
GLfloat screenVertices[] = {
0, 0, 0, 0, height, 0,
width, height, 0, width, 0, 0};
GLushort indices[] = {
0, 1, 2,
2, 3, 0 };
GLfloat texcoords[] = { //texcoords sent to the drawFromFBO shader
0, 0, 0, 1, 1, 1,
1, 1, 1, 0, 0, 0 };
IndexBuffer ibo(indices, 6);
VertexArray vao;
vao.addBuffer(new Buffer(screenVertices, 4 * 3, 3), 0);
vao.addBuffer(new Buffer(texcoords, 2 * 6, 2), 1);
GLuint fbo;
glGenFramebuffers(1, &fbo);
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
GLuint texture;
glGenTextures(1, &texture);
glBindTexture(GL_TEXTURE_2D, texture);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, fbowidth, fboheight, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glBindTexture(GL_TEXTURE_2D, 0);
glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, texture, 0);
if(glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
std::cout << "false" << std::endl;
glEnable(GL_TEXTURE_2D);
//the x-values mess up at ~783 thru 800 and the y-values at 0 thru ~313
while(!window.closed()) {
glClearColor(0.2f, 0.2f, 0.2f, 1.0f); //grey
window.clear(); //calls glclear for depth and color buffer
//bind framebuffer and shader
shader.enable(); //literally just calls glUseProgram(id) with the compiled shader id
glViewport(0, 0, fbowidth, fboheight);
glBindFramebuffer(GL_FRAMEBUFFER, fbo); //bind the fbo
glClearColor(1.0f, 0.0f, 1.0f, 1.0f); //set clear color to pink
glClear(GL_COLOR_BUFFER_BIT);
//render a red square to the framebuffer texture
glBegin(GL_QUADS); {
glColor3f(1.0f, 0.0f, 0.0f); //set the color to red
glVertex3f(700, 400, 0);
glVertex3f(700, 450, 0);
glVertex3f(750, 450, 0);
glVertex3f(750, 400, 0);
} glEnd();
shader.disable();
glBindFramebuffer(GL_FRAMEBUFFER, 0); //set framebuffer to the default
//render from framebuffer to screen
glViewport(0, 0, width, height);
drawFromFBO.enable();
glActiveTexture(GL_TEXTURE0);
drawFromFBO.setUniform1i("texfbo0", 0);
glBindTexture(GL_TEXTURE_2D, texture);
vao.bind();
ibo.bind();
glDrawElements(GL_TRIANGLES, ibo.getCount(), GL_UNSIGNED_SHORT, NULL);
ibo.unbind();
vao.unbind();
drawFromFBO.disable();
window.update();
}
If you want to see any thing extra, the file is located at my Github: here
I have code which is the equivalent of the following:
init code:
glCullFace(GL_FRONT_AND_BACK);
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LESS);
//clear to pink
glClearColor(1.0f, 0.0f, 1.0f, 0.0f);
GLuint textureObject;
glGenTextures(1, &textureObject);
glBindTexture(GL_TEXTURE_2D, textureObject);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 512, 512, 0, GL_RGBA,
GL_UNSIGNED_BTYE, NULL);
GLuint fbo;
glGenFramebuffers(1, &fbo);
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
textureObject, 0);
glReadBuffer(GL_COLOR_ATTACHMENT0);
glDrawBuffer(GL_COLOR_ATTACHMENT0);
assert(glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER)
== GL_FRAMEBUFFER_COMPLETE);
Object obj = CreateAFullscreenQuad(textureObject);
draw code:
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo);
glViewport(0, 0, 512, 512);
//clear to cyan
GLfloat clear[] = {0, 1, 1, 1};
glClearBufferfv(GL_COLOR, 0, clear);
SetUpPerspectiveAndCameraMatrix();
DrawSomeStuff();
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
glViewport(0, 0, window.width, window.height);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
SetUpPerspectiveAndCameraMatrix();
obj.Draw();
SwapBuffers();
glxinfo excerpt:
OpenGL vendor string: VMware, Inc.
OpenGL renderer string: Gallium 0.4 on llvmpipe (LLVM 3.4, 128 bits)
OpenGL version string: 2.1 Mesa 10.1.3
The problem is that the call to glClearBufferfv doesn't seem to clear the whole buffer. As you can see, it clears the triangular shape, but it doesn't touch the other areas. They are also not the glClearColor color (pink). If I use the regular glClear call, it does the same thing, but pink instead of cyan.
Turns out I created a feedback loop by drawing the fullscreen quad while the FBO was bound, drawing the contents of the buffer to itself. Apparently the effects of this end up being interspersed with the effects of glClear.
I have a test program that programmatically renders a texture and then renders a simple quad that is skinned with the previously drawn texture. The program is extremely simple and everything is done in 2D. This program works great under linux and everything looks like it should:
However when I run the program on my mac running 10.7 nothing shows up:
I'm at a complete loss as to why this program isn't working on my mac.
Here are the relevant bits of the program.
Creating the texture:
void createTextureObject(){
cout<<"Creating a new texture of size:"<<textureSize<<endl;
//glDeleteTextures(1, &textureId);
glGenTextures(1, &textureId);
glBindTexture(GL_TEXTURE_2D, textureId);
glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_TRUE); // automatic mipmap generation included in OpenGL v1.4
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, textureSize, textureSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
isTextureValid = true;
createFBObject();
}
Creating the Frame Buffer Object:
void createFBObject(){
cout<<"Creating a new frame buffer object"<<endl;
glDeleteFramebuffers(1, &fboId);
glGenFramebuffersEXT(1, &fboId);
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fboId);
glGenRenderbuffersEXT(1, &rboId);
glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, rboId);
glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT, textureSize, textureSize);
glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0);
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, textureId, 0);
glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, rboId);
bool status = checkFramebufferStatus();
if(!status){
cout<<"FrameBufferObject not created! Quitting!"<<endl;
exit(1);
fboUsed = false;
}
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
}
Rendering to the texture:
void drawToTexture(){
if (!isTextureValid)
createTextureObject();
glViewport(0, 0, textureSize, textureSize);
glLoadIdentity();
// set the rendering destination to FBO
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fboId);
// clear buffer
glClearColor(0, 0, 0, 1.0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// draw to the texture
glColor3f(0.0, 1.0, 0.0);
for (int i=1; i<=5; i++){
glBegin(GL_LINE_LOOP);
glVertex2f(-1 * i/5.0f, -1 * i/5.0f);
glVertex2f( 1 * i/5.0f, -1 * i/5.0f);
glVertex2f( 1 * i/5.0f, 1 * i/5.0f);
glVertex2f(-1 * i/5.0f, 1 * i/5.0f);
glEnd();
}
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
}
Rendering the textured quad:
void drawTexturedQuad(){
glViewport(50, 50, textureSize, textureSize);
glLoadIdentity();
glClearColor(0.2, 0.2, 0.2, 0.2);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glBindTexture(GL_TEXTURE_2D, textureId);
int size = 1;
int texS = 1;
glBegin(GL_QUADS);
glColor4f(1, 1, 1, 1);
glTexCoord2f(texS, texS); glVertex3f(size, size,0);
glTexCoord2f(0, texS); glVertex3f(-1 * size , size,0);
glTexCoord2f(0, 0); glVertex3f(-1 * size, -1 * size,0);
glTexCoord2f(texS, 0); glVertex3f(size, -1 * size,0);
glEnd();
glBindTexture(GL_TEXTURE_2D, 0);
}
I'm using GLUT and my display call back is simply:
void displayCB(){
drawToTexture();
drawTexturedQuad();
glutSwapBuffers();
}
Additionally I have other methods check to see if FrameBufferObjects are supported by OpenGL and if they are not the program quits. Additionally I have other logic that sets textureSize whenever the window is resized.
glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_TRUE); // automatic mipmap generation included in OpenGL v1.4
This might be a problem. The GL specification doesn't say exactly at what point mipmaps should be generated, and of course, this generates problems with render to texture. So the GL_EXT_framebuffer_object (and core versions too) introduced glGenerateMipmapEXT, which you call exactly in the point where you want mipmaps generated (usually after rendering to the texture).
So, remove the GL_GENERATE_MIPMAP stuff and use glGenerateMipmap manually when needed. You can read more about this problem in the GL_EXT_framebuffer_object specification.
Are you sure that your buffer id is 0 and not 1?
Maybe another FBO was already created before.
Also check texture dimensions try make them power of 2