diff --git a/CMakeLists.txt b/CMakeLists.txt index 8ed8e77..973a70a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,6 +1,6 @@ cmake_minimum_required(VERSION 3.25) -set(BLT_GRAPHICS_VERSION 0.13.14) +set(BLT_GRAPHICS_VERSION 0.13.15) set(BLT_GRAPHICS_TEST_VERSION 0.0.1) project(BLT_WITH_GRAPHICS VERSION ${BLT_GRAPHICS_VERSION}) diff --git a/include/blt/gfx/renderer/batch_2d_renderer.h b/include/blt/gfx/renderer/batch_2d_renderer.h index 8661ad7..86c97a2 100644 --- a/include/blt/gfx/renderer/batch_2d_renderer.h +++ b/include/blt/gfx/renderer/batch_2d_renderer.h @@ -107,40 +107,45 @@ namespace blt::gfx color4 blend; // should we outline this object? bool outline = false; + float outline_thickness = 1.25f; // what color should we outline with? color4 outline_color; render_info_t() = default; - static render_info_t make_info(const std::string_view texture, const color4 outline = disabled) + static render_info_t make_info(const std::string_view texture, const color4 outline = disabled, float outline_thickness = 1.25f) { render_info_t info{texture, empty, full}; if (outline != disabled) { info.outline = true; info.outline_color = outline; + info.outline_thickness = outline_thickness; } return info; } - static render_info_t make_info(const color4 color, const color4 outline = disabled) + static render_info_t make_info(const color4 color, const color4 outline = disabled, float outline_thickness = 1.25f) { render_info_t info{"", color, empty}; if (outline != disabled) { info.outline = true; info.outline_color = outline; + info.outline_thickness = outline_thickness; } return info; } - static render_info_t make_info(const std::string_view texture, const color4 color, const color4 blend, const color4 outline = disabled) + static render_info_t make_info(const std::string_view texture, const color4 color, const color4 blend, const color4 outline = disabled, + float outline_thickness = 1.25f) { render_info_t info{texture, color, blend}; if (outline != disabled) { info.outline = true; info.outline_color = outline; + info.outline_thickness = outline_thickness; } return info; } @@ -169,10 +174,10 @@ namespace blt::gfx using object_container = hashmap_t>>; private: - std::unique_ptr square_vao = nullptr; - std::unique_ptr line_vao = nullptr; - std::unique_ptr square_shader = nullptr; - std::unique_ptr point_shader = nullptr; + std::unique_ptr square_vao; + std::unique_ptr line_vao; + std::unique_ptr square_shader; + std::unique_ptr point_shader; resource_manager& resources; matrix_state_manager& state; // texture name -> draw info @@ -201,6 +206,10 @@ namespace blt::gfx // called after draw_objects() void post_reset(); + void draw_points(bool outlined, const f32 denominator); + void draw_lines(bool outlined, const f32 denominator); + void draw_rectangles(bool outlined, const f32 denominator); + void draw_objects(); inline void update_z_index(f32 z_index) diff --git a/libraries/BLT b/libraries/BLT index 9c0fc81..12169a7 160000 --- a/libraries/BLT +++ b/libraries/BLT @@ -1 +1 @@ -Subproject commit 9c0fc819690a99cbf8cdf923f1aeda22ff57ae9b +Subproject commit 12169a700195f23d5ebce54d0edb79bee4f8b0e1 diff --git a/libraries/imgui b/libraries/imgui index a1b0682..231cbee 160000 --- a/libraries/imgui +++ b/libraries/imgui @@ -1 +1 @@ -Subproject commit a1b06823fe2d964a62fda99385499b218cf5cea5 +Subproject commit 231cbee0fc4f59dbe5b8b853a11b08dc84e57c65 diff --git a/libraries/openal-soft b/libraries/openal-soft index 6675317..111397c 160000 --- a/libraries/openal-soft +++ b/libraries/openal-soft @@ -1 +1 @@ -Subproject commit 6675317107257c2cc16c947b359d557821d85bf2 +Subproject commit 111397c71a5f1c2c88e05da9c84edfdba2e472a4 diff --git a/src/blt/gfx/renderer/batch_2d_renderer.cpp b/src/blt/gfx/renderer/batch_2d_renderer.cpp index 3e0c7b0..ea8e959 100644 --- a/src/blt/gfx/renderer/batch_2d_renderer.cpp +++ b/src/blt/gfx/renderer/batch_2d_renderer.cpp @@ -187,34 +187,85 @@ namespace blt::gfx pre_reset(); const f32 denominator = 1.0f / (draw.z_max - draw.z_min); - square_shader->bind(); + glEnable(GL_STENCIL_TEST); + glClear(GL_STENCIL_BUFFER_BIT); + glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE); + glStencilMask(0xFF); + + glStencilFunc(GL_ALWAYS, 1, 0xFF); + draw_points(false, denominator); + glStencilFunc(GL_NOTEQUAL, 1, 0xFF); + glStencilMask(0x00); + glDisable(GL_DEPTH_TEST); + draw_points(true, denominator); + glEnable(GL_DEPTH_TEST); + + draw_rectangles(false, denominator); + draw_lines(false, denominator); + + glDisable(GL_STENCIL_TEST); + + post_reset(); + } + + void batch_renderer_2d::render_reset() + { + draw.z_min = std::numeric_limits::max(); + draw.z_max = std::numeric_limits::min(); + } + + void batch_renderer_2d::pre_reset() + { + draw.draw_count = 0; + } + + void batch_renderer_2d::post_reset() + { + + } + + void batch_renderer_2d::draw_points(const bool outlined, const f32 denominator) + { + point_shader->bind(); square_vao->bind(); - for (auto& [texture, objects] : draw.complex_rectangles) + for (auto& [texture, objects] : draw.complex_points) { // resource manager handles the check for empty string if (auto val = resources.get(texture)) val.value()->bind(); for (auto& [render_info, object] : objects) { - auto& [z_index, rect] = object; + auto& [z_index, point] = object; mat4x4 model; - model.translate(rect.pos.x(), rect.pos.y(), 0.0f); - model.scale(rect.size.x(), rect.size.y(), 1); - if (rect.rotation != 0) - model.rotateZ(toRadians(rect.rotation)); + model.translate(point.pos.x(), point.pos.y(), 0.0f); + if (outlined) + { + BLT_TRACE(render_info.outline_thickness); + model.scale(point.scale * render_info.outline_thickness, point.scale * render_info.outline_thickness, 1.0); + point_shader->setVec4("color", render_info.outline_color); + point_shader->setVec4("use_texture", blt::vec4{0,0,0,0}); + } else + { + model.scale(point.scale, point.scale, 1.0); + point_shader->setVec4("color", render_info.color); + point_shader->setVec4("use_texture", render_info.blend); + } + + + point_shader->setVec4("outline_color", render_info.outline_color); + point_shader->setFloat("z_index", (z_index - draw.z_min) * denominator); + point_shader->setMatrix("model", model); - square_shader->setVec4("color", render_info.color); - square_shader->setVec4("use_texture", render_info.blend); - square_shader->setVec4("outline_color", render_info.outline_color); - square_shader->setFloat("z_index", (z_index - draw.z_min) * denominator); - square_shader->setMatrix("model", model); glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0); draw.draw_count++; } objects.clear(); } - + } + + void batch_renderer_2d::draw_lines(bool outlined, const f32 denominator) + { mat4x4 empty_model; square_shader->setMatrix("model", empty_model); line_vao->bind(); @@ -267,50 +318,47 @@ namespace blt::gfx } objects.clear(); } - - point_shader->bind(); + } + + void batch_renderer_2d::draw_rectangles(bool outlined, const f32 denominator) + { + square_shader->bind(); square_vao->bind(); - for (auto& [texture, objects] : draw.complex_points) + for (auto& [texture, objects] : draw.complex_rectangles) { // resource manager handles the check for empty string if (auto val = resources.get(texture)) val.value()->bind(); for (auto& [render_info, object] : objects) { - auto& [z_index, point] = object; + auto& [z_index, rect] = object; mat4x4 model; - model.translate(point.pos.x(), point.pos.y(), 0.0f); - model.scale(point.scale, point.scale, 1.0); - - point_shader->setVec4("color", render_info.color); - point_shader->setVec4("use_texture", render_info.blend); - point_shader->setVec4("outline_color", render_info.outline_color); - point_shader->setFloat("z_index", (z_index - draw.z_min) * denominator); - point_shader->setMatrix("model", model); + if (outlined) { + auto nsx = rect.size.x() * render_info.outline_thickness; + auto nsy = rect.size.y() * render_info.outline_thickness; + auto ns = blt::vec2(nsx, nsy); + auto s = (rect.size - ns) / 2.0f; + model.translate(rect.pos - s); + model.scale(ns); + square_shader->setVec4("color", render_info.outline_color); + square_shader->setVec4("use_texture", {0,0,0,0}); + } else { + model.translate(rect.pos); + model.scale(rect.size); + square_shader->setVec4("color", render_info.color); + square_shader->setVec4("use_texture", render_info.blend); + } + if (rect.rotation != 0) + model.rotateZ(toRadians(rect.rotation)); + square_shader->setVec4("outline_color", render_info.outline_color); + square_shader->setFloat("z_index", (z_index - draw.z_min) * denominator); + square_shader->setMatrix("model", model); glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0); draw.draw_count++; } objects.clear(); } - - post_reset(); - } - - void batch_renderer_2d::render_reset() - { - draw.z_min = std::numeric_limits::max(); - draw.z_max = std::numeric_limits::min(); - } - - void batch_renderer_2d::pre_reset() - { - draw.draw_count = 0; - } - - void batch_renderer_2d::post_reset() - { - } }