我正在尝试创建一个圆柱体和平面放在圆柱体下面。在我为平面创建新的顶点缓冲区对象之前,圆柱体渲染得很好。但由于某种原因,当我运行程序时,圆柱体和平面都没有渲染。我已经为圆柱体创建了EBO,但我仍然得到一个黑色窗口。我不知道我是否需要为每个形状创建一个EBO,为每个形状创建一个Vao,或者我的绘图函数是否有问题。谁能指出可能的问题是什么?以下是我的代码:
# include <GL\glew.h>
# include <GLFW\glfw3.h>
# include <iostream>
// GLM library
# include <glm/glm.hpp>
# include <glm/gtc/matrix_transform.hpp>
# include <glm/gtc/type_ptr.hpp>
using namespace std;
int width, height;
const double PI = 3.14159;
const float toRadians = PI / 180.0f;
// Draw Primitive(s)
void draw() {
GLenum mode = GL_TRIANGLES;
GLsizei indices = 60;
glDrawElements(mode, indices, GL_UNSIGNED_BYTE, nullptr);
}
// Create and Compile Shaders
static GLuint CompileShader(const string& source, GLuint shaderType) {
// Create Shader Object
GLuint shaderID = glCreateShader(shaderType);
const char* src = source.c_str();
// Attach source code to Shader object
glShaderSource(shaderID, 1, &src, nullptr);
// Compile Shader
glCompileShader(shaderID);
// Return ID of Compiled shader
return shaderID;
}
// Create Program Object
static GLuint CreateShaderProgram(const string& vertexShader, const string& fragmentShader) {
// Compile vertex shader
GLuint vertexShaderComp = CompileShader(vertexShader, GL_VERTEX_SHADER);
// Compile fragment shader
GLuint fragmentShaderComp = CompileShader(fragmentShader, GL_FRAGMENT_SHADER);
// Create program object
GLuint shaderProgram = glCreateProgram();
// Attch vertex and fragment shaders to program object
glAttachShader(shaderProgram, vertexShaderComp);
glAttachShader(shaderProgram, fragmentShaderComp);
// Link shaders to create executable
glLinkProgram(shaderProgram);
// Delete compiled vertex and fragment shaders
glDeleteShader(vertexShaderComp);
glDeleteShader(fragmentShaderComp);
// Return Shader Program
return shaderProgram;
}
int main(void) {
width = 640; height = 480;
GLFWwindow* window;
// Initialize the library
if (!glfwInit())
return -1;
// Create a windowed mode window and its OpenGL context
window = glfwCreateWindow(width, height, "Main Window", NULL, NULL);
if (!window) {
glfwTerminate();
return -1;
}
// Make the window's context current
glfwMakeContextCurrent(window);
// Initialize GLEW
if (glewInit() != GLEW_OK)
cout << "Error!" << endl;
GLfloat cylinderVertices[] = {
// Base of the cylinder
// Triangle One // Color
0.0, 0.0, 0.0, 1.0, 0.0, 0.0, // Vertex 0 red
cos(0 * toRadians), sin(0 * toRadians), 0.0, 0.0, 1.0, 0.0, // Vertex 1 green
cos(60 * toRadians), sin(60 * toRadians), 0.0, 0.0, 0.0, 1.0, // Vertex 2 blue
// Part of Triangle Two
cos(120 * toRadians), sin(120 * toRadians), 0.0, 1.0, 0.0, 1.0, // Vertex 3 purple
// Part of Triangle Three
cos(180 * toRadians), sin(180 * toRadians), 0.0, 0.0, 1.0, 0.0, // Vertex 4 greem
// Part of Triangle Four
cos(240 * toRadians), sin(240 * toRadians), 0.0, 0.0, 0.0, 1.0, // Vertex 5 blue
// Part of Triangle Five
cos(300 * toRadians), sin(300 * toRadians), 0.0, 1.0, 0.0, 1.0, // Vertex 6 purple
// Part of Triangle Six
cos(360 * toRadians), sin(360 * toRadians), 0.0, 0.0, 1.0, 0.0, // Vertex 7 green
// Sides of the cylinder
// Part of Triangle Seven
cos(0 * toRadians), sin(0 * toRadians), 2.0, 1.0, 0.0, 0.0, // Vertex 8 red
// Part of Triangle Eight
cos(60 * toRadians), sin(60 * toRadians), 2.0, 0.0, 1.0, 0.0, // Vertex 9 green
// Part of Triangle Nine
cos(120 * toRadians), sin(120 * toRadians), 2.0, 0.0, 0.0, 1.0, // Vertex 10 blue
// Part of Triangle Ten
cos(180 * toRadians), sin(180 * toRadians), 2.0, 1.0, 0.0, 1.0, // Vertex 11 purple
// Part of Triangle Eleven
cos(240 * toRadians), sin(240 * toRadians), 2.0, 1.0, 0.0, 0.0, // Vertex 12 red
// Part of Triangle Twelve
cos(300 * toRadians), sin(300 * toRadians), 2.0, 0.0, 1.0, 0.0, // Vertex 13 green
};
// Define element indices
GLubyte cylinderIndices[] = {
// Bottom base
0,1,2,
0,2,3,
0,3,4,
0,4,5,
0,5,6,
0,6,7,
// Sides
1,2,8,
2,9,8,
2,3,9,
3,10,9,
3,4,10,
4,11,10,
5,11,4,
5,12,11,
5,6,12,
6,13,12,
6,1,13,
1,8,13
};
GLfloat planeVertices[] = {
// positon attributes (x,y,z)
0.0f, 0.0f, 0.0f, // vert 14
0.0f, 1.0f, 0.0f, // red
0.0f, 0.866f, 0.0f, // vert 15
0.0f, 1.0f, 0.0f, // green
1.0f, 0.0f, 0.0f, // vert 16
0.0f, 1.0f, 0.0f, // blue
1.0f, 0.866f, 0.0f, // vert 17
1.0f, 0.0f, 1.0f // purple
};
// Define element indices
GLubyte planeIndices[] = {
14,16,15,
16,17,15
};
// Enable Depth Buffer
glEnable(GL_DEPTH_TEST);
// Wireframe mode
// glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
GLuint cylinderVBO, planeVBO, EBO, VAO;
glGenBuffers(1, &cylinderVBO); // Create VBO and returns ID
glGenBuffers(1, &planeVBO);
glGenBuffers(1, &EBO); // Create EBO
glGenVertexArrays(1, &VAO); // Create VAO
glBindVertexArray(VAO);
glBindBuffer(GL_ARRAY_BUFFER, cylinderVBO); // Select VBO and activate buffer
glBindBuffer(GL_ARRAY_BUFFER, planeVBO);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO); // Select EBO
glBufferData(GL_ARRAY_BUFFER, sizeof(cylinderVertices), cylinderVertices, GL_STATIC_DRAW); // Load vertex attributes
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(cylinderIndices), cylinderIndices, GL_STATIC_DRAW); // Load indices attributes
glBufferData(GL_ARRAY_BUFFER, sizeof(planeVertices), planeVertices, GL_STATIC_DRAW); // Load vertex attributes
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(planeIndices), planeIndices, GL_STATIC_DRAW); // Load indices attributes
// Specify attributes location and layout to GPU
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat), (GLvoid*)0);
glEnableVertexAttribArray(0);
// Color attribute location and layout
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat), (GLvoid*)(3 * sizeof(GLfloat)));
glEnableVertexAttribArray(1);
glBindVertexArray(0);
// Vertex shader source code
string vertexShaderSource =
"#version 330 core\n"
"layout(location = 0) in vec4 vPosition;"
"layout(location = 1) in vec4 aColor;"
"out vec4 oColor;"
"uniform mat4 model;"
"uniform mat4 view;"
"uniform mat4 projection;"
"void main()\n"
"{\n"
"gl_Position = projection * view * model * vPosition;"
"oColor = aColor;"
"}\n";
// Fragment shader source code
string fragmentShaderSource =
"#version 330 core\n"
"in vec4 oColor;"
"out vec4 fragColor;"
"void main()\n"
"{\n"
"fragColor = oColor;"
"}\n";
// Creating Shader Program
GLuint shaderProgram = CreateShaderProgram(vertexShaderSource, fragmentShaderSource);
while (!glfwWindowShouldClose(window)) {
// Resize window and graphics simultaneously
glfwGetFramebufferSize(window, &width, &height);
glViewport(0, 0, width, height);
// Render here
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// Use Shader Program exe and select VAO before drawing
glUseProgram(shaderProgram); // Call Shader per-frame when updating attributes
// Declare identity matrix
glm::mat4 modelMatrix(1.0f);
glm::mat4 viewMatrix(1.0f);
glm::mat4 projectionMatrix(1.0f);
// Initialize transforms
modelMatrix = glm::scale(modelMatrix, glm::vec3(0.5f, 0.5f, 0.5f));
// I increased the third argument from -3.0f to -6.0f to make the object smaller
// Moved the cup to the right by increasing the x coordinate
viewMatrix = glm::translate(viewMatrix, glm::vec3(0.5f, 0.0f, -6.0f));
// I changed up somme of the arguments, so the object would tilt right instead of toward me
viewMatrix = glm::rotate(viewMatrix, 45.0f * toRadians, glm::vec3(-0.5f, 1.0f, 1.5f));
projectionMatrix = glm::perspective(45.0f * toRadians, (GLfloat)width / (GLfloat)height, 0.1f, 100.0f);
// Select uniform shader and variable
GLuint modelLoc = glGetUniformLocation(shaderProgram, "model");
GLuint viewLoc = glGetUniformLocation(shaderProgram, "view");
GLuint projectionLoc = glGetUniformLocation(shaderProgram, "projection");
// Pass transform to Shader
glUniformMatrix4fv(viewLoc, 1, GL_FALSE, glm::value_ptr(viewMatrix));
glUniformMatrix4fv(projectionLoc, 1, GL_FALSE, glm::value_ptr(projectionMatrix));
glBindVertexArray(VAO); // User-defined VAO must be called before draw
for (GLuint i = 0; i < 4; i++) {
glm::mat4 modelMatrix(1.0f);
glUniformMatrix4fv(modelLoc, 1, GL_FALSE, glm::value_ptr(modelMatrix));
// Draw primitive(s)
draw();
}
// Unbind Shader exe and VOA after drawing per frame
glBindVertexArray(0); // In case different VAO will be used after
glUseProgram(0); // In case different shader will be used after
glBindVertexArray(VAO);
// Swap front and back buffers
glfwSwapBuffers(window);
// Poll for and process events
glfwPollEvents();
}
glfwTerminate();
return 0;
}
1条答案
按热度按时间egmofgnx1#
好的,所以你的平面和圆柱体缓冲区布局(IND索引)有一点结构问题。
顶点缓冲区
首先,让我们从顶点数据和相关的缓冲区开始(我们将在后面考虑索引)。
对于如何将数据发送到GPU,您有两个选择。
1.为每个形状分离顶点缓冲区。即指定一个圆柱体VBO(具有所有圆柱体顶点)和一个平面VBO(具有所有平面顶点)。
1.将两组顶点合并为单个顶点缓冲区。
如果要单独指定缓冲区,则依次设置每个缓冲区。
如果您希望将缓冲区合并为一个大的BLOB,则生成一个大的数组:
索引缓冲区
现在,根据您以前设置顶点缓冲区的方式,您将必须执行一个操作(但不能同时执行两个操作!)以下几个方面。
如果已分离顶点缓冲区(一个用于圆柱体,一个用于平面),则还需要单独的索引缓冲区。
但是,如果您希望将这两个形状合并到单个缓冲区中,请改为执行以下操作:
顶点缓冲区对象
如果为每个形状设置了单独的缓冲区,则在设置VAOS的方式上有两个选择。
1.1创建两个Vao,每个形状一个。
要呈现这样的数据,您需要2个绘制调用,每个形状一个。
1.2设置1个VAO,但在运行时重新绑定顶点和索引缓冲区。
要呈现这样的数据,您需要2个绘制调用,每个形状一个。
1.但是,如果已指定单个顶点缓冲区和单个索引缓冲区中的所有数据,则可以执行以下操作:
要呈现这样的数据,您需要一次绘制调用。
就是这样。