title: Draw to renderbuffer with FBO
body: <p>My question is pretty close to this one: <a href="https://stackoverflow.com/questions/4213023/fbo-and-render-to-renderbuffer">FBO and Render to renderbuffer</a>.
  I am currently trying to render a simple triangle on a renderbuffer like in this <a href="http://developer.apple.com/library/mac/#documentation/GraphicsImaging/Conceptual/OpenGL-MacProgGuide/opengl_offscreen/opengl_offscreen.html" rel="nofollow noreferrer">tutorial</a>. My program is a plugin to Igor Pro that performs off screen rendering with OpenGL. </p>
  
  <p>Unfortunately I am getting only zero when I am trying to read the pixel values.
  I already know that the <code>initBuffers</code> function works and that the problem lies in the <code>display</code> function.</p>
  
  <p>1) What is the problem with my code?</p>
  
  <p>2) I'd like to render a list of vertex data without using the immediate mode. I have previously done an implementation with VBOs. Can I reuse that code?</p>
  
  <p>My code is the following:</p>
  
  <pre><code>/*  
  RenderTriangle.cpp
  */
  
  #include "VC10\triangulation.h"
  #include "XOPStandardHeaders.h"         // Include ANSI headers, Mac headers, IgorXOP.h, XOP.h and XOPSupport.h
  #include &lt;vector&gt;
  
  
  // Prototypes
  HOST_IMPORT int main(IORecHandle ioRecHandle);
  
  // Global Variables
  const int windowSize = 512;
  
  int size,el_size;
  float* waveX=NULL;
  float* waveY=NULL;
  float* waveZ=NULL;
  GLuint framebuffer, renderbuffer;
  
  // Custom error codes
  #define OLD_IGOR 1 + FIRST_XOP_ERR
  #define NON_EXISTENT_WAVE 2 + FIRST_XOP_ERR
  #define REQUIRES_SP_OR_DP_WAVE 3 + FIRST_XOP_ERR
  
  #pragma pack(2)     // All structures passed to Igor are two-byte aligned.
  typedef struct WaveParams {
    waveHndl waveZ;
    waveHndl waveY;
    waveHndl waveX;   
    double result;
  } WaveParams, *WaveParamsPtr;
  #pragma pack()      // Restore default structure alignment
  
  // Prototypes of the OpenGL callbacks
  void initBuffers(void);
  void display(void);
  void readPixels(void);
  
  void initBuffers(void){
  
    GLenum status;
  
    //Generate the fbo where we will bind a render buffer object
    glGenFramebuffers(1,&amp;framebuffer);
    glBindFramebuffer(GL_DRAW_FRAMEBUFFER,framebuffer);
  
    //Generate render buffer object
    glGenRenderbuffers(1,&amp;renderbuffer);
    glBindRenderbuffer(GL_RENDERBUFFER,renderbuffer);
  
    glRenderbufferStorage(GL_RENDERBUFFER,GL_RGBA8, windowSize, windowSize);
  
    glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, renderbuffer);
  
    status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
  
    if (status != GL_FRAMEBUFFER_COMPLETE)
      XOPNotice("Error Framebuffer Complete");
    else
      XOPNotice("Framebuffer Complete");
  }
  
  void display(void){//display a simple triangle
  
    glViewport(0,0,windowSize,windowSize);
    glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
    glClearColor(1.0f, 0.0f, 0.0f,0.5f);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glLoadIdentity();
  
    glBegin(GL_TRIANGLES);// Drawing Using Triangles
      glColor3f(1.0f, 0.0f, 0.0f);glVertex3f( 0.0f, 1.0f, 0.0f);// Top
      glColor3f(1.0f, 0.0f, 0.0f);glVertex3f(-1.0f,-1.0f, 0.0f);// Bottom Left
      glColor3f(1.0f, 0.0f, 0.0f);glVertex3f( 1.0f,-1.0f, 0.0f);// Bottom Right
    glEnd();// Finished Drawing The Triangle
  
    glFlush();
  
  }
  
  // Idle callback function for OpenGL API
  void readPixels(void){
  
    //glBindFramebuffer(GL_FRAMEBUFFER, 0);
  
    float* pixels = (float*)malloc(windowSize*windowSize*sizeof(float));
    glReadBuffer(GL_COLOR_ATTACHMENT0);
    glReadPixels(0, 0, windowSize, windowSize, GL_DEPTH_COMPONENT, GL_FLOAT, pixels);
  
    waveHndl waveH;
    char waveName[MAX_OBJ_NAME+1];
    DataFolderHandle dfH;
    CountInt dimensionSizes[MAX_DIMENSIONS+1];
    float* wp;
    IndexInt p;
    double offset, delta;
    int err;
    strcpy(waveName, "wave1");
    dfH = NULL; // Put wave in the current data folder
    MemClear(dimensionSizes, sizeof(dimensionSizes));
  
    dimensionSizes[ROWS] = windowSize; // Make 1D wave with 100 points
    dimensionSizes[COLUMNS] = windowSize;
  
    if (MDMakeWave(&amp;waveH, waveName, dfH, dimensionSizes, NT_FP32, 1))
      XOPNotice("Can't create wave when reading pixel values");
  
    wp = (float*)WaveData(waveH); // Get a pointer to the wave data
  
    for(p = 0; p &lt; windowSize*windowSize; p++)
    *wp++ = pixels[p]; // Store point number in wave
  
  
  
  }
  void deleteBuffers(){
    glDeleteFramebuffers(1,&amp;framebuffer);
    glDeleteRenderbuffers(1,&amp;renderbuffer);
  }
  // Main function for the XOP
  extern "C" int
    RenderTriangle(WaveParamsPtr p)
  {
    //Pointers to the input waves
    waveX=(float*)WaveData(p-&gt;waveX);
    waveY=(float*)WaveData(p-&gt;waveY);
    waveZ=(float*)WaveData(p-&gt;waveZ);
  
    //Creates the window
    char *myargv [1];
    int myargc=1, windowHandle;
    myargv [0]=strdup ("RenderTriangle");
  
    glutInit(&amp;myargc,myargv);
    glutInitDisplayMode(GLUT_SINGLE | GLUT_DEPTH | GLUT_RGB);
    glutInitWindowSize(windowSize,windowSize);
    windowHandle = glutCreateWindow("OpenGL");
  
    //Init glew library 
    glewInit(); 
  
    //Creates the fbo and render buffer object
    initBuffers(); 
  
    display();
  
    readPixels();
  
    //Deletes the fbo and render buffer object
    deleteBuffers();
  
    p-&gt;result = 1;
  
    return 0;
  }
  
  static XOPIORecResult
    RegisterFunction()
  {
    int funcIndex;
  
    funcIndex = (int)GetXOPItem(0);           // Which function invoked ?
    switch (funcIndex) {
    case 0:                                   // y = RenderTriangle(w,x) (curve fitting function).
      return (XOPIORecResult)RenderTriangle;  // This function is called using the direct method.
      break;
    }
    return 0;
  }
  
  /*  XOPEntry()
  
  This is the entry point from the host application to the XOP for all
  messages after the INIT message.
  */
  extern "C" void
    XOPEntry(void)
  {   
    XOPIORecResult result = 0;
  
    switch (GetXOPMessage()) {
    case FUNCADDRS:
      result = RegisterFunction();    // This tells Igor the address of our function.
      break;
    }
    SetXOPResult(result);
  }
  
  /*  main(ioRecHandle)
  
  This is the initial entry point at which the host application calls XOP.
  The message sent by the host must be INIT.
  main() does any necessary initialization and then sets the XOPEntry field of the
  ioRecHandle to the address to be called for future messages.
  */
  HOST_IMPORT int
    main(IORecHandle ioRecHandle)
  {   
    XOPInit(ioRecHandle);                         // Do standard XOP initialization.
    SetXOPEntry(XOPEntry);                            // Set entry point for future calls.
  
    if (igorVersion &lt; 600) {
      SetXOPResult(OLD_IGOR);
      return EXIT_FAILURE;
    }
  
    SetXOPResult(0);
    return EXIT_SUCCESS;
  }
  </code></pre>