Correct resize and safer pointers

This commit is contained in:
Corentin 2021-07-07 15:57:26 +09:00
commit 3b2be83590
9 changed files with 193 additions and 81 deletions

View file

@ -26,10 +26,11 @@ public:
~GlApplication(); ~GlApplication();
void run(); void run();
std::weak_ptr<GlWindow> create_window(int width, int height, const std::string& title); std::shared_ptr<GlWindow> create_window(int width, int height, const std::string& title);
std::shared_ptr<GlWindow> get_window(size_t index) const;
private: private:
static bool application_created; static GlApplication* application_pointer;
}; };
class GlComponent; class GlComponent;
@ -46,22 +47,28 @@ public:
GlWindow(GlWindow&&) = delete; GlWindow(GlWindow&&) = delete;
~GlWindow(); ~GlWindow();
std::weak_ptr<GlComponent> create_component( std::shared_ptr<GlComponent> 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> x, const std::variant<int, float> y, const std::variant<int, float> width,
const std::variant<int, float> height); const std::variant<int, float> height);
private: private:
const GlApplication& app; GlApplication* app;
int width; int width;
int height; int height;
bool need_resize_refresh;
size_t index;
bool initialized;
GLFWwindow* glfw_window; GLFWwindow* glfw_window;
GLuint gl_program; GLuint gl_program;
GlWindow(const GlApplication& app, int width, int height, const std::string& title); GlWindow(GlApplication* app, size_t index, int width, int height, const std::string& title);
void init();
void deinit();
void draw(); void draw();
static void glfw_resize_callback(GLFWwindow* window, int width, int height); static void glfw_resize_callback(GLFWwindow* window, int width, int height);

View file

@ -18,16 +18,16 @@ public:
GlComponent(GlComponent&&) = delete; GlComponent(GlComponent&&) = delete;
~GlComponent(); ~GlComponent();
void render(); void set_background_color(float r, float g, float b, float a = 0.0f);
private: private:
// std::weak_ptr<GlWindow> window; std::shared_ptr<GlWindow> window;
GlWindow* window;
std::variant<int, float> position_x; std::variant<int, float> position_x;
std::variant<int, float> position_y; std::variant<int, float> position_y;
std::variant<int, float> size_width; std::variant<int, float> size_width;
std::variant<int, float> size_height; std::variant<int, float> size_height;
bool coord_all_relative;
std::array<float, 4> background_color; std::array<float, 4> background_color;
@ -38,11 +38,14 @@ private:
GLuint gl_ebo; GLuint gl_ebo;
GlComponent( GlComponent(
GlWindow* window, const std::variant<int, float> x, const std::variant<int, float> y, std::shared_ptr<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); const std::variant<int, float> width, const std::variant<int, float> height);
void init(); void init();
void set_vbo_data();
void deinit(); void deinit();
void render();
void on_resize();
}; };
} // namespace uui } // namespace uui

19
make.py
View file

@ -4,7 +4,7 @@ import os
from pathlib import Path from pathlib import Path
import shutil import shutil
from umake import make from umake import get_hash, make
class Config: class Config:
@ -31,17 +31,32 @@ class Config:
def main(): def main():
def pre_compile(): def pre_compile():
<<<<<<< HEAD
=======
# Compiling vulkan shaders
# for shader_path in (
# list((Config.SOURCE_DIR / 'uui' / 'vulkan').rglob('*.vert'))
# + list((Config.SOURCE_DIR / 'uui' / 'vulkan').rglob('*.frag'))):
# out_path = Config.BIN_DIR / shader_path.relative_to(Config.SOURCE_DIR)
# if not out_path.parent.exists():
# out_path.parent.mkdir(parents=True)
# if subprocess.run(['glslc', str(shader_path), '-o', str(out_path) + '.spv']).returncode != 0:
# print(f'Error while compiling shader {shader_path}')
# return
>>>>>>> 675cbbf (Correct resize and safer pointers)
# Copying OpenGL shaders # Copying OpenGL shaders
src_opengl_shader_path = Config.SOURCE_DIR / 'uui' / 'opengl' / 'shaders' src_opengl_shader_path = Config.SOURCE_DIR / 'uui' / 'opengl' / 'shaders'
for shader_path in ( for shader_path in (
list(src_opengl_shader_path.rglob('*.vert')) list(src_opengl_shader_path.rglob('*.vert'))
+ list(src_opengl_shader_path.rglob('*.frag'))): + list(src_opengl_shader_path.rglob('*.frag'))):
out_path = Config.BIN_DIR / shader_path.relative_to(Config.SOURCE_DIR) out_path = Config.BIN_DIR / shader_path.relative_to(Config.SOURCE_DIR)
if out_path.exists() and get_hash(shader_path) == get_hash(out_path):
continue
if not out_path.parent.exists(): if not out_path.parent.exists():
out_path.parent.mkdir(parents=True) out_path.parent.mkdir(parents=True)
shutil.copy(shader_path, out_path) shutil.copy(shader_path, out_path)
# Config.PRE_COMPILE_FUNCTION = pre_compile Config.PRE_COMPILE_FUNCTION = pre_compile
make(Config) make(Config)

View file

@ -7,24 +7,28 @@ using namespace std;
int main() int main()
{ {
cout << "Example Staring" << endl;
try try
{ {
cout << "Starting example 1" << endl;
{ {
uui::GlApplication app; uui::GlApplication app;
// uui::GlApplication app2; // exception : application already created // uui::GlApplication app2; // exception : application already created
auto window_1 = app.create_window(800, 600, "OpenGl!"); auto window = app.create_window(800, 600, "OpenGl!");
window_1.lock()->create_component(0, 1, 0.5f, 50); auto comp = window->create_component(0, 100, 0.5f, 50);
comp->set_background_color(0.8f, 0.1f, 0.5f);
app.run(); app.run();
} }
cout << "\nStarting example 2" << endl;
{ {
uui::GlApplication app; uui::GlApplication app;
auto window_1 = app.create_window(800, 600, "OpenGl!"); auto window_1 = app.create_window(800, 600, "OpenGl!");
window_1.lock()->create_component(0.25f, 0.25f, 0.5f, 0.5f); auto comp = window_1->create_component(0.25f, 0.25f, 0.5f, 0.5f);
window_1.lock()->create_component(0.75f, 0.75f, 0.25f, 0.25f); comp->set_background_color(0.8f, 0.1f, 0.5f);
comp = window_1->create_component(0.75f, 0.75f, 0.25f, 0.25f);
comp->set_background_color(0.2f, 0.1f, 0.5f);
auto window_2 = app.create_window(600, 600, "OpenGL 2!"); auto window_2 = app.create_window(600, 600, "OpenGL 2!");
window_2.lock()->create_component(0, 0.5f, 100, 0.5f); comp = window_2->create_component(0, 0.5f, 100, 0.5f);
comp->set_background_color(0.2f, 0.5f, 0.3f);
app.run(); app.run();
} }
} }

View file

@ -3,11 +3,11 @@
#include <chrono> #include <chrono>
#include <iostream> #include <iostream>
bool uui::GlApplication::application_created = false; uui::GlApplication* uui::GlApplication::application_pointer = nullptr;
uui::GlApplication::GlApplication() uui::GlApplication::GlApplication()
{ {
if(application_created) if(application_pointer != nullptr)
throw std::runtime_error("GlApplication error: the application already created"); throw std::runtime_error("GlApplication error: the application already created");
if constexpr(debug_mode) if constexpr(debug_mode)
std::cout << "Creating the GlApplication in debug mode" << std::endl; std::cout << "Creating the GlApplication in debug mode" << std::endl;
@ -23,7 +23,7 @@ uui::GlApplication::GlApplication()
if constexpr(uui::GlApplication::debug_mode) if constexpr(uui::GlApplication::debug_mode)
glfwWindowHint(GLFW_OPENGL_DEBUG_CONTEXT, true); glfwWindowHint(GLFW_OPENGL_DEBUG_CONTEXT, true);
application_created = true; application_pointer = this;
} }
uui::GlApplication::~GlApplication() uui::GlApplication::~GlApplication()
@ -31,7 +31,7 @@ uui::GlApplication::~GlApplication()
std::cout << "Destroying the GlApplication" << std::endl; std::cout << "Destroying the GlApplication" << std::endl;
windows.clear(); windows.clear();
glfwTerminate(); glfwTerminate();
application_created = false; application_pointer = nullptr;
} }
void uui::GlApplication::run() void uui::GlApplication::run()
@ -67,6 +67,7 @@ void uui::GlApplication::run()
glfwMakeContextCurrent((*(windows.end() - 2))->glfw_window); glfwMakeContextCurrent((*(windows.end() - 2))->glfw_window);
glfwSwapInterval(1); glfwSwapInterval(1);
} }
window->deinit();
windows.erase(it); windows.erase(it);
it -= 1; it -= 1;
} }
@ -78,9 +79,10 @@ void uui::GlApplication::run()
std::cout << "Ending the GlApplication" << std::endl; std::cout << "Ending the GlApplication" << std::endl;
} }
std::weak_ptr<uui::GlWindow> uui::GlApplication::create_window(int width, int height, const std::string& title) std::shared_ptr<uui::GlWindow> uui::GlApplication::create_window(int width, int height, const std::string& title)
{ {
std::shared_ptr<uui::GlWindow> window(new uui::GlWindow(*this, width, height, title)); std::shared_ptr<uui::GlWindow> window(new uui::GlWindow(this, windows.size(), width, height, title));
window->init();
windows.push_back(window); windows.push_back(window);
glfwSwapInterval(1); glfwSwapInterval(1);
if(windows.size() > 1) if(windows.size() > 1)
@ -90,3 +92,10 @@ std::weak_ptr<uui::GlWindow> uui::GlApplication::create_window(int width, int he
} }
return window; return window;
} }
std::shared_ptr<uui::GlWindow> uui::GlApplication::get_window(size_t index) const
{
if(index > windows.size())
throw std::runtime_error("Application doesn't have window at given index");
return windows[index];
}

View file

@ -6,21 +6,27 @@
#include "uui/opengl/gl_utils.hpp" #include "uui/opengl/gl_utils.hpp"
uui::GlComponent::GlComponent( uui::GlComponent::GlComponent(
GlWindow* window, const std::variant<int, float> x, const std::variant<int, float> y, std::shared_ptr<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): const std::variant<int, float> width, const std::variant<int, float> height):
window(window), window(window),
position_x(x), position_y(y), size_width(width), size_height(height), initialized(false) position_x(x), position_y(y), size_width(width), size_height(height), initialized(false)
{ {
std::cout << "Creating a GlBox" << std::endl; std::cout << "Creating a GlBox" << std::endl;
auto zero_to_float = [](std::variant<int, float>& value) { coord_all_relative = true;
if(value.index() == 0 && std::get<0>(value) == 0) auto parse_coords = [&](std::variant<int, float>& value) {
value = 0.0f; if(value.index() == 0)
{
if(std::get<0>(value) == 0)
value = 0.0f;
else
coord_all_relative = false;
}
}; };
zero_to_float(position_x); parse_coords(position_x);
zero_to_float(position_y); parse_coords(position_y);
zero_to_float(size_width); parse_coords(size_width);
zero_to_float(size_height); parse_coords(size_height);
background_color = {0.0f, 0.0f, 0.0f, 0.0f}; background_color = {0.0f, 0.0f, 0.0f, 0.0f};
} }
@ -32,6 +38,14 @@ uui::GlComponent::~GlComponent()
deinit(); deinit();
} }
void uui::GlComponent::set_background_color(float r, float g, float b, float a)
{
background_color = {r, g, b, a};
glBindVertexArray(gl_vao);
set_vbo_data();
glBindVertexArray(0); // Optional : for safety
}
void uui::GlComponent::init() void uui::GlComponent::init()
{ {
if(initialized) if(initialized)
@ -45,44 +59,7 @@ void uui::GlComponent::init()
if constexpr(uui::GlApplication::debug_mode) if constexpr(uui::GlApplication::debug_mode)
_glCheckError(); _glCheckError();
{ set_vbo_data();
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[] = { unsigned int indices[] = {
0, 1, 3, // first triangle 0, 1, 3, // first triangle
@ -102,6 +79,55 @@ void uui::GlComponent::init()
initialized = true; initialized = true;
} }
void uui::GlComponent::set_vbo_data()
{
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, background_color[0] , background_color[1], background_color[2], background_color[3], // top right
x_max, y_max, 0.0f, background_color[0] , background_color[1], background_color[2], background_color[3], // bottom right
x_min, y_max, 0.0f, background_color[0] , background_color[1], background_color[2], background_color[3], // bottom left
x_min, y_min, 0.0f, background_color[0] , background_color[1], background_color[2], background_color[3] // 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,
7 * sizeof(float), // stride
(void*)0 // offset
);
glEnableVertexAttribArray(0);
glVertexAttribPointer(
1, // index
3, // size
GL_FLOAT, // type
GL_FALSE, // enable normalization,
7 * sizeof(float), // stride
(void*)(3 * sizeof(float)) // offset
);
glEnableVertexAttribArray(1);
}
void uui::GlComponent::deinit() void uui::GlComponent::deinit()
{ {
if(!initialized) if(!initialized)
@ -120,3 +146,13 @@ void uui::GlComponent::render()
if constexpr(uui::GlApplication::debug_mode) if constexpr(uui::GlApplication::debug_mode)
_glCheckError(); _glCheckError();
} }
void uui::GlComponent::on_resize()
{
if(!coord_all_relative)
{
glBindVertexArray(gl_vao);
set_vbo_data();
glBindVertexArray(0); // Optional : for safety
}
}

View file

@ -2,7 +2,9 @@
out vec4 FragColor; out vec4 FragColor;
in vec4 backgroundColor;
void main() void main()
{ {
FragColor = vec4(1.0f, 0.5f, 0.2f, 1.0f); FragColor = backgroundColor;
} }

View file

@ -1,8 +1,12 @@
#version 460 core #version 460 core
layout (location = 0) in vec3 aPos; layout (location = 0) in vec3 vPos;
layout (location = 1) in vec4 vBackgroundColor;
out vec4 backgroundColor;
void main() void main()
{ {
gl_Position = vec4(aPos.x, aPos.y, aPos.z, 1.0); gl_Position = vec4(vPos.x, vPos.y, vPos.z, 1.0);
backgroundColor = vBackgroundColor;
} }

View file

@ -55,9 +55,10 @@ void uui::GlWindow::glfw_resize_callback(GLFWwindow* window, int width, int heig
{ {
glfwMakeContextCurrent(window); glfwMakeContextCurrent(window);
auto gl_window = reinterpret_cast<uui::GlWindow*>(glfwGetWindowUserPointer(window)); auto gl_window = reinterpret_cast<uui::GlWindow*>(glfwGetWindowUserPointer(window));
glViewport(0, 0, width, height);
gl_window->width = width; gl_window->width = width;
gl_window->height = height; gl_window->height = height;
glViewport(0, 0, width, height); gl_window->need_resize_refresh = true;
} }
static void glfw_key_callback(GLFWwindow* window, int key, int scancode, int action, int mods) static void glfw_key_callback(GLFWwindow* window, int key, int scancode, int action, int mods)
@ -66,11 +67,27 @@ static void glfw_key_callback(GLFWwindow* window, int key, int scancode, int act
glfwSetWindowShouldClose(window, true); glfwSetWindowShouldClose(window, true);
} }
uui::GlWindow::GlWindow(const uui::GlApplication& app, int width, int height, const std::string& title): uui::GlWindow::GlWindow(uui::GlApplication* app, size_t index, int width, int height, const std::string& title):
app(app), width(width), height(height) app(app), width(width), height(height), need_resize_refresh(false), index(index), initialized(false)
{ {
std::cout << "Creating a GlWindow" << std::endl; std::cout << "Creating a GlWindow" << std::endl;
this->title = title; this->title = title;
}
uui::GlWindow::~GlWindow()
{
std::cout << "Closing a GlWindow" << std::endl;
if(initialized)
{
std::cout << "Destructor-deinit a GlWindow" << std::endl;
deinit();
}
}
void uui::GlWindow::init()
{
if(initialized)
throw std::runtime_error("GlWindow error : calling init while already initialized");
glfw_window = glfwCreateWindow(width, height, title.c_str(), NULL, NULL); glfw_window = glfwCreateWindow(width, height, title.c_str(), NULL, NULL);
if(glfw_window == NULL) if(glfw_window == NULL)
@ -161,15 +178,23 @@ uui::GlWindow::GlWindow(const uui::GlApplication& app, int width, int height, co
} }
glDeleteShader(vertex_shader); glDeleteShader(vertex_shader);
glDeleteShader(fragment_shader); glDeleteShader(fragment_shader);
initialized = true;
} }
uui::GlWindow::~GlWindow() void uui::GlWindow::deinit()
{ {
std::cout << "Closing a GlWindow" << std::endl; if(!initialized)
throw std::runtime_error("GlWindow error : calling deinit while not initialized");
std::cout << "Deinit a GlWindow" << std::endl;
glfwMakeContextCurrent(glfw_window); glfwMakeContextCurrent(glfw_window);
glDeleteProgram(gl_program); glDeleteProgram(gl_program);
for(auto& component: components) component->deinit();
components.clear(); components.clear();
glfwDestroyWindow(glfw_window); glfwDestroyWindow(glfw_window);
initialized = false;
} }
void uui::GlWindow::draw() void uui::GlWindow::draw()
@ -179,18 +204,25 @@ void uui::GlWindow::draw()
glClear(GL_COLOR_BUFFER_BIT); glClear(GL_COLOR_BUFFER_BIT);
glUseProgram(gl_program); glUseProgram(gl_program);
if(need_resize_refresh)
{
for(auto& component: components) component->on_resize();
need_resize_refresh = false;
}
for(auto& component: components) component->render(); for(auto& component: components) component->render();
glfwSwapBuffers(glfw_window); glfwSwapBuffers(glfw_window);
} }
std::weak_ptr<uui::GlComponent> uui::GlWindow::create_component( std::shared_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> x, const std::variant<int, float> y, const std::variant<int, float> width,
const std::variant<int, float> height) const std::variant<int, float> height)
{ {
if(!initialized)
throw std::runtime_error("GlWindow error : cannot create component while not initialized");
glfwMakeContextCurrent(glfw_window); glfwMakeContextCurrent(glfw_window);
// std::shared_ptr<uui::GlWindow> self_ptr(this); std::shared_ptr<uui::GlComponent> component(new uui::GlComponent(app->get_window(index), x, y, width, height));
std::shared_ptr<uui::GlComponent> component(new uui::GlComponent(this, x, y, width, height));
component->init(); component->init();
components.push_back(component); components.push_back(component);
return component; return component;