diff options
Diffstat (limited to 'src/renderer')
| -rw-r--r-- | src/renderer/RSoftwareBackend.cpp | 210 | ||||
| -rw-r--r-- | src/renderer/RSoftwareBackend.hpp | 41 | ||||
| -rw-r--r-- | src/renderer/RenderGroup.cpp | 106 | ||||
| -rw-r--r-- | src/renderer/RenderGroup.hpp | 84 | ||||
| -rw-r--r-- | src/renderer/Renderer.cpp | 311 | ||||
| -rw-r--r-- | src/renderer/Renderer.hpp | 110 | 
6 files changed, 459 insertions, 403 deletions
diff --git a/src/renderer/RSoftwareBackend.cpp b/src/renderer/RSoftwareBackend.cpp new file mode 100644 index 0000000..f0e2e5f --- /dev/null +++ b/src/renderer/RSoftwareBackend.cpp @@ -0,0 +1,210 @@ +#include <renderer/RSoftwareBackend.hpp> + +#include <SDL3/SDL_video.h> +#include <GL/glew.h> + +#include <algorithm> +#include <cstdlib> +#include <cstdio> + + +RSoftwareBackend::RSoftwareBackend(SDL_Window* window, Renderer& renderer) +    : m_window {window} +    , m_renderer {renderer} +{ +    m_canvas.rshift = 0; +    m_canvas.gshift = 8; +    m_canvas.bshift = 16; +    m_canvas.ashift = 24; +    m_canvas.pixels = nullptr; + + +    glEnable(GL_TEXTURE_2D); +    glActiveTexture(GL_TEXTURE0); + +    glGenTextures(1, &m_gltexture_id); +    glBindTexture(GL_TEXTURE_2D, m_gltexture_id); + +    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 +RSoftwareBackend::ResizeCanvas(int32_t w, int32_t h) +{ +    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; +} + +void +RSoftwareBackend::Draw() +{ +    ResizeCanvas(m_renderer.m_screen_w, m_renderer.m_screen_h); +    SortRenderEntities(); + + +    REntity_Rectangle clear_rect = { +        REntityType_Rectangle, +        0, 0, +        (float)(m_canvas.w-1), (float)(m_canvas.h-1), +        0.0f, +        m_renderer.m_clear_color +    }; +    DrawRectangle(clear_rect); + + +    float z = -1; +    for (RSortEntry sort_entry : m_renderer.m_sort_entries) { +        if (sort_entry.z >= z) { +            z = sort_entry.z; +        } + +        REntity& entity = m_renderer.m_render_entities[sort_entry.entity_index]; +        switch (entity.type) { +            case REntityType_Rectangle: { +                DrawRectangle(entity.rect); +            } break; + +            case REntityType_MonoBitmap: { +                Color color = {0.0f, 0.0f, 0.0f, 1.0f}; +                DrawMonoBitmap(entity.bitmap, color); +            } break; + +            default:; +        } +    } + + +    glActiveTexture(GL_TEXTURE0); +    glBindTexture(GL_TEXTURE_2D, m_gltexture_id); +    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); +} + +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) { +                  return e1.z < e2.z; +              }); +} + +void +RSoftwareBackend::DrawRectangle(REntity_Rectangle& rect) +{ +    int32_t xmin = m_renderer.WorldXToScreenX(rect.x0); +    int32_t ymin = m_renderer.WorldYToScreenY(rect.y0); +    int32_t xmax = m_renderer.WorldXToScreenX(rect.x1); +    int32_t ymax = m_renderer.WorldYToScreenY(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; +        } +    } +} + + +void +RSoftwareBackend::DrawMonoBitmap(REntity_MonoBitmap& mono_bitmap, Color color) +{ +    int32_t x0 = (int32_t)mono_bitmap.x; +    int32_t y0 = (int32_t)mono_bitmap.y; +    int32_t x1 = (int32_t)mono_bitmap.x + mono_bitmap.w - 1; +    int32_t y1 = (int32_t)mono_bitmap.y + mono_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*)mono_bitmap.data + (-cut_bot * mono_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 += mono_bitmap.w; +        rgba += m_canvas.w; +    } +} + diff --git a/src/renderer/RSoftwareBackend.hpp b/src/renderer/RSoftwareBackend.hpp new file mode 100644 index 0000000..5457c7e --- /dev/null +++ b/src/renderer/RSoftwareBackend.hpp @@ -0,0 +1,41 @@ +#pragma once + +#include <SDL3/SDL.h> +#include <renderer/Renderer.hpp> + + +class RSoftwareBackend { +public: +    struct Canvas { +        uint32_t rshift; +        uint32_t gshift; +        uint32_t bshift; +        uint32_t ashift; +        int32_t w; +        int32_t h; +        uint32_t *pixels; +    }; + + +public: +    RSoftwareBackend(SDL_Window* window, Renderer& renderer); + +    void Draw(); + + +private: +    void ResizeCanvas(int32_t w, int32_t h); +    void SortRenderEntities(); + +    void DrawRectangle(REntity_Rectangle& rect); +    void DrawMonoBitmap(REntity_MonoBitmap& mono_bitmap, Color color); + + +private: +    SDL_Window* m_window{}; +    Renderer& m_renderer; + +    uint32_t m_gltexture_id{}; +    Canvas m_canvas; +}; + diff --git a/src/renderer/RenderGroup.cpp b/src/renderer/RenderGroup.cpp deleted file mode 100644 index e393393..0000000 --- a/src/renderer/RenderGroup.cpp +++ /dev/null @@ -1,106 +0,0 @@ -#include <renderer/RenderGroup.hpp> -#include <algorithm> - -RSortEntry::RSortEntry(float z, size_t entity_index) -        : z(z), entity_index(entity_index) { -} - -RenderGroup::RenderGroup() { -    m_REntities.reserve(1024); -    m_RSortEntries.reserve(1024); -} - -void RenderGroup::Reset() { -    m_CameraWidth = 0; -    m_CameraHeight = 0; -    m_REntities.clear(); -    m_RSortEntries.clear(); -    m_REntities.reserve(1024); -    m_RSortEntries.reserve(1024); -} - -void RenderGroup::SetCameraSize(float width, float height) { -    m_CameraWidth = width; -    m_CameraHeight = height; -} - -float RenderGroup::GetScale() { -    float screen_width = static_cast<float>(m_ScreenWidth); -    float screen_height = static_cast<float>(m_ScreenHeight); -    float xunits = screen_width / m_CameraWidth; -    float yunits = screen_height / m_CameraHeight; -    float scale = std::min(xunits, yunits); -    return scale; -} - -V2F32 RenderGroup::ViewPosToScreenPos(V2F32 view_pos) { -    float scale = GetScale(); -    float screen_width = static_cast<float>(m_ScreenWidth); -    float screen_height = static_cast<float>(m_ScreenHeight); -    float viewport_width = m_CameraWidth * scale; -    float viewport_height = m_CameraHeight * 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; -} - -V2F32 RenderGroup::ViewSizeToScreenSize(V2F32 view_size) { -    float scale = GetScale(); - -    V2F32 result; -    result.x = view_size.x * scale; -    result.y = view_size.y * scale; - -    return result; -} - -ImVec2 RenderGroup::ViewPosToScreenPosImGui(V2F32 view_pos) { -    V2F32 screen_pos = ViewPosToScreenPos(view_pos); -    ImVec2 result = {screen_pos.x, screen_pos.y}; -    return result; -} - -ImVec2 RenderGroup::ViewSizeToScreenSizeImGui(V2F32 view_size) { -    V2F32 screen_size = ViewSizeToScreenSize(view_size); -    ImVec2 result = {screen_size.x, screen_size.y}; -    return result; -} - -void RenderGroup::Clear(Color color) { -    m_ClearColor = color; -} - -void RenderGroup::PushRectangle(RectF32 rect, float z, Color color) { -    m_REntities.emplace_back(REntity{.rect{ -            REntityType_Rectangle, -            rect.x0, rect.y0, -            rect.x1, rect.y1, -            z, -            color} -    }); -    m_RSortEntries.emplace_back(z, m_REntities.size()-1); -} - -void RenderGroup::PushBitmap(V3F32 pos, int w, int h, void *data) { -    m_REntities.emplace_back(REntity{.bitmap{ -            REntityType_Bitmap, -            pos.x, pos.y, -            w, h, -            pos.z, -            data -    }}); -    m_RSortEntries.emplace_back(pos.z, m_REntities.size()-1); -} - -void RenderGroup::Sort() { -    std::sort(m_RSortEntries.begin(), m_RSortEntries.end(), -              [](const RSortEntry& e1, const RSortEntry& e2) { -                  return e1.z < e2.z; -              }); -} - diff --git a/src/renderer/RenderGroup.hpp b/src/renderer/RenderGroup.hpp deleted file mode 100644 index ddaa9ff..0000000 --- a/src/renderer/RenderGroup.hpp +++ /dev/null @@ -1,84 +0,0 @@ -#pragma once - -#include <basic/defs.hpp> -#include <basic/math.hpp> -#include <vector> -#include <imgui.h> - -enum REntityType : int32_t { -    REntityType_Rectangle, -    REntityType_Bitmap, -}; - -struct REntity_Rectangle { -    REntityType type; -    float x0; -    float y0; -    float x1; -    float y1; -    float z; -    Color color; -}; - -struct REntity_Bitmap { -    REntityType type; -    float x; -    float y; -    int32_t w; -    int32_t h; -    float z; -    void *data; -}; - -union REntity { -    REntityType type; -    REntity_Rectangle rect; -    REntity_Bitmap bitmap; -}; - -struct RSortEntry { -    RSortEntry(float z, size_t entity_index); -    float z; -    size_t entity_index; -}; - - -class RenderGroup { -public: -    RenderGroup(); -    void Clear(Color color); -    void Reset(); - -    void SetCameraSize(float width, float height); -    V2F32 ViewPosToScreenPos(V2F32 view_pos); -    V2F32 ViewSizeToScreenSize(V2F32 view_size); -    ImVec2 ViewPosToScreenPosImGui(V2F32 view_pos); -    ImVec2 ViewSizeToScreenSizeImGui(V2F32 view_size); -    float GetScale(); - - -public: -    void PushRectangle(RectF32 rect, float z, Color color); -    void PushBitmap(V3F32 pos, int w, int h, void *bitmap); -    void Sort(); - - -public: -    int32_t m_ScreenWidth; -    int32_t m_ScreenHeight; - - -private: -    friend class Renderer; - -    float m_CameraWidth; -    float m_CameraHeight; - - -    Color m_ClearColor; - -    std::vector<REntity> m_REntities; -    std::vector<RSortEntry> m_RSortEntries; -}; - - 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 <renderer/Renderer.hpp> +#include <renderer/RSoftwareBackend.hpp> +  #include <GL/glew.h> +#include <imgui.h> -#include <cstdio> -#include <cstdlib> +#include <memory> -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<RSoftwareBackend>(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<float>(m_screen_w); +    float screen_height = static_cast<float>(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<float>(m_screen_w); +    float screen_height = static_cast<float>(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;  } diff --git a/src/renderer/Renderer.hpp b/src/renderer/Renderer.hpp index 24d4b71..4fdf524 100644 --- a/src/renderer/Renderer.hpp +++ b/src/renderer/Renderer.hpp @@ -1,41 +1,111 @@  #pragma once  #include <basic/math.hpp> -#include <renderer/RenderGroup.hpp> +  #include <SDL3/SDL.h>  #include <SDL3/SDL_video.h> +#include <imgui.h> + +#include <vector> +#include <memory> + + +class RSoftwareBackend; +class Renderer; + +extern Renderer g_renderer; + + +enum REntityType : int32_t { +    REntityType_Rectangle, +    REntityType_MonoBitmap, +}; -struct RCanvas { -    uint32_t rshift; -    uint32_t gshift; -    uint32_t bshift; -    uint32_t ashift; +struct REntity_Rectangle { +    REntityType type; +    float x0; +    float y0; +    float x1; +    float y1; +    float z; +    Color color; +}; + +struct REntity_MonoBitmap { +    REntityType type; +    float x; +    float y;      int32_t w;      int32_t h; -    uint32_t *pixels; +    float z; +    void *data; +}; + +union REntity { +    REntityType type; +    REntity_Rectangle rect; +    REntity_MonoBitmap bitmap; +}; + +struct RSortEntry { +    float z; +    size_t entity_index;  };  class Renderer {  public: -    Renderer(SDL_Window *window); +    void Init(SDL_Window* window); + + +    /* core functions */ + +    void Draw(); +    void Reset(); + +    void Clear(Color color); +    void PushRectangle(RectF32 rect, float z, Color color); +    void PushMonoBitmap(V3F32 pos, int w, int h, void* bitmap); + + +    /* helper functions */ + +    void SetScreenSize(int32_t w, int32_t h); +    void SetCameraSize(float w, float h); + + +    int32_t WorldXToScreenX(float x); +    int32_t WorldYToScreenY(float y); + +    int32_t WorldWidthToScreenWidth(float w); +    int32_t WorldHeightToScreenHeight(float h); + + +    /* temporary helper functions (from old RGroup api) */ +    float GetScale(); +    V2F32 ViewPosToScreenPos(V2F32 view_pos); +    V2F32 ViewSizeToScreenSize(V2F32 view_size); +    ImVec2 ViewPosToScreenPosImGui(V2F32 view_pos); +    ImVec2 ViewSizeToScreenSizeImGui(V2F32 view_size); + + + +    // Todo: make this private +public: +    int32_t m_screen_w; +    int32_t m_screen_h; -    bool Init(); -    void ResizeCanvas(int32_t w, int32_t h); -    void Draw(RenderGroup &render_group); +    float m_camera_w; +    float m_camera_h; +    Color m_clear_color {}; +    std::vector<REntity> m_render_entities; +    std::vector<RSortEntry> m_sort_entries; -private: -    void DrawRectangle(RenderGroup& rgroup, REntity_Rectangle& rect); -    void DrawMonoBitmap(REntity_Bitmap& bitmap, Color color); -    int32_t WorldXToScreenX(RenderGroup& rgroup, float x); -    int32_t WorldYToScreenY(RenderGroup& rgroup, float y); +    std::unique_ptr<RSoftwareBackend> m_backend; -private: -    SDL_Window *m_Window; -    uint32_t m_GlTexId; -    RCanvas m_Canvas; +    friend class RSoftwareBackend;  };  | 
