OpenGL stencil buffer concave polygon - c++
I'm trying to do this example.
I couldn't understand how it works still and I'm having difficulties in visualizing how the code would look like.
I stumbled upon this post which was the closest I think I could find.
From the redbook link, how can I do a "two-pass algorithm" to get the desired output? How do I use GL_INVERT and check if the pixel is covered even number of times?
I somehow managed to understand how the stencil works for the concave polygon but my problem now is the polygon is being rendered incorrectly.
http://img.photobucket.com/albums/v442/ardo/ScreenShot2013-12-30at24155PM.png
The location of where I am drawing this is in a framebuffer which is set up like this:
//multisample
glGenRenderbuffersEXT(1, &colorBuffer);
glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, colorBuffer);
glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER_EXT, multisampling, GL_RGBA,800, 600);
//multi sample depth
glGenRenderbuffersEXT(1, &depthBuffer);
glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, depthBuffer);
glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER_EXT, multisampling, GL_DEPTH24_STENCIL8, 800, 600);
//multisamplefbo
glGenFramebuffersEXT(1, &mFBO);
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, mFBO);
glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_RENDERBUFFER_EXT, colorBuffer);
glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER_EXT, depthBuffer);
Then my drawing code is:
glEnable(GL_STENCIL_TEST);
glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
glStencilFunc(GL_ALWAYS, 0x1, 0x1);
glStencilOp(GL_KEEP, GL_INVERT, GL_INVERT);
glBegin(GL_TRIANGLE_FAN);
glVertex3f(1.396900,3.130690,0);
glVertex3f(2.034830,2.466900,0);
glVertex3f(2.486338,2.441036,0);
glVertex3f(2.802204,2.437803,0);
glVertex3f(2.910181,2.447098,0);
glVertex3f(2.957240,2.466900,0);
glVertex3f(3.019335,2.552570,0);
glVertex3f(3.130733,2.673799,0);
glVertex3f(3.284830,2.828970,0);
glVertex3f(3.474490,3.087590,0);
glVertex3f(4.319320,2.596210,0);
glVertex3f(4.508980,2.147930,0);
glVertex3f(4.714798,1.866680,0);
glVertex3f(4.907215,1.620586,0);
glVertex3f(5.101651,1.397930,0);
glVertex3f(5.186114,1.317364,0);
glVertex3f(5.254869,1.269024,0);
glVertex3f(5.302510,1.261700,0);
glVertex3f(5.323633,1.304180,0);
glVertex3f(5.312832,1.405254,0);
glVertex3f(5.264703,1.573711,0);
glVertex3f(5.173841,1.818340,0);
glVertex3f(5.034840,2.147930,0);
glVertex3f(4.875695,2.492816,0);
glVertex3f(4.727900,2.780675,0);
glVertex3f(4.591307,3.016304,0);
glVertex3f(4.465765,3.204503,0);
glVertex3f(4.351127,3.350070,0);
glVertex3f(4.247241,3.457803,0);
glVertex3f(4.153958,3.532502,0);
glVertex3f(4.071129,3.578965,0);
glVertex3f(3.998605,3.601990,0);
glVertex3f(3.936235,3.606376,0);
glVertex3f(3.841363,3.578427,0);
glVertex3f(3.766900,3.510000,0);
glVertex3f(2.974490,3.458280,0);
glVertex3f(2.672770,2.958280,0);
glVertex3f(2.379670,3.070350,0);
glVertex3f(1.853810,3.303110,0);
glVertex3f(1.396910,3.303110,0);
glVertex3f(1.396910,3.130690,0);
glVertex3f(1.396900,3.130690,0);
glVertex3f(1.396900,3.130690,0);
glEnd();
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
glStencilFunc(GL_EQUAL, 0x1, 0x1);
glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
glColor3f(1,0,1);
glBegin(GL_TRIANGLE_FAN);
glVertex3f(1.396900,3.130690,0);
glVertex3f(2.034830,2.466900,0);
glVertex3f(2.486338,2.441036,0);
glVertex3f(2.802204,2.437803,0);
glVertex3f(2.910181,2.447098,0);
glVertex3f(2.957240,2.466900,0);
glVertex3f(3.019335,2.552570,0);
glVertex3f(3.130733,2.673799,0);
glVertex3f(3.284830,2.828970,0);
glVertex3f(3.474490,3.087590,0);
glVertex3f(4.319320,2.596210,0);
glVertex3f(4.508980,2.147930,0);
glVertex3f(4.714798,1.866680,0);
glVertex3f(4.907215,1.620586,0);
glVertex3f(5.101651,1.397930,0);
glVertex3f(5.186114,1.317364,0);
glVertex3f(5.254869,1.269024,0);
glVertex3f(5.302510,1.261700,0);
glVertex3f(5.323633,1.304180,0);
glVertex3f(5.312832,1.405254,0);
glVertex3f(5.264703,1.573711,0);
glVertex3f(5.173841,1.818340,0);
glVertex3f(5.034840,2.147930,0);
glVertex3f(4.875695,2.492816,0);
glVertex3f(4.727900,2.780675,0);
glVertex3f(4.591307,3.016304,0);
glVertex3f(4.465765,3.204503,0);
glVertex3f(4.351127,3.350070,0);
glVertex3f(4.247241,3.457803,0);
glVertex3f(4.153958,3.532502,0);
glVertex3f(4.071129,3.578965,0);
glVertex3f(3.998605,3.601990,0);
glVertex3f(3.936235,3.606376,0);
glVertex3f(3.841363,3.578427,0);
glVertex3f(3.766900,3.510000,0);
glVertex3f(2.974490,3.458280,0);
glVertex3f(2.672770,2.958280,0);
glVertex3f(2.379670,3.070350,0);
glVertex3f(1.853810,3.303110,0);
glVertex3f(1.396910,3.303110,0);
glVertex3f(1.396910,3.130690,0);
glVertex3f(1.396900,3.130690,0);
glVertex3f(1.396900,3.130690,0);
glEnd();
glDisable(GL_STENCIL_TEST);
The way I have my multisampling set up is here (This is before the drawing is written)
[self checkError];
glEnable(GL_DEPTH_TEST);
[self checkError];
glDepthMask(GL_TRUE);
[self checkError];
glDepthFunc(GL_LESS);
[self checkError];
glClearDepth(10000.0);
[self checkError];
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
[self checkError];
if(multisampling != 0){
//Set multisampled framebuffer
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, mFBO);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
//Antialiasing functions
glEnable (GL_POLYGON_SMOOTH);
glEnable (GL_BLEND);
glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glHint (GL_POLYGON_SMOOTH_HINT, GL_NICEST);
glLineWidth (1.5);
}
glDisable(GL_CULL_FACE);
And my blit call:
glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, mFBO);
glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, currentFramebuffer);
glBlitFramebuffer(0, 0, 800, 600, 0, 0, 800, 600, GL_COLOR_BUFFER_BIT, GL_NEAREST);
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, mFBO);
glReadBuffer(GL_COLOR_ATTACHMENT0_EXT);
glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, currentFramebuffer);
glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, currentFramebuffer);
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, currentFramebuffer);
What don't you get? The example starts out with a stencil buffer cleared to 0x00 and each time you draw a fragment (whether it passes or fails a depth/stencil test) it performs a bitwise inversion of the stencil buffer (e.g. ~0x00 --> 0xff). If you do this an odd number of times, the stencil buffer will be non-zero, but if you have an even number of fragments it will be zero.
Some things that might be confusing are the use of 1 as the bitmask for the stencil test and the stencil op in the second pass. This effectively limits the test to a single bit. In other words, the bit flipping I mentioned earlier will only happen for bit 1. Thus, you can actually simplify your test for even/odd to a test of a single bit... if the stencil buffer stores a value of 1 then you drew an odd number of fragments. If it stores a value of 0 then you drew an even number.
The second pass in your example actually does the exact stencil test I described. It tests the stencil buffer for 1 and fails the stencil test if the first bit != 1.
// The stencil op below is a convoluted way of clearing the stencil buffer
glStencilOp (GL_ZERO, GL_ZERO, GL_ZERO);
glStencilFunc (GL_EQUAL, 1, 1); // Test: (Stencil & 1) == 1
Related
Stencil buffer behaviour in simple case (GL_ALWAYS, GL_LEQUAL)
I don't understand why those two codes doesn't yield the same result. I have enabled depth testing and stencil testing and my main loop looks like this : myShader.Use() // Use shader program glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); // define model, projection, view, .... glBindVertexArray(VAO[0]); glStencilMask(0xFF); // Enable stencil buffer writing glStencilFunc(GL_ALWAYS, 1, 0xFF); glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE); drawCube(&myShader, model, projection, view); glBindVertexArray(0); Obviously, my cube renders in this case. However, if I use this code, nothing renders at all : myShader.Use() // Use shader program glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); // define model, projection, view, .... glBindVertexArray(VAO[0]); glStencilMask(0xFF); // Enable stencil buffer writing glStencilFunc(GL_LEQUAL, 1, 0xFF); glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE); drawCube(&myShader, model, projection, view); glBindVertexArray(0); With only one object in my scene, both code should behave the same way. Yet, it doesn't. I thought it had something to do with the default value in the stencil buffer. However, since I'm clearing the stencil buffer before doing this, the default value should be 0. By the way, with this code, the cube renders as well : myShader.Use() // Use shader program glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); // define model, projection, view, .... glBindVertexArray(VAO[0]); glStencilMask(0xFF); // Enable stencil buffer writing glStencilFunc(GL_LEQUAL, 0, 0xFF); glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE); drawCube(&myShader, model, projection, view); glBindVertexArray(0); I don't understand what is happening.
glStencilFunc(GL_LEQUAL, 1, 0xFF) means if 1 <= 0, because the stencil buffer contains 0, since you cleared it. The reference value is 1, because you pass this value to the function. This always fails. See the Khronos reference page (glStencilFunc): GL_LEQUAL Passes if ( ref & mask ) <= ( stencil & mask ).
Self-occlusion-aware multiple geometry blending in C++ OpenGL (rendering)
I have got several meshes (~100) of the same complex object in various poses with slightly different rotation and translation parameters. The object consists of multiple rigid components like arms and legs. The goal is to generate a unique grayscale picture showing the accumulation of these poses for a particular body part. The heat-map obtained gives an idea of probable pixel locations for the body part, where white represents maximum probability, and black minimum (the lighter the higher probability). Say I'm interested in the accumulation of the legs. If many leg pose samples lie on the same (x,y) pixel location, than I expect to see light pixels there. Ultimately the leg poses might not exactly overlap, so I also expect to see a smooth transition to the black low probability around the leg silhouette boundaries. To solve this task I have decided to use rendering in OpenGL frame buffers as these are known to be computationally cheap, and because I need to run this accumulation procedure very often. What I did is the following. I accumulate the corresponding renderings of the body part I'm interested in (let's still keep the leg example) on the same frame buffer 'fboLegsId' using GL_BLEND. In order to discriminate between the legs and the rest of the body, I texture the mesh with two colors: rgba(gray,gray,gray,255) for the legs, where gray = 255 / Number of samples = 255/100 rgba(0,0,0,0) for the rest of the body Then I accumulate the 100 renderings (which for the leg should sum up to white = 255) by doing the following: glBindFramebuffer(GL_FRAMEBUFFER, fboLegsId); glClearColor(0,0,0,255); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glBlendFunc(GL_ONE, GL_ONE); glEnable(GL_BLEND); for each sample s = 0...100 mesh.render(pose s); end glReadPixels(...) This performs almost as I expected. I do obtain the smooth grayscale heat-map I wanted. However there are self-occlusion problems which arise even when I use only 1 sample. Say for a single pose sample, one of the arms moved before the leg, partially occluding them. I expect the influence of the occluded leg parts to be cancelled during rendering. However it renders as if the arm is invisible/translucent, allowing for pixels behind to be fully shown. This leads to wrong renderings and therefore wrong accumulations. If I simple disable blending, I see the correct self-occlusion aware result. So, apparently the problem lies somewhere at blending time. I also tried different blending functions, and so far the following one produced the closer results to a self-occlusion aware accumulation approach: glBlendFunc(GL_ONE, GL_SRC_ALPHA); Anyway there is still a problem here: one single sample looks now correct; two or more accumulated samples instead show overlapping artefacts with other samples. It looks like each accumulation replaces the current buffer pixel if the pixel is not part of the legs. And if the leg was found many times in front of the (let's say) the arm, than it becomes darker and darker, instead of lighter and lighter. I tried to fix this by clearing depth buffer at each rendering iteration enabling depth computations, but this did not solve the problem. I feel like there is either something conceptually wrong in my approach, or a small mistake somewhere. I've tried a different approach based on the suggestions which performs as expected. Now I'm working with 2 frame buffers. The first one (SingleFBO) is used to render single samples with correct self-occlusion handling. The second (AccFBO) is used to accumulate the 2D textures from the first buffer using blending. Please, check my code below: // clear the accumulation buffer glBindFramebuffer(GL_FRAMEBUFFER, AccFBO); glClearColor(0.f, 0.f, 0.f, 1.f); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); for each sample s = 0...100 { // set rendering destination to SingleFBO glBindFramebuffer(GL_FRAMEBUFFER, SingleFBO); glClearColor(0.f, 0.f, 0.f, 1.f); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glEnable(GL_DEPTH_TEST); glDisable(GL_LIGHTING); mesh->render(pose s); glDisable(GL_DEPTH_TEST); glEnable(GL_LIGHTING); // set rendering destination to the accumulation buffer glBindFramebuffer(GL_FRAMEBUFFER, AccFBO); glClear(GL_DEPTH_BUFFER_BIT); glBlendFunc(GL_ONE, GL_ONE); glEnable(GL_BLEND); // draw texture from previous buffer to a quad glBindTexture(GL_TEXTURE_2D, textureLeg); glEnable(GL_TEXTURE_2D); glDisable(GL_DEPTH_TEST); glDisable(GL_LIGHTING); glDepthMask(GL_FALSE); glMatrixMode(GL_PROJECTION); glPushMatrix(); glLoadIdentity(); glMatrixMode(GL_MODELVIEW); glPushMatrix(); glLoadIdentity(); glBegin( GL_QUADS ); { glTexCoord2f(0,0); glVertex2f(-1.0f, -1.0f); glTexCoord2f(1,0); glVertex2f(1.0f, -1.0f); glTexCoord2f(1,1); glVertex2f(1.0f, 1.0f); glTexCoord2f(0,1); glVertex2f(-1.0f, 1.0f); } glEnd(); glPopMatrix(); glMatrixMode(GL_PROJECTION); glPopMatrix(); glMatrixMode(GL_MODELVIEW); // restore glDisable(GL_TEXTURE_2D); glEnable(GL_DEPTH_TEST); glEnable(GL_LIGHTING); glDepthMask(GL_TRUE); glDisable(GL_BLEND); } glBindFramebuffer(GL_FRAMEBUFFER, AccFBO); glReadPixels(...) Please, check also my (standard) code for initializing the SingleFBO (similarly for AccFBO): // create a texture object glGenTextures(1, &textureLeg); glBindTexture(GL_TEXTURE_2D, textureLeg); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, 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, GL_TRUE); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, 0); glBindTexture(GL_TEXTURE_2D, 0); // create a renderbuffer object to store depth info glGenRenderbuffers(1, &rboLeg); glBindRenderbuffer(GL_RENDERBUFFER, rboLeg); glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, width, height); glBindRenderbuffer(GL_RENDERBUFFER, 0); // create a framebuffer object glGenFramebuffers(1, &SingleFBO); glBindFramebuffer(GL_FRAMEBUFFER, SingleFBO); // attach the texture to FBO color attachment point glFramebufferTexture2D(GL_FRAMEBUFFER, // 1. fbo target: GL_FRAMEBUFFER GL_COLOR_ATTACHMENT0, // 2. attachment point GL_TEXTURE_2D, // 3. tex target: GL_TEXTURE_2D textureLeg, // 4. tex ID 0); // 5. mipmap level: 0(base) // attach the renderbuffer to depth attachment point glFramebufferRenderbuffer(GL_FRAMEBUFFER, // 1. fbo target: GL_FRAMEBUFFER GL_DEPTH_ATTACHMENT, // 2. attachment point GL_RENDERBUFFER, // 3. rbo target: GL_RENDERBUFFER rboLeg); // 4. rbo ID // check FBO status GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER); if(status != GL_FRAMEBUFFER_COMPLETE) error(...); // switch back to window-system-provided framebuffer glBindFramebuffer(GL_FRAMEBUFFER, 0);
Here's a different approach: Create two frame buffers: normal and acc. normal frame buffer should have a texture storage (with glFramebufferTexture2D). Here's the basic algorithm: Clear acc to black Bind normal, clear to black, and render scene with white legs, and other parts black Bind acc, render a full screen rectangle, with normal texture on it, with blend mode GL_ONE, GL_ONE Forward the animation, and if it haven't finished, goto 2. You have the result in acc So, basically, acc will contain the individual frames summed.
Multisample Texture produces artifacts at horizon
I have implemented a deferred rendering and am trying to use multisample textures for anti aliasing. I render the scene into a FBO with multisample textures, use glBlit to create regular textures in a second FBO and finally bind the texture to the lighting shader that produces the final image. // draw to textures mMultiGeometryFBO->bind(); glViewport(0,0,mWidth,mHeight); glEnable(GL_DEPTH_TEST); glClear( GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT ); // calling all modules to draw to FBO for(auto r : mRenderer) r->renderMaterial(camera); glBindFramebuffer(GL_READ_FRAMEBUFFER, mMultiGeometryFBO->fbo()); glBindFramebuffer(GL_DRAW_FRAMEBUFFER, mGeometryFBO->fbo()); glReadBuffer(GL_COLOR_ATTACHMENT0); glDrawBuffer(GL_COLOR_ATTACHMENT0); glBlitFramebuffer(0, 0, mWidth, mHeight, 0, 0, mWidth, mHeight, GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT, GL_LINEAR); glReadBuffer(GL_COLOR_ATTACHMENT1); glDrawBuffer(GL_COLOR_ATTACHMENT1); glBlitFramebuffer(0, 0, mWidth, mHeight, 0, 0, mWidth, mHeight, GL_COLOR_BUFFER_BIT, GL_LINEAR); glReadBuffer(GL_COLOR_ATTACHMENT2); glDrawBuffer(GL_COLOR_ATTACHMENT2); glBlitFramebuffer(0, 0, mWidth, mHeight, 0, 0, mWidth, mHeight, GL_COLOR_BUFFER_BIT, GL_LINEAR); // draw to screen glBindFramebuffer(GL_FRAMEBUFFER, 0); glClear(GL_DEPTH_BUFFER_BIT); mSkybox->renderMaterial(camera); mShader->use(); mShader->setTexture("tDiffuse", mDiffuseColor, 0); mShader->setTexture("tNormal", mNormals, 1); mShader->setTexture("tMaterial", mMaterialParams, 2); mShader->setTexture("tDepth", mDepthBuffer, 3); mShader->setTexture("tLights", mLightColor, 4); mQuad->draw(); This produces a visible line at the horizon (between geometry and skybox). The color is the clear color. Only clearing the depth reduces the problem when moving. Rendering the SkyBox to the FBO before rendering the geometry produces less visible artifacts, but the line is still there. Edit: forgot the picture
Resolving the multisample target before the lighting pass does not make sense, conceptually. What you will get is that the values in your gbuffers will be averaged at the edges of objects. This is especially bad for the normal directions. Think about it: If you have a pixel which contains 50% of your ground plane, and 50% of your sky, you will get a normal direction which is (normal_ground + normal_sky)/2. This is totally different from calculating the final color of each of this parts with their original normal and mixing the resulting colors. If you want to do multisampling with deferred rendering, you have to use the multisampling target for the lighting, and will have to enable per sample shading and actually access and light each sample individually, and only blit the final result to a non-multisampled target. However, that will be exorbitantly expensive. You especially lose the benefits of multisampling vs. supersampling. I don't know if there are some neat tricks trick to still work with multisampling in a more efficient way, but the usual approach is to not use multisampling at all and doing the anti-aliasing via some image-based postprocessing pass.
Render to FBO + glReadPixels all black
I am trying to render a simple checkerboard in a FBO and then do a glReadPixels(). When I do it without FBO, everything works fine. So I assume that my render function is ok and so is the glReadPixels(). With the FBO, all I get are the lines that I draw after the calls to FBO have been done. Here is my code (Python, aiming cross platform): def renderFBO(): #WhyYouNoWorking(GL_FRAMEBUFFER) # degug function... error checking glBindFramebuffer( GL_DRAW_FRAMEBUFFER, framebuffer) glBindRenderbuffer( GL_RENDERBUFFER, renderbufferA) glRenderbufferStorage( GL_RENDERBUFFER, GL_RGBA, window.width, window.height) glBindRenderbuffer( GL_RENDERBUFFER, renderbufferB) glRenderbufferStorage( GL_RENDERBUFFER, GL_DEPTH_COMPONENT, window.width, window.height) glBindFramebuffer( GL_DRAW_FRAMEBUFFER, framebuffer) glFramebufferRenderbuffer( GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, renderbufferA) glFramebufferRenderbuffer( GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, renderbufferB) #WhyYouNoWorking(GL_FRAMEBUFFER) glDrawBuffer(GL_COLOR_ATTACHMENT0) glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT) glViewport( 0, 0, window.width, window.height) DrawChecker(Nbr = 16, Dark = 25.0/255, Light = 75.0/255) for i in range(len(labelSysInfo)): pyglet.text.Label(labelSysInfo[i], font_name='Times New Roman', font_size=26, x=(window.width*0.68), y= (window.height*0.04*i)+(window.height*2/3), anchor_x='left', anchor_y='center', color = (250, 250, 250, 150)).draw() glReadPixels(0, 0, window.width, window.height, GL_RGBA, GL_UNSIGNED_BYTE, a) glBindFramebuffer( GL_FRAMEBUFFER, 0) My other function: def on_draw(dt): glDrawBuffer(GL_BACK) glClear(GL_COLOR_BUFFER_BIT) glClearColor( 0.0, 0.0, 0.0, 1.0) glLoadIdentity() glEnable(GL_TEXTURE_2D) glDisable(GL_TEXTURE_2D) BlueLine() # draw a simple line. works fine DropFrameTest() # draw a simple line. works fine In the main, the call to renderFBO() is done once, and then on_draw is called periodically. dt = pyglet.clock.tick() renderFBO() pyglet.clock.schedule_interval(on_draw, 0.007) pyglet.app.run()
At a guess, you've bound the framebuffer to the GL_DRAW_FRAMEBUFFER only. Use glBindFramebuffer(GL_FRAMEBUFFER, ... and glFramebufferRenderbuffer(GL_FRAMEBUFFER, ... to both read and write with the same FBO. I'm sure you already have but checking for framebuffer completeness (glCheckFramebufferStatus) and for GL errors (glGetError, or the new extension) is also very useful. [EDIT] (The shotgun problem solving tactics from the comments) If you see an image on the first frame, but none on the next there must be something staying behind from the previous frame. The most common problem is forgetting to clear the depth buffer - but you haven't. Next up are stencil buffers and blending (neither look like they're enabled to begin with). Maybe a new FBO handle is being generated each frame and you're running out? Another common problem is accumulating matrix transforms, but you have glLoadIdentity so should be no issue there.
glStencilFunc(GL_NEVER, 0, 0) still renders?
I have problems utilizing the stencil buffer, and it's seems to boil down to not work at all. Given the following code: glEnable(GL_STENCIL_TEST); glClearStencil(0); glClear(GL_STENCIL_BUFFER_BIT | GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glColor4f(1, 1, 1, 1); glStencilFuncSeparate(GL_FRONT_AND_BACK, GL_NEVER, 0, 0); glStencilOpSeparate(GL_FRONT_AND_BACK, GL_INCR, GL_INCR, GL_INCR); glBegin(GL_TRIANGLES); { draw something } glEnd(); The triangles are still drawn!? Am I missing something trivial here? Note: I'm not rendering to a frame buffer, I'm using glStencil...Separate just to make sure it's not related to front\back, I've kept bits of code that to me doesn't seem related.
You don't have a stencil buffer. And by the specification (from 4.3 core, folio page 432): If there is no stencil buffer, no stencil modification can occur, and it is as if the stencil tests always pass, regardless of any calls to StencilFunc.