OpenGL/GLFW C++ 程序不绘制任何东西

OpenGL/GLFW C++ program doesn't draw anything

所以,我制作了这个包含三个主要文件的程序:

当我实现 object class 时(之前我只有椭圆形,然后我决定制作一个矩形并发现一些共同点)我 运行 进入一个问题,就是屏幕上什么也没有显示。

GLObject.cpp 包含 "GLObjectsInit()" 函数的定义,它设置了绘图程序 (draw_program) 以及在其中声明的不规则块的所有偏移量和矩阵步幅程序。

void GLObjectsInit()
{
    CompileDrawProgram(); // Compiles the draw_program

    coord_loc = glGetAttribLocation(draw_program, "coord");
    color_loc = glGetAttribLocation(draw_program, "color");

    static const GLchar* uniformNames[4] = {
        "TransformBlock.res",
        "TransformBlock.tsl",
        "TransformBlock.rot",
        "TransformBlock.scale"
    };
    GLuint uniformIndices[4];
    glGetUniformIndices(draw_program, 4, uniformNames, uniformIndices);

    GLint uniformOffsets[4];
    GLint matrixStrides[4];
    glGetActiveUniformsiv(draw_program, 4, uniformIndices, GL_UNIFORM_OFFSET, uniformOffsets);
    glGetActiveUniformsiv(draw_program, 4, uniformIndices, GL_UNIFORM_MATRIX_STRIDE, matrixStrides);

    resolution_offset = uniformOffsets[0];
    translation_offset = uniformOffsets[1];
    rotation_matrix_offset = uniformOffsets[2];
    rotation_matrix_stride = uniformOffsets[2];
    scale_offset = uniformOffsets[3];
}

绘图程序:

顶点着色器:

#version 450 core
in vec4 coord;
in vec4 color;
layout(std140, binding = 0) uniform TransformBlock
{
    vec4 res;
    vec4 tsl;
    vec4 scale;
    mat4 rot;
} trs;

out vec4 color_vs;
void main(void)
{
    color_vs = color;
    gl_Position = ((coord * trs.scale * trs.rot) + trs.tsl) * trs.res;
}

片段着色器:

#version 450 core

out vec4 color;
in vec4 color_vs;

void main(void)
{
    color = color_vs;
}

.h文件只包含headers要包含的和一些静态变量的声明(声​​明为static是为了避免多重定义错误):

#define _USE_MATH_DEFINES
#include <math.h>
#include <glm.hpp>
#define GLEW_STATIC
#include <GL/glew.h>
#include <GLFW/glfw3.h>

static GLuint draw_program;

static GLuint coord_loc, color_loc;
static GLuint resolution_offset, translation_offset, scale_offset;
static GLuint rotation_matrix_offset, rotation_matrix_stride;

椭圆object有一些修改object位置和比例的方法,还有draw()方法(我只写draw()方法和构造函数,因为我不认为其他人参与了这个问题。

Ellipse.h:

#include "GLObject.h"

class Ellipse//: public GLObject
{
protected:
    GLuint points_buffer, uniforms_buffer, vao;
    vertex* points;
    unsigned int size;
    bool fill;

    double ang;
    glm::mat4 rotation_matrix;
    glm::vec4 center, scale;

public:
    void Draw();

    //Other methods

    Ellipse(double w, double h, glm::vec4 cen, bool fill, glm::vec4 col = glm::vec4(1, 1, 1, 1));
    Ellipse(double r, glm::vec4 cen, bool fill, glm::vec4 col = glm::vec4(1, 1, 1, 1)) :
        Ellipse(r, r, cen, fill, col) {}

    ~Ellipse();
};

Ellipse.cpp:

#include "Ellipse.h"
using namespace std;

void Ellipse::Draw()
{
    GLFWwindow* window = glfwGetCurrentContext();

    glUseProgram(draw_program);
    glBindVertexArray(vao);
    glBindBufferBase(GL_UNIFORM_BUFFER, 0, uniforms_buffer);

    int w, h;   glm::vec4 res;
    glfwGetFramebufferSize(window, &w, &h);
    glViewport(0, 0, w, h);

    if (w > h) res = glm::vec4(static_cast<float>(h) / w, 1, 1, 1);
    else       res = glm::vec4(1, static_cast<float>(w) / h, 1, 1);

    glNamedBufferSubData(uniforms_buffer, resolution_offset, sizeof(glm::vec4), &res);

    if (fill) glDrawArrays(GL_TRIANGLES, 0, size);
    else      glDrawArrays(GL_LINES, 0, size);
}

Ellipse::Ellipse(double w, double h, glm::vec4 cen, bool fill, glm::vec4 col)
{
    // Calculate the ellipse

    glCreateVertexArrays(1, &vao);

    glCreateBuffers(1, &uniforms_buffer);
    glNamedBufferStorage(uniforms_buffer, sizeof(GLfloat) * 112, NULL, GL_DYNAMIC_STORAGE_BIT);

    glCreateBuffers(1, &points_buffer);
    glNamedBufferStorage(points_buffer, sizeof(vertex) * size, points, GL_DYNAMIC_STORAGE_BIT);
    glVertexArrayVertexBuffer(vao, 0, points_buffer, 0, sizeof(vertex));

    glVertexArrayAttribBinding(vao, coord_loc, 0);
    glVertexArrayAttribFormat(vao, coord_loc, 4, GL_FLOAT, GL_FALSE, offsetof(vertex, coord));
    glEnableVertexArrayAttrib(vao, coord_loc);

    glVertexArrayAttribBinding(vao, color_loc, 0);
    glVertexArrayAttribFormat(vao, color_loc, 4, GL_FLOAT, GL_FALSE, offsetof(vertex, color));
    glEnableVertexArrayAttrib(vao, color_loc);

    center = cen;   ang = 0;
    scale = glm::vec4(w, h, 1, 1);
    rotation_matrix = glm::mat4(1);

    glNamedBufferSubData(uniforms_buffer, scale_offset, sizeof(glm::vec4), &scale);
    glNamedBufferSubData(uniforms_buffer, translation_offset, sizeof(glm::vec4), &center);
    glNamedBufferSubData(uniforms_buffer, rotation_matrix_offset, sizeof(glm::mat4), &rotation_matrix[0]);
}

Ellipse::~Ellipse()
{
    glDeleteBuffers(1, &points_buffer);
    glDeleteBuffers(1, &uniforms_buffer);
    glDeleteVertexArrays(1, &vao);
    delete[] points;
}

主要的只有:

#include "Ellipse.h"
using namespace std;

int main()
{
    glfwInit();

    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 2);
    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 0);

    GLFWwindow* window = glfwCreateWindow(500, 500, "Title", NULL, NULL);
    glfwMakeContextCurrent(window);

    glewExperimental = GL_TRUE;
    glewInit();

    glfwSwapInterval(1);

    GLObjectsInit();
    Ellipse ball1(0.25, 0.25, glm::vec4(0, 0, 0.5, 1), true);

    while (!glfwWindowShouldClose(window))
    {
        glfwPollEvents();
        glClear(GL_COLOR_BUFFER_BIT);
        ball1.Draw();
        glfwSwapBuffers(window);
    }
    glfwDestroyWindow(window);
    glfwTerminate();

    return 0;
}

经过多次尝试,我终于找到了问题所在:

在 GLObjects.h 文件中,我将一些变量声明为静态变量,因为如果我不这样做,它会产生一些多重定义错误。将它们声明为静态解决了这个问题,但创建了另一个问题,因为现在每个文件都有自己的这些变量副本。

因此,为了解决这个问题,我所做的是将这些变量声明为 extern,然后在 GLObject.cpp 文件中定义它们。