OpenGL/GLFW C++ 程序不绘制任何东西
OpenGL/GLFW C++ program doesn't draw anything
所以,我制作了这个包含三个主要文件的程序:
- 一个 main.cpp 文件,其中包含程序本身
- 其中包含 GLObject class,它是每个 object
的基础 class
- 一个包含椭圆 class,派生的 object
当我实现 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), ¢er);
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 文件中定义它们。
所以,我制作了这个包含三个主要文件的程序:
- 一个 main.cpp 文件,其中包含程序本身
- 其中包含 GLObject class,它是每个 object 的基础 class
- 一个包含椭圆 class,派生的 object
当我实现 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), ¢er);
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 文件中定义它们。