Remove inheritances, component implementation

This commit is contained in:
Corentin 2021-07-07 03:59:23 +09:00
commit 20835586ab
15 changed files with 375 additions and 229 deletions

View file

@ -1,6 +1,7 @@
#include <iostream>
#include "uui/opengl/application.hpp"
#include "uui/opengl/component.hpp"
using namespace std;
@ -13,16 +14,17 @@ int main()
{
uui::GlApplication app;
// uui::GlApplication app2; // exception : application already created
auto window_1 = app.add_window(800, 600, "OpenGl!");
window_1.lock()->add_box();
auto window_1 = app.create_window(800, 600, "OpenGl!");
window_1.lock()->create_component(0, 1, 0.5f, 50);
app.run();
}
{
uui::GlApplication app;
auto window_1 = app.add_window(800, 600, "OpenGl!");
window_1.lock()->add_box();
auto window_2 = app.add_window(600, 600, "OpenGL 2!");
window_2.lock()->add_box();
auto window_1 = app.create_window(800, 600, "OpenGl!");
window_1.lock()->create_component(0.25f, 0.25f, 0.5f, 0.5f);
window_1.lock()->create_component(0.75f, 0.75f, 0.25f, 0.25f);
auto window_2 = app.create_window(600, 600, "OpenGL 2!");
window_2.lock()->create_component(0, 0.5f, 100, 0.5f);
app.run();
}
}

View file

@ -3,6 +3,8 @@
#include <chrono>
#include <iostream>
bool uui::GlApplication::application_created = false;
uui::GlApplication::GlApplication()
{
if(application_created)
@ -76,14 +78,15 @@ void uui::GlApplication::run()
std::cout << "Ending the GlApplication" << std::endl;
}
std::weak_ptr<uui::Window> uui::GlApplication::add_window(int width, int height, const std::string& title)
std::weak_ptr<uui::GlWindow> uui::GlApplication::create_window(int width, int height, const std::string& title)
{
windows.push_back(std::make_unique<GlWindow>(*this, width, height, title));
std::shared_ptr<uui::GlWindow> window(new uui::GlWindow(*this, width, height, title));
windows.push_back(window);
glfwSwapInterval(1);
if(windows.size() > 1)
{
glfwMakeContextCurrent((*(windows.end() - 2))->glfw_window);
glfwSwapInterval(0);
}
return windows.back();
return window;
}

View file

@ -1,178 +0,0 @@
#include "uui/opengl/box.hpp"
#include <iostream>
#include "uui/opengl/application.hpp"
#include "uui/shader.hpp"
GLenum glCheckError_(const char* file, int line)
{
GLenum errorCode;
while((errorCode = glGetError()) != GL_NO_ERROR)
{
std::string error;
switch(errorCode)
{
case GL_INVALID_ENUM:
error = "INVALID_ENUM";
break;
case GL_INVALID_VALUE:
error = "INVALID_VALUE";
break;
case GL_INVALID_OPERATION:
error = "INVALID_OPERATION";
break;
case GL_STACK_OVERFLOW:
error = "STACK_OVERFLOW";
break;
case GL_STACK_UNDERFLOW:
error = "STACK_UNDERFLOW";
break;
case GL_OUT_OF_MEMORY:
error = "OUT_OF_MEMORY";
break;
case GL_INVALID_FRAMEBUFFER_OPERATION:
error = "INVALID_FRAMEBUFFER_OPERATION";
break;
}
std::cout << error << " | " << file << " (" << line << ")" << std::endl;
}
return errorCode;
}
#define glCheckError() glCheckError_(__FILE__, __LINE__)
uui::GlBox::GlBox()
{
std::cout << "Creating a GlBox" << std::endl;
// Vertex shader compilation
GLuint vertex_shader = glCreateShader(GL_VERTEX_SHADER);
{
auto vertex_src = readFile("bin/uui/opengl/shaders/main.vert");
auto vertex_str = std::string(vertex_src.begin(), vertex_src.end());
auto vertex_code = vertex_str.c_str();
glShaderSource(vertex_shader, 1, &vertex_code, NULL);
glCompileShader(vertex_shader);
if constexpr(uui::GlApplication::debug_mode)
{
int success;
char info[512];
glGetShaderiv(vertex_shader, GL_COMPILE_STATUS, &success);
if(!success)
{
glGetShaderInfoLog(vertex_shader, 512, NULL, info);
std::cout << "GlBox vertex shader creation error : " << info << std::endl;
}
}
}
// Fragment shader compilation
GLuint fragment_shader = glCreateShader(GL_FRAGMENT_SHADER);
{
auto fragment_src = readFile("bin/uui/opengl/shaders/main.frag");
auto fragment_str = std::string(fragment_src.begin(), fragment_src.end());
auto fragment_code = fragment_str.c_str();
glShaderSource(fragment_shader, 1, &fragment_code, NULL);
glCompileShader(fragment_shader);
if constexpr(uui::GlApplication::debug_mode)
{
int success;
char info[512];
glGetShaderiv(fragment_shader, GL_COMPILE_STATUS, &success);
if(!success)
{
glGetShaderInfoLog(fragment_shader, 512, NULL, info);
std::cout << "GlBox fragment shader creation error : " << info << std::endl;
}
}
}
// Creating shader program
gl_program = glCreateProgram();
glAttachShader(gl_program, vertex_shader);
if constexpr(uui::GlApplication::debug_mode)
glCheckError();
glAttachShader(gl_program, fragment_shader);
if constexpr(uui::GlApplication::debug_mode)
glCheckError();
glLinkProgram(gl_program);
if constexpr(uui::GlApplication::debug_mode)
{
int success;
char info[512];
glGetProgramiv(gl_program, GL_LINK_STATUS, &success);
if(!success)
{
glGetProgramInfoLog(gl_program, 512, NULL, info);
std::cout << "GlBox error : " << info << std::endl;
}
}
glDeleteShader(vertex_shader);
glDeleteShader(fragment_shader);
glGenVertexArrays(1, &gl_vao);
glGenBuffers(1, &gl_vbo);
glGenBuffers(1, &gl_ebo);
// bind the Vertex Array Object first, then bind and set vertex buffer(s), and then configure vertex attributes(s).
glBindVertexArray(gl_vao);
if constexpr(uui::GlApplication::debug_mode)
glCheckError();
// clang-format off
float vertices[] = {
0.5f, 0.5f, 0.0f, // top right
0.5f, -0.5f, 0.0f, // bottom right
-0.5f, -0.5f, 0.0f, // bottom left
-0.5f, 0.5f, 0.0f // top left
};
// clang-format on
glBindBuffer(GL_ARRAY_BUFFER, gl_vbo);
if constexpr(uui::GlApplication::debug_mode)
glCheckError();
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
if constexpr(uui::GlApplication::debug_mode)
glCheckError();
glVertexAttribPointer(
0, // index
3, // size
GL_FLOAT, // type
GL_FALSE, // enable normalization,
3 * sizeof(float), // stride
(void*)0 // offset
);
glEnableVertexAttribArray(0);
unsigned int indices[] = {
0, 1, 3, // first triangle
1, 2, 3 // second triangle
};
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, gl_ebo);
if constexpr(uui::GlApplication::debug_mode)
glCheckError();
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
if constexpr(uui::GlApplication::debug_mode)
glCheckError();
// unbinding VBO/VAO
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
}
uui::GlBox::~GlBox()
{
std::cout << "Closing a GlBox" << std::endl;
glDeleteVertexArrays(1, &gl_vao);
glDeleteBuffers(1, &gl_vbo);
glDeleteBuffers(1, &gl_ebo);
glDeleteProgram(gl_program);
}
void uui::GlBox::render()
{
glUseProgram(gl_program);
glBindVertexArray(gl_vao);
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, (void*)0);
if constexpr(uui::GlApplication::debug_mode)
glCheckError();
}

View file

@ -0,0 +1,122 @@
#include "uui/opengl/component.hpp"
#include <iostream>
#include "uui/opengl/application.hpp"
#include "uui/opengl/gl_utils.hpp"
uui::GlComponent::GlComponent(
GlWindow* window, const std::variant<int, float> x, const std::variant<int, float> y,
const std::variant<int, float> width, const std::variant<int, float> height):
window(window),
position_x(x), position_y(y), size_width(width), size_height(height), initialized(false)
{
std::cout << "Creating a GlBox" << std::endl;
auto zero_to_float = [](std::variant<int, float>& value) {
if(value.index() == 0 && std::get<0>(value) == 0)
value = 0.0f;
};
zero_to_float(position_x);
zero_to_float(position_y);
zero_to_float(size_width);
zero_to_float(size_height);
background_color = {0.0f, 0.0f, 0.0f, 0.0f};
}
uui::GlComponent::~GlComponent()
{
std::cout << "Closing a GlBox" << std::endl;
if(initialized)
deinit();
}
void uui::GlComponent::init()
{
if(initialized)
throw std::runtime_error("GlBox error : calling init while already initialized");
glGenVertexArrays(1, &gl_vao);
glGenBuffers(1, &gl_vbo);
glGenBuffers(1, &gl_ebo);
// bind the Vertex Array Object first, then bind and set vertex buffer(s), and then configure vertex attributes(s).
glBindVertexArray(gl_vao);
if constexpr(uui::GlApplication::debug_mode)
_glCheckError();
{
float vert_x = position_x.index() == 1 ? std::get<1>(position_x)
: static_cast<float>(std::get<0>(position_x)) / static_cast<float>(window->width);
float vert_y = position_y.index() == 1 ? std::get<1>(position_y)
: static_cast<float>(std::get<0>(position_y)) / static_cast<float>(window->height);
float vert_w = size_width.index() == 1 ? std::get<1>(size_width)
: static_cast<float>(std::get<0>(size_width)) / static_cast<float>(window->width);
float vert_h = size_height.index() == 1 ? std::get<1>(size_height)
: static_cast<float>(std::get<0>(size_height)) / static_cast<float>(window->height);
float x_min = (2.0f * vert_x) - 1.0f;
float x_max = x_min + (2.0f * vert_w);
float y_min = (-2.0f * vert_y) + 1.0f;
float y_max = y_min - (2.0f * vert_h);
// clang-format off
float vertices[] = {
x_max, y_min, 0.0f, // top right
x_max, y_max, 0.0f, // bottom right
x_min, y_max, 0.0f, // bottom left
x_min, y_min, 0.0f // top left
};
// clang-format on
glBindBuffer(GL_ARRAY_BUFFER, gl_vbo);
if constexpr(uui::GlApplication::debug_mode)
_glCheckError();
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
if constexpr(uui::GlApplication::debug_mode)
_glCheckError();
}
glVertexAttribPointer(
0, // index
3, // size
GL_FLOAT, // type
GL_FALSE, // enable normalization,
3 * sizeof(float), // stride
(void*)0 // offset
);
glEnableVertexAttribArray(0);
unsigned int indices[] = {
0, 1, 3, // first triangle
1, 2, 3 // second triangle
};
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, gl_ebo);
if constexpr(uui::GlApplication::debug_mode)
_glCheckError();
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
if constexpr(uui::GlApplication::debug_mode)
_glCheckError();
// unbinding VBO/VAO
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
initialized = true;
}
void uui::GlComponent::deinit()
{
if(!initialized)
throw std::runtime_error("GlBox error : calling deinit while not initialized");
glDeleteVertexArrays(1, &gl_vao);
glDeleteBuffers(1, &gl_vbo);
glDeleteBuffers(1, &gl_ebo);
initialized = false;
}
void uui::GlComponent::render()
{
glBindVertexArray(gl_vao);
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, (void*)0);
if constexpr(uui::GlApplication::debug_mode)
_glCheckError();
}

View file

@ -0,0 +1,39 @@
#include "uui/opengl/gl_utils.hpp"
#include <iostream>
#include <string>
GLenum uui::gl::glCheckError(const char* file, int line)
{
GLenum errorCode;
while((errorCode = glGetError()) != GL_NO_ERROR)
{
std::string error;
switch(errorCode)
{
case GL_INVALID_ENUM:
error = "INVALID_ENUM";
break;
case GL_INVALID_VALUE:
error = "INVALID_VALUE";
break;
case GL_INVALID_OPERATION:
error = "INVALID_OPERATION";
break;
case GL_STACK_OVERFLOW:
error = "STACK_OVERFLOW";
break;
case GL_STACK_UNDERFLOW:
error = "STACK_UNDERFLOW";
break;
case GL_OUT_OF_MEMORY:
error = "OUT_OF_MEMORY";
break;
case GL_INVALID_FRAMEBUFFER_OPERATION:
error = "INVALID_FRAMEBUFFER_OPERATION";
break;
}
std::cout << error << " | " << file << " (" << line << ")" << std::endl;
}
return errorCode;
}

View file

@ -1,4 +1,5 @@
#version 460 core
out vec4 FragColor;
void main()

View file

@ -2,7 +2,9 @@
#include <iostream>
#include "uui/opengl/box.hpp"
#include "uui/opengl/component.hpp"
#include "uui/opengl/gl_utils.hpp"
#include "uui/shader.hpp"
static void APIENTRY
glDebugOutput(GLenum source, GLenum type, unsigned int id, GLenum severity, GLsizei length, const char* message, const void* userParam)
@ -49,9 +51,12 @@ glDebugOutput(GLenum source, GLenum type, unsigned int id, GLenum severity, GLsi
std::cout << std::endl;
}
static void glfw_resize_callback(GLFWwindow* window, int width, int height)
void uui::GlWindow::glfw_resize_callback(GLFWwindow* window, int width, int height)
{
glfwMakeContextCurrent(window);
auto gl_window = reinterpret_cast<uui::GlWindow*>(glfwGetWindowUserPointer(window));
gl_window->width = width;
gl_window->height = height;
glViewport(0, 0, width, height);
}
@ -61,7 +66,8 @@ static void glfw_key_callback(GLFWwindow* window, int key, int scancode, int act
glfwSetWindowShouldClose(window, true);
}
uui::GlWindow::GlWindow(const uui::GlApplication& app, int width, int height, const std::string& title): app(app)
uui::GlWindow::GlWindow(const uui::GlApplication& app, int width, int height, const std::string& title):
app(app), width(width), height(height)
{
std::cout << "Creating a GlWindow" << std::endl;
this->title = title;
@ -71,6 +77,7 @@ uui::GlWindow::GlWindow(const uui::GlApplication& app, int width, int height, co
throw std::runtime_error("GLWindow : failed to create GLFW window");
glfwMakeContextCurrent(glfw_window);
glfwSetWindowUserPointer(glfw_window, this);
glfwSetFramebufferSizeCallback(glfw_window, glfw_resize_callback);
glfwSetKeyCallback(glfw_window, glfw_key_callback);
@ -89,12 +96,78 @@ uui::GlWindow::GlWindow(const uui::GlApplication& app, int width, int height, co
glDebugMessageControl(GL_DONT_CARE, GL_DONT_CARE, GL_DONT_CARE, 0, nullptr, GL_TRUE);
}
}
// Vertex shader compilation
GLuint vertex_shader = glCreateShader(GL_VERTEX_SHADER);
{
auto vertex_src = readFile("bin/uui/opengl/shaders/main.vert");
auto vertex_str = std::string(vertex_src.begin(), vertex_src.end());
auto vertex_code = vertex_str.c_str();
glShaderSource(vertex_shader, 1, &vertex_code, NULL);
glCompileShader(vertex_shader);
if constexpr(uui::GlApplication::debug_mode)
{
int success;
char info[512];
glGetShaderiv(vertex_shader, GL_COMPILE_STATUS, &success);
if(!success)
{
glGetShaderInfoLog(vertex_shader, 512, NULL, info);
std::cout << "GlBox vertex shader creation error : " << info << std::endl;
}
}
}
// Fragment shader compilation
GLuint fragment_shader = glCreateShader(GL_FRAGMENT_SHADER);
{
auto fragment_src = readFile("bin/uui/opengl/shaders/main.frag");
auto fragment_str = std::string(fragment_src.begin(), fragment_src.end());
auto fragment_code = fragment_str.c_str();
glShaderSource(fragment_shader, 1, &fragment_code, NULL);
glCompileShader(fragment_shader);
if constexpr(uui::GlApplication::debug_mode)
{
int success;
char info[512];
glGetShaderiv(fragment_shader, GL_COMPILE_STATUS, &success);
if(!success)
{
glGetShaderInfoLog(fragment_shader, 512, NULL, info);
std::cout << "GlBox fragment shader creation error : " << info << std::endl;
}
}
}
// Creating shader program
gl_program = glCreateProgram();
glAttachShader(gl_program, vertex_shader);
if constexpr(uui::GlApplication::debug_mode)
_glCheckError();
glAttachShader(gl_program, fragment_shader);
if constexpr(uui::GlApplication::debug_mode)
_glCheckError();
glLinkProgram(gl_program);
if constexpr(uui::GlApplication::debug_mode)
{
int success;
char info[512];
glGetProgramiv(gl_program, GL_LINK_STATUS, &success);
if(!success)
{
glGetProgramInfoLog(gl_program, 512, NULL, info);
std::cout << "GlBox error : " << info << std::endl;
}
}
glDeleteShader(vertex_shader);
glDeleteShader(fragment_shader);
}
uui::GlWindow::~GlWindow()
{
std::cout << "Closing a GlWindow" << std::endl;
glfwMakeContextCurrent(glfw_window);
glDeleteProgram(gl_program);
components.clear();
glfwDestroyWindow(glfw_window);
}
@ -105,13 +178,20 @@ void uui::GlWindow::draw()
glClearColor(0.1f, 0.1f, 0.1f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
glUseProgram(gl_program);
for(auto& component: components) component->render();
glfwSwapBuffers(glfw_window);
}
void uui::GlWindow::add_box()
std::weak_ptr<uui::GlComponent> uui::GlWindow::create_component(
const std::variant<int, float> x, const std::variant<int, float> y, const std::variant<int, float> width,
const std::variant<int, float> height)
{
glfwMakeContextCurrent(glfw_window);
components.push_back(std::make_unique<GlBox>());
// std::shared_ptr<uui::GlWindow> self_ptr(this);
std::shared_ptr<uui::GlComponent> component(new uui::GlComponent(this, x, y, width, height));
component->init();
components.push_back(component);
return component;
}