Use glTranslatef and shaders? In newer OpenGL it's encouraged to use shaders and pass the model-view-projection as parameters. But what if I drew a complex object, and wanted to translate/rotate it and draw many copies? 

For example I wanted to do something like this :

glBindFramebuffer(GL_FRAMEBUFFER, fbo[0]);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
{
    shader.bind();

    glm::mat4 projectionMatrix = glm::perspective(20.0f, (float)SCRWIDTH/(float)SCRHEIGHT, 0.0f, 100.0f);
    glm::mat4 viewMatrix = glm::lookAt(
        glm::vec3(0, 0, 2), 
        glm::vec3(0, 0, 0), 
        glm::vec3(0, 1, 0)
    );
    glm::mat4 modelMatrix = glm::toMat4(quaternion);
    glm::mat4 MVP = projectionMatrix * viewMatrix * modelMatrix;
    GLint loc_MVP = glGetUniformLocation(shader.id(), "MVP");    
    glUniformMatrix4fv(loc_MVP, 1, GL_FALSE, &amp;MVP[0][0]);

    glTranslatef(1,0,0);
    gluSphere(...);
    glTranslatef(2,0,0);
    gluSphere(...);

    shader.unbind();
}
glBindFramebuffer(GL_FRAMEBUFFER, 0);


But my experiment shows that the glTranslatef doesn't work here, all the spheres are rendered at (0,0,0). I don't want to call the shader 100 times, each time calculating a different MVP matrix. Is there any easy way around this?

The vertex shader looks like this :

#version 330 core

uniform mat4 MVP;
in vec3 in_Position;

void main(void) {
    gl_Position = MVP * vec4(in_Position, 1.0);
}
Update the uniform and draw again.

auto tMVP = glm::translate(MVP, glm::vec3(1,0,0));
glUniformMatrix4fv(loc_MVP, 1, GL_FALSE, &amp;tMVP[0][0]);
gluSphere(...);

tMVP = glm::translate(MVP, glm::vec3(2,0,0));
glUniformMatrix4fv(loc_MVP, 1, GL_FALSE, &amp;MVP[0][0]);
gluSphere(...);


Using glTranslate would have done the exact same thing behind the scenes.



You can instead use instancing instead where you upload all the transforms into a buffer and then tell the gpu to use that. 

However the more portable way involves allocating a vertex attribute for the data. This involves using glVertexAttribDivisor.

So a full mat4 would need 4 vertex attributes. You can decrease that to 2 by separating out the translation as a vec3 and the rotation as a quaternion and pass the view-perspective as a uniform and combining it all in the vertex shader.