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 setup –
composeComponent() 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
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
Canvascomponent has been implemented that serves as the central rendering point for all UI widgets. The solution provides:RenderTargetandTexture(RGBA8 format with render flags) for offscreen UI renderingRectTransformcomponents andWidgetsystem, automatically iterating through children to update and draw themmarkDirty()is called, preventing redundant draw callsdrawRect()anddrawMesh()methods that work withMaterialInstanceandCommandBuffersetClipRegion()anddisableClip()composeComponent()automatically creates aRectTransformif none existsAdditional context
Key implementation details:
Current features:
"canvas"hash for identificationsetSize()resizes both texture and associatedRectTransformworldTransform()combined with local scaling matrixUsage example: