Skip to content

Renderer

High-level graphics rendering system for drawing shapes, text, sprites, and tilemaps.

Description

The Renderer class provides a unified API for drawing shapes, text, and images. It abstracts the underlying hardware implementation (DrawSurface) and manages display configuration, including rotation and resolution scaling.

All drawing operations are performed in logical screen space. If the logical resolution differs from the physical resolution, the renderer will automatically scale the output to fit the display using a high-performance nearest-neighbor algorithm.

The renderer uses integer-only math for optimal performance on ESP32 and supports multiple sprite formats (1bpp, 2bpp, 4bpp) and multi-layer sprites.

Namespace

namespace pixelroot32::graphics {
    class Renderer {
        // ...
    };
}

Inheritance

  • Base class: None (standalone class)
  • Used by: Engine (manages renderer instance)

Constructors

Renderer(const DisplayConfig& config)

Constructs the Renderer with a specific display configuration.

Parameters:

  • config (const DisplayConfig&): The display configuration settings (width, height, rotation, etc.)

Example:

#include "graphics/Renderer.h"
#include "graphics/DisplayConfig.h"

// 128x128 game logic scaled to 240x240 display
pixelroot32::graphics::DisplayConfig config(
    pixelroot32::graphics::DisplayType::ST7789,
    0,      // rotation
    240, 240, // physical resolution
    128, 128  // logical resolution (rendering space)
);

pixelroot32::graphics::Renderer renderer(config);
renderer.init();

Public Methods

void init()

Initializes the renderer and the underlying draw surface.

Returns:

  • void

Notes:

  • Must be called after construction and before any drawing operations
  • Initializes the platform-specific DrawSurface implementation
  • Safe to call multiple times (idempotent)

Example:

Renderer renderer(displayConfig);
renderer.init();  // Initialize before use

void beginFrame()

Prepares the buffer for a new frame (clears screen).

Returns:

  • void

Notes:

  • Should be called once at the start of each frame
  • Clears the display buffer
  • Typically called automatically by Engine, but can be called manually

Example:

void draw(Renderer& renderer) override {
    renderer.beginFrame();
    // Draw everything...
    renderer.endFrame();
}

void endFrame()

Finalizes the frame and sends the buffer to the display.

Returns:

  • void

Notes:

  • Should be called once at the end of each frame
  • Sends the completed frame buffer to the display
  • Typically called automatically by Engine, but can be called manually

void setOffsetBypass(bool bypass)

Enables or disables camera offset bypass.

Parameters:

  • bypass (bool): true to ignore global offsets, false to apply them.

Notes:

  • When enabled, all subsequent draw calls will ignore xOffset and yOffset.
  • Useful for drawing fixed UI elements that should not move with the camera.

bool isOffsetBypassEnabled() const

Checks if the offset bypass is currently active.

Returns:

  • bool: true if bypass is enabled.

DrawSurface& getDrawSurface()

Gets the underlying DrawSurface implementation.

Returns:

  • DrawSurface&: Reference to the DrawSurface

Notes:

  • Advanced usage: typically not needed unless implementing custom drawing
  • Provides low-level access to the display driver

void drawText(std::string_view text, int16_t x, int16_t y, Color color, uint8_t size)

Draws a string of text using the default font and scaling.

Parameters:

  • text (std::string_view): The text to draw
  • x (int16_t): X coordinate (top-left corner of text)
  • y (int16_t): Y coordinate (top-left corner of text)
  • color (Color): Text color
  • size (uint8_t): Text size multiplier (1 = 5x7 pixels, 2 = 10x14 pixels, etc.)

Performance Notes:

  • Efficient for small amounts of text
  • Uses integer-only scaling (no floats)

Example:

renderer.drawText("Hello World", 10, 10, Color::White, 1);
renderer.drawText("Score: 100", 10, 30, Color::Yellow, 2);

void drawText(std::string_view text, int16_t x, int16_t y, Color color, uint8_t size, const Font* font)

Draws a string of text using a specific font and scaling.

Parameters:

  • text (std::string_view): The text to draw
  • x (int16_t): X coordinate
  • y (int16_t): Y coordinate
  • color (Color): Text color
  • size (uint8_t): Text size multiplier
  • font (const Font*): Pointer to the font to use. If nullptr, uses the default font

Example:

const Font* customFont = &FONT_5X7;
renderer.drawText("Custom Font", 10, 10, Color::White, 1, customFont);

void drawTextCentered(std::string_view text, int16_t y, Color color, uint8_t size)

Draws text centered horizontally at a given Y coordinate using the default font.

Parameters:

  • text (std::string_view): The text to draw
  • y (int16_t): Y coordinate
  • color (Color): Text color
  • size (uint8_t): Text size

Example:

renderer.drawTextCentered("Game Over", 64, Color::White, 2);

void drawTextCentered(std::string_view text, int16_t y, Color color, uint8_t size, const Font* font)

Draws text centered horizontally at a given Y coordinate using a specific font.

Parameters:

  • text (std::string_view): The text to draw
  • y (int16_t): Y coordinate
  • color (Color): Text color
  • size (uint8_t): Text size
  • font (const Font*): Pointer to the font to use. If nullptr, uses the default font

void drawFilledCircle(int x, int y, int radius, Color color)

Draws a filled circle.

Parameters:

  • x (int): Center X coordinate
  • y (int): Center Y coordinate
  • radius (int): Radius of the circle in pixels
  • color (Color): Fill color

Example:

renderer.drawFilledCircle(64, 64, 20, Color::Red);

void drawCircle(int x, int y, int radius, Color color)

Draws a circle outline.

Parameters:

  • x (int): Center X coordinate
  • y (int): Center Y coordinate
  • radius (int): Radius of the circle in pixels
  • color (Color): Outline color

Example:

renderer.drawCircle(64, 64, 20, Color::White);

void drawRectangle(int x, int y, int width, int height, Color color)

Draws a rectangle outline.

Parameters:

  • x (int): Top-left X coordinate
  • y (int): Top-left Y coordinate
  • width (int): Width of the rectangle in pixels
  • height (int): Height of the rectangle in pixels
  • color (Color): Outline color

Example:

renderer.drawRectangle(10, 10, 100, 50, Color::Blue);

void drawFilledRectangle(int x, int y, int width, int height, Color color)

Draws a filled rectangle.

Parameters:

  • x (int): Top-left X coordinate
  • y (int): Top-left Y coordinate
  • width (int): Width of the rectangle in pixels
  • height (int): Height of the rectangle in pixels
  • color (Color): Fill color

Example:

renderer.drawFilledRectangle(10, 10, 100, 50, Color::Green);

void drawLine(int x1, int y1, int x2, int y2, Color color)

Draws a line between two points.

Parameters:

  • x1 (int): Start X coordinate
  • y1 (int): Start Y coordinate
  • x2 (int): End X coordinate
  • y2 (int): End Y coordinate
  • color (Color): Line color

Example:

renderer.drawLine(0, 0, 128, 128, Color::White);

void drawPixel(int x, int y, Color color)

Draws a single pixel.

Parameters:

  • x (int): X coordinate
  • y (int): Y coordinate
  • color (Color): Pixel color

Performance Notes:

  • Very fast, but avoid calling thousands of times per frame
  • Use for special effects or debugging

Example:

renderer.drawPixel(64, 64, Color::Red);

void drawSprite(const Sprite& sprite, int x, int y, Color color, bool flipX = false)

Draws a 1bpp monochrome sprite using the Sprite descriptor.

Parameters:

  • sprite (const Sprite&): Sprite descriptor (data, width, height)
  • x (int): Top-left X coordinate in logical screen space
  • y (int): Top-left Y coordinate in logical screen space
  • color (Color): Color used for "on" pixels
  • flipX (bool, optional): If true, sprite is mirrored horizontally. Default: false

Performance Notes:

  • Very efficient for 1bpp sprites (integer-only operations)
  • Sprite data should be stored in flash (const/constexpr) for best performance

Example:

renderer.drawSprite(playerSprite, 100, 100, Color::White);
renderer.drawSprite(playerSprite, 120, 100, Color::White, true);  // Flipped

void drawSprite(const Sprite& sprite, int x, int y, float scaleX, float scaleY, Color color, bool flipX = false)

Draws a scaled 1bpp monochrome sprite using nearest-neighbor scaling.

Parameters:

  • sprite (const Sprite&): Sprite descriptor
  • x (int): Top-left X coordinate
  • y (int): Top-left Y coordinate
  • scaleX (float): Horizontal scaling factor (e.g., 2.0 for double width)
  • scaleY (float): Vertical scaling factor
  • color (Color): Color used for "on" pixels
  • flipX (bool, optional): If true, sprite is mirrored horizontally before scaling. Default: false

Performance Notes:

  • Slower than non-scaled version due to scaling calculations
  • The destination size is calculated as ceil(width * scaleX) x ceil(height * scaleY)

Example:

renderer.drawSprite(playerSprite, 100, 100, 2.0f, 2.0f, Color::White);  // 2x size

void drawSprite(const Sprite2bpp& sprite, int x, int y, bool flipX = false)

Draws a 2bpp sprite. Available when PIXELROOT32_ENABLE_2BPP_SPRITES is defined.

Parameters:

  • sprite (const Sprite2bpp&): 2bpp sprite descriptor
  • x (int): X coordinate
  • y (int): Y coordinate
  • flipX (bool, optional): Horizontal flip. Default: false

void drawSprite(const Sprite4bpp& sprite, int x, int y, bool flipX = false)

Draws a 4bpp sprite. Available when PIXELROOT32_ENABLE_4BPP_SPRITES is defined.

Parameters:

  • sprite (const Sprite4bpp&): 4bpp sprite descriptor
  • x (int): X coordinate
  • y (int): Y coordinate
  • flipX (bool, optional): Horizontal flip. Default: false

void drawMultiSprite(const MultiSprite& sprite, int x, int y)

Draws a multi-layer sprite composed of several 1bpp layers.

Parameters:

  • sprite (const MultiSprite&): Multi-layer sprite descriptor
  • x (int): Top-left X coordinate in logical screen space
  • y (int): Top-left Y coordinate in logical screen space

Performance Notes:

  • Each layer is rendered separately, so more layers = more draw calls
  • Still efficient as each layer uses 1bpp format
  • Use for multi-color sprites without higher bit-depths

Example:

static const SpriteLayer layers[] = {
    { outlineData, Color::Black },
    { fillData, Color::Red },
    { highlightData, Color::Yellow }
};

static const MultiSprite playerMultiSprite = {
    8,      // width
    8,      // height
    layers, // layers array
    3       // layer count
};

renderer.drawMultiSprite(playerMultiSprite, 100, 100);

void drawMultiSprite(const MultiSprite& sprite, int x, int y, float scaleX, float scaleY)

Draws a scaled multi-layer sprite.

Parameters:

  • sprite (const MultiSprite&): Multi-layer sprite descriptor
  • x (int): Top-left X coordinate
  • y (int): Top-left Y coordinate
  • scaleX (float): Horizontal scaling factor
  • scaleY (float): Vertical scaling factor

void drawTileMap(const TileMap& map, int originX, int originY, Color color)

Draws a 1bpp tilemap.

Parameters:

  • map (const TileMap&): Tilemap descriptor (indices, 1bpp tiles, dimensions)
  • originX (int): X coordinate of the top-left corner
  • originY (int): Y coordinate of the top-left corner
  • color (Color): Color used for all tiles in the map

void drawTileMap(const TileMap2bpp& map, int originX, int originY)

Draws a 2bpp tilemap. Available when PIXELROOT32_ENABLE_2BPP_SPRITES is defined.

Parameters:

  • map (const TileMap2bpp&): Tilemap descriptor (indices, 2bpp tiles, dimensions)
  • originX (int): X coordinate
  • originY (int): Y coordinate

void drawTileMap(const TileMap4bpp& map, int originX, int originY)

Draws a 4bpp tilemap. Available when PIXELROOT32_ENABLE_4BPP_SPRITES is defined.

Parameters:

  • map (const TileMap4bpp&): Tilemap descriptor (indices, 4bpp tiles, dimensions)
  • originX (int): X coordinate
  • originY (int): Y coordinate

Performance Notes:

  • Very efficient for rendering large backgrounds
  • Only visible tiles are drawn (viewport culling)
  • Use tilemaps instead of individual sprites for backgrounds

Example:

static const uint8_t levelIndices[] = {
    0, 1, 2, 3,
    4, 5, 6, 7,
    // ... more rows
};

static const TileMap levelMap = {
    levelIndices,
    16,        // width in tiles
    16,        // height in tiles
    tileSprites, // tile sprite array
    8,         // tile width
    8,         // tile height
    16         // tile count
};

renderer.drawTileMap(levelMap, 0, 0, Color::White);

int getLogicalWidth() const

Gets the logical rendering width.

Returns:

  • int: The width of the logical screen space.

int getLogicalHeight() const

Gets the logical rendering height.

Returns:

  • int: The height of the logical screen space.

Note: These methods replace the removed getWidth() and getHeight().

void setDisplayOffset(int x, int y)

Sets a global offset for all drawing operations. Useful for camera/parallax effects.

Parameters:

  • x (int): X offset in pixels
  • y (int): Y offset in pixels

Notes:

  • All subsequent drawing operations are offset by this amount
  • Useful for camera scrolling and parallax effects
  • Reset to (0, 0) to disable offset

Example:

// Camera scrolling
camera.setPosition(playerX - 64, playerY - 64);
renderer.setDisplayOffset(-camera.getX(), -camera.getY());
renderer.drawTileMap(background, 0, 0, Color::White);

void setDisplaySize(int w, int h)

Sets the logical display size.

Parameters:

  • w (int): Width in pixels
  • h (int): Height in pixels

Notes:

  • Typically set via DisplayConfig during construction
  • Use this to change display size at runtime if needed

int getXOffset() const

Gets the current X display offset.

Returns:

  • int: X offset in pixels

int getYOffset() const

Gets the current Y display offset.

Returns:

  • int: Y offset in pixels

void setContrast(uint8_t level)

Sets the display contrast (brightness).

Parameters:

  • level (uint8_t): Contrast level (0-255)

Notes:

  • Platform-specific: may not be supported on all displays
  • Higher values = brighter display

void setFont(const uint8_t* font)

Sets the font for text rendering.

Parameters:

  • font (const uint8_t*): Pointer to the font data

Notes:

  • Sets the default font for drawText() calls without font parameter
  • Use font constants like FONT_5X7 from Font.h

Usage Example

#include "graphics/Renderer.h"
#include "graphics/DisplayConfig.h"

void draw(Renderer& renderer) override {
    renderer.beginFrame();

    // Draw background
    renderer.drawFilledRectangle(0, 0, 128, 128, Color::Black);

    // Draw sprites
    renderer.drawSprite(playerSprite, playerX, playerY, Color::White);
    renderer.drawSprite(enemySprite, enemyX, enemyY, Color::Red);

    // Draw UI
    renderer.drawText("Score: 100", 10, 10, Color::White, 1);
    renderer.drawTextCentered("Game Over", 64, Color::Yellow, 2);

    renderer.endFrame();
}

Performance Considerations

  • Integer-only math: All operations use integer arithmetic for ESP32 efficiency
  • Sprite storage: Store sprite data in flash (const/constexpr) for best performance
  • Batch operations: Group similar draw calls together
  • Tilemaps: Dibuja un mapa de tiles completo. Implementa viewport culling automático y caché de paleta para máximo rendimiento.
  • Sprites 2bpp/4bpp: Optimizado para ESP32 (IRAM + acceso de 16 bits).

ESP32 Considerations

  • Memory: Sprite data should be in flash, not RAM
  • Frame rate: Limit draw calls per frame for consistent FPS
  • Display offset: Use for scrolling instead of redrawing everything

See Also