I am trying to use OpenGL with shaders to render two triangles on my screen; a big red one, and a smaller blue one. Each triangle is defined by a set of vertex positions and colours, together with a set of vertex indices. I am using a different vertex array object for each triangle.
Below is my code, which I have reduced to the smallest compilable example which is still giving me problems. The problem is that only the second triangle (object2, the small blue triangle) is rendered. So even though I am binding the vertex array object for the first triangle (object1, the big red triangle), and then drawing the elements, this object is not rendered.
What am I doing wrong?
#include <GL/glew.h>
#include <GL/glut.h>
#include <Eigen/Eigen>
#include <fstream>
GLuint object1_vertex_buffer, object1_colour_buffer, object1_index_buffer, object1_vertex_array;
GLuint object2_vertex_buffer, object2_colour_buffer, object2_index_buffer, object2_vertex_array;
GLuint shader_program, vertex_shader, fragment_shader;
void RenderScene()
{
glClear(GL_COLOR_BUFFER_BIT);
glClear(GL_DEPTH_BUFFER_BIT);
glBindVertexArray(object1_vertex_array);
glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_INT, (void*)0);
glBindVertexArray(object2_vertex_array);
glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_INT, (void*)0);
glutSwapBuffers();
}
int main(int argc, char** argv)
{
// Make the objects
Eigen::Vector3f object1_vertices[3];
object1_vertices[0] << 0, 0, 0;
object1_vertices[1] << 0.8, 0, 0;
object1_vertices[2] << 0.8, 0.8, 0;
Eigen::Vector3f object1_colours[3];
object1_colours[0] << 1.0, 0.0, 0.0;
object1_colours[1] << 1.0, 0.0, 0.0;
object1_colours[2] << 1.0, 0.0, 0.0;
int object1_indices[3];
object1_indices[0] = 0;
object1_indices[1] = 1;
object1_indices[2] = 2;
Eigen::Vector3f object2_vertices[3];
object2_vertices[0] << 0, 0, 0;
object2_vertices[1] << 0.5, 0, 0;
object2_vertices[2] << 0.5, 0.5, 0;
Eigen::Vector3f object2_colours[3];
object2_colours[0] << 0.0, 0.0, 1.0;
object2_colours[1] << 0.0, 0.0, 1.0;
object2_colours[2] << 0.0, 0.0, 1.0;
int object2_indices[3];
object2_indices[0] = 0;
object2_indices[1] = 1;
object2_indices[2] = 2;
// Set up OpenGL
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA);
glutInitWindowSize(1000, 1000);
glutCreateWindow("Test");
glutDisplayFunc(RenderScene);
glewInit();
glClearColor(1.0f, 1.0f, 1.0f, 0.0f);
glEnable(GL_DEPTH_TEST);
// Make the buffers
glGenBuffers(1, &object1_vertex_buffer);
glGenBuffers(1, &object1_colour_buffer);
glGenBuffers(1, &object1_index_buffer);
glGenVertexArrays(1, &object1_vertex_array);
glGenBuffers(1, &object2_vertex_buffer);
glGenBuffers(1, &object2_colour_buffer);
glGenBuffers(1, &object2_index_buffer);
glGenVertexArrays(1, &object2_vertex_array);
// Fill the buffer data
glBindVertexArray(object1_vertex_array);
glBindBuffer(GL_ARRAY_BUFFER, object1_vertex_buffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(object1_vertices), &object1_vertices[0], GL_STATIC_DRAW);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
glBindBuffer(GL_ARRAY_BUFFER, object1_colour_buffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(object1_colours), &object1_colours[0], GL_STATIC_DRAW);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, object1_index_buffer);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, 3 * sizeof(int), &object1_indices[0], GL_STATIC_DRAW);
glBindVertexArray(object2_vertex_array);
glBindBuffer(GL_ARRAY_BUFFER, object2_vertex_buffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(object2_vertices), &object2_vertices[0], GL_STATIC_DRAW);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
glBindBuffer(GL_ARRAY_BUFFER, object2_colour_buffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(object2_colours), &object2_colours[0], GL_STATIC_DRAW);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, object2_index_buffer);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, 3 * sizeof(int), &object2_indices[0], GL_STATIC_DRAW);
// Make the shader program
shader_program = glCreateProgram();
vertex_shader = glCreateShader(GL_VERTEX_SHADER);
std::ifstream vertex_file_in;
vertex_file_in.open("../src/vertex-shader.glsl");
std::stringstream vertex_file_stream;
vertex_file_stream << vertex_file_in.rdbuf();
std::string vertex_shader_string = vertex_file_stream.str();
std::cout << vertex_shader_string << std::endl;
const GLchar* ptr_vertex_shader_string = &vertex_shader_string[0];
const GLchar** vertex_shader_strings = &ptr_vertex_shader_string;
int vertex_shader_lengths[] = {(int)vertex_shader_string.length()};
glShaderSource(vertex_shader, 1, vertex_shader_strings, vertex_shader_lengths);
glCompileShader(vertex_shader);
glAttachShader(shader_program, vertex_shader);
fragment_shader = glCreateShader(GL_FRAGMENT_SHADER);
std::ifstream fragment_file_in;
fragment_file_in.open("../src/fragment-shader.glsl");
std::stringstream fragment_file_stream;
fragment_file_stream << fragment_file_in.rdbuf();
std::string fragment_shader_string = fragment_file_stream.str();
const GLchar* ptr_fragment_shader_string = &fragment_shader_string[0];
const GLchar** fragment_shader_strings = &ptr_fragment_shader_string;
int fragment_shader_lengths[] = {(int)fragment_shader_string.length()};
glShaderSource(fragment_shader, 1, fragment_shader_strings, fragment_shader_lengths);
glCompileShader(fragment_shader);
glAttachShader(shader_program, fragment_shader);
glBindAttribLocation(shader_program, 0, "position");
glBindAttribLocation(shader_program, 1, "colour");
glLinkProgram(shader_program);
glUseProgram(shader_program);
glEnableVertexAttribArray(0);
glEnableVertexAttribArray(1);
// Run the main loop
glutMainLoop();
}
........
........
........
// Vertex shader
#version 330
layout (location = 0) in vec3 position;
layout (location = 1) in vec3 colour;
out vec4 frag_colour;
void main()
{
gl_Position = vec4(position, 1.0);
frag_colour = vec4(colour, 1.0);
}
........
........
........
// Fragment shader
#version 330
in vec4 frag_colour;
void main()
{
gl_FragColor = frag_colour;
}