使用 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:如何使用深度排序的顶点数组设计高效的渲染系统?
OpenGL - glDrawElements vs 顶点数组对象