diff --git a/assets/shaders/shape.frag b/assets/shaders/shape.frag new file mode 100644 index 0000000..63e8e10 --- /dev/null +++ b/assets/shaders/shape.frag @@ -0,0 +1,8 @@ +#version 330 core +out vec4 FragColor; + +uniform vec3 objectColor; + +void main() { + FragColor = vec4(objectColor, 1.0); +} diff --git a/assets/shaders/shape.vert b/assets/shaders/shape.vert new file mode 100644 index 0000000..e044e00 --- /dev/null +++ b/assets/shaders/shape.vert @@ -0,0 +1,8 @@ +#version 330 core +layout (location = 0) in vec2 aPos; + +uniform mat4 projection; + +void main() { + gl_Position = projection * vec4(aPos.x, aPos.y, 0.0, 1.0); +} diff --git a/client/CMakeLists.txt b/client/CMakeLists.txt index 9763995..9c3db6c 100644 --- a/client/CMakeLists.txt +++ b/client/CMakeLists.txt @@ -10,3 +10,5 @@ find_package(OpenGL REQUIRED) find_package(Freetype REQUIRED) target_link_libraries(bettolac PRIVATE bettola SDL3::SDL3 GLEW::glew OpenGL::GL Freetype::Freetype) + +target_include_directories(bettolac PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/src) diff --git a/client/src/gfx/shape_renderer.cpp b/client/src/gfx/shape_renderer.cpp new file mode 100644 index 0000000..1f36d85 --- /dev/null +++ b/client/src/gfx/shape_renderer.cpp @@ -0,0 +1,82 @@ +#include + +#include "shape_renderer.h" + +/* Yep, definately need a math lib, for now, this is just copy form txt_renderer + * TODO: Refactor to math lib. + */ +void ortho_proj(float* mat, float left, float right, float bottom, float top, + float near, float far) { + + mat[0] = 2.0f / (right - left); + mat[4] = 0.0f; + mat[8] = 0.0f; + mat[12] = -(right + left) / (right - left); + + mat[1] = 0.0f; + mat[5] = 2.0f / (top - bottom); + mat[9] = 0.0f; + mat[13] = -(top + bottom) / (top - bottom); + + mat[2] = 0.0f; + mat[6] = 0.0f; + mat[10] = -2.0f / (far - near); + mat[14] = -(far + near) / (far - near); + + mat[3] = 0.0f; + mat[7] = 0.0f; + mat[11] = 0.0f; + mat[15] = 1.0f; +} + +ShapeRenderer::ShapeRenderer(unsigned int screen_width, unsigned int screen_height) { + ortho_proj(_projection, 0.0f, (float)screen_width, 0.0f, (float)screen_height, -1.0f, 1.0f); + + /* Load shader. */ + _shape_shader = new Shader("assets/shaders/shape.vert", + "assets/shaders/shape.frag"); + _shape_shader->use(); + _shape_shader->set_mat4("projection", _projection); + + /* Configure VAO/VBO. */ + glGenVertexArrays(1, &_vao); + glGenBuffers(1, &_vbo); + glBindVertexArray(_vao); + glBindBuffer(GL_ARRAY_BUFFER, _vbo); + glBufferData(GL_ARRAY_BUFFER, sizeof(float) * 6 * 2, NULL, GL_DYNAMIC_DRAW); + glEnableVertexAttribArray(0); + glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(float), 0); + glBindBuffer(GL_ARRAY_BUFFER, 0); + glBindVertexArray(0); +} + +ShapeRenderer::~ShapeRenderer(void) { + delete _shape_shader; +} + +void ShapeRenderer::draw_rect(int x, int y, int width, int height, float color[3]) { + _shape_shader->use(); + _shape_shader->set_vec3("objectColor", color[0], color[1], color[2]); + + float x_f = (float)x; + float y_f = (float)y; + float w_f = (float)width; + float h_f = (float)height; + + /* This is ugly :) */ + float vertices[6][2] = { + { x_f, y_f + h_f }, + { x_f, y_f }, + { x_f + w_f, y_f }, + + { x_f, y_f + h_f }, + { x_f + w_f, y_f }, + {x_f + w_f, y_f + h_f } + }; + + glBindVertexArray(_vao); + glBindBuffer(GL_ARRAY_BUFFER, _vbo); + glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(vertices), vertices); + glDrawArrays(GL_TRIANGLES, 0, 6); + glBindVertexArray(0); +} diff --git a/client/src/gfx/shape_renderer.h b/client/src/gfx/shape_renderer.h new file mode 100644 index 0000000..eb0ec52 --- /dev/null +++ b/client/src/gfx/shape_renderer.h @@ -0,0 +1,16 @@ +#pragma once + +#include "shader.h" + +class ShapeRenderer { +public: + ShapeRenderer(unsigned int screen_width, unsigned int screen_height); + ~ShapeRenderer(void); + + void draw_rect(int x, int y, int width, int height, float color[3]); + +private: + Shader* _shape_shader; + unsigned int _vao, _vbo; + float _projection[16]; +}; diff --git a/client/src/main.cpp b/client/src/main.cpp index 08c4dcd..9531906 100644 --- a/client/src/main.cpp +++ b/client/src/main.cpp @@ -4,6 +4,8 @@ #include #include "terminal.h" +#include "gfx/shape_renderer.h" +#include "ui/ui_window.h" const int SCREEN_WIDTH = 1280; const int SCREEN_HEIGHT = 720; @@ -58,6 +60,12 @@ int main(int argc, char** argv) { TextRenderer* txt_render_instance = new TextRenderer(SCREEN_WIDTH, SCREEN_HEIGHT); txt_render_instance->load_font("assets/fonts/hack/Hack-Regular.ttf", 14); + /* Init shape renderer. */ + ShapeRenderer* shape_renderer_instance = new ShapeRenderer(SCREEN_WIDTH, SCREEN_HEIGHT); + + /* Create UI window. */ + UIWindow* test_window = new UIWindow("Terminal", 100, 100, 800, 500); + /* Create terminal. */ Terminal* term = new Terminal(); @@ -75,8 +83,7 @@ int main(int argc, char** argv) { glClearColor(0.1f, 0.1f, 0.1, 1.0f); glClear(GL_COLOR_BUFFER_BIT); - /* Render text. */ - float white[] = { 1.0f, 1.0f, 1.0f }; + test_window->render(shape_renderer_instance, txt_render_instance); term->render(txt_render_instance); /* It's really odd to call it SwapWindow now, rather than SwapBuffer. */ @@ -85,6 +92,8 @@ int main(int argc, char** argv) { /* Cleanup. */ delete term; + delete test_window; + delete shape_renderer_instance; delete txt_render_instance; SDL_GL_DestroyContext(context); SDL_DestroyWindow(window); diff --git a/client/src/ui/ui_window.cpp b/client/src/ui/ui_window.cpp new file mode 100644 index 0000000..41c71c8 --- /dev/null +++ b/client/src/ui/ui_window.cpp @@ -0,0 +1,32 @@ +#include "ui_window.h" +#include "gfx/shape_renderer.h" +#include "gfx/txt_renderer.h" + +UIWindow::UIWindow(const char* title, int x, int y, int width, int height) { + _title = title; + _x = x; + _y = y; + _width = width; + _height = height; +} + +void UIWindow::render(ShapeRenderer* shape_renderer, TextRenderer* txt_renderer) { + int title_bar_height = 30; + + /* Define colours. */ + float frame_color[] = { 0.2f, 0.2f, 0.25f }; + float title_bar_color[] = { 0.15f, 0.15f, 0.2f }; + float title_text_color[] = { 0.9f, 0.9f, 0.9f }; + + /* Draw main window frame/background. */ + shape_renderer->draw_rect(_x, _y, _width, _height, frame_color); + + /* Draw title bar. */ + shape_renderer->draw_rect(_x, _y+_height-title_bar_height, _width, + title_bar_height, title_bar_color); + + /* Draw title text. */ + txt_renderer->render_text(_title.c_str(), _x+5, _y+_height-title_bar_height+8, + 1.0f, title_text_color); +} + diff --git a/client/src/ui/ui_window.h b/client/src/ui/ui_window.h new file mode 100644 index 0000000..e36238b --- /dev/null +++ b/client/src/ui/ui_window.h @@ -0,0 +1,18 @@ +#pragma once + +#include + +#include "gfx/shape_renderer.h" +#include "gfx/txt_renderer.h" + +class UIWindow { +public: + UIWindow(const char* title, int x, int y, int width, int height); + + void render(ShapeRenderer* shape_renderer, TextRenderer* txt_renderer); + +private: + int _x, _y, _width, _height; + std::string _title; +}; +