export module vibe2.rendering; import vibe2.core; import vibe2.themes; import vibe2.external.sdl_wrapper; export namespace vibe2::rendering { // Utilidades básicas de renderizado namespace utils { // Calcular posición centrada para texto inline int getCenteredTextX(int text_length, int char_width = debug::DEFAULT_TEXT_SIZE) { const int text_pixel_width = text_length * char_width; return (SCREEN_WIDTH - text_pixel_width) / 2; } // Calcular posición alineada a la derecha inline int getRightAlignedX(int text_length, int char_width = debug::DEFAULT_TEXT_SIZE, int margin = debug::MARGIN) { const int text_pixel_width = text_length * char_width; return SCREEN_WIDTH - text_pixel_width - margin; } // Convertir color RGB a valores normalizados inline void rgbToFloat(int r, int g, int b, float& rf, float& gf, float& bf) { rf = r / 255.0f; gf = g / 255.0f; bf = b / 255.0f; } } // Renderizador de fondos degradados class GradientRenderer { private: vibe2::sdl::Renderer* renderer_; public: GradientRenderer(vibe2::sdl::Renderer* renderer) : renderer_(renderer) {} void renderBackground(const themes::ThemeData& theme_data) { // Crear quad de pantalla completa con degradado vibe2::sdl::Vertex bg_vertices[4]; // Vértice superior izquierdo bg_vertices[0].position = {0, 0}; bg_vertices[0].tex_coord = {0.0f, 0.0f}; bg_vertices[0].color = {theme_data.bg_top_r, theme_data.bg_top_g, theme_data.bg_top_b, 1.0f}; // Vértice superior derecho bg_vertices[1].position = {SCREEN_WIDTH, 0}; bg_vertices[1].tex_coord = {1.0f, 0.0f}; bg_vertices[1].color = {theme_data.bg_top_r, theme_data.bg_top_g, theme_data.bg_top_b, 1.0f}; // Vértice inferior derecho bg_vertices[2].position = {SCREEN_WIDTH, SCREEN_HEIGHT}; bg_vertices[2].tex_coord = {1.0f, 1.0f}; bg_vertices[2].color = {theme_data.bg_bottom_r, theme_data.bg_bottom_g, theme_data.bg_bottom_b, 1.0f}; // Vértice inferior izquierdo bg_vertices[3].position = {0, SCREEN_HEIGHT}; bg_vertices[3].tex_coord = {0.0f, 1.0f}; bg_vertices[3].color = {theme_data.bg_bottom_r, theme_data.bg_bottom_g, theme_data.bg_bottom_b, 1.0f}; // Índices para 2 triángulos int bg_indices[6] = {0, 1, 2, 2, 3, 0}; // Renderizar sin textura vibe2::sdl::renderGeometry(renderer_, nullptr, bg_vertices, 4, bg_indices, 6); } }; // Sistema de batch rendering básico class BatchRenderer { private: static constexpr int MAX_SPRITES = 10000; vibe2::sdl::Vertex vertices_[MAX_SPRITES * 4]; int indices_[MAX_SPRITES * 6]; int sprite_count_; vibe2::sdl::Renderer* renderer_; public: BatchRenderer(vibe2::sdl::Renderer* renderer) : sprite_count_(0), renderer_(renderer) {} void clear() { sprite_count_ = 0; } void addSprite(float x, float y, float w, float h, const Color& color) { if (sprite_count_ >= MAX_SPRITES) return; int vertex_index = sprite_count_ * 4; int index_start = sprite_count_ * 6; // Convertir colores de Uint8 (0-255) a float (0.0-1.0) float rf = color.r / 255.0f; float gf = color.g / 255.0f; float bf = color.b / 255.0f; // Crear 4 vértices para el quad vertices_[vertex_index + 0].position = {x, y}; vertices_[vertex_index + 0].tex_coord = {0.0f, 0.0f}; vertices_[vertex_index + 0].color = {rf, gf, bf, 1.0f}; vertices_[vertex_index + 1].position = {x + w, y}; vertices_[vertex_index + 1].tex_coord = {1.0f, 0.0f}; vertices_[vertex_index + 1].color = {rf, gf, bf, 1.0f}; vertices_[vertex_index + 2].position = {x + w, y + h}; vertices_[vertex_index + 2].tex_coord = {1.0f, 1.0f}; vertices_[vertex_index + 2].color = {rf, gf, bf, 1.0f}; vertices_[vertex_index + 3].position = {x, y + h}; vertices_[vertex_index + 3].tex_coord = {0.0f, 1.0f}; vertices_[vertex_index + 3].color = {rf, gf, bf, 1.0f}; // Índices para 2 triángulos indices_[index_start + 0] = vertex_index + 0; indices_[index_start + 1] = vertex_index + 1; indices_[index_start + 2] = vertex_index + 2; indices_[index_start + 3] = vertex_index + 2; indices_[index_start + 4] = vertex_index + 3; indices_[index_start + 5] = vertex_index + 0; sprite_count_++; } void renderBatch(vibe2::sdl::Texture* texture = nullptr) { if (sprite_count_ > 0) { vibe2::sdl::renderGeometry(renderer_, texture, vertices_, sprite_count_ * 4, indices_, sprite_count_ * 6); } } int getSpriteCount() const { return sprite_count_; } }; }