From e4584401ad865afb5a0fec8b7cab67794490a10d Mon Sep 17 00:00:00 2001 From: fschildt Date: Mon, 24 Nov 2025 19:55:42 +0100 Subject: rendering: refactor z-based sorting/drawing --- src/games/Game.hpp | 8 ++++++ src/games/minesweeper/Minesweeper.cpp | 16 +++++------- src/games/snake/Snake.cpp | 14 +++++----- src/games/tetris/Board.cpp | 8 +++--- src/games/tetris/Tetris.cpp | 48 +++++++++++++++++------------------ src/games/tetris/Tetris.hpp | 1 - src/games/tetris/Tetromino.cpp | 6 ++--- src/renderer/RSoftwareBackend.cpp | 11 ++++---- src/renderer/Renderer.cpp | 20 +++++++-------- src/renderer/Renderer.hpp | 23 ++++++++--------- 10 files changed, 79 insertions(+), 76 deletions(-) diff --git a/src/games/Game.hpp b/src/games/Game.hpp index a020012..aad3c1b 100644 --- a/src/games/Game.hpp +++ b/src/games/Game.hpp @@ -26,6 +26,14 @@ public: game_exit }; + enum ZLayer { + z_background = 0, + z_layer1, + z_layer2, + z_layer3, + z_text + }; + static std::unique_ptr Select(GameType type); diff --git a/src/games/minesweeper/Minesweeper.cpp b/src/games/minesweeper/Minesweeper.cpp index ae019c4..5cc3215 100644 --- a/src/games/minesweeper/Minesweeper.cpp +++ b/src/games/minesweeper/Minesweeper.cpp @@ -331,6 +331,7 @@ Minesweeper::ScreenPosToViewPos(V2F32 screen_pos) void Minesweeper::DrawBoard() { + uint32_t z = 1; Color covered_cell_color {0.6f, 0.6f, 0.6f}; Color uncovered_cell_color {0.4f, 0.4f, 0.4f}; Color mine_color {0.8f, 0.2f, 0.2f}; @@ -363,10 +364,9 @@ Minesweeper::DrawBoard() if (is_flagged) { - V3F32 flag_pos = { + V2F32 flag_pos = { cell_pos.x + flag_offset.x, cell_pos.y + flag_offset.y, - 1.0f }; Rectangle flag_rect = { flag_pos.x, @@ -374,15 +374,14 @@ Minesweeper::DrawBoard() flag_pos.x + flag_size.x, flag_pos.y + flag_size.y, }; - g_renderer.PushRectangle(flag_rect, flag_color, flag_pos.z); + g_renderer.PushRectangle(flag_rect, flag_color, z); } } else { if (is_mine) { - V3F32 mine_pos = { + V2F32 mine_pos = { cell_pos.x, cell_pos.y, - 1.0f }; Rectangle mine_rect = { mine_pos.x, @@ -390,21 +389,20 @@ Minesweeper::DrawBoard() mine_pos.x + m_cell_inner_size.x, mine_pos.y + m_cell_inner_size.y, }; - g_renderer.PushRectangle(mine_rect, mine_color, mine_pos.z); + g_renderer.PushRectangle(mine_rect, mine_color, z); } else { g_renderer.PushRectangle(cell_rect, uncovered_cell_color, 0.0f); - V3F32 mine_count_pos = { + V2F32 mine_count_pos = { cell_pos.x, cell_pos.y, - 1.0f }; int32_t mine_count = m_adjacent_mine_counts[y*m_grid_width + x]; if (mine_count > 0) { Color color = s_mine_count_colors[mine_count-1]; Glyph& glyph = m_font.GetGlyph('0' + (char32_t)mine_count); - g_renderer.PushAlphaBitmap(glyph.bitmap, mine_count_pos, color); + g_renderer.PushAlphaBitmap(glyph.bitmap, mine_count_pos, color, z); } } } diff --git a/src/games/snake/Snake.cpp b/src/games/snake/Snake.cpp index 2149730..81de4f0 100644 --- a/src/games/snake/Snake.cpp +++ b/src/games/snake/Snake.cpp @@ -297,7 +297,8 @@ Snake::Draw() /* draw map background */ - V3F32 map_world_pos = {map_x, map_y, 0.0f}; + uint32_t z = 1; + V3F32 map_world_pos = {map_x, map_y}; V2F32 map_world_dim = {map_view_width, map_view_height}; Rectangle map_world_rect = { map_world_pos.x, @@ -306,7 +307,7 @@ Snake::Draw() map_world_pos.y + map_world_dim.y }; Color bg_color = {0.0f, 0.0f, 0.0f, 1.0f}; - g_renderer.PushRectangle(map_world_rect, bg_color, map_world_pos.z); + g_renderer.PushRectangle(map_world_rect, bg_color, z); /* draw snake */ @@ -335,7 +336,7 @@ Snake::Draw() }; Color color = {0.3f, 0.3f, 0.3f, 1.0f}; - g_renderer.PushRectangle(world_rect, color, world_pos.z); + g_renderer.PushRectangle(world_rect, color, z); tail++; } tail = 0; @@ -363,16 +364,15 @@ Snake::Draw() }; Color color = {0.3f, 0.3f, 0.3f, 1.0f}; - g_renderer.PushRectangle(world_rect, color, world_pos.z); + g_renderer.PushRectangle(world_rect, color, z); tail++; } /* draw food */ - V3F32 pos = { + V2F32 pos = { map_world_pos.x + (float)m_food_position.x * tile_size + bodypart_offset, map_world_pos.y + (float)m_food_position.y * tile_size + bodypart_offset, - 1.0f }; V2F32 dim = {bodypart_size, bodypart_size}; Rectangle rect = { @@ -382,6 +382,6 @@ Snake::Draw() pos.y + dim.y }; Color color = {0.3f, 0.6f, 0.4f, 1.0f}; - g_renderer.PushRectangle(rect, color, pos.z); + g_renderer.PushRectangle(rect, color, z); } diff --git a/src/games/tetris/Board.cpp b/src/games/tetris/Board.cpp index 7f391b4..6188eb8 100644 --- a/src/games/tetris/Board.cpp +++ b/src/games/tetris/Board.cpp @@ -1,5 +1,6 @@ #include #include +#include #include void @@ -99,10 +100,9 @@ Board::Draw(int32_t level) // background - V3F32 bg_world_pos = { + V2F32 bg_world_pos = { board_world_pos.x, board_world_pos.y, - 0.0f }; V2F32 bg_world_dim = { tetromino_size_with_border * 10, @@ -115,7 +115,7 @@ Board::Draw(int32_t level) bg_world_pos.y + bg_world_dim.y, }; Color bg_color = {0.0f, 0.0f, 0.0f, 1.0f}; - g_renderer.PushRectangle(bg_world_rect, bg_color, bg_world_pos.z); + g_renderer.PushRectangle(bg_world_rect, bg_color, Game::z_layer1); // tetromino parts @@ -145,7 +145,7 @@ Board::Draw(int32_t level) Color color = Tetromino::GetColor(tetromino_id); - g_renderer.PushRectangle(world_rect, color, world_pos.z); + g_renderer.PushRectangle(world_rect, color, Game::z_layer1); } } } diff --git a/src/games/tetris/Tetris.cpp b/src/games/tetris/Tetris.cpp index d5c735d..ecc2c3a 100644 --- a/src/games/tetris/Tetris.cpp +++ b/src/games/tetris/Tetris.cpp @@ -271,7 +271,7 @@ void Tetris::DrawLineCounter() { std::u32string& text = m_frame_arena.Allocate(U"Lines: xxx"); - V3F32 pos = {0.5f, 2.6f, 4.0f}; + V2F32 pos = {0.5f, 2.6f}; Color color = {0.9f, 0.9f, 0.9f, 1.0f}; int line_count = std::min(m_line_counter, 999); @@ -284,19 +284,19 @@ Tetris::DrawLineCounter() line_count /= 10; - g_renderer.PushText(text, m_font, pos, color); + g_renderer.PushText(text, m_font, pos, color, z_text); pos.x += 0.2f; } void Tetris::DrawStatistics() { - V3F32 pos = {0.4f, 0.5f, s_text_z}; + V2F32 pos = {0.4f, 0.5f}; std::u32string& title_text = m_frame_arena.Allocate(U"Statistics"); - V3F32 title_pos = {pos.x + 0.02f, pos.y + 1.64f, pos.z}; - g_renderer.PushText(title_text, m_font, title_pos, s_text_color); + V2F32 title_pos = {pos.x + 0.02f, pos.y + 1.64f}; + g_renderer.PushText(title_text, m_font, title_pos, s_text_color, z_text); float yadvance = -0.2f; float tetrominoes_x0 = pos.x; @@ -329,7 +329,7 @@ Tetris::DrawStatistics() float counters_x0 = pos.x + 0.4f; float counters_y0 = pos.y + 0.05f - yadvance * (float)Tetromino::id_count; - V3F32 counters_pos = {counters_x0, counters_y0, s_text_z}; + V2F32 counters_pos = {counters_x0, counters_y0}; std::u32string& t_count = m_frame_arena.Allocate(int32_to_u32string(m_tetromino_counters[Tetromino::t_piece])); std::u32string& j_count = m_frame_arena.Allocate(int32_to_u32string(m_tetromino_counters[Tetromino::j_piece])); @@ -339,25 +339,25 @@ Tetris::DrawStatistics() std::u32string& l_count = m_frame_arena.Allocate(int32_to_u32string(m_tetromino_counters[Tetromino::l_piece])); std::u32string& i_count = m_frame_arena.Allocate(int32_to_u32string(m_tetromino_counters[Tetromino::i_piece])); - g_renderer.PushText(t_count, m_font, counters_pos, s_text_color); + g_renderer.PushText(t_count, m_font, counters_pos, s_text_color, z_text); counters_pos.y += yadvance; - g_renderer.PushText(j_count, m_font, counters_pos, s_text_color); + g_renderer.PushText(j_count, m_font, counters_pos, s_text_color, z_text); counters_pos.y += yadvance; - g_renderer.PushText(z_count, m_font, counters_pos, s_text_color); + g_renderer.PushText(z_count, m_font, counters_pos, s_text_color, z_text); counters_pos.y += yadvance; - g_renderer.PushText(o_count, m_font, counters_pos, s_text_color); + g_renderer.PushText(o_count, m_font, counters_pos, s_text_color, z_text); counters_pos.y += yadvance; - g_renderer.PushText(s_count, m_font, counters_pos, s_text_color); + g_renderer.PushText(s_count, m_font, counters_pos, s_text_color, z_text); counters_pos.y += yadvance; - g_renderer.PushText(l_count, m_font, counters_pos, s_text_color); + g_renderer.PushText(l_count, m_font, counters_pos, s_text_color, z_text); counters_pos.y += yadvance; - g_renderer.PushText(i_count, m_font, counters_pos, s_text_color); + g_renderer.PushText(i_count, m_font, counters_pos, s_text_color, z_text); } void Tetris::DrawScore() { - V3F32 pos = {3.0f, 2.6f, s_text_z}; + V2F32 pos = {3.0f, 2.6f}; std::u32string& top_label = m_frame_arena.Allocate(U"Top"); @@ -367,25 +367,25 @@ Tetris::DrawScore() std::u32string& score_value = m_frame_arena.Allocate(int32_to_u32string(m_score)); - g_renderer.PushText(top_label, m_font, pos, s_text_color); + g_renderer.PushText(top_label, m_font, pos, s_text_color, z_text); pos.y -= 0.1f; - g_renderer.PushText(top_value, m_font, pos, s_text_color); + g_renderer.PushText(top_value, m_font, pos, s_text_color, z_text); pos.y -= 0.2f; - g_renderer.PushText(score_label, m_font, pos, s_text_color); + g_renderer.PushText(score_label, m_font, pos, s_text_color, z_text); pos.y -= 0.1f; - g_renderer.PushText(score_value, m_font, pos, s_text_color); + g_renderer.PushText(score_value, m_font, pos, s_text_color, z_text); } void Tetris::DrawNextTetromino() { - V3F32 pos = {3.0f, 1.4f, s_text_z}; + V2F32 pos = {3.0f, 1.4f}; - V3F32 label_pos = {pos.x, pos.y + 0.4f, pos.z}; + V2F32 label_pos = {pos.x, pos.y + 0.4f}; std::u32string& label_text = m_frame_arena.Allocate(U"Next:"); - g_renderer.PushText(label_text, m_font, label_pos, s_text_color); + g_renderer.PushText(label_text, m_font, label_pos, s_text_color, z_layer1); V2F32 tetromino_pos = {pos.x, pos.y}; @@ -395,13 +395,13 @@ Tetris::DrawNextTetromino() void Tetris::DrawLevel() { - V3F32 pos = {3.0f, 1.1f}; + V2F32 pos = {3.0f, 1.1f}; std::u32string& label = m_frame_arena.Allocate(U"Level"); - g_renderer.PushText(label, m_font, pos, s_text_color); + g_renderer.PushText(label, m_font, pos, s_text_color, z_text); pos.y -= 0.1f; std::u32string& level = m_frame_arena.Allocate(int32_to_u32string(m_level)); - g_renderer.PushText(level, m_font, pos, s_text_color); + g_renderer.PushText(level, m_font, pos, s_text_color, z_text); } diff --git a/src/games/tetris/Tetris.hpp b/src/games/tetris/Tetris.hpp index 1c60a98..905458a 100644 --- a/src/games/tetris/Tetris.hpp +++ b/src/games/tetris/Tetris.hpp @@ -36,7 +36,6 @@ private: private: static constexpr Color s_text_color {0.9f, 0.9f, 0.9f, 1.0f}; - static constexpr float s_text_z {10.0f}; static constexpr size_t s_frame_strings_capacity {32}; static constexpr char s_tetris_highscore_path[]{"tetris_highscore.txt"}; diff --git a/src/games/tetris/Tetromino.cpp b/src/games/tetris/Tetromino.cpp index 416a8df..a3ec9dd 100644 --- a/src/games/tetris/Tetromino.cpp +++ b/src/games/tetris/Tetromino.cpp @@ -1,4 +1,5 @@ #include +#include #include #include @@ -218,10 +219,9 @@ Tetromino::Draw(Id id, int32_t ori, V2F32 pos, float scale) V2F32 local_dim = {tetromino_size, tetromino_size}; - V3F32 world_pos = { + V2F32 world_pos = { pos.x + local_pos.x, pos.y + local_pos.y, - 1.0f }; V2F32 world_dim = local_dim; Rectangle world_rect = { @@ -233,7 +233,7 @@ Tetromino::Draw(Id id, int32_t ori, V2F32 pos, float scale) Color color = GetColor(id); - g_renderer.PushRectangle(world_rect, color, world_pos.z); + g_renderer.PushRectangle(world_rect, color, Game::z_layer1); } } } diff --git a/src/renderer/RSoftwareBackend.cpp b/src/renderer/RSoftwareBackend.cpp index 587ac74..f4f31f3 100644 --- a/src/renderer/RSoftwareBackend.cpp +++ b/src/renderer/RSoftwareBackend.cpp @@ -1,3 +1,4 @@ +#include "renderer/Renderer.hpp" #include #include @@ -38,8 +39,8 @@ RSoftwareBackend::Draw() SortRenderEntities(); - for (RSortEntry sort_entry : m_renderer.m_sort_entries) { - REntity& entity = m_renderer.m_render_entities[sort_entry.entity_index]; + for (RZBuffEntry& entry : m_renderer.m_z_buff) { + REntity& entity = m_renderer.m_render_entities[entry.entity_index]; switch (entity.type) { case REntityType_Rectangle: { DrawRectangle(entity.rect); @@ -92,9 +93,9 @@ RSoftwareBackend::Resize(int32_t w, int32_t h) void RSoftwareBackend::SortRenderEntities() { - auto& sort_entries = m_renderer.m_sort_entries; - std::sort(sort_entries.begin(), sort_entries.end(), - [](const RSortEntry& e1, const RSortEntry& e2) { + auto& z_buff = m_renderer.m_z_buff; + std::sort(z_buff.begin(), z_buff.end(), + [](const RZBuffEntry& e1, const RZBuffEntry& e2) { return e1.z < e2.z; }); } diff --git a/src/renderer/Renderer.cpp b/src/renderer/Renderer.cpp index 4b6cb2a..87e2ff7 100644 --- a/src/renderer/Renderer.cpp +++ b/src/renderer/Renderer.cpp @@ -15,7 +15,7 @@ Renderer::Init(SDL_Window* window) { m_window = window; m_render_entities.reserve(1024); - m_sort_entries.reserve(1024); + m_z_buff.reserve(1024); m_backend = std::make_unique(*this); } @@ -23,7 +23,7 @@ void Renderer::Reset() { m_render_entities.clear(); - m_sort_entries.clear(); + m_z_buff.clear(); SetCameraSize(0.0f, 0.0f); } @@ -68,7 +68,7 @@ Renderer::SetClearColor(Color color) } void -Renderer::PushAlphaBitmap(AlphaBitmap& bitmap, V3F32 pos, Color color) +Renderer::PushAlphaBitmap(AlphaBitmap& bitmap, V2F32 pos, Color color, uint32_t z) { m_render_entities.emplace_back(REntity{.bitmap{ REntityType_AlphaBitmap, @@ -76,33 +76,33 @@ Renderer::PushAlphaBitmap(AlphaBitmap& bitmap, V3F32 pos, Color color) pos, color }}); - m_sort_entries.emplace_back(pos.z, m_render_entities.size()-1); + m_z_buff.emplace_back(z, m_render_entities.size()-1); } void -Renderer::PushRectangle(Rectangle rect, Color color, float z) +Renderer::PushRectangle(Rectangle rect, Color color, uint32_t z) { m_render_entities.emplace_back(REntity{.rect{ REntityType_Rectangle, rect, color }}); - m_sort_entries.emplace_back(z, m_render_entities.size()-1); + m_z_buff.emplace_back(z, m_render_entities.size()-1); } void -Renderer::PushCircle(Circle circle, Color color, float z) +Renderer::PushCircle(Circle circle, Color color, uint32_t z) { m_render_entities.emplace_back(REntity{.circle{ REntityType_Circle, circle, color }}); - m_sort_entries.emplace_back(z, m_render_entities.size()-1); + m_z_buff.emplace_back(z, m_render_entities.size()-1); } void -Renderer::PushText(std::u32string& text, Font& font, V3F32 pos, Color color) +Renderer::PushText(std::u32string& text, Font& font, V2F32 pos, Color color, uint32_t z) { m_render_entities.emplace_back(REntity{.text{ REntityType_Text, @@ -111,7 +111,7 @@ Renderer::PushText(std::u32string& text, Font& font, V3F32 pos, Color color) pos, color }}); - m_sort_entries.emplace_back(pos.z, m_render_entities.size()-1); + m_z_buff.emplace_back(z, m_render_entities.size()-1); } diff --git a/src/renderer/Renderer.hpp b/src/renderer/Renderer.hpp index 47837ee..da57e29 100644 --- a/src/renderer/Renderer.hpp +++ b/src/renderer/Renderer.hpp @@ -29,7 +29,7 @@ enum REntityType : int32_t { struct REntity_AlphaBitmap { REntityType type; AlphaBitmap& bitmap; - V3F32 pos; + V2F32 pos; Color color; }; @@ -49,7 +49,7 @@ struct REntity_Text { REntityType type; std::u32string& text; Font& font; - V3F32 pos; + V2F32 pos; Color color; }; @@ -62,9 +62,9 @@ union REntity { REntity_Text text; }; -struct RSortEntry { - float z; - size_t entity_index; +struct RZBuffEntry { + uint32_t z; + uint32_t entity_index; }; @@ -82,15 +82,14 @@ public: void SetScreenSize(int32_t w, int32_t h); void SetCameraSize(float w, float h); - void PushAlphaBitmap(AlphaBitmap& bitmap, V3F32 pos, Color color); - void PushRectangle(Rectangle rect, Color color, float z); - void PushCircle(Circle circle, Color color, float z); - void PushText(std::u32string& text, Font& font, V3F32 pos, Color color); + void PushAlphaBitmap(AlphaBitmap& bitmap, V2F32 pos, Color color, uint32_t z); + void PushRectangle(Rectangle rect, Color color, uint32_t z); + void PushCircle(Circle circle, Color color, uint32_t z); + void PushText(std::u32string& text, Font& font, V2F32 pos, Color color, uint32_t z); /* helper functions */ - int32_t WorldXToScreenX(float x); int32_t WorldYToScreenY(float y); int32_t WorldWidthToScreenWidth(float w); @@ -109,11 +108,9 @@ public: Color m_clear_color {}; std::vector m_render_entities; - std::vector m_sort_entries; + std::vector m_z_buff; std::unique_ptr m_backend; - - friend class RSoftwareBackend; }; -- cgit v1.2.3