无法使用VAO和EBO(openGL)绘制多个对象



我正在尝试使用顶点数组对象和元素缓冲区对象。我设法使用带有 EBO 绑定的单个 VAO 在屏幕上绘制字母"H",因为我的所有顶点和索引都在一个数组中。我想将每个矩形拆分为不同的对象并赋予它们不同的颜色,但只有一个矩形在屏幕上绘制。

代码如下:

#include <glew.h>
#include <glfw3.h>
#include <iostream>
const char* vertexShaderSource = "#version 330 coren"
"layout (location = 0) in vec3 aPos;n"
"void main()n"
"{n"
"gl_Position = vec4(aPos.x, aPos.y, aPos.z, 1.0);n"
"}";
const char* fragmentShaderSource = "#version 330 coren"
"out vec4 FragColor;n"
"void main()n"
"{n"
"FragColor = vec4(0.2f, 0.6f, 0.7f, 1.0f);n"
"}";
const char* fragmentShaderSource2 = "#version 330 coren"
"out vec4 FragColor;n"
"void main()n"
"{n"
"FragColor = vec4(0.7f, 0.4f, 0.3f, 1.0f);n"
"}";
const char* fragmentShaderSource3 = "#version 330 coren"
"out vec4 FragColor;n"
"void main()n"
"{n"
"FragColor = vec4(0.1f, 0.2f, 0.6f, 1.0f);n"
"}";
int main(void)
{
GLFWwindow* window;
glewInit();
glfwInit();
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
/* Initialize the library */
if (!glfwInit())
return -1;
/* Create a windowed mode window and its OpenGL context */
window = glfwCreateWindow(640, 480, "Hello World", NULL, NULL);
if (!window)
{
glfwTerminate();
return -1;
}
/* Make the window's context current */
glfwMakeContextCurrent(window);
if (glewInit() != GLEW_OK)
std::cout << "Error!" << std::endl;
float vertices[] = {
0.2f, 0.7f, 0.0f,
0.3f, 0.7f, 0.0f,
0.3f, 0.2f, 0.0f,
0.2f, 0.2f, 0.0f
};
float vertices2[] = {
0.6f, 0.7f, 0.0f,
0.7f, 0.7f, 0.0f,
0.7f, 0.2f, 0.0f,
0.6f, 0.2f, 0.0f
};
float vertices3[] = {
0.3f, 0.4f, 0.0f,
0.3f, 0.5f, 0.0f,
0.6f, 0.5f, 0.0f,
0.6f, 0.4f, 0.0f
};
unsigned int indices[] = {    
1, 0, 2,
2, 3, 0
};  
unsigned int indices2[] = {
5, 4, 6,
6, 7, 4
};
unsigned int indices3[] = {
8, 9, 11,
11, 10, 9
};
unsigned int vertexShader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertexShader, 1, &vertexShaderSource, NULL);
glCompileShader(vertexShader);
int  success;
char infoLog[512];
glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &success);
if (!success)
{
glGetShaderInfoLog(vertexShader, 512, NULL, infoLog);
std::cout << "ERROR::SHADER::VERTEX::COMPILATION_FAILEDn" << infoLog << std::endl;
}
unsigned int fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragmentShader, 1, &fragmentShaderSource, NULL);
glCompileShader(fragmentShader);
glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &success);
if (!success)
{
glGetShaderInfoLog(fragmentShader, 512, NULL, infoLog);
std::cout << "ERROR::SHADER::VERTEX::COMPILATION_FAILEDn" << infoLog << std::endl;
}
unsigned int fragmentShader2 = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragmentShader2, 1, &fragmentShaderSource2, NULL);
glCompileShader(fragmentShader2);
unsigned int fragmentShader3 = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragmentShader3, 1, &fragmentShaderSource3, NULL);
glCompileShader(fragmentShader3);
unsigned int shaderProgram;
shaderProgram = glCreateProgram();
unsigned int shaderProgram2;
shaderProgram2 = glCreateProgram();
unsigned int shaderProgram3;
shaderProgram3 = glCreateProgram();
glAttachShader(shaderProgram, vertexShader);
glAttachShader(shaderProgram, fragmentShader);
glLinkProgram(shaderProgram);
glAttachShader(shaderProgram2, fragmentShader2);
glAttachShader(shaderProgram2, vertexShader);
glLinkProgram(shaderProgram2);
glAttachShader(shaderProgram3, fragmentShader3);
glAttachShader(shaderProgram3, vertexShader);
glLinkProgram(shaderProgram3);
glGetProgramiv(shaderProgram, GL_LINK_STATUS, &success);
if (!success)
{
glGetShaderInfoLog(shaderProgram, 512, NULL, infoLog);
std::cout << "ERROR::SHADER::VERTEX::COMPILATION_FAILEDn" << infoLog << std::endl;
}
glDeleteShader(vertexShader);
glDeleteShader(fragmentShader);
glDeleteShader(fragmentShader2);
glDeleteShader(fragmentShader3);
unsigned int VBOs[3], VAOs[3], EBOs[3];
glGenVertexArrays(3, VAOs);
glGenBuffers(3, VBOs);
glGenBuffers(3, EBOs);
glBindVertexArray(VAOs[0]);
glBindBuffer(GL_ARRAY_BUFFER, VBOs[0]);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBOs[0]);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);
glEnableVertexAttribArray(0);
glBindVertexArray(VAOs[1]);
glBindBuffer(GL_ARRAY_BUFFER, VBOs[1]);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices2), vertices2, GL_STATIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBOs[1]);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices2), indices2, GL_STATIC_DRAW);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);
glEnableVertexAttribArray(0);
glBindVertexArray(VAOs[2]);
glBindBuffer(GL_ARRAY_BUFFER, VBOs[2]);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices3), vertices3, GL_STATIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBOs[2]);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices3), indices3, GL_STATIC_DRAW);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
/* Loop until the user closes the window */
while (!glfwWindowShouldClose(window))
{
/* Render here */
glClear(GL_COLOR_BUFFER_BIT);
glUseProgram(shaderProgram);
glBindVertexArray(VAOs[0]);
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
glUseProgram(shaderProgram2);
glBindVertexArray(VAOs[1]);
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
glUseProgram(shaderProgram3);
glBindVertexArray(VAOs[2]);
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
/* Swap front and back buffers */
glfwSwapBuffers(window);
/* Poll for and process events */
glfwPollEvents();
}
glDeleteVertexArrays(3, VAOs);
glDeleteBuffers(3, VBOs);
glDeleteBuffers(3, EBOs);
glfwTerminate();
return 0;
}

你会在这里得到:

float vertices2[] = {
0.6f, 0.7f, 0.0f,
0.7f, 0.7f, 0.0f,
0.7f, 0.2f, 0.0f,
0.6f, 0.2f, 0.0f
};

与:

unsigned int indices2[] = {
5, 4, 6,
6, 7, 4
};

这说不通。您只将 4 个顶点复制到VBO[1],并且您将属性指针设置为该缓冲区中的偏移量 0,因此唯一有效的索引是0123

你的索引被设置为好像你所有的顶点都像以前一样在一个大数组中,实际上,这将是一个更好的策略:保留一个大的顶点数组,一个大的元素索引数组和一个VAO,并通过更改glDrawElements()调用中的indices参数来绘制该数组的各个部分, 喜欢这个:

glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0); // first 6 indices
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, (void*)(6*sizeof(GLuint))); // second 6 indices
// ...

也不是说在这里使用 3 个不同的着色器效率非常低。最好只是将颜色添加为另一个属性,并对所有内容使用单个绘制调用(意味着单个着色器,单个 VAO(。

最新更新