如何在LWJGL3中使用VAO与VBO渲染三角形?附错误代码
Hey there, I totally feel your pain—spending three days stuck on a basic triangle render is no fun at all. Let's break down what might be going wrong here, since your code snippet cuts off, but I can walk through the common pitfalls and share a complete, working example using VAOs and VBOs in LWJGL that you can compare against your test class.
First, let's recap the core steps you need to get right for triangle rendering with VAO/VBO:
- Initialize GLFW and create a window
- Set up the OpenGL context
- Create and bind your VAO
- Create a VBO, fill it with vertex data, and link it to the VAO's attribute pointers
- Compile and link a basic vertex/fragment shader program
- Render the triangle in the main loop
- Clean up resources properly
Common Mistakes to Check
- Forgot to bind the VAO before rendering: You need to call
glBindVertexArray(vaoID)before drawing. - Incorrect vertex attribute setup: Making sure the
glVertexAttribPointerparameters (size, type, normalized, stride, offset) match your vertex data format. - Shader compilation/link errors: Always check for shader logs—even a tiny typo in GLSL will break everything.
- Not enabling vertex attributes: Don't forget
glEnableVertexAttribArray(index)after setting up the pointer. - Incorrect draw call: Using
glDrawArrays(GL_TRIANGLES, 0, 3)(not points or lines, and correct vertex count).
Complete Working Example for Your test Class
Here's a full, minimal implementation you can adapt to your code:
package quad; import java.nio.FloatBuffer; import org.lwjgl.BufferUtils; import org.lwjgl.glfw.GLFWVidMode; import org.lwjgl.opengl.GL; import static org.lwjgl.system.MemoryUtil.NULL; import static org.lwjgl.glfw.GLFW.*; import static org.lwjgl.opengl.GL11.*; import static org.lwjgl.opengl.GL15.*; import static org.lwjgl.opengl.GL20.*; import static org.lwjgl.opengl.GL30.*; public class test { private long window; private int vaoID, vboID, shaderProgram; public void run() { init(); loop(); cleanup(); } private void init() { // Initialize GLFW if (!glfwInit()) { throw new IllegalStateException("Unable to initialize GLFW"); } // Configure GLFW glfwDefaultWindowHints(); glfwWindowHint(GLFW_VISIBLE, GLFW_FALSE); glfwWindowHint(GLFW_RESIZABLE, GLFW_TRUE); // Create the window window = glfwCreateWindow(800, 600, "LWJGL Triangle", NULL, NULL); if (window == NULL) { throw new RuntimeException("Failed to create the GLFW window"); } // Get the resolution of the primary monitor GLFWVidMode vidmode = glfwGetVideoMode(glfwGetPrimaryMonitor()); // Center the window glfwSetWindowPos(window, (vidmode.width() - 800) / 2, (vidmode.height() - 600) / 2); // Make the OpenGL context current glfwMakeContextCurrent(window); // Enable v-sync glfwSwapInterval(1); // Make the window visible glfwShowWindow(window); // Initialize OpenGL GL.createCapabilities(); glClearColor(0.2f, 0.3f, 0.3f, 1.0f); // Set up VAO, VBO float[] vertices = { -0.5f, -0.5f, 0.0f, // Bottom-left 0.5f, -0.5f, 0.0f, // Bottom-right 0.0f, 0.5f, 0.0f // Top }; // Create VAO vaoID = glGenVertexArrays(); glBindVertexArray(vaoID); // Create VBO vboID = glGenBuffers(); glBindBuffer(GL_ARRAY_BUFFER, vboID); FloatBuffer vertexBuffer = BufferUtils.createFloatBuffer(vertices.length); vertexBuffer.put(vertices).flip(); glBufferData(GL_ARRAY_BUFFER, vertexBuffer, GL_STATIC_DRAW); // Link vertex attribute glVertexAttribPointer(0, 3, GL_FLOAT, false, 3 * Float.BYTES, 0); glEnableVertexAttribArray(0); // Unbind VBO and VAO (optional, but good practice) glBindBuffer(GL_ARRAY_BUFFER, 0); glBindVertexArray(0); // Create shader program String vertexShaderSource = """ #version 330 core layout (location = 0) in vec3 aPos; void main() { gl_Position = vec4(aPos.x, aPos.y, aPos.z, 1.0); } """; String fragmentShaderSource = """ #version 330 core out vec4 FragColor; void main() { FragColor = vec4(1.0f, 0.5f, 0.2f, 1.0f); } """; // Compile vertex shader int vertexShader = glCreateShader(GL_VERTEX_SHADER); glShaderSource(vertexShader, vertexShaderSource); glCompileShader(vertexShader); // Check for compilation errors if (glGetShaderi(vertexShader, GL_COMPILE_STATUS) == GL_FALSE) { System.err.println("Vertex shader compilation failed: " + glGetShaderInfoLog(vertexShader)); glDeleteShader(vertexShader); return; } // Compile fragment shader int fragmentShader = glCreateShader(GL_FRAGMENT_SHADER); glShaderSource(fragmentShader, fragmentShaderSource); glCompileShader(fragmentShader); if (glGetShaderi(fragmentShader, GL_COMPILE_STATUS) == GL_FALSE) { System.err.println("Fragment shader compilation failed: " + glGetShaderInfoLog(fragmentShader)); glDeleteShader(fragmentShader); return; } // Link shader program shaderProgram = glCreateProgram(); glAttachShader(shaderProgram, vertexShader); glAttachShader(shaderProgram, fragmentShader); glLinkProgram(shaderProgram); if (glGetProgrami(shaderProgram, GL_LINK_STATUS) == GL_FALSE) { System.err.println("Shader program linking failed: " + glGetProgramInfoLog(shaderProgram)); glDeleteProgram(shaderProgram); glDeleteShader(vertexShader); glDeleteShader(fragmentShader); return; } // Clean up shaders (no longer needed after linking) glDeleteShader(vertexShader); glDeleteShader(fragmentShader); } private void loop() { while (!glfwWindowShouldClose(window)) { // Clear the screen glClear(GL_COLOR_BUFFER_BIT); // Use shader program glUseProgram(shaderProgram); // Bind VAO glBindVertexArray(vaoID); // Draw the triangle glDrawArrays(GL_TRIANGLES, 0, 3); // Swap buffers and poll events glfwSwapBuffers(window); glfwPollEvents(); } } private void cleanup() { // Delete resources glDeleteVertexArrays(vaoID); glDeleteBuffers(vboID); glDeleteProgram(shaderProgram); // Terminate GLFW glfwTerminate(); } public static void main(String[] args) { new test().run(); } }
Steps to Compare with Your Code
- Check if you're properly creating and linking your shaders—add error checking like in the example, it's crucial for debugging.
- Verify your vertex attribute setup matches your vertex data (if you're using different stride/offset values, make sure they align).
- Ensure you're binding the VAO and using the shader program before calling
glDrawArrays. - Double-check your draw call parameters—
GL_TRIANGLESwith 3 vertices is correct for a single triangle.
If you can share the rest of your truncated code, especially the shader setup and render loop parts, we can pinpoint the exact issue more easily. But this example should give you a solid baseline to work from!
内容的提问来源于stack exchange,提问作者Fish_In_A_Suit

