title: Ping-pong rendering between two FBOs fails after first frame.
body: <p>I am trying to create two FBOs and implement a ping-pong render. But, I only get the first frame to work properly. I am trying to simulate a game-of-life and, after the first frame, I only get a black screen. Could you help me check it? I have spent hours on this issue. </p>
  
  <p><strong>Edit</strong></p>
  
  <p>Maybe I didn't describe clearly. Actually, I want to use the textureB as the texture and render it to textureA, then use the textureA to render to screen, then vice versa.</p>
  
  <p><strong>Edit</strong>
  I can see the first frame, which is the textureB. After it go through the fragment shader, it become black. At first, I suspect the fragment shader, I change it to only revert the black to white and white to black. It still becomes all black.</p>
  
  <p><strong>Set up the fbo and texture</strong></p>
  
  <pre><code>glEnable(GL_TEXTURE_2D);
      glGenTextures(1, &amp;textureA);
      glBindTexture(GL_TEXTURE_2D, textureA);
      glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
      glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_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_RGBA, 256, 256, 0, GL_RGBA,
                   GL_UNSIGNED_BYTE, NULL);
  
      glGenTextures(1, &amp;textureB);
      glBindTexture(GL_TEXTURE_2D, textureB);
      glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
      glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_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);
  
      data=(GLubyte*)malloc(256*256*4*sizeof(GLubyte));
      GLubyte val;
      for (int i = 0; i &lt; 256 * 256 * 4; i+=4) {   
          if (rand()%10 ==1) 
              { val = 0; } 
          else 
              { val = 255; }
          data[i] = data[i+1] = data[i+2] = val;
          data[i+3] = 255;
      }
      glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 256, 256, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
  
      glGenFramebuffers(1, &amp;fboA);
      glBindFramebuffer(GL_FRAMEBUFFER, fboA);
      glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, textureA, 0);
  
      glGenFramebuffers(1, &amp;fboB);
      glBindFramebuffer(GL_FRAMEBUFFER, fboB);
      glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, textureB, 0);
  </code></pre>
  
  <p><strong>Render Loop</strong></p>
  
  <pre><code>if ([context API] == kEAGLRenderingAPIOpenGLES2) {
  
  
          if(counter%2==0)
          {
              glUseProgram(automateProg);
              glBindFramebuffer(GL_FRAMEBUFFER, fboA);
              glActiveTexture(GL_TEXTURE0);
              glBindTexture(GL_TEXTURE_2D, textureB);
              glUniform1i(AUTOMATE_TEXT, 0);
              glUniform1f(DU, 1.0/256);
              glUniform1f(DV, 1.0/256);
              // Update attribute values.
              glVertexAttribPointer(ATTRIB_VERTEX_2, 2, GL_FLOAT, 0, 0, squareVertices);
              glEnableVertexAttribArray(ATTRIB_VERTEX_2);
  
              glVertexAttribPointer(ATTRIB_TEXCOORD_2, 2, GL_FLOAT, GL_FALSE, 0, texCoord);    
              //glEnableVertexAttribArray(ATTRIB_TEXCOORD_2);
              glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
              if (![self validateProgram:automateProg]) {
                  NSLog(@"Failed to validate program: %d", automateProg);
                  return;
              }
  
              glBindFramebuffer(GL_FRAMEBUFFER, 0);
              glUseProgram(0);
          }
          else
          {
              glUseProgram(automateProg);            
              glBindFramebuffer(GL_FRAMEBUFFER, fboB);
              glActiveTexture(GL_TEXTURE0);
              glBindTexture(GL_TEXTURE_2D, textureA);
              glUniform1i(AUTOMATE_TEXT, 0);
              glUniform1f(DU, 1.0/256);
              glUniform1f(DV, 1.0/256);
              // Update attribute values.
              glVertexAttribPointer(ATTRIB_VERTEX_2, 2, GL_FLOAT, 0, 0, squareVertices);
              glEnableVertexAttribArray(ATTRIB_VERTEX_2);
              glVertexAttribPointer(ATTRIB_TEXCOORD_2, 2, GL_FLOAT, GL_FALSE, 0, texCoord); 
              //glEnableVertexAttribArray(ATTRIB_TEXCOORD_2);
              glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
              if (![self validateProgram:automateProg]) {
                  NSLog(@"Failed to validate program: %d", automateProg);
                  return;
              }
  
              glBindFramebuffer(GL_FRAMEBUFFER, 0);
              glUseProgram(0);
          }
  
          [(EAGLView *)self.view setFramebuffer];
          glClearColor(0.5f, 0.5f, 0.5f, 1.0f);
          glClear(GL_COLOR_BUFFER_BIT);
  
          if (counter % 2 == 0) {
              glUseProgram(normalProg);
              glActiveTexture(GL_TEXTURE0);
              glBindTexture(GL_TEXTURE_2D, textureB);
              glUniform1i(NORMAL_TEXT, 0);
              glVertexAttribPointer(ATTRIB_VERTEX, 2, GL_FLOAT, 0, 0, squareVertices);
              glEnableVertexAttribArray(ATTRIB_VERTEX);
              glVertexAttribPointer(ATTRIB_TEXCOORD, 2, GL_FLOAT, GL_FALSE, 0, texCoord); 
              glEnableVertexAttribArray(ATTRIB_TEXCOORD);
              glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
              if (![self validateProgram:normalProg]) {
                  NSLog(@"Failed to validate program: %d", normalProg);
                  return;
              }
              glUseProgram(0);
  
          } else {
              glUseProgram(normalProg);
              glActiveTexture(GL_TEXTURE0);
              glBindTexture(GL_TEXTURE_2D, textureA);
              glUniform1i(NORMAL_TEXT, 0);
              glVertexAttribPointer(ATTRIB_VERTEX, 2, GL_FLOAT, 0, 0, squareVertices);
              glEnableVertexAttribArray(ATTRIB_VERTEX);
              glVertexAttribPointer(ATTRIB_TEXCOORD, 2, GL_FLOAT, GL_FALSE, 0, texCoord); 
              glEnableVertexAttribArray(ATTRIB_TEXCOORD);
              glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
              if (![self validateProgram:normalProg]) {
                  NSLog(@"Failed to validate program: %d", normalProg);
                  return;
              }
              glUseProgram(0);
          }
          counter++;
  
  [(EAGLView *)self.view presentFramebuffer];
  </code></pre>
  
  <p><strong>Fragment Shader</strong></p>
  
  <pre><code>precision mediump float;
  varying vec2 v_texCoord;
  uniform sampler2D tex; //the input texture
  uniform float du; //the width of the cells
  uniform float dv; //the height of the cells
      void main() {
          int count = 0;
  
          vec4 C = texture2D( tex, v_texCoord );
          vec4 E = texture2D( tex, vec2(v_texCoord.x + du, v_texCoord.y) );
          vec4 N = texture2D( tex, vec2(v_texCoord.x, v_texCoord.y + dv) );
          vec4 W = texture2D( tex, vec2(v_texCoord.x - du, v_texCoord.y) );
          vec4 S = texture2D( tex, vec2(v_texCoord.x, v_texCoord.y - dv) );
          vec4 NE = texture2D( tex, vec2(v_texCoord.x + du, v_texCoord.y + dv) );
          vec4 NW = texture2D( tex, vec2(v_texCoord.x - du, v_texCoord.y + dv) );
          vec4 SE = texture2D( tex, vec2(v_texCoord.x + du, v_texCoord.y - dv) );
          vec4 SW = texture2D( tex, vec2(v_texCoord.x - du, v_texCoord.y - dv) );
  
          if (E.r == 1.0) { count++; }
          if (N.r == 1.0) { count++; }
          if (W.r == 1.0) { count++; }
          if (S.r == 1.0) { count++; }
          if (NE.r == 1.0) { count++; }
          if (NW.r == 1.0) { count++; }
          if (SE.r == 1.0) { count++; }
          if (SW.r == 1.0) { count++; }
  
          if ( (count == 2 || count == 3)) {
              gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0); //cell lives...
          } else {
              gl_FragColor = vec4(0.0,0.0,0.0, 1.0); //cell dies...
          }
      }
  </code></pre>