季节问候大家!我改编了this tutorial中的代码以支持使用VAO / VBO,但现在我明白了:
代替漂亮的圆形。这是代码:
#define GLEW_STATIC
#include <GLEW/glew.h>
#include <GLFW/glfw3.h>
#include <corecrt_math_defines.h>
#include <cmath>
#include <vector>
#define SCREEN_WIDTH 3000
#define SCREEN_HEIGHT 1900
void drawPolygon(GLuint& vao, GLuint& vbo, GLfloat x,
GLfloat y, GLdouble radius, GLint numberOfSides);
int main(void) {
if (!glfwInit()) {
return -1;
}
GLFWwindow* window = glfwCreateWindow(SCREEN_WIDTH,
SCREEN_HEIGHT, "Hello World", NULL, NULL);
if (!window) {
glfwTerminate();
return -1;
}
glfwMakeContextCurrent(window);
glewExperimental = GL_TRUE;
glewInit();
glGetError();
glViewport(0.0f, 0.0f, SCREEN_WIDTH, SCREEN_HEIGHT);
GLuint vao, vbo;
glGenVertexArrays(1, &vao);
glGenBuffers(1, &vbo);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0, SCREEN_WIDTH, 0, SCREEN_HEIGHT, -1, 1);
while (!glfwWindowShouldClose(window)) {
glClear(GL_COLOR_BUFFER_BIT);
drawPolygon(vao, vbo, SCREEN_WIDTH / 2,
SCREEN_HEIGHT / 2, 250.0f, 50);
glfwSwapBuffers(window);
glfwPollEvents();
}
glfwTerminate();
return 0;
}
void drawPolygon(GLuint& vao, GLuint& vbo, GLfloat x,
GLfloat y, GLdouble radius, GLint numberOfSides) {
int numVertices = numberOfSides + 2;
GLdouble twicePi = 2.0f * M_PI;
vector<GLdouble> circleVerticesX;
vector<GLdouble> circleVerticesY;
circleVerticesX.push_back(x);
circleVerticesY.push_back(y);
for (int i = 1; i < numVertices; i++) {
circleVerticesX.push_back(x + (radius *
cos(i * twicePi / numberOfSides)));
circleVerticesY.push_back(y + (radius *
sin(i * twicePi / numberOfSides)));
}
vector<GLdouble> vertices;
for (int i = 0; i < numVertices; i++) {
vertices.push_back(circleVerticesX[i]);
vertices.push_back(circleVerticesY[i]);
}
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBufferData(GL_ARRAY_BUFFER, numVertices * sizeof(
GLdouble), vertices.data(), GL_STATIC_DRAW);
glBindVertexArray(vao);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 2, GL_DOUBLE, GL_FALSE,
2 * sizeof(GLdouble), (void*)0);
glDrawArrays(GL_TRIANGLE_FAN, 0, 27);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
}
我到底做错了什么?使用the original code是可行的,所以我对这个荒谬的结果感到困惑! MTIA给任何可以帮助的人:-)
答案 0 :(得分:2)
VBO的大小为numVertices * sizeof(GLdouble)
,是顶点数据实际大小的一半(每个顶点都有一个x 和 y分量)。因此,最终绘制的顶点数量是VBO实际具有顶点数据的两倍。超出VBO范围的读取似乎在OpenGL实现中仅导致零,这就是为什么圆的下半部分的所有顶点都位于左下角的原因(除非您明确启用健壮的缓冲区访问,否则不能保证这一点,只是您的驱动程序和GPU似乎在做什么)…
注释:
double
。 double
占用两倍的内存带宽,并且double
上的算术通常比float
至少慢一点(是的,即使在x86 CPU上,因为浮点算术实际上不是使用如今已经可以使用x87 FPU)。特别是为float
算术构建了GPU。尤其是在消费类GPU上,double
算法比float
显着地 (一个数量级)。vertices
而不是先将顶点数据推入circleVerticesX
和circleVerticesY
然后从那里复制到vertices
呢?您确切地知道将要生成多少个顶点。因此,无需在生成坐标的循环中动态增长顶点容器(除其他事项外,.push_back()
几乎肯定会阻止循环的矢量化)。我建议在进入循环之前至少.reserve()
个元素的相应数量(假设这是一个std::vector
)。就我个人而言,我将通过
auto vertex_data = std::unique_ptr<GLfloat[]> { new GLfloat[numVertices * 2] };
在这种情况下。
glDrawArrays
调用来绘制实际的顶点数,而不是总是27
…