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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.20 10:12:32