From 9d72ed2d5801b1506158082f08bd0b47e58db17f Mon Sep 17 00:00:00 2001 From: fschildt Date: Mon, 29 Sep 2025 13:20:43 +0200 Subject: renderer: major refactor; vectors: now aggregates --- src/renderer/Renderer.cpp | 311 ++++++++++++++++++---------------------------- 1 file changed, 118 insertions(+), 193 deletions(-) (limited to 'src/renderer/Renderer.cpp') diff --git a/src/renderer/Renderer.cpp b/src/renderer/Renderer.cpp index 9217f5c..413b3cb 100644 --- a/src/renderer/Renderer.cpp +++ b/src/renderer/Renderer.cpp @@ -1,233 +1,158 @@ #include +#include + #include +#include -#include -#include +#include -Renderer::Renderer(SDL_Window *window) : m_Window(window), m_Canvas{} -{ -} +Renderer g_renderer; -bool -Renderer::Init() +void +Renderer::Init(SDL_Window* window) { - GLenum err = glewInit(); - if (err) { - printf("glewInit() error\n"); - return false; - } - - int32_t window_width; - int32_t window_height; - if (!SDL_GetWindowSize(m_Window, &window_width, &window_height)) { - printf("Error: SDL_GetWindowSize: %s\n", SDL_GetError()); - return false; - } - - - m_Canvas.rshift = 0; - m_Canvas.gshift = 8; - m_Canvas.bshift = 16; - m_Canvas.ashift = 24; - ResizeCanvas(window_width, window_height); + m_render_entities.reserve(1024); + m_sort_entries.reserve(1024); + m_backend = std::make_unique(window, *this); +} - glEnable(GL_TEXTURE_2D); - glActiveTexture(GL_TEXTURE0); +void +Renderer::Draw() +{ + m_backend->Draw(); +} - glGenTextures(1, &m_GlTexId); - glBindTexture(GL_TEXTURE_2D, m_GlTexId); +void +Renderer::Reset() +{ + m_render_entities.clear(); + m_sort_entries.clear(); + m_render_entities.reserve(1024); + m_sort_entries.reserve(1024); + SetCameraSize(0.0f, 0.0f); +} - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); +void +Renderer::SetScreenSize(int32_t w, int32_t h) +{ + m_screen_w = w; + m_screen_h = h; +} +void +Renderer::SetCameraSize(float w, float h) +{ + m_camera_w = w; + m_camera_h = h; +} - return true; +int32_t +Renderer::WorldXToScreenX(float world_x) +{ + float screen_x = (world_x / m_camera_w) * (float)m_screen_w; + return (int32_t)screen_x; } +int32_t +Renderer::WorldYToScreenY(float world_y) +{ + float screen_y = (world_y / m_camera_h) * (float)m_screen_h; + return (int32_t)screen_y; +} void -Renderer::ResizeCanvas(int32_t w, int32_t h) +Renderer::Clear(Color color) { - size_t realloc_size = (size_t)(w * h) * sizeof(m_Canvas.pixels[0]); - void *realloc_data = realloc(m_Canvas.pixels, realloc_size); - if (!realloc_data) { - printf("could not resize offscreen buffer\n"); - return; - } - - m_Canvas.w = w; - m_Canvas.h = h; - m_Canvas.pixels = (uint32_t*)realloc_data; + m_clear_color = color; } - void -Renderer::Draw(RenderGroup& rgroup) +Renderer::PushRectangle(RectF32 rect, float z, Color color) { - rgroup.Sort(); - REntity_Rectangle clear_rect = { - REntityType_Rectangle, - 0, 0, - (float)(m_Canvas.w-1), (float)(m_Canvas.h-1), - 0.0f, - rgroup.m_ClearColor - }; - DrawRectangle(rgroup, clear_rect); - - - float z = -1; - for (RSortEntry sort_entry : rgroup.m_RSortEntries) { - if (sort_entry.z >= z) { - z = sort_entry.z; - } - - REntity& entity = rgroup.m_REntities[sort_entry.entity_index]; - switch (entity.type) { - case REntityType_Rectangle: { - DrawRectangle(rgroup, entity.rect); - } break; - - case REntityType_Bitmap: { - Color color = {0.0f, 0.0f, 0.0f, 1.0f}; - DrawMonoBitmap(entity.bitmap, color); - } break; - - default:; - } - } - - - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, m_GlTexId); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, m_Canvas.w, m_Canvas.h, 0, GL_RGBA, GL_UNSIGNED_BYTE, m_Canvas.pixels); - - glBegin(GL_QUADS); - glTexCoord2f(0.0f, 0.0f); glVertex2f(-1.0f, -1.0f); - glTexCoord2f(1.0f, 0.0f); glVertex2f( 1.0f, -1.0f); - glTexCoord2f(1.0f, 1.0f); glVertex2f( 1.0f, 1.0f); - glTexCoord2f(0.0f, 1.0f); glVertex2f(-1.0f, 1.0f); - glEnd(); - - glBindTexture(GL_TEXTURE_2D, 0); + m_render_entities.emplace_back(REntity{.rect{ + REntityType_Rectangle, + rect.x0, rect.y0, + rect.x1, rect.y1, + z, + color} + }); + m_sort_entries.emplace_back(z, m_render_entities.size()-1); } - void -Renderer::DrawRectangle(RenderGroup& rgroup, REntity_Rectangle& rect) +Renderer::PushMonoBitmap(V3F32 pos, int w, int h, void *data) { - int32_t xmin = WorldXToScreenX(rgroup, rect.x0); - int32_t ymin = WorldYToScreenY(rgroup, rect.y0); - int32_t xmax = WorldXToScreenX(rgroup, rect.x1); - int32_t ymax = WorldYToScreenY(rgroup, rect.y1); - - if (xmin < 0) { - xmin = 0; - } - if (ymin < 0) { - ymin = 0; - } - if (xmax >= m_Canvas.w) { - xmax = m_Canvas.w - 1; - } - if (ymax >= m_Canvas.h) { - ymax = m_Canvas.h - 1; - } - - uint32_t rshift = m_Canvas.rshift; - uint32_t gshift = m_Canvas.gshift; - uint32_t bshift = m_Canvas.bshift; - for (int32_t y = ymin; y <= ymax; ++y) { - uint32_t *pixel = m_Canvas.pixels + y * m_Canvas.w + xmin; - for (int32_t x = xmin; x <= xmax; ++x) { - uint32_t r = (uint32_t)(rect.color.r * 255.0f); - uint32_t g = (uint32_t)(rect.color.g * 255.0f); - uint32_t b = (uint32_t)(rect.color.b * 255.0f); - uint32_t val = r << rshift | g << gshift | b << bshift; - *pixel++ = val; - } - } + m_render_entities.emplace_back(REntity{.bitmap{ + REntityType_MonoBitmap, + pos.x, pos.y, + w, h, + pos.z, + data + }}); + m_sort_entries.emplace_back(pos.z, m_render_entities.size()-1); } -void -Renderer::DrawMonoBitmap(REntity_Bitmap& bitmap, Color color) + +/* temporary helper functions (from old RGroup api) */ + +float +Renderer::GetScale() { - int32_t x0 = (int32_t)bitmap.x; - int32_t y0 = (int32_t)bitmap.y; - int32_t x1 = (int32_t)bitmap.x + bitmap.w - 1; - int32_t y1 = (int32_t)bitmap.y + bitmap.h - 1; - - int32_t cut_left = 0; - int32_t cut_bot = 0; - - if (x0 < 0) { - cut_left = x0; - x0 = 0; - } - if (y0 < 0) { - cut_bot = y0; - y0 = 0; - } - if (x1 >= m_Canvas.w) { - x1 = m_Canvas.w - 1; - } - if (y1 >= m_Canvas.h) { - y1 = m_Canvas.h - 1; - } - - - uint32_t rshift = m_Canvas.rshift; - uint32_t gshift = m_Canvas.gshift; - uint32_t bshift = m_Canvas.bshift; - - uint8_t* grayscale = (uint8_t*)bitmap.data + (-cut_bot * bitmap.w) + (-cut_left); - uint32_t* rgba = m_Canvas.pixels + y0 * m_Canvas.w + x0; - for (int32_t y = y0; y <= y1; y++) { - uint8_t *grayscale_pixels = grayscale; - uint32_t *rgba_pixels = rgba; - for (int32_t x = x0; x <= x1; x++) { - float alpha = *grayscale_pixels / 255.0f; - - // Todo: we do not want to blend with existing color! - - uint32_t rgba_result = *rgba_pixels; - float r0 = (rgba_result >> rshift) & 0xff; - float g0 = (rgba_result >> gshift) & 0xff; - float b0 = (rgba_result >> bshift) & 0xff; - - float r1 = r0 + (color.r - r0)*alpha; - float g1 = g0 + (color.g - g0)*alpha; - float b1 = b0 + (color.b - b0)*alpha; - - rgba_result = (uint32_t)r1 << rshift | (uint32_t)g1 << gshift | (uint32_t)b1 << bshift; - *rgba_pixels = rgba_result; - - grayscale_pixels++; - rgba_pixels++; - } - - grayscale += bitmap.w; - rgba += m_Canvas.w; - } + float screen_width = static_cast(m_screen_w); + float screen_height = static_cast(m_screen_h); + float xunits = screen_width / m_camera_w; + float yunits = screen_height / m_camera_h; + float scale = std::min(xunits, yunits); + return scale; } +V2F32 +Renderer::ViewPosToScreenPos(V2F32 view_pos) +{ + float scale = GetScale(); + float screen_width = static_cast(m_screen_w); + float screen_height = static_cast(m_screen_h); + float viewport_width = m_camera_w * scale; + float viewport_height = m_camera_h * scale; + float viewport_x0 = (screen_width - viewport_width) / 2; + float viewport_y0 = (screen_height - viewport_height) / 2; + + V2F32 result; + result.x = viewport_x0 + view_pos.x * scale; + result.y = screen_height - (viewport_y0 + view_pos.y * scale); + + return result; +} -int32_t -Renderer::WorldXToScreenX(RenderGroup& rgroup, float x) +V2F32 +Renderer::ViewSizeToScreenSize(V2F32 view_size) { - float xscreen = (x / rgroup.m_CameraWidth) * (float)rgroup.m_ScreenWidth; - return (int32_t)xscreen; + float scale = GetScale(); + + V2F32 result; + result.x = view_size.x * scale; + result.y = view_size.y * scale; + + return result; } -int32_t -Renderer::WorldYToScreenY(RenderGroup& rgroup, float y) +ImVec2 +Renderer::ViewPosToScreenPosImGui(V2F32 view_pos) +{ + V2F32 screen_pos = ViewPosToScreenPos(view_pos); + ImVec2 result = {screen_pos.x, screen_pos.y}; + return result; +} + +ImVec2 +Renderer::ViewSizeToScreenSizeImGui(V2F32 view_size) { - float yscreen = (y / rgroup.m_CameraHeight) * (float)rgroup.m_ScreenHeight; - return (int32_t)yscreen; + V2F32 screen_size = ViewSizeToScreenSize(view_size); + ImVec2 result = {screen_size.x, screen_size.y}; + return result; } -- cgit v1.2.3