此问题已在此处有答案:
What is the result of NULL + int?(4个答案)
8天前关闭
我试图用一个自定义的FragmentShader来绘制一个三角形,以获得三角形的渐变效果。
我试图使用索引绘图而不是绘制数组。
虽然glDrawArrays(...)
工作得很好,但glDrawElements(...)
不适合我。我只是得到一个空白的屏幕与索引绘图,而不是一个正常的输出(截图如下所附)。
有人能告诉我我哪里做错了吗?
- 这是我的代码 *
#include <iostream>
#include <glad/glad.h>
#include <GLFW/glfw3.h>
// Vertex Shader source code
const char* vertexShaderSource =
"#version 330 core\n"
"layout (location = 0) in vec3 aPos;\n"
"layout (location = 1) in vec3 aColor;\n"
"out vec3 outColor;\n"
"void main() {\n"
" gl_Position = vec4(aPos, 1.0);\n"
" outColor = aColor;\n"
"}\n\0";
// Fragment Shader source code
const char* fragmentShaderSource =
"#version 330 core\n"
"out vec4 FragColor;\n"
"in vec3 outColor;\n"
"void main() {\n"
" FragColor = vec4(outColor, 1.0f);\n"
"}\n\0";
const int width{ 800 };
const int height{ 600 };
bool WIREFRAME_MODE = false;
int main() {
glfwInit();
#pragma region Creating a Window
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
GLFWwindow* window = glfwCreateWindow(width, height, "Triangle Exercise", nullptr, nullptr);
if (!window) {
std::cout << " >> Failed to create window!" << std::endl;
glfwTerminate();
return -1;
}
glfwMakeContextCurrent(window);
#pragma endregion
gladLoadGL();
glViewport(0, 0, width, height);
#pragma region Shader Compilation
// Vertex Shader
GLuint vertexShader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertexShader, 1, &vertexShaderSource, nullptr);
glCompileShader(vertexShader);
// Fragment Shader
GLuint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragmentShader, 1, &fragmentShaderSource, nullptr);
glCompileShader(fragmentShader);
// Shader Program
GLuint shaderProgram = glCreateProgram();
glAttachShader(shaderProgram, vertexShader);
glAttachShader(shaderProgram, fragmentShader);
glLinkProgram(shaderProgram);
// Delete the shaders
glDeleteShader(vertexShader);
glDeleteShader(fragmentShader);
#pragma endregion
#pragma region Vertex and Index data
// Vertex data
GLfloat vertices[] = {
// positions // colors
0.5f, -0.5f, 0.0f, 1.0f, 0.0f, 0.0f, // bottom right
-0.5f, -0.5f, 0.0f, 0.0f, 1.0f, 0.0f, // bottom left
0.0f, 0.5f, 0.0f, 0.0f, 0.0f, 1.0f // top
};
// Index data
GLuint indices[] = {
0, 1, 2
};
#pragma endregion
#pragma region VAO, VBO and EBO
GLuint VAO; // Vertex Attribute Object ref
GLuint VBO; // Vertex Buffer Object ref
GLuint EBO; // Element Buffer Object ref
glGenVertexArrays(1, &VAO);
glGenBuffers(1, &VBO);
glGenBuffers(1, &EBO);
glBindVertexArray(VAO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
// Point to the X,Y,Z vertex data in the VBO (at layout location 0)
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * (sizeof(GLfloat)), (void*)0);
glEnableVertexAttribArray(0);
// Point to the RGB color data in the VBO (at layout location 1)
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6 * (sizeof(GLfloat)), (void*)(3*sizeof(GLfloat)));
glEnableVertexAttribArray(1);
glBindBuffer(GL_ARRAY_BUFFER, 0); // unbind VBO
glBindVertexArray(0); // unbind VAO
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); // unbind EBO (conatined in VAO)
#pragma endregion
// While window isn't closed
while (!glfwWindowShouldClose(window)) {
if (WIREFRAME_MODE) {
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); // Wireframe mode
}
else {
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); // Fill mode
}
glClearColor(0, 0, 0, 1); // black background
glClear(GL_COLOR_BUFFER_BIT);
glUseProgram(shaderProgram);
glBindVertexArray(VAO);
// WORKS FINE
glDrawArrays(GL_TRIANGLES, 0, sizeof(vertices) / sizeof(GLfloat));
// DOESN'T WORK?
//
//glDrawElements(GL_TRIANGLES, sizeof(indices)/sizeof(GLuint), GL_UNSIGNED_INT, indices);
//
glfwSwapBuffers(window);
glfwPollEvents();
}
#pragma region Cleanup
glDeleteProgram(shaderProgram);
glDeleteBuffers(1, &VBO);
glDeleteBuffers(1, &VAO);
glDeleteBuffers(1, &EBO);
glfwDestroyWindow(window);
#pragma endregion
glfwTerminate();
return 0;
}
使用glDrawArrays()
输出屏幕截图:
使用glDrawElements()
输出屏幕截图:
我试着检查我的EBO的参数是否错误,但它们对我来说似乎很好。
1条答案
按热度按时间hlswsv351#
glDrawElements
(“indices”)的最后一个参数不应该是指向indices数组的指针,而是“数组中第一个索引在缓冲区数据存储中的偏移量”(ref),然后转换为GLvoid*
。这里,绘制调用应该使用所有3个索引,因此偏移量应该为0:(其他大致等效的表达式也是可能的,诸如
0
、NULL
和nullptr
。这种混淆可能来自this等文档,其中参数被错误地描述为“指向索引存储位置的指针”。我怀疑这就是
glDrawElements
在旧版OpenGL中的工作方式(例如:OpenGL 1.1),并且由于函数的使用发生了变化,而函数原型保持不变,因此必须将字节偏移转换为空指针。