title: opengl - framebuffer texture clipped smaller than I set it?
body: <p>I'm using opengl ES 2.0
  I'm using a framebuffer linked to a texture to compile an offscreen render (of some simplistic metaballs), and then I'm rendering that texture to the main back buffer.</p>
  
  <p>Everything is looking great except that the texture appears clipped, ie. it is not the full window dimensions (short of about 128 pixels on one axis). Here's a screenshot: <a href="http://tinypic.com/r/9telwg/7" rel="nofollow">http://tinypic.com/r/9telwg/7</a></p>
  
  <p>Any ideas what could cause this? I read <a href="http://www.opengl.org/discussion_boards/ubbthreads.php?ubb=showflat&amp;Number=300318" rel="nofollow" title="here">here</a> to set glViewport to the size of the texture, but that gives me a different aspect ratio since the texture metaballsTexture is square (1024x1024) and my window is 768x1024. It also still remains a bit clipped, as it seems I can't get the frame buffer to be big enough, even though the texture is bigger than my window size. Below is my code. I call PrepareToAddMetaballs() during the render when I'm ready, then successive calls to AddMetaball, now rendered onto my offscreeen FBO, then FinishedAddingMetaballs when I'm done, and later call Render() to display the offscreen texture linked to the FBO onto the main backbuffer.</p>
  
  <pre><code>#include "Metaballs.h"
  #include "s3e.h"
  #include "IwGL.h"
  #include "Render.h"
  #include "vsml.h"
  #include &lt;vector&gt;
  #include &lt;string&gt;
  #include &lt;iostream&gt;
  #include "1013Maths.h"
  
  #define GL_RGBA8 0x8058
  
  MetaBalls::MetaBalls() : metaballsTexture(NULL), metaballsShader(NULL) {
      glGenFramebuffers(1, &amp;myFBO);
  
      metaballTexture[0] = NULL;
      metaballTexture[1] = NULL;
      metaballTexture[2] = NULL;
      CRender::Instance()-&gt;CreateTexture("WaterCanvas.png", &amp;metaballsTexture);
      CRender::Instance()-&gt;CreateTexture("metaball.pvr", &amp;metaballTexture[0]);
      CRender::Instance()-&gt;CreateTexture("metaball-1.png", &amp;metaballTexture[1]);
      CRender::Instance()-&gt;CreateTexture("metaball-2.png", &amp;metaballTexture[2]);
      CRender::Instance()-&gt;CreateShader("Shaders/metaballs.fs", "Shaders/metaballs.vs", &amp;metaballsShader);
  
      glBindFramebuffer(GL_FRAMEBUFFER, myFBO);
      // Attach texture to frame buffer
      glBindTexture(GL_TEXTURE_2D, metaballsTexture-&gt;m_id);
      glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, metaballsTexture-&gt;m_id, 0);
      glClearColor(1,1,1,0);
      glClear(GL_COLOR_BUFFER_BIT);
  
      if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {
          std::string error = "Metaballs framebuffer incomplete";
          std::cerr &lt;&lt; error &lt;&lt; std::endl;
          throw error;
      }
  
      float w = PTM_DOWNSCALE(float(metaballsTexture-&gt;GetWidth()));
      float h = PTM_DOWNSCALE(float(metaballsTexture-&gt;GetHeight()));
  
      CRender::Instance()-&gt;BuildQuad(
          tVertex( b2Vec3(0,0,0), b2Vec2(0,1) ),
          tVertex( b2Vec3(w,0,0), b2Vec2(1,1) ),
          tVertex( b2Vec3(w,h,0), b2Vec2(1,0) ),
          tVertex( b2Vec3(0,h,0), b2Vec2(0,0) ),
          buffer);
  
  }
  
  MetaBalls::~MetaBalls() {
      CRender::Instance()-&gt;ReleaseShader(metaballsShader);
      CRender::Instance()-&gt;ReleaseTexture(metaballsTexture);
      CRender::Instance()-&gt;ReleaseTexture(metaballTexture[0]);
      CRender::Instance()-&gt;ReleaseTexture(metaballTexture[1]);
      CRender::Instance()-&gt;ReleaseTexture(metaballTexture[2]);
      glDeleteFramebuffers(1, &amp;myFBO);
  }
  
  void MetaBalls::PrepareToAddMetaballs(b2Vec3&amp; paintColour) {
  
      // bind render to texture
      glBindFramebuffer(GL_FRAMEBUFFER, myFBO);
      // Set our viewport so our texture isn't clipped (appears stretched and clipped)
      // glViewport(0, 0, metaballsTexture-&gt;GetWidth(), metaballsTexture-&gt;GetHeight());
      glClearColor(paintColour.x, paintColour.y, paintColour.z, 0.0f);
      glClear(GL_COLOR_BUFFER_BIT);
  
  }
  
  void MetaBalls::FinishedAddingMetaballs() {
      glBindFramebuffer(GL_FRAMEBUFFER, NULL);
      // CRender::Instance()-&gt;SetWindowViewport();
  }
  
  void MetaBalls::AddMetaball(float x, float y, uint size) {
  
      // render the metaball texture to larger texture
      VSML::setIdentityMatrix(pTransform);
      pTransform[12] = PTM_DOWNSCALE(x);
      pTransform[13] = PTM_DOWNSCALE(y+4); // the +4 is for a bit of overlap with land
      float oldview[16];
      float identity[16];
      VSML::setIdentityMatrix(identity);
      memcpy(oldview, CRender::Instance()-&gt;GetViewMatrix(), sizeof(float)*16);
      memcpy(CRender::Instance()-&gt;GetViewMatrix(),identity, sizeof(float)*16);
      CRender::Instance()-&gt;DrawSprite(metaballTexture[size], pTransform, 1.0f, true);
      memcpy(CRender::Instance()-&gt;GetViewMatrix(),oldview, sizeof(float)*16);
  }
  
  void MetaBalls::Render() {
  
      VSML::setIdentityMatrix(pTransform);
      pTransform[12] = PTM_DOWNSCALE(-128);
      pTransform[13] = PTM_DOWNSCALE(-256);
  
      // render our metaballs texture using alpha test shader
      CRender::Instance()-&gt;BindShader(metaballsShader);
      CRender::Instance()-&gt;BindTexture(0, metaballsTexture);
  
      CRender::Instance()-&gt;SetMatrix(metaballsShader, "view", CRender::Instance()-&gt;GetViewMatrix());
      CRender::Instance()-&gt;SetMatrix(metaballsShader, "world", pTransform);
      CRender::Instance()-&gt;SetMatrix(metaballsShader, "proj", CRender::Instance()-&gt;GetProjMatrix());
  
      CRender::Instance()-&gt;SetBlending(true);
      CRender::Instance()-&gt;DrawPrimitives(buffer);
      CRender::Instance()-&gt;SetBlending(false);
  
  }
  </code></pre>
  
  <p>====================</p>
  
  <h1>EDIT</h1>
  
  <p>Aha! Got it. I haven't found this example anywhere, but I fixed it by adjusting the perspective matrix. It was set to 1024x768 when it was working, but with a window size of 768x1024, the projection matrix was changing, as well as the viewport. By setting each to 1024x768 manually (I chose to use constants), the metaballs are rendered correctly offscreen with proper aspect ratio. Their 1024x1024 texture is rendered as a billboard with that aspect ratio nice and sharp. After I'm done I restore them to what the rest of the application uses. Below is the working code:</p>
  
  <pre><code>#include "Metaballs.h"
  #include "s3e.h"
  #include "IwGL.h"
  #include "Render.h"
  #include "vsml.h"
  #include &lt;vector&gt;
  #include &lt;string&gt;
  #include &lt;iostream&gt;
  #include "1013Maths.h"
  
  MetaBalls::MetaBalls() : metaballsTexture(NULL), metaballsShader(NULL) {
  
      glGenFramebuffers(1, &amp;myFBO);
  
      metaballTexture[0] = NULL;
      metaballTexture[1] = NULL;
      metaballTexture[2] = NULL;
      CRender::Instance()-&gt;CreateTexture("WaterCanvas.png", &amp;metaballsTexture);
      CRender::Instance()-&gt;CreateTexture("metaball.pvr", &amp;metaballTexture[0]);
      CRender::Instance()-&gt;CreateTexture("metaball-1.png", &amp;metaballTexture[1]);
      CRender::Instance()-&gt;CreateTexture("metaball-2.png", &amp;metaballTexture[2]);
      CRender::Instance()-&gt;CreateShader("Shaders/metaballs.fs", "Shaders/metaballs.vs", &amp;metaballsShader);
  
      glBindFramebuffer(GL_FRAMEBUFFER, myFBO);
  
      // Attach texture to frame buffer
      glBindTexture(GL_TEXTURE_2D, metaballsTexture-&gt;m_id);
      glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, metaballsTexture-&gt;m_id, 0);
  
      if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {
          std::string error = "Metaballs framebuffer incomplete";
          std::cerr &lt;&lt; error &lt;&lt; std::endl;
          throw error;
      }
  
      float w = PTM_DOWNSCALE(float(metaballsTexture-&gt;m_width));
      float h = PTM_DOWNSCALE(float(metaballsTexture-&gt;m_height));
  
      CRender::Instance()-&gt;BuildQuad(
          tVertex( b2Vec3(0,0,0), b2Vec2(0,1) ),
          tVertex( b2Vec3(w,0,0), b2Vec2(1,1) ),
          tVertex( b2Vec3(w,h,0), b2Vec2(1,0) ),
          tVertex( b2Vec3(0,h,0), b2Vec2(0,0) ),
          buffer);
  
      // return to default state
      glBindFramebuffer(GL_FRAMEBUFFER, 0);
  }
  
  MetaBalls::~MetaBalls() {
      CRender::Instance()-&gt;ReleaseShader(metaballsShader);
      CRender::Instance()-&gt;ReleaseTexture(metaballsTexture);
      CRender::Instance()-&gt;ReleaseTexture(metaballTexture[0]);
      CRender::Instance()-&gt;ReleaseTexture(metaballTexture[1]);
      CRender::Instance()-&gt;ReleaseTexture(metaballTexture[2]);
      glDeleteFramebuffers(1, &amp;myFBO);
  }
  
  void MetaBalls::PrepareToAddMetaballs(b2Vec3&amp; paintColour) {
  
      // bind render to texture
      glBindFramebuffer(GL_FRAMEBUFFER, myFBO);
  
      // Set orthographic projection
      cfloat w = SCREEN_WIDTH / PTM_RATIO;
      cfloat h = SCREEN_HEIGHT / PTM_RATIO;
      VSML::ortho(-w, 0, -h, 0, 0.0f, -1.0f, CRender::Instance()-&gt;m_Proj);
  
      // Set our viewport so our texture isn't clipped
      glViewport(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT);
      glClearColor(paintColour.x, paintColour.y, paintColour.z, 0.1f);
      glClear(GL_COLOR_BUFFER_BIT);
  
  }
  
  void MetaBalls::FinishedAddingMetaballs() {
      glBindFramebuffer(GL_FRAMEBUFFER, NULL);
      CRender::Instance()-&gt;SetWindowViewport();
  }
  
  void MetaBalls::AddMetaball(float x, float y, uint size) {
  
      // render the metaball texture to larger texture
      VSML::setIdentityMatrix(pTransform);
      pTransform[12] = PTM_DOWNSCALE(x);
      pTransform[13] = PTM_DOWNSCALE(y);
      float oldview[16];
      float identity[16];
      VSML::setIdentityMatrix(identity);
      memcpy(oldview, CRender::Instance()-&gt;GetViewMatrix(), sizeof(float)*16);
      memcpy(CRender::Instance()-&gt;GetViewMatrix(),identity, sizeof(float)*16);
      CRender::Instance()-&gt;DrawSprite(metaballTexture[size], pTransform, 1.0f, true);
      memcpy(CRender::Instance()-&gt;GetViewMatrix(),oldview, sizeof(float)*16);
  }
  
  void MetaBalls::Render() {
  
      VSML::setIdentityMatrix(pTransform);
      pTransform[12] = PTM_DOWNSCALE(0);
      pTransform[13] = PTM_DOWNSCALE(-256);
  
      // render our metaballs texture using alpha test shader
      CRender::Instance()-&gt;BindShader(metaballsShader);
      CRender::Instance()-&gt;BindTexture(0, metaballsTexture);
  
      CRender::Instance()-&gt;SetMatrix(metaballsShader, "view", CRender::Instance()-&gt;GetViewMatrix());
      CRender::Instance()-&gt;SetMatrix(metaballsShader, "world", pTransform);
      CRender::Instance()-&gt;SetMatrix(metaballsShader, "proj", CRender::Instance()-&gt;GetProjMatrix());
  
      CRender::Instance()-&gt;SetBlending(true);
      CRender::Instance()-&gt;DrawPrimitives(buffer);
      CRender::Instance()-&gt;SetBlending(false);
  
  }
  </code></pre>