You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

将带纹理四边形移至独立类后消失,无报错求排查

问题:将带纹理的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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.22 17:44:58