Skip to content

Uikit: Canvas component #1325

Description

@eprikazchikov

Is your feature request related to a problem? Please describe.

UI widgets currently lack a centralized rendering system. Each widget would need to manage its own rendering logic, coordinate systems, and material handling, leading to code duplication and inconsistent behavior across different UI elements.

Describe the solution you'd like

A Canvas component has been implemented that serves as the central rendering point for all UI widgets. The solution provides:

  • Render-to-texture architecture – Canvas creates its own RenderTarget and Texture (RGBA8 format with render flags) for offscreen UI rendering
  • Widget hierarchy integration – Works with RectTransform components and Widget system, automatically iterating through children to update and draw them
  • Dirty state management – UI is only re-rendered when markDirty() is called, preventing redundant draw calls
  • Direct rendering API – Provides drawRect() and drawMesh() methods that work with MaterialInstance and CommandBuffer
  • Clip region support – Implements scissor-based clipping via setClipRegion() and disableClip()
  • Automatic setupcomposeComponent() automatically creates a RectTransform if none exists
  • Final composition – Renders the canvas texture to screen using a default post-effect material with proper alpha blending (One, OneMinusSourceAlpha)

Additional context

Key implementation details:

// Canvas creates its own render target and texture
Canvas() : m_target(Engine::objectCreate<RenderTarget>()),
           m_texture(Engine::objectCreate<Texture>()) {
    m_texture->setFormat(Texture::RGBA8);
    m_texture->setFlags(Texture::Render);
    m_target->setColorAttachment(0, m_texture);
}

// Two-phase rendering:
// 1. Draw widgets to offscreen target (only when dirty)
// 2. Draw resulting texture to backbuffer
void draw(CommandBuffer* buffer) {
    if(m_dirty) {
        m_buffer->setRenderTarget(m_target);
        // render widgets...
    }
    m_buffer->drawMesh(defaultPlane(), 0, Material::Translucent, *m_finalMaterial);
}

Current features:

  • Tag system: canvas objects are tagged with "canvas" hash for identification
  • Size management: setSize() resizes both texture and associated RectTransform
  • World transform support: widgets use worldTransform() combined with local scaling matrix
  • Hash combining for transform state to optimize material updates

Usage example:

Canvas* canvas = actor->addComponent<Canvas>();
canvas->setSize(1920, 1080);
canvas->setClipRegion(Vector4(0, 0, 100, 100)); // clip to 100x100 area
// Widgets added as children will be rendered through canvas
canvas->markDirty(); // force re-render

Metadata

Metadata

Assignees

No one assigned

    Labels

    P2This issue should be included to the next release

    Fields

    No fields configured for Feature.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions