void multidrawindirect_app::render(double currentTime)
{
    int j;
    static const float one = 1.0f;
    static const float black[] = { 0.0f, 0.0f, 0.0f, 0.0f };

        
    static double last_time = 0.0;
    static double total_time = 0.0;

    if (!paused)
        total_time += (currentTime - last_time);
    last_time = currentTime;

    float t = float(total_time);
    int i = int(total_time * 3.0f);

    glViewport(0, 0, info.windowWidth, info.windowHeight);
    glClearBufferfv(GL_COLOR, 0, black);
    glClearBufferfv(GL_DEPTH, 0, &one);

    const vmath::mat4 view_matrix = vmath::lookat(vmath::vec3(100.0f * cosf(t * 0.023f), 100.0f * cosf(t * 0.023f), 300.0f * sinf(t * 0.037f) - 600.0f),
                                                  vmath::vec3(0.0f, 0.0f, 260.0f),
                                                  vmath::normalize(vmath::vec3(0.1f - cosf(t * 0.1f) * 0.3f, 1.0f, 0.0f)));
    const vmath::mat4 proj_matrix = vmath::perspective(50.0f,
                                                       (float)info.windowWidth / (float)info.windowHeight,
                                                       1.0f,
                                                       2000.0f);

    glUseProgram(render_program);

    glUniform1f(uniforms.time, t);
    glUniformMatrix4fv(uniforms.view_matrix, 1, GL_FALSE, view_matrix);
    glUniformMatrix4fv(uniforms.proj_matrix, 1, GL_FALSE, proj_matrix);
    glUniformMatrix4fv(uniforms.viewproj_matrix, 1, GL_FALSE, proj_matrix * view_matrix);

    glBindVertexArray(object.get_vao());

    if (mode == MODE_MULTIDRAW)
    {
        glMultiDrawArraysIndirect(GL_TRIANGLES, NULL, NUM_DRAWS, 0);
    }
    else if (mode == MODE_SEPARATE_DRAWS)
    {
        for (j = 0; j < NUM_DRAWS; j++)
        {
            GLuint first, count;
            object.get_sub_object_info(j % object.get_sub_object_count(), first, count);
            glDrawArraysInstancedBaseInstance(GL_TRIANGLES,
                                              first,
                                              count,
                                              1, j);
        }
    }
}
void multidrawindirect_app::startup()
{
    int i;

    load_shaders();

    object.load("media/objects/asteroids.sbm");

    glGenBuffers(1, &indirect_draw_buffer);
    glBindBuffer(GL_DRAW_INDIRECT_BUFFER, indirect_draw_buffer);
    glBufferData(GL_DRAW_INDIRECT_BUFFER,
                 NUM_DRAWS * sizeof(DrawArraysIndirectCommand),
                 NULL,
                 GL_STATIC_DRAW);

    DrawArraysIndirectCommand * cmd = (DrawArraysIndirectCommand *)
        glMapBufferRange(GL_DRAW_INDIRECT_BUFFER,
                         0,
                         NUM_DRAWS * sizeof(DrawArraysIndirectCommand),
                         GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT);

    for (i = 0; i < NUM_DRAWS; i++)
    {
        object.get_sub_object_info(i % object.get_sub_object_count(),
                                   cmd[i].first,
                                   cmd[i].count);
        cmd[i].primCount = 1;
        cmd[i].baseInstance = i;
    }

    glUnmapBuffer(GL_DRAW_INDIRECT_BUFFER);

    glBindVertexArray(object.get_vao());

    glGenBuffers(1, &draw_index_buffer);
    glBindBuffer(GL_ARRAY_BUFFER, draw_index_buffer);
    glBufferData(GL_ARRAY_BUFFER,
                 NUM_DRAWS * sizeof(GLuint),
                 NULL,
                 GL_STATIC_DRAW);

    GLuint * draw_index =
        (GLuint *)glMapBufferRange(GL_ARRAY_BUFFER,
                                   0,
                                   NUM_DRAWS * sizeof(GLuint),
                                   GL_MAP_WRITE_BIT |
                                   GL_MAP_INVALIDATE_BUFFER_BIT);

    for (i = 0; i < NUM_DRAWS; i++)
    {
        draw_index[i] = i;
    }

    glUnmapBuffer(GL_ARRAY_BUFFER);

    glVertexAttribIPointer(10, 1, GL_UNSIGNED_INT, 0, NULL);
    glVertexAttribDivisor(10, 1);
    glEnableVertexAttribArray(10);

    glEnable(GL_DEPTH_TEST);
    glDepthFunc(GL_LEQUAL);

    glEnable(GL_CULL_FACE);
}