OpenGL绘制无图形且无报错问题排查求助
问题分析与修复方案
核心错误点及修正
- 缓冲区对象提前销毁:Entity构造函数中的VBO和EBO是局部变量,构造完成后立即被销毁,导致VAO关联的缓冲区失效。需将VBO、EBO改为Entity的成员变量。
- glDrawElements参数错误:最后一个参数不应传入CPU端的
&indices,VAO已绑定EBO,OpenGL会从EBO中读取索引,应传NULL或0。 - 顶点超出NDC范围被裁剪:原始顶点z值为1.0,经缩放后变为1.5,超出标准化设备坐标(NDC)的z范围[-1,1],导致图形被裁剪。需调整顶点z值或修改缩放逻辑。
- 回调函数重复注册:
glfwSetFramebufferSizeCallback放在渲染循环中会重复设置,应移到窗口初始化完成后仅调用一次。
修改后的代码
Entity.h(补充成员变量)
#pragma once #include "VAO.h" #include "VBO.h" #include "EBO.h" #include "Shader.h" #include <glm/glm.hpp> #include <vector> class Entity { private: VAO vao; VBO vbo; EBO ebo; std::vector<glm::vec3> vertices; std::vector<GLuint> indices; public: Entity(std::vector<glm::vec3>& vertices, std::vector<GLuint>& indices); void Draw(Shader& shader); };
Entity.cpp(修正构造与Draw方法)
#include "Entity.h" Entity::Entity(std::vector<glm::vec3>& vertices, std::vector<GLuint>& indices) : vbo(vertices), ebo(indices) { this->vertices = vertices; this->indices = indices; vao.Bind(); vao.LinkAttrib(vbo, 0, 3, GL_FLOAT, sizeof(glm::vec3), (void*)0); vao.Unbind(); } void Entity::Draw(Shader& shader) { shader.Activate(); vao.Bind(); glDrawElements(GL_TRIANGLES, indices.size(), GL_UNSIGNED_INT, NULL); }
main.cpp(调整顶点与回调位置)
#include <glad/glad.h> #include <GLFW/glfw3.h> #include <glm/glm.hpp> #include <iostream> #include <stb/stb_image.h> #include "Entity.h" const unsigned int width = 800; const unsigned int height = 800; void framebuffer_size_callback(GLFWwindow* window, int width, int height); // 调整z值到NDC范围内 glm::vec3 vertices[] ={ glm::vec3(-0.5f, -0.5f, 0.0f), glm::vec3(-0.5f, 0.5f, 0.0f), glm::vec3( 0.5f, -0.5f, 0.0f), glm::vec3( 0.5f, 0.5f, 0.0f) }; GLuint indices[] = { 0,1,2, 1,2,3 }; int main() { glfwInit(); 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, "Physics", NULL, NULL); if (window == NULL) { std::cout << "Failed to initialize OpenGL window" << std::endl; glfwTerminate(); return -1; } glfwMakeContextCurrent(window); gladLoadGL(); glViewport(0, 0, width, height); // 仅设置一次窗口大小回调 glfwSetFramebufferSizeCallback(window, framebuffer_size_callback); Shader shaderProgram("default.vert", "default.frag"); GLuint uniID = glGetUniformLocation(shaderProgram.ID, "scale"); shaderProgram.Activate(); std::vector <glm::vec3> verts(vertices, vertices + sizeof(vertices) / sizeof(glm::vec3)); std::vector <GLuint> ind(indices, indices + sizeof(indices) / sizeof(GLuint)); Entity square(verts, ind); while (!glfwWindowShouldClose(window)) { glClearColor(0.11f, 0.11f, 0.11f, 1.0f); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); shaderProgram.Activate(); glUniform1f(uniID, 0.5f); square.Draw(shaderProgram); glfwSwapBuffers(window); glfwPollEvents(); } shaderProgram.Delete(); glfwTerminate(); return 0; } void framebuffer_size_callback(GLFWwindow* window, int width, int height) { glViewport(0, 0, width, height); }
可选:调整顶点着色器缩放逻辑(仅缩放XY轴)
#version 330 core #extension GL_ARB_separate_shader_objects : enable layout (location = 0) in vec3 aPos; uniform float scale; void main() { gl_Position = vec4(aPos.x * (1.0 + scale), aPos.y * (1.0 + scale), aPos.z, 1.0); }
内容的提问来源于stack exchange,提问作者LawlessWalrus
相关产品推荐
相关产品推荐

