将带纹理四边形移至独立类后消失,无报错求排查
问题:将带纹理的OpenGL四边形代码迁移至Model类后图形消失
原本实现了一个带纹理的四边形,为优化代码结构将其迁移至独立model类中,但现在四边形消失且无任何错误提示。发现VAO和VBO未能正确创建,但这段代码是直接从main.cpp中复制过来的,现在却无法正常工作。
主文件代码
#include <glad/glad.h> #include <GLFW/glfw3.h> #include <stb/stb_image.h> #include <texture.h> #include <window.h> #include <shader.h> #include <model.h> #include <iostream> GLfloat vertexes[] { 0.5, 0.5, 0.0, 1.0, 0.0, 0.0, 1.0, 1.0, -0.5, -0.5, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.5, -0.5, 0.0, 0.0, 0.0, 1.0, 1.0, 0.0, 0.5, 0.5, 0.0, 1.0, 0.0, 0.0, 1.0, 1.0, -0.5, 0.5, 0.0, 1.0, 1.0, 1.0, 0.0, 1.0, -0.5, -0.5, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0 }; const int width = 1900; const int height = 1200; int main() { glfwInit(); window window(width, height, "Voxel Engine"); gladLoadGL(); glViewport(0, 0, width, height); // shader shader_program shader("src/shaders/vertex_shader.shader", "src/shaders/fragment_shader.shader"); model model1(vertexes); /*// vao and vbo unsigned int vbo, vao; glGenBuffers(1, &vbo); glBindBuffer(GL_ARRAY_BUFFER, vbo); glBufferData(GL_ARRAY_BUFFER, sizeof(vertexes), vertexes, GL_STATIC_DRAW); glGenVertexArrays(1, &vao); glBindVertexArray(vao); glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)0); glEnableVertexAttribArray(0); glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)(3 * sizeof(float))); glEnableVertexAttribArray(1); glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)(6 * sizeof(float))); glEnableVertexAttribArray(2); glBindVertexArray(0); glBindBuffer(GL_ARRAY_BUFFER, 0);*/ texture test_img("resources/test_img.png", GL_TEXTURE0, GL_RGB, GL_UNSIGNED_BYTE); test_img.uniform_shader(shader, "tex_0", 0); while (!glfwWindowShouldClose(window.glfw_window)) { glfwPollEvents(); glClearColor(0.08, 0.12, 0.24, 1.0); glClear(GL_COLOR_BUFFER_BIT); shader.use(); //glBindTexture(GL_TEXTURE_2D, texture1); test_img.bind(); glBindVertexArray(model1.vao); glDrawArrays(GL_TRIANGLES, 0, 6); window.swap_buffers(); } glDeleteVertexArrays(1, &model1.vao); glDeleteBuffers(1, &model1.vbo); //glDeleteTextures(1, &texture1); test_img.destroy(); shader.destroy(); window.destroy(); glfwTerminate(); return 0; }
Model头文件
#ifndef MODEL_CLASS_H #define MODEL_CLASS_H #include <glad/glad.h> class model { public: unsigned int vao, vbo; model(GLfloat vertexes[]); void render(); void destroy(); }; #endif
Model实现文件
#include <model.h> model::model(GLfloat vertexes[]) { // vao and vbo glGenBuffers(1, &vbo); glBindBuffer(GL_ARRAY_BUFFER, vbo); glBufferData(GL_ARRAY_BUFFER, sizeof(vertexes), vertexes, GL_STATIC_DRAW); glGenVertexArrays(1, &vao); glBindVertexArray(vao); glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)0); glEnableVertexAttribArray(0); glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)(3 * sizeof(float))); glEnableVertexAttribArray(1); glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)(6 * sizeof(float))); glEnableVertexAttribArray(2); glBindVertexArray(0); glBindBuffer(GL_ARRAY_BUFFER, 0); }
问题分析与修复
核心问题出在model类构造函数的sizeof(vertexes)上:
- 在
main.cpp中,vertexes是数组类型,sizeof(vertexes)返回整个数组的字节大小(6个顶点×8个float×4字节=192字节)。 - 但当数组作为参数传递给函数时,会自动退化为指针。此时
sizeof(vertexes)返回的是指针的大小(通常为4或8字节),远小于实际数组大小,导致glBufferData只上传了极少一部分数据,OpenGL无法渲染完整的四边形。
修复方案1:传递数组大小作为参数
修改model类构造函数,让调用者传入数组的实际字节大小:
修改Model头文件
#ifndef MODEL_CLASS_H #define MODEL_CLASS_H #include <glad/glad.h> class model { public: unsigned int vao, vbo; // 新增数组大小参数 model(GLfloat vertexes[], GLsizeiptr size); void render(); void destroy(); }; #endif
修改Model实现文件
#include <model.h> model::model(GLfloat vertexes[], GLsizeiptr size) { glGenBuffers(1, &vbo); glBindBuffer(GL_ARRAY_BUFFER, vbo); // 使用传入的size代替sizeof(vertexes) glBufferData(GL_ARRAY_BUFFER, size, vertexes, GL_STATIC_DRAW); glGenVertexArrays(1, &vao); glBindVertexArray(vao); glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)0); glEnableVertexAttribArray(0); glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)(3 * sizeof(float))); glEnableVertexAttribArray(1); glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)(6 * sizeof(float))); glEnableVertexAttribArray(2); glBindVertexArray(0); glBindBuffer(GL_ARRAY_BUFFER, 0); }
修改main.cpp中的调用
// 传入数组的实际大小 model model1(vertexes, sizeof(vertexes));
修复方案2:使用C++容器替代C风格数组
改用std::vector或std::array可以避免数组退化为指针的问题,以std::vector为例:
修改Model头文件
#ifndef MODEL_CLASS_H #define MODEL_CLASS_H #include <glad/glad.h> #include <vector> class model { public: unsigned int vao, vbo; model(const std::vector<GLfloat>& vertexes); void render(); void destroy(); }; #endif
修改Model实现文件
#include <model.h> model::model(const std::vector<GLfloat>& vertexes) { glGenBuffers(1, &vbo); glBindBuffer(GL_ARRAY_BUFFER, vbo); glBufferData(GL_ARRAY_BUFFER, vertexes.size() * sizeof(GLfloat), vertexes.data(), GL_STATIC_DRAW); glGenVertexArrays(1, &vao); glBindVertexArray(vao); glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)0); glEnableVertexAttribArray(0); glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)(3 * sizeof(float))); glEnableVertexAttribArray(1); glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)(6 * sizeof(float))); glEnableVertexAttribArray(2); glBindVertexArray(0); glBindBuffer(GL_ARRAY_BUFFER, 0); }
修改main.cpp中的数组定义
std::vector<GLfloat> vertexes = { 0.5, 0.5, 0.0, 1.0, 0.0, 0.0, 1.0, 1.0, -0.5, -0.5, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.5, -0.5, 0.0, 0.0, 0.0, 1.0, 1.0, 0.0, 0.5, 0.5, 0.0, 1.0, 0.0, 0.0, 1.0, 1.0, -0.5, 0.5, 0.0, 1.0, 1.0, 1.0, 0.0, 1.0, -0.5, -0.5, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0 }; // 调用构造函数 model model1(vertexes);
补充完善Model类方法
建议实现render和destroy方法,让代码结构更清晰:
// 在Model实现文件中添加 void model::render() { glBindVertexArray(vao); glDrawArrays(GL_TRIANGLES, 0, 6); } void model::destroy() { glDeleteVertexArrays(1, &vao); glDeleteBuffers(1, &vbo); }
之后在main.cpp的渲染循环中可以直接调用model1.render(),销毁阶段调用model1.destroy()即可。
内容的提问来源于stack exchange,提问作者luke
相关产品推荐
相关产品推荐

