VBO 和 VAO 不绘制 opengl 和 LWJGL3
VBO and VAO not drawing opengl and LWJGL3
我已经使用 open GL 玩了一段时间,我已经到了可以绘制 3d 形状的地步,我的形状、顶点和索引绝对正确,但我的形状变得一团糟。我现在想重做我的画。我以前只使用没有 VAO 的 VBO,只是绑定和绘制它们。这行得通,但我怀疑这是我的错误。所以我开始使用 VAO,但我没有发现我的代码有任何问题,而且我仍然无法让它绘制我的白色方块(没有像 wiki 教程那样的着色器)。
我初始化 window 的代码在这里:
private void initWindow() {
//Makes sure window can work
if (!glfwInit()) {
throw new IllegalStateException("Failed to Initialize GLFW!");
}
//Create window object and set its hints
glfwWindowHint(GLFW_VISIBLE, GLFW_FALSE);
this.windowRef = glfwCreateWindow(width, height, name, NULL, NULL);
if (windowRef == 0) {
throw new IllegalStateException("Failed to create Window!");
}
GLFWVidMode videoMode = glfwGetVideoMode(glfwGetPrimaryMonitor());
glfwSetWindowPos(windowRef, (videoMode.width() - width) / 2, (videoMode.height() - height) / 2);
// Make the OpenGL context current
glfwMakeContextCurrent(windowRef);
// Enable v-sync
glfwSwapInterval(1);
//Make GL capabilites for window
GL.createCapabilities();
glfwShowWindow(windowRef);
}
我的缓冲区和对象初始化代码在这里
public void loadGL() {
float[] vertex = {
0f, 0f, 0f, //0
0.5f, 0, 0, //1
0.5f, 0, 0.5f, //2
0f, 0f, 0.5f, //3
0f, 0.5f, 0f, //4
0.5f, 0.5f, 0, //5
0.5f, 0.5f, 0.5f,//6
0f, 0.5f, 0.5f//7
};
int[] index = {
0, 1, 2, //0
0, 2, 3, //1
0, 3, 4, //2
3, 7, 4,//3
0, 4, 1,//4
1, 5, 4,//5
1, 5, 2,//6
2, 6, 5,//7
2, 3, 6,//8
3, 7, 6,//9
4, 5, 7,//10
5, 6, 7//11
};
size = 12*3;
indicesBuff = BufferUtils.createIntBuffer(index.length);
vertBuff = BufferUtils.createFloatBuffer(vertex.length);
indicesBuff.put(index);
vertBuff.put(vertex);
indicesBuff.flip();
vertBuff.flip();
vao = glGenVertexArrays();
glBindVertexArray(vao);
vboID = glGenBuffers();
glBindBuffer(GL_ARRAY_BUFFER, vboID);
glBufferData(GL_ARRAY_BUFFER, vertBuff, GL_STATIC_DRAW);
GL20.glVertexAttribPointer(0, 3, GL_FLOAT, false, 0, 0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
ibo = glGenBuffers();
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, indicesBuff, GL_STATIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
glBindVertexArray(0);
}
最后我的主循环在这里,它在 window init:
之后调用
private void mainLoop() {
loadGL();
glClearColor(0.5f, 0.5f, 0.5f, 1);
while (!glfwWindowShouldClose(windowRef)) {
//Render Stuff here
//TODO: later skip this block if nothing has changed
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // clear
the framebuffer
glBindVertexArray(vao);
glEnableVertexAttribArray(0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo);
glDrawElements(GL_TRIANGLES, size, GL_UNSIGNED_INT, 0);
// glBegin(GL_QUADS);
// glVertex3f(-0.5f, -0.5f, 0);
// glVertex3f(-0.5f, 0.5f, 0);
// glVertex3f(0.5f, -0.5f, 0);
// glVertex3f(0.5f, 0.5f, 0);
// glEnd();
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
glDisableVertexAttribArray(0);
glBindVertexArray(0);
glfwSwapBuffers(windowRef);
glfwPollEvents();
}
}
顺便说一下,它是用 glBegin 绘制的,所以可以工作,但对于我想做的事情来说效率不高。
现代的 OpenGL 渲染方式是使用 Shader 程序。
如果您不使用着色器程序,则必须使用 glVertexPointer
and you have to enable the client-side capability for vertex coordinates by glEnableClientState( GL_VERTEX_ARRAY )
:
推荐的方式定义顶点数据数组
vao = glGenVertexArrays();
glBindVertexArray(vao);
vboID = glGenBuffers();
glBindBuffer(GL_ARRAY_BUFFER, vboID);
glBufferData(GL_ARRAY_BUFFER, vertBuff, GL_STATIC_DRAW);
GL20.glVertexPointer(3, GL_FLOAT, 0, 0); // <--------------
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(vao);
glEnableClientState( GL_VERTEX_ARRAY ); // <--------------
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo);
glDrawElements(GL_TRIANGLES, size, GL_UNSIGNED_INT, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
glDisableClientState( GL_VERTEX_ARRAY ); // <---------------
glBindVertexArray(0);
进一步注意,客户端能力(或顶点属性数组)的状态和对索引(元素)缓冲区的引用存储在 Vertex Array Objects 状态向量中。
因此,在指定顶点数组对象时启用顶点坐标并在绑定顶点数组对象时对索引缓冲区进行投标就足够了。绘制几何图形时顶点坐标的启用和禁用以及索引缓冲区的绑定可以省略:
vao = glGenVertexArrays();
glBindVertexArray(vao);
vboID = glGenBuffers();
glBindBuffer(GL_ARRAY_BUFFER, vboID);
glBufferData(GL_ARRAY_BUFFER, vertBuff, GL_STATIC_DRAW);
GL20.glVertexPointer(3, GL_FLOAT, 0, 0); // <--------------
glEnableClientState( GL_VERTEX_ARRAY ); // <--------------
glBindBuffer(GL_ARRAY_BUFFER, 0);
ibo = glGenBuffers();
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, indicesBuff, GL_STATIC_DRAW);
// skip glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
glBindVertexArray(0);
glBindVertexArray(vao);
glDrawElements(GL_TRIANGLES, size, GL_UNSIGNED_INT, 0);
glBindVertexArray(0);
我已经使用 open GL 玩了一段时间,我已经到了可以绘制 3d 形状的地步,我的形状、顶点和索引绝对正确,但我的形状变得一团糟。我现在想重做我的画。我以前只使用没有 VAO 的 VBO,只是绑定和绘制它们。这行得通,但我怀疑这是我的错误。所以我开始使用 VAO,但我没有发现我的代码有任何问题,而且我仍然无法让它绘制我的白色方块(没有像 wiki 教程那样的着色器)。
我初始化 window 的代码在这里:
private void initWindow() {
//Makes sure window can work
if (!glfwInit()) {
throw new IllegalStateException("Failed to Initialize GLFW!");
}
//Create window object and set its hints
glfwWindowHint(GLFW_VISIBLE, GLFW_FALSE);
this.windowRef = glfwCreateWindow(width, height, name, NULL, NULL);
if (windowRef == 0) {
throw new IllegalStateException("Failed to create Window!");
}
GLFWVidMode videoMode = glfwGetVideoMode(glfwGetPrimaryMonitor());
glfwSetWindowPos(windowRef, (videoMode.width() - width) / 2, (videoMode.height() - height) / 2);
// Make the OpenGL context current
glfwMakeContextCurrent(windowRef);
// Enable v-sync
glfwSwapInterval(1);
//Make GL capabilites for window
GL.createCapabilities();
glfwShowWindow(windowRef);
}
我的缓冲区和对象初始化代码在这里
public void loadGL() {
float[] vertex = {
0f, 0f, 0f, //0
0.5f, 0, 0, //1
0.5f, 0, 0.5f, //2
0f, 0f, 0.5f, //3
0f, 0.5f, 0f, //4
0.5f, 0.5f, 0, //5
0.5f, 0.5f, 0.5f,//6
0f, 0.5f, 0.5f//7
};
int[] index = {
0, 1, 2, //0
0, 2, 3, //1
0, 3, 4, //2
3, 7, 4,//3
0, 4, 1,//4
1, 5, 4,//5
1, 5, 2,//6
2, 6, 5,//7
2, 3, 6,//8
3, 7, 6,//9
4, 5, 7,//10
5, 6, 7//11
};
size = 12*3;
indicesBuff = BufferUtils.createIntBuffer(index.length);
vertBuff = BufferUtils.createFloatBuffer(vertex.length);
indicesBuff.put(index);
vertBuff.put(vertex);
indicesBuff.flip();
vertBuff.flip();
vao = glGenVertexArrays();
glBindVertexArray(vao);
vboID = glGenBuffers();
glBindBuffer(GL_ARRAY_BUFFER, vboID);
glBufferData(GL_ARRAY_BUFFER, vertBuff, GL_STATIC_DRAW);
GL20.glVertexAttribPointer(0, 3, GL_FLOAT, false, 0, 0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
ibo = glGenBuffers();
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, indicesBuff, GL_STATIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
glBindVertexArray(0);
}
最后我的主循环在这里,它在 window init:
之后调用 private void mainLoop() {
loadGL();
glClearColor(0.5f, 0.5f, 0.5f, 1);
while (!glfwWindowShouldClose(windowRef)) {
//Render Stuff here
//TODO: later skip this block if nothing has changed
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // clear
the framebuffer
glBindVertexArray(vao);
glEnableVertexAttribArray(0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo);
glDrawElements(GL_TRIANGLES, size, GL_UNSIGNED_INT, 0);
// glBegin(GL_QUADS);
// glVertex3f(-0.5f, -0.5f, 0);
// glVertex3f(-0.5f, 0.5f, 0);
// glVertex3f(0.5f, -0.5f, 0);
// glVertex3f(0.5f, 0.5f, 0);
// glEnd();
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
glDisableVertexAttribArray(0);
glBindVertexArray(0);
glfwSwapBuffers(windowRef);
glfwPollEvents();
}
}
顺便说一下,它是用 glBegin 绘制的,所以可以工作,但对于我想做的事情来说效率不高。
现代的 OpenGL 渲染方式是使用 Shader 程序。
如果您不使用着色器程序,则必须使用 glVertexPointer
and you have to enable the client-side capability for vertex coordinates by glEnableClientState( GL_VERTEX_ARRAY )
:
vao = glGenVertexArrays();
glBindVertexArray(vao);
vboID = glGenBuffers();
glBindBuffer(GL_ARRAY_BUFFER, vboID);
glBufferData(GL_ARRAY_BUFFER, vertBuff, GL_STATIC_DRAW);
GL20.glVertexPointer(3, GL_FLOAT, 0, 0); // <--------------
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(vao);
glEnableClientState( GL_VERTEX_ARRAY ); // <--------------
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo);
glDrawElements(GL_TRIANGLES, size, GL_UNSIGNED_INT, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
glDisableClientState( GL_VERTEX_ARRAY ); // <---------------
glBindVertexArray(0);
进一步注意,客户端能力(或顶点属性数组)的状态和对索引(元素)缓冲区的引用存储在 Vertex Array Objects 状态向量中。 因此,在指定顶点数组对象时启用顶点坐标并在绑定顶点数组对象时对索引缓冲区进行投标就足够了。绘制几何图形时顶点坐标的启用和禁用以及索引缓冲区的绑定可以省略:
vao = glGenVertexArrays();
glBindVertexArray(vao);
vboID = glGenBuffers();
glBindBuffer(GL_ARRAY_BUFFER, vboID);
glBufferData(GL_ARRAY_BUFFER, vertBuff, GL_STATIC_DRAW);
GL20.glVertexPointer(3, GL_FLOAT, 0, 0); // <--------------
glEnableClientState( GL_VERTEX_ARRAY ); // <--------------
glBindBuffer(GL_ARRAY_BUFFER, 0);
ibo = glGenBuffers();
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, indicesBuff, GL_STATIC_DRAW);
// skip glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
glBindVertexArray(0);
glBindVertexArray(vao);
glDrawElements(GL_TRIANGLES, size, GL_UNSIGNED_INT, 0);
glBindVertexArray(0);