Box implementation, improved window API

This commit is contained in:
Corentin 2021-07-06 17:33:29 +09:00
commit 988b0bdbcd
12 changed files with 224 additions and 27 deletions

View file

@ -1,13 +1,16 @@
#pragma once #pragma once
#include <memory>
#include <string> #include <string>
#include "window.hpp"
namespace uui namespace uui
{ {
class Application class Application
{ {
public: public:
virtual void run() = 0; virtual void run() = 0;
virtual void add_window(int width, int height, const std::string& title) = 0; virtual std::weak_ptr<Window> add_window(int width, int height, const std::string& title) = 0;
}; };
} // namespace uui } // namespace uui

12
include/uui/component.hpp Normal file
View file

@ -0,0 +1,12 @@
#pragma once
namespace uui
{
class Component
{
public:
virtual void render() = 0;
};
}

View file

@ -16,14 +16,18 @@ class GlApplication: public Application
friend class GlWindow; friend class GlWindow;
public: public:
#ifdef DEBUG
constexpr static bool debug_mode = true;
#else
constexpr static bool debug_mode = false;
#endif
std::vector<std::shared_ptr<GlWindow>> windows;
GlApplication(); GlApplication();
~GlApplication(); ~GlApplication();
void run(); void run();
void add_window(int width, int height, const std::string& title); std::weak_ptr<Window> add_window(int width, int height, const std::string& title);
private:
std::vector<std::unique_ptr<GlWindow>> windows;
}; };
class GlWindow: public Window class GlWindow: public Window
@ -34,6 +38,8 @@ public:
GlWindow(const GlApplication& app, int width, int height, const std::string& title); GlWindow(const GlApplication& app, int width, int height, const std::string& title);
~GlWindow(); ~GlWindow();
void add_box();
private: private:
const GlApplication& app; const GlApplication& app;

View file

@ -0,0 +1,22 @@
#pragma once
#include "graphic_context.hpp"
#include "uui/component.hpp"
namespace uui
{
class GlBox: public Component
{
public:
GlBox();
~GlBox();
void render();
private:
GLuint gl_vbo;
GLuint gl_vao;
GLuint gl_program;
};
} // namespace uui

View file

@ -1,22 +1,25 @@
#pragma once #pragma once
#include <iostream>
#include <memory> #include <memory>
#include <mutex>
#include <optional>
#include <string> #include <string>
#include <thread>
#include <vector> #include <vector>
#include "graphic_context.hpp" #include "graphic_context.hpp"
#include "uui/component.hpp"
namespace uui
{
class Window class Window
{ {
public: public:
std::string title; std::string title;
std::vector<std::unique_ptr<Component>> components;
virtual void draw() = 0; virtual void add_box() = 0;
protected: protected:
GLFWwindow* glfw_window; GLFWwindow* glfw_window;
virtual void draw() = 0;
}; };
} // namespace uui

15
make.py
View file

@ -2,6 +2,7 @@
import os import os
from pathlib import Path from pathlib import Path
import shutil
from umake import make from umake import make
@ -30,14 +31,16 @@ class Config:
def main(): def main():
def pre_compile(): def pre_compile():
# Compiling fragment shaders # Copying OpenGL shaders
for frag_path in Config.SOURCE_DIR.rglob('*.frag'): src_opengl_shader_path = Config.SOURCE_DIR / 'uui' / 'opengl' / 'shaders'
out_path = (Config.BIN_DIR / frag_path.relative_to(Config.SOURCE_DIR)) for shader_path in (
list(src_opengl_shader_path.rglob('*.vert'))
+ list(src_opengl_shader_path.rglob('*.frag'))):
out_path = (Config.BIN_DIR / shader_path.relative_to(Config.SOURCE_DIR))
if not out_path.parent.exists(): if not out_path.parent.exists():
out_path.parent.mkdir(parents=True) out_path.parent.mkdir(parents=True)
if subprocess.run(['glslc', str(frag_path), '-o', str(out_path) + '.spv']).returncode != 0: shutil.copy(shader_path, out_path)
print(f'Error while compiling fragment shader {frag_path}')
return
Config.PRE_COMPILE_FUNCTION = pre_compile Config.PRE_COMPILE_FUNCTION = pre_compile
make(Config) make(Config)

View file

@ -11,8 +11,10 @@ int main()
try try
{ {
uui::GlApplication app; uui::GlApplication app;
app.add_window(800, 600, "Vulkan!"); auto window_1 = app.add_window(800, 600, "OpenGl!");
app.add_window(600, 600, "Vulkan 2!"); window_1.lock()->add_box();
auto window_2 = app.add_window(600, 600, "OpenGL 2!");
window_2.lock()->add_box();
app.run(); app.run();
} }
catch(const std::exception& error) catch(const std::exception& error)

View file

@ -1,8 +1,11 @@
#include "uui/opengl/application.hpp" #include "uui/opengl/application.hpp"
#include <chrono>
#include <iostream>
uui::GlApplication::GlApplication() uui::GlApplication::GlApplication()
{ {
std::cout << "Creating the GlApplication" << std::endl;
// Init GLFW // Init GLFW
glfwInit(); glfwInit();
// Set all the required options for GLFW // Set all the required options for GLFW
@ -13,12 +16,14 @@ uui::GlApplication::GlApplication()
uui::GlApplication::~GlApplication() uui::GlApplication::~GlApplication()
{ {
std::cout << "Destroying the GlApplication" << std::endl;
windows.clear();
glfwTerminate(); glfwTerminate();
} }
void uui::GlApplication::run() void uui::GlApplication::run()
{ {
std::cout << "Starting the Application" << std::endl; std::cout << "Starting the GlApplication" << std::endl;
auto start_time = std::chrono::high_resolution_clock::now(); auto start_time = std::chrono::high_resolution_clock::now();
auto end_time = start_time; auto end_time = start_time;
@ -57,10 +62,10 @@ void uui::GlApplication::run()
} }
frame_count += 1; frame_count += 1;
} }
std::cout << "Ending the Application" << std::endl; std::cout << "Ending the GlApplication" << std::endl;
} }
void uui::GlApplication::add_window(int width, int height, const std::string& title) std::weak_ptr<uui::Window> uui::GlApplication::add_window(int width, int height, const std::string& title)
{ {
windows.push_back(std::make_unique<GlWindow>(*this, width, height, title)); windows.push_back(std::make_unique<GlWindow>(*this, width, height, title));
glfwSwapInterval(1); glfwSwapInterval(1);
@ -69,4 +74,5 @@ void uui::GlApplication::add_window(int width, int height, const std::string& ti
glfwMakeContextCurrent((*(windows.end() - 2))->glfw_window); glfwMakeContextCurrent((*(windows.end() - 2))->glfw_window);
glfwSwapInterval(0); glfwSwapInterval(0);
} }
return windows.back();
} }

114
src/uui/opengl/box.cpp Normal file
View file

@ -0,0 +1,114 @@
#include "uui/opengl/box.hpp"
#include <iostream>
#include "uui/opengl/application.hpp"
#include "uui/shader.hpp"
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_code = vertex_src.data();
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 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_code = fragment_src.data();
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 error : " << info << std::endl;
}
}
}
// Creating shader program
gl_program = glCreateProgram();
glAttachShader(gl_program, vertex_shader);
glAttachShader(gl_program, fragment_shader);
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);
// clang-format off
float vertices[] = {
-0.5f, -0.5f, 0.0f,
0.5f, -0.5f, 0.0f,
0.0f, 0.5f, 0.0f
};
// clang-format on
glGenVertexArrays(1, &gl_vao);
glGenBuffers(1, &gl_vbo);
// bind the Vertex Array Object first, then bind and set vertex buffer(s), and then configure vertex attributes(s).
glBindVertexArray(gl_vao);
glBindBuffer(GL_ARRAY_BUFFER, gl_vbo);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
glVertexAttribPointer(
0, // index
3, // size
GL_FLOAT, // type
GL_FALSE, // enable normalization,
3 * sizeof(float), // stride
nullptr // offset
);
glEnableVertexAttribArray(0);
// unbinding VBO/VAO
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
}
uui::GlBox::~GlBox()
{
std::cout << "Closing a GlBox" << std::endl;
glDeleteVertexArrays(1, &gl_vao);
glDeleteProgram(gl_program);
glDeleteBuffers(1, &gl_vbo);
}
void uui::GlBox::render()
{
glBindVertexArray(gl_vao);
glDrawArrays(GL_TRIANGLES, 0, 3);
glUseProgram(gl_program);
}

View file

@ -0,0 +1,7 @@
#version 460 core
out vec4 FragColor;
void main()
{
FragColor = vec4(1.0f, 0.5f, 0.2f, 1.0f);
}

View file

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

View file

@ -2,32 +2,43 @@
#include <iostream> #include <iostream>
#include "uui/opengl/box.hpp"
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)
{ {
std::cout << "Creating a Window" << std::endl; std::cout << "Creating a GlWindow" << std::endl;
this->title = title; this->title = title;
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)
throw std::runtime_error("GLWindow : failed to create GLFW window"); throw std::runtime_error("GLWindow : failed to create GLFW window");
glfwMakeContextCurrent(glfw_window); glfwMakeContextCurrent(glfw_window);
if(!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress)) if(!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress))
throw std::runtime_error("GLWindow : Failed to initialize OpenGL context"); throw std::runtime_error("GLWindow : Failed to initialize OpenGL context");
glViewport(0, 0, width, height);
} }
uui::GlWindow::~GlWindow() uui::GlWindow::~GlWindow()
{ {
std::cout << "Closing a Window" << std::endl; std::cout << "Closing a GlWindow" << std::endl;
glfwMakeContextCurrent(glfw_window); glfwMakeContextCurrent(glfw_window);
components.clear();
glfwDestroyWindow(glfw_window); glfwDestroyWindow(glfw_window);
} }
void uui::GlWindow::draw() void uui::GlWindow::draw()
{ {
glfwMakeContextCurrent(glfw_window); glfwMakeContextCurrent(glfw_window);
glClearColor(0.2f, 0.3f, 0.3f, 1.0f); glClearColor(0.1f, 0.1f, 0.1f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT); glClear(GL_COLOR_BUFFER_BIT);
for(auto& component: components) component->render();
glfwSwapBuffers(glfw_window); glfwSwapBuffers(glfw_window);
} }
void uui::GlWindow::add_box()
{
glfwMakeContextCurrent(glfw_window);
components.push_back(std::make_unique<GlBox>());
}