I am trying to display a sphere and a torus on the same screen, but it seems like the "glutInitDisplayMode" is what is causing me to display only one.
When I keep it as glutInitDisplayMode(GLUT_SINGLE | GLUT_RGBA |GLUT_DEPTH)
the torus displays.
When I keep it as glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH)
the sphere displays. What can I do to display both?
The render code is below:
static void render(void) {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glMatrixMode(GL_MODELVIEW);
// clear the drawing buffer.
glClear(GL_COLOR_BUFFER_BIT);
// clear the identity matrix.
glLoadIdentity();
glTranslatef(0.0, 0.0, -5.0);
glColor3f(0.0, 0.0, 0.0);
glRotatef(zRotated, 0.0, 0.0, 1.0);
// scaling transfomation
glScalef(1.0, 1.0, 1.0);
// built-in (glut library) function , draw you a sphere.
glutSolidTorus(innerRadius, outerRadius, sides, rings);
// Flush buffers to screen
glFlush();
// glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// activate our shader program
glUseProgram(programId);
// turn on depth buffering
glEnable(GL_DEPTH_TEST);
float aspectRatio = (float)width / (float)height;
glm::mat4 projection = glm::perspective(glm::radians(45.0f), aspectRatio, 0.1f, 1000.0f);
// view matrix - orient everything around our preferred view
glm::mat4 view = glm::lookAt(
glm::vec3(40,30,30), // eye/camera location
glm::vec3(0,0,0), // where to look
glm::vec3(0,1,0) // up
);
// model matrix: translate, scale, and rotate the model
glm::vec3 rotationAxis(0,1,0);
glm::mat4 model = glm::mat4(1.0f);
model = glm::rotate(model, glm::radians(angle), glm::vec3(0, 1, 0)); // rotate about the y-axis
model = glm::scale(model, glm::vec3(25.0f, 25.0f, 25.0f));
// model-view-projection matrix
glm::mat4 mvp = projection * view * model;
GLuint mvpMatrixId = glGetUniformLocation(programId, "MVP");
glUniformMatrix4fv(mvpMatrixId, 1, GL_FALSE, &mvp[0][0]);
// texture sampler - a reference to the texture we've previously created
// send the texture id to the texture sampler
GLuint textureUniformId = glGetUniformLocation(programId, "textureSampler");
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, textureId);
glUniform1i(textureUniformId, 0);
// find the names (ids) of each vertex attribute
GLint positionAttribId = glGetAttribLocation(programId, "position");
GLint colourAttribId = glGetAttribLocation(programId, "colour");
GLint textureCoordsAttribId = glGetAttribLocation(programId, "textureCoords");
GLint normalAttribId = glGetAttribLocation(programId, "normal");
// provide the vertex positions to the shaders
glBindBuffer(GL_ARRAY_BUFFER, positions_vbo);
glEnableVertexAttribArray(positionAttribId);
glVertexAttribPointer(positionAttribId, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
// provide the vertex texture coordinates to the shaders
glBindBuffer(GL_ARRAY_BUFFER, textureCoords_vbo);
glEnableVertexAttribArray(textureCoordsAttribId);
glVertexAttribPointer(textureCoordsAttribId, 2, GL_FLOAT, GL_FALSE, 0, nullptr);
// provide the vertex normals to the shaders
glBindBuffer(GL_ARRAY_BUFFER, normals_vbo);
glEnableVertexAttribArray(normalAttribId);
glVertexAttribPointer(normalAttribId, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
// draw the triangles
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer);
glDrawElements(GL_TRIANGLES, numVertices, GL_UNSIGNED_INT, (void*)0);
// disable the attribute arrays
glDisableVertexAttribArray(positionAttribId);
glDisableVertexAttribArray(textureCoordsAttribId);
glDisableVertexAttribArray(normalAttribId);
glDisableVertexAttribArray(colourAttribId);
// make the draw buffer to display buffer (i.e. display what we have drawn)
glutSwapBuffers();
}
glutSolidTorus
draws a torus, by the use of the fixed function attributes. For this a compatibility profile OpenGL Context indispensable.
glutSolidTorus
is not compatible with you shader program. Invalidate the currently installed program, before glutSolidTorus
:
glUseProgram(0);
glutSolidTorus(innerRadius, outerRadius, sides, rings);
Note, OpenGL is a state engine. If a program is installed, it is kept, until another program is installed or it is invalidated, even beyond frames. In you case is is not an issue in the first frame, but it would be still installed at the begin of the 2nd frame, when glutSolidTorus
is called.
If you are use a double buffered window (GLUT_DOUBLE
) you have to call glutSwapBuffers
. glutSwapBuffers
swaps the buffers. The buffer in which was drawn, is shown in the window. The buffer which was show int eh window is prepared for drawing in the next frame.
In a single buffered window you can do glFlush
. This forces OpenGL to finish drawing. Since the buffer which is draw to is the same, which is shown on the window, this causes that all what is drawing to the buffer is immediately shown in the window.
Move the singe glFlush
call form the middle of the render
function to its end, right before glutSwapBuffers
:
void render()
{
// ...
glUseProgram(0);
glutSolidTorus(innerRadius, outerRadius, sides, rings);
// glFlush(); <---- delete
// ...
glUseProgram(programId);
// ...
glDrawElements(GL_TRIANGLES, numVertices, GL_UNSIGNED_INT, (void*)0);
// ...
glFlush();
glutSwapBuffers();
}