使用 OpenGL 和顶点数组对象渲染两个对象

Posted

技术标签:

【中文标题】使用 OpenGL 和顶点数组对象渲染两个对象【英文标题】:Rendering two objects with OpenGL and vertex array objects 【发布时间】:2015-12-03 17:08:06 【问题描述】:

我正在尝试使用带有着色器的 OpenGL 在我的屏幕上渲染两个三角形;一个大的红色,一个较小的蓝色。每个三角形由一组顶点位置和颜色以及一组顶点索引定义。我为每个三角形使用不同的顶点数组对象。

下面是我的代码,我已将其简化为最小的可编译示例,但仍然给我带来问题。问题是只渲染了第二个三角形(object2,小蓝色三角形)。所以即使我为第一个三角形(object1,大红色三角形)绑定顶点数组对象,然后绘制元素,这个对象也不会被渲染。

我做错了什么?

#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;

【问题讨论】:

【参考方案1】:

glEnableVertexAttribArray 必须为每个 vao 调用:

// 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);
glEnableVertexAttribArray(0);
glEnableVertexAttribArray(1);

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);
glEnableVertexAttribArray(0);
glEnableVertexAttribArray(1);

【讨论】:

以上是关于使用 OpenGL 和顶点数组对象渲染两个对象的主要内容,如果未能解决你的问题,请参考以下文章

OpenGL顶点数组对象不记录VBO和IBO绑定

OpenGL:如何使用深度排序的顶点数组设计高效的渲染系统?

opengl渲染4k数据提高效率

OpenGL - glDrawElements vs 顶点数组对象

Modern OpenGL - 顶点数组、属性与绑定点(OpenGL 4.5+)

渲染镶嵌对象的最佳方式 (OpenGL)