// Set this renderer to use the specified FBO and
// set the viewport size to be the width and height of this FBO.
bool Renderer::SetupGraphics(FrameBuffer* buffer)
{
    bool succeeded = false;
    do {
        if (mGlProgram == 0)
        {
            if (!InitializeGLProgram())
            {
              break;
            }
        }
        glUseProgram(mGlProgram);
        if (!checkGlError("glUseProgram")) break;

        glBindFramebuffer(GL_FRAMEBUFFER, buffer->GetFrameBufferName());

        mFrameBuffer = buffer;
        mSurfaceWidth = mFrameBuffer->GetWidth();
        mSurfaceHeight = mFrameBuffer->GetHeight();

        glViewport(0, 0, mSurfaceWidth, mSurfaceHeight);
        if (!checkGlError("glViewport")) break;
        succeeded = true;
    } while (false);

    return succeeded;
}
// Set this renderer to use the default frame-buffer (screen) and
// set the viewport size to be the given width and height (pixels).
bool Renderer::SetupGraphics(int width, int height)
{
    bool succeeded = false;
    do {
        if (mGlProgram == 0)
        {
            if (!InitializeGLProgram())
            {
              break;
            }
        }
        glUseProgram(mGlProgram);
        if (!checkGlError("glUseProgram")) break;

        glBindFramebuffer(GL_FRAMEBUFFER, 0);

        mFrameBuffer = NULL;
        mSurfaceWidth = width;
        mSurfaceHeight = height;

        glViewport(0, 0, mSurfaceWidth, mSurfaceHeight);
        if (!checkGlError("glViewport")) break;
        succeeded = true;
    } while (false);

    return succeeded;
}
  bool InitializeGL() {
    static const GLfloat vVertices[] = {
        // front
        -1.0f, -1.0f, +1.0f,  // point blue
        +1.0f, -1.0f, +1.0f,  // point magenta
        -1.0f, +1.0f, +1.0f,  // point cyan
        +1.0f, +1.0f, +1.0f,  // point white
        // back
        +1.0f, -1.0f, -1.0f,  // point red
        -1.0f, -1.0f, -1.0f,  // point black
        +1.0f, +1.0f, -1.0f,  // point yellow
        -1.0f, +1.0f, -1.0f,  // point green
        // right
        +1.0f, -1.0f, +1.0f,  // point magenta
        +1.0f, -1.0f, -1.0f,  // point red
        +1.0f, +1.0f, +1.0f,  // point white
        +1.0f, +1.0f, -1.0f,  // point yellow
        // left
        -1.0f, -1.0f, -1.0f,  // point black
        -1.0f, -1.0f, +1.0f,  // point blue
        -1.0f, +1.0f, -1.0f,  // point green
        -1.0f, +1.0f, +1.0f,  // point cyan
        // top
        -1.0f, +1.0f, +1.0f,  // point cyan
        +1.0f, +1.0f, +1.0f,  // point white
        -1.0f, +1.0f, -1.0f,  // point green
        +1.0f, +1.0f, -1.0f,  // point yellow
        // bottom
        -1.0f, -1.0f, -1.0f,  // point black
        +1.0f, -1.0f, -1.0f,  // point red
        -1.0f, -1.0f, +1.0f,  // point blue
        +1.0f, -1.0f, +1.0f   // point magenta
    };

    static const GLfloat vColors[] = {
        // front
        0.0f, 0.0f, 1.0f,  // blue
        1.0f, 0.0f, 1.0f,  // magenta
        0.0f, 1.0f, 1.0f,  // cyan
        1.0f, 1.0f, 1.0f,  // white
        // back
        1.0f, 0.0f, 0.0f,  // red
        0.0f, 0.0f, 0.0f,  // black
        1.0f, 1.0f, 0.0f,  // yellow
        0.0f, 1.0f, 0.0f,  // green
        // right
        1.0f, 0.0f, 1.0f,  // magenta
        1.0f, 0.0f, 0.0f,  // red
        1.0f, 1.0f, 1.0f,  // white
        1.0f, 1.0f, 0.0f,  // yellow
        // left
        0.0f, 0.0f, 0.0f,  // black
        0.0f, 0.0f, 1.0f,  // blue
        0.0f, 1.0f, 0.0f,  // green
        0.0f, 1.0f, 1.0f,  // cyan
        // top
        0.0f, 1.0f, 1.0f,  // cyan
        1.0f, 1.0f, 1.0f,  // white
        0.0f, 1.0f, 0.0f,  // green
        1.0f, 1.0f, 0.0f,  // yellow
        // bottom
        0.0f, 0.0f, 0.0f,  // black
        1.0f, 0.0f, 0.0f,  // red
        0.0f, 0.0f, 1.0f,  // blue
        1.0f, 0.0f, 1.0f   // magenta
    };

    static const GLfloat vNormals[] = {
        // front
        +0.0f, +0.0f, +1.0f,  // forward
        +0.0f, +0.0f, +1.0f,  // forward
        +0.0f, +0.0f, +1.0f,  // forward
        +0.0f, +0.0f, +1.0f,  // forward
        // back
        +0.0f, +0.0f, -1.0f,  // backbard
        +0.0f, +0.0f, -1.0f,  // backbard
        +0.0f, +0.0f, -1.0f,  // backbard
        +0.0f, +0.0f, -1.0f,  // backbard
        // right
        +1.0f, +0.0f, +0.0f,  // right
        +1.0f, +0.0f, +0.0f,  // right
        +1.0f, +0.0f, +0.0f,  // right
        +1.0f, +0.0f, +0.0f,  // right
        // left
        -1.0f, +0.0f, +0.0f,  // left
        -1.0f, +0.0f, +0.0f,  // left
        -1.0f, +0.0f, +0.0f,  // left
        -1.0f, +0.0f, +0.0f,  // left
        // top
        +0.0f, +1.0f, +0.0f,  // up
        +0.0f, +1.0f, +0.0f,  // up
        +0.0f, +1.0f, +0.0f,  // up
        +0.0f, +1.0f, +0.0f,  // up
        // bottom
        +0.0f, -1.0f, +0.0f,  // down
        +0.0f, -1.0f, +0.0f,  // down
        +0.0f, -1.0f, +0.0f,  // down
        +0.0f, -1.0f, +0.0f   // down
    };

    if (!InitializeGLProgram())
      return false;

    modelviewmatrix_ = glGetUniformLocation(program_, "modelviewMatrix");
    modelviewprojectionmatrix_ =
        glGetUniformLocation(program_, "modelviewprojectionMatrix");
    normalmatrix_ = glGetUniformLocation(program_, "normalMatrix");

    glViewport(0, 0, display_size_.width, display_size_.height);
    glEnable(GL_CULL_FACE);

    GLintptr positionsoffset = 0;
    GLintptr colorsoffset = sizeof(vVertices);
    GLintptr normalsoffset = sizeof(vVertices) + sizeof(vColors);
    glGenBuffers(1, &vbo_);
    glBindBuffer(GL_ARRAY_BUFFER, vbo_);
    glBufferData(GL_ARRAY_BUFFER,
                 sizeof(vVertices) + sizeof(vColors) + sizeof(vNormals), 0,
                 GL_STATIC_DRAW);
    glBufferSubData(GL_ARRAY_BUFFER, positionsoffset, sizeof(vVertices),
                    &vVertices[0]);
    glBufferSubData(GL_ARRAY_BUFFER, colorsoffset, sizeof(vColors),
                    &vColors[0]);
    glBufferSubData(GL_ARRAY_BUFFER, normalsoffset, sizeof(vNormals),
                    &vNormals[0]);
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0,
                          reinterpret_cast<const void*>(positionsoffset));
    glEnableVertexAttribArray(0);
    glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0,
                          reinterpret_cast<const void*>(normalsoffset));
    glEnableVertexAttribArray(1);
    glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, 0,
                          reinterpret_cast<const void*>(colorsoffset));
    glEnableVertexAttribArray(2);

    glClearColor(0.0, 0.0, 0.0, 1.0);
    glClear(GL_COLOR_BUFFER_BIT);
    return true;
  }