Итак, я сделал эту программу, которая имеет три основных файла:
- файл main.cpp, который содержит саму программу
- , которая содержит класс GLObject, который являетсябазовый класс для каждого объекта
- , который содержит класс Ellipse, производный объект
Пока я реализовывал класс объекта (до того, как у меня был только класс эллипса, я решилсделать прямоугольник и найти несколько общих частей) Я столкнулся с проблемой, которая заключается в том, что на экране ничего не появляется.
GLObject.cpp содержит определения функций "GLObjectsInit ()", которая устанавливаетпрограмма рисования (draw_program) и все смещения и шаги матрицы блока uniorm, объявленные внутри этой программы.
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 файлы содержат только заголовки для включения и объявление некоторых статических переменных (объявляемых как статические, чтобы избежатьошибка определения наконечника):
#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;
Объект эллипса имеет несколько методов для изменения положения и масштаба объекта, а также имеет метод 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;
}