I see a strange problem with the multi-pass ping-pong multi-RT renderer
I use 3 shaders and FBO, I do not get errors at any stage. I use opengl 4, so I do not use glBegin / glEnd, I use my own matrices for conversion, and I use vertex buffers for rendering
The general idea of this test is to display three different colors for three separate fbo attachments (I understand that this is not an efficient rendering of vbo twice in the first pass, but this is only to help me understand the problem in some other source) Then I associate a separate texture set with fbo and use the first set as samplers. The final run consists in mixing the results in a reverse buffer
It is odd that both squares appear red when the first one should be red and the second green (since these values come from the second shader).
If I change the SamplePix function in the second shader to always take from the second sampler, both look green, and if the search comes from the third, then everything looks yellow, but it seems to only be read from it.
At the moment, I can’t explain why I can read from each sampler, but the loop doesn’t seem to look right (in shader 2)
Also, if I switch to rendering the texture selected in shader 2, I see a black square in the second pass (image 2)
Hope someone can shed some light on the problem. (I also tried to add an object with synchronization after the first pass, but this did not affect)

Texture example:

// initial setup of shaders and vertex buffers ommitted for now (in separate source files) // fbo setup like so const int DepthLayers = 3; bool InitFBO() { // width and height 768pixels for (int j=0; j<DepthLayers; j++) { const int idx = j + (DepthLayers*i); glGenTextures(1, &g_FBOManager.m_fboTex[ idx ]); glBindTexture(GL_TEXTURE_2D, g_FBOManager.m_fboTex[ idx ]); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); //no mipmaps glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_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); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, g_XMLSettings->WWidth(), g_XMLSettings->WHeight(), 0, GL_RGBA, GL_UNSIGNED_BYTE, 0); //depth glGenTextures(1, &g_FBOManager.m_fboDepthTex[ idx ]); glBindTexture(GL_TEXTURE_2D, g_FBOManager.m_fboDepthTex[ idx ]); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); //no mipmaps glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 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_DEPTH_TEXTURE_MODE, GL_INTENSITY); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_NONE/* GL_COMPARE_R_TO_TEXTURE*/); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL); glTexImage2D( GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT32, g_XMLSettings->WWidth(), g_XMLSettings->WHeight(), 0, GL_DEPTH_COMPONENT, GL_FLOAT, 0); glBindTexture(GL_TEXTURE_2D, g_FBOManager.m_fboDepthTex[idx]); pglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT,GL_TEXTURE_2D, g_FBOManager.m_fboDepthTex[idx], 0); glBindTexture(GL_TEXTURE_2D, g_FBOManager.m_fboTex[idx]); // attach a texture to FBO color attachment point pglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, g_FBOManager.m_fboTex[idx], 0); // check FBO status pglBindFramebufferEXT( GL_FRAMEBUFFER_EXT, g_FBOManager.FboId(i) ); if(!CheckFramebufferStatus()) { return false; } } BindFrameBuffer(-1); // unbind fbo if (GLGETERROR("1", fileBuf, lineBuf)) ; // check for glErrors return true; // all ok } // code to init second set of textures before the render loop const int w = g_XMLSettings->WWidth(); //res: 768 square const int h = g_XMLSettings->WHeight(); glGenTextures(bufCount, &ttex[0]); for (int i=0; i<bufCount; ++i) { glBindTexture(GL_TEXTURE_2D, ttex[i]); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB8, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0); } const int bufCount = 3; void EnableTexture1() { glActiveTextureARB(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, g_BackTexture); glUniform1iARB(g_pPassAShader->m_clr_idx, 0); } void RenderLoop() { GLenum buffers[] = { GL_COLOR_ATTACHMENT0_EXT, GL_COLOR_ATTACHMENT1_EXT, GL_COLOR_ATTACHMENT2_EXT }; glColor4f(0.0f, 0.0f, 0.0f, 0.0f); glClearColor(0.0f, 0.0f, 0.0f, 0.0f); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA); glUseProgramObjectARB(g_pPassAShader->m_glContext); EnableTexture1(); //... code omitted to set transform matrix and supply to shader if (!BindFrameBuffer(0)) assert(0); const GLuint DTex = g_FBOManager.GetDepthTexture(0); glBindTexture(GL_TEXTURE_2D, DTex); pglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT,GL_TEXTURE_2D, DTex, 0); for (UINT i=0; i<bufCount; ++i) { glBindTexture(GL_TEXTURE_2D, g_FBOManager.GetTexture(i)); pglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT + i, GL_TEXTURE_2D, g_FBOManager.GetTexture(i), 0); if (!CheckFramebufferStatus()) assert(0); } glDrawBuffers(bufCount,buffers); // this is very important! if we don't clear it won't get written to glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glDisable(GL_BLEND); EnableTexture1(); RenderVertexCache(0); //... code omitted to set transform matrix and supply to shader // render the second quad to other FBO tex RenderVertexCache(0); DisableShader(0); BindFrameBuffer(-1); // unbinds fbo //pass 2 if (!BindFrameBuffer(0)) assert(0); // bind other set of textures to the fbo for (UINT i=0; i<bufCount; ++i) { glBindTexture(GL_TEXTURE_2D,ttex[i]); pglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT + i, GL_TEXTURE_2D, ttex[i], 0); if (!CheckFramebufferStatus()) assert(0); } glDrawBuffers(bufCount,buffers); // this is very important! if we don't clear it won't get written to glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ); // bind our set from prev pass to the samplers as input glUseProgramObjectARB(g_pPassBShader->m_glContext); for (UINT i=0; i<bufCount; ++i) { glActiveTextureARB(GL_TEXTURE0+i); glBindTexture(GL_TEXTURE_2D,g_FBOManager.GetTexture(i)); glUniform1iARB(g_pPassBShader->m_intex_idx[i], i); } VertexBufferManager2::RenderUsingOrthoEx(g_pPassBShader); // renders a full screen quad DisableShader(0); BindFrameBuffer(-1); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // pass 3 glUseProgramObjectARB(g_pPassCShader->m_glContext); for (UINT i=0; i<bufCount; ++i) { glActiveTextureARB(GL_TEXTURE0+i); glBindTexture(GL_TEXTURE_2D, ttex[i]); glUniform1iARB(g_pPassCShader->m_intex_idx[i], i); } VertexBufferManager2::RenderUsingOrthoEx(g_pPassCShader); if (GLGETERROR("at1", fileBuf, lineBuf)) ; // reports any glErrors } // the three shaders (fragment shaders only) // vertex shaders transfer uv and transform vertices (version set to 410 in all) // shader for pass1 //-------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------