title: How to switch shader programs in glsl
body: <p>I want to do volume rendering using programmable pipeline (using glsl) and no fixed pipelines. I implement it with 2 passes with 2 shader programs, <code>exitPointProg</code> and <code>rayCastProg</code>. the first pass is to get the exit points (i.e. the back face) of a cube bounding box which will be used as a texture in the next pass which doing the raycasting. the idea to do the raycasting volume rendering comes from <a href="http://www.daimi.au.dk/~trier/?page_id=98" rel="nofollow">here</a>. I think I have done the most of the things right cause I have implemented this with fixed pipeline combined with the programmable pipeline. the things that confused me is that I achieved the result with the very first frame, and with a flash the display on the screen turn totally white (I set the <code>glClearColor(1.0f, 1.0f, 1.0f, 1.0f)</code>. I think there maybe some wrong with the switch of the shader programs or the FBO. here is what I do in the render() function.</p>
  
  <ol>
  <li>1st pass, render to a fbo with <code>exitPoints</code> texture bound to it to get the exit points of cube bounding box, using shader program <code>exitPointProg</code>.</li>
  <li><p>2ed pass, mapped the <code>exitPoints</code> texture (bound to <code>GL_TEXTURE1</code>) into the shader program <code>rayCastProg</code> as a uniform sampler2D variable which will used in the shader.
  here is the <code>setupFBO</code> and <code>render</code> and two subroutines:
  the <code>setupFBO()</code> function:</p>
  
  <pre><code>void SimpleRayCasting::setupFBO()
  {
      GLuint textureHandles[1];
      glGenTextures(1, textureHandles);
      entryPoints = textureHandles[0];
  
  
      glActiveTexture(GL_TEXTURE1);
      glBindTexture(GL_TEXTURE_2D, exitPoints);
      glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
      glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
      glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
      glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
      glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
      glTexImage2D(GL_TEXTURE_2D, 0,GL_RGBA16F, width, height, 0, GL_RGBA, GL_FLOAT, NULL);
  
  
      GLuint depthRenderBuffer;
      glGenRenderbuffers(1, &amp;depthRenderBuffer);
      glBindRenderbuffer(GL_RENDERBUFFER, depthRenderBuffer);
      glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, width, height);
  
      glGenFramebuffers(1, &amp;frameBuffer);
      glBindFramebuffer(GL_FRAMEBUFFER, frameBuffer);
      glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 
                      exitPoints, 0/* level */);
      glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, 
                      depthRenderBuffer);
  
  
      checkFramebufferState(__FILE__, __LINE__);
      GLenum drawbufs[] = {GL_COLOR_ATTACHMENT0};
      glDrawBuffers(1, drawbufs);
      glBindFramebuffer(GL_FRAMEBUFFER,0);
  }
  </code></pre>
  
  <p>the <code>render()</code> function:</p>
  
  <pre><code>void SimpleRayCasting::render()
  {
      getExitPoints();
      GLUtils::checkForOpenGLError(__FILE__,__LINE__);
      rayCasting();
      GLUtils::checkForOpenGLError(__FILE__,__LINE__);
  }
  </code></pre>
  
  <p>the <code>getExitPoints()</code> function:</p>
  
  <pre><code>void SimpleRayCasting::getExitPoints() 
  {
      // render to the texture
      glBindFramebuffer(GL_FRAMEBUFFER, frameBuffer);
      glEnable(GL_DEPTH_TEST);
      glViewport(0, 0, width, height);
      // checkFramebufferState(__FILE__, __LINE__); 
      glClearColor(0.2f, 0.2f, 0.2f, 1.0);
      glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
      exitPointsProg.use();
      // note that the model will recalculated.
      model = mat4(1.0f);
      model *= glm::rotate(angle , vec3(0.0f,1.0f,0.0f));
      model *= glm::rotate(90.0f, vec3(1.0f, 0.0f, 0.0f));
      model *= glm::translate(vec3(-0.5f, -0.5f, -0.5f));
      view = glm::lookAt(vec3(0.0f,0.0f,2.0f), vec3(0.0f,0.0f,0.0f), vec3(0.0f,1.0f,0.0f));
      projection = mat4(1.0f);
      projection = glm::perspective(60.0f, (float)width/(float)height,0.01f, 400.0f);   
      setMatrices(exitPointsProg);
      glEnable(GL_CULL_FACE);
      glCullFace(GL_FRONT);
      drawBoundBox();
      glDisable(GL_CULL_FACE);
      glBindFramebuffer(GL_FRAMEBUFFER, 0);
  }
  </code></pre>
  
  <p>the <code>rayCasting</code> function:</p>
  
  <pre><code>void SimpleRayCasting::rayCasting()
  {
      // Directly render to the screen
      glBindFramebuffer(GL_FRAMEBUFFER, 0);
      glEnable(GL_DEPTH_TEST);
      glViewport(0, 0, width, height);
      glClearColor(1.0f, 1.0f, 1.0f, 1.0);
      glClear(GL_COLOR_BUFFER_BIT |  GL_DEPTH_BUFFER_BIT);
      rayCastProg.use();
      model = mat4(1.0f);
      model *= glm::rotate(angle, vec3(0.0f,1.0f,0.0f));
      model *= glm::rotate(90.0f, vec3(1.0f, 0.0f, 0.0f));
      model *= glm::translate(vec3(-0.5f, -0.5f, -0.5f));
      view = glm::lookAt(vec3(0.0f,0.0f,2.0f), vec3(0.0f,0.0f,0.0f), vec3(0.0f,1.0f,0.0f));
      projection = mat4(1.0f);
      projection = glm::perspective(60.0f, (float)width/(float)height,0.01f, 400.0f);   
      setMatrices(rayCastProg);
      rayCastProg.setUniform("StepSize", stepSize);
      glActiveTexture(GL_TEXTURE1);
      glBindTexture(GL_TEXTURE_2D, exitPoints);
      rayCastProg.setUniform("ExitPoints", 1);
      glActiveTexture(GL_TEXTURE4);
      glBindTexture(GL_TEXTURE_3D, volume_to);
      rayCastProg.setUniform("VolumeTex", 4);
      glActiveTexture(GL_TEXTURE5);
      glBindTexture(GL_TEXTURE_1D, transferFunc_to);
      rayCastProg.setUniform("TransferFunc", 5);
      glEnable(GL_CULL_FACE);
      glCullFace(GL_BACK);
      drawBoundBox();
      glDisable(GL_CULL_FACE);
      glBindFramebuffer(GL_FRAMEBUFFER, 0);
  }
  </code></pre>
  
  <p>I am using a class inherited from QGLWidget in Qt. As I have mentioned early, I got the right result with just the 1st frame and quickly it flash away and turn totally white. I don't know what's wrong with this, is there something wrong with the switch of the shader program or the FBO thing? I have been working on this a long time and can't figure it out, any help will be appreciated!</p></li>
  </ol>
  
  <p><strong>edit to ask</strong>
  is there any demo or tutorial demonstrate how to use multiple glsl shader programs with FBO?</p>