Skip to content

IRenderer#

Base class for renderer.

Header:#include <AUI/Render/IRenderer.h>
CMake:aui_link(my_target PUBLIC aui::views)

Detailed Description#

The rendering engine provides graphics rendering capabilities for the AUI Framework's user interface system. It offers both hardware-accelerated (OpenGL) and software-based rendering backends. The engine handles drawing primitives, text rendering, visual effects, and maintains consistent rendering behavior across different platforms and hardware capabilities.

The renderer is shared across windows and manages its own resources such as textures, but each window has its own rendering context.

Core Renderer Interface#

Category Key Methods Purpose
Shape Drawing rectangle(), roundedRectangle(), rectangleBorder() Basic geometric shapes
Line Drawing line(), lines(), points() Vector graphics primitives
Text Rendering string(), prerenderString(), newMultiStringCanvas() Text output and caching
Visual Effects boxShadow(), boxShadowInner(), squareSector() Advanced visual effects
State Management setColor(), setTransform(), setBlending() Rendering context control
Masking pushMaskBefore(), pushMaskAfter(), popMaskBefore(), popMaskAfter() Stencil-based clipping

The renderer maintains internal state including:

  • Current color multiplier (mColor)
  • Transformation matrix (mTransform)
  • Target window (mWindow)
  • Stencil depth for masking (mStencilDepth)
  • Texture pool for resource management (mTexturePool)

HiDPI (High‑DPI) support#

The framework uses logical units dp for layout and drawing. All logical values are multiplied by the window pixel ratio before they reach the renderer. The renderer works with physical pixels only (px).

This ensures that the UI appears consistent across displays with varying pixel densities.

Examples#

examples/ui/embedded_sdl/src/main.cpp

SDL3 - This code demonstrates how to integrate the AUI Framework with SDL3 to create a window with OpenGL rendering.

    }
    void endResize(ASurface& window) override {
    }

    IRenderer& renderer() override {
        return *m_renderer;
    }
};
/// [EmbedRenderingContext]

Public Types#


IPrerenderedString#

class IRenderer::IPrerenderedString

Empty structure.


IMultiStringCanvas#

class IRenderer::IMultiStringCanvas

Empty structure.

Public Methods#

backdrops#


void IRenderer::backdrops(glm::ivec2 position, glm::ivec2 size, std::span<ass::Backdrop::Any> backdrops)

Draws rectangular backdrop effects.

Arguments
position
rectangle position (px)
size
rectangle size (px)
backdrops
array of backdrop effects. Impl might apply optimizations on using several effects at once.

Implementation might draw stub (i.e., gray rectangle) instead of drawing complex backdrop effects.

boxShadow#


virtual void IRenderer::boxShadow(glm::vec2 position, glm::vec2 size, float blurRadius, const AColor& color)

Draws a rectangle-shaped shadow.

Arguments
position
position
size
rectangle size
blurRadius
blur radius
color
shadow color

boxShadowInner#


virtual void IRenderer::boxShadowInner(glm::vec2 position, glm::vec2 size, float blurRadius, float spreadRadius, float borderRadius, const AColor& color, glm::vec2 offset)

Draws inner (inset) rectangle-shaped shadow.

Arguments
position
position
size
rectangle size
blurRadius
blur radius
spreadRadius
spread (offset) radius
borderRadius
border radius of the rectangle.
color
shadow color
offset
shadow offset. Unlike outer shadow (ctx.render.boxShadow), the offset is passed to the shader instead of a simple rectangle position offset.

getNewTexture#


_<ITexture> IRenderer::getNewTexture()

Creates new texture (image representation optimized for GPU rendering).

Examples:

examples/app/game_of_life/src/main.cpp

Game of Life - Game of Life implementation that uses advanced large dynamic data rendering techniques such as ITexture, AImage to be GPU friendly. The computation is performed in AThreadPool.

    _<ITexture> mTexture;

    void updateTexture() {
        if (!mTexture) {
            mTexture = AWindow::current()->getRenderingContext()->renderer().getNewTexture();
        }

        CellsImage image(mCells->size());
        for (unsigned y = 0; y < image.height(); ++y) {
            for (unsigned x = 0; x < image.width(); ++x) {

line#


void IRenderer::line(const ABrush& brush, glm::vec2 p1, glm::vec2 p2, const ABorderStyle& style = ABorderStyle::Solid { }, AMetric width = 1 _dp)
Performance note
if you want to drawElements multiple lines, consider using ARender::lines function instead.

lines#


virtual void IRenderer::lines(const ABrush& brush, AArrayView<glm::vec2> points, const ABorderStyle& style, AMetric width)

Draws polyline (non-loop line strip).

Arguments
brush
brush
points
polyline points
style
style
width
line width

Examples:

examples/ui/views/src/DemoGraphView.cpp

Views Example - All-in-one views building example.

void DemoGraphView::render(ARenderContext ctx) {
    AView::render(ctx);

    ctx.render.lines(ASolidBrush{0xff0000_rgb }, mPoints, ABorderStyle::Dashed{}, 4_dp);

}
examples/app/game_of_life/src/main.cpp

Game of Life - Game of Life implementation that uses advanced large dynamic data rendering techniques such as ITexture, AImage to be GPU friendly. The computation is performed in AThreadPool.

            }
            for (int i = 1; i < mCells->size().y; ++i) {
                points << std::make_pair(glm::vec2(0.f, i * SCALE), glm::vec2(getSize().x, i * SCALE));
            }
            ctx.render.lines(ASolidBrush { AColor::GRAY }, points);
        };
        drawGrid();
    }

    void onPointerPressed(const APointerPressedEvent& event) override {

void IRenderer::lines(const ABrush& brush, AArrayView<glm::vec2> points, const ABorderStyle& style = ABorderStyle::Solid { })

Draws polyline (non-loop line strip).

Arguments
brush
brush
points
polyline points
style
style

Examples:

examples/ui/views/src/DemoGraphView.cpp

Views Example - All-in-one views building example.

void DemoGraphView::render(ARenderContext ctx) {
    AView::render(ctx);

    ctx.render.lines(ASolidBrush{0xff0000_rgb }, mPoints, ABorderStyle::Dashed{}, 4_dp);

}
examples/app/game_of_life/src/main.cpp

Game of Life - Game of Life implementation that uses advanced large dynamic data rendering techniques such as ITexture, AImage to be GPU friendly. The computation is performed in AThreadPool.

            }
            for (int i = 1; i < mCells->size().y; ++i) {
                points << std::make_pair(glm::vec2(0.f, i * SCALE), glm::vec2(getSize().x, i * SCALE));
            }
            ctx.render.lines(ASolidBrush { AColor::GRAY }, points);
        };
        drawGrid();
    }

    void onPointerPressed(const APointerPressedEvent& event) override {

virtual void IRenderer::lines(const ABrush& brush, AArrayView<std::pair<glm::vec2, glm::vec2> > points, const ABorderStyle& style, AMetric width)

Draws multiple individual lines in a batch.

Arguments
brush
brush
points
line points
style
style
width
line width

Examples:

examples/ui/views/src/DemoGraphView.cpp

Views Example - All-in-one views building example.

void DemoGraphView::render(ARenderContext ctx) {
    AView::render(ctx);

    ctx.render.lines(ASolidBrush{0xff0000_rgb }, mPoints, ABorderStyle::Dashed{}, 4_dp);

}
examples/app/game_of_life/src/main.cpp

Game of Life - Game of Life implementation that uses advanced large dynamic data rendering techniques such as ITexture, AImage to be GPU friendly. The computation is performed in AThreadPool.

            }
            for (int i = 1; i < mCells->size().y; ++i) {
                points << std::make_pair(glm::vec2(0.f, i * SCALE), glm::vec2(getSize().x, i * SCALE));
            }
            ctx.render.lines(ASolidBrush { AColor::GRAY }, points);
        };
        drawGrid();
    }

    void onPointerPressed(const APointerPressedEvent& event) override {

void IRenderer::lines(const ABrush& brush, AArrayView<std::pair<glm::vec2, glm::vec2> > points, const ABorderStyle& style = ABorderStyle::Solid { })

Draws multiple individual lines in a batch.

Arguments
brush
brush
points
line points
style
style

Examples:

examples/ui/views/src/DemoGraphView.cpp

Views Example - All-in-one views building example.

void DemoGraphView::render(ARenderContext ctx) {
    AView::render(ctx);

    ctx.render.lines(ASolidBrush{0xff0000_rgb }, mPoints, ABorderStyle::Dashed{}, 4_dp);

}
examples/app/game_of_life/src/main.cpp

Game of Life - Game of Life implementation that uses advanced large dynamic data rendering techniques such as ITexture, AImage to be GPU friendly. The computation is performed in AThreadPool.

            }
            for (int i = 1; i < mCells->size().y; ++i) {
                points << std::make_pair(glm::vec2(0.f, i * SCALE), glm::vec2(getSize().x, i * SCALE));
            }
            ctx.render.lines(ASolidBrush { AColor::GRAY }, points);
        };
        drawGrid();
    }

    void onPointerPressed(const APointerPressedEvent& event) override {

newMultiStringCanvas#


virtual _<IMultiStringCanvas> IRenderer::newMultiStringCanvas(const AFontStyle& style)

Creates new canvas for batching multiple prerender string calls.

Returns
a new instance of IMultiStringCanvas

newRenderViewToTexture#


virtual _unique<IRenderViewToTexture> IRenderer::newRenderViewToTexture()

Returns a new instance of IRenderViewToTexture interface associated with this renderer.

Returns
A new instance. Can return null if unsupported.

points#


virtual void IRenderer::points(const ABrush& brush, AArrayView<glm::vec2> points, AMetric size)

Draws points list.

Arguments
brush
brush
points
points
size
point size

popMaskAfter#


virtual void IRenderer::popMaskAfter()

Switches drawing to the color buffer back from the stencil. Decreases stencil depth.

Stencil buffer should not be changed after calling this function. Should be called after the popMaskBefore function.

popMaskBefore#


virtual void IRenderer::popMaskBefore()

Switches drawing to the stencil buffer instead of color buffer.

Stencil pixel is decreased by each affected pixel. Should be called before the popMaskAfter function.

prerenderString#


virtual _<IPrerenderedString> IRenderer::prerenderString(glm::vec2 position, const AString& text, const AFontStyle& fs)

Analyzes string and creates an instance of IRenderer::IPrerenderedString which helps IRenderer to efficiently render the string.

Arguments
position
string baseline
text
string to prerender
fs
font style
Returns
an instance of IPrerenderedString

pushMaskAfter#


virtual void IRenderer::pushMaskAfter()

Switches drawing to the color buffer back from the stencil. Increases stencil depth.

Stencil buffer should not be changed after calling this function. Should be called after the pushMaskBefore function.

pushMaskBefore#


virtual void IRenderer::pushMaskBefore()

witches drawing to the stencil buffer instead of color buffer.

Stencil pixel is increased by each affected pixel. Should be called before the pushMaskAfter function.

rectangle#


virtual void IRenderer::rectangle(const ABrush& brush, glm::vec2 position, glm::vec2 size)

Draws simple rectangle.

Arguments
brush
brush to use
position
rectangle position (px)
size
rectangle size (px)

Examples:

examples/app/fractal/src/FractalView.cpp

Fractal Example - Fractal viewer application demonstrating usage of custom shaders.

    AView::render(context);

    mShader.use();
    mTexture->bind();
    context.render.rectangle(ACustomShaderBrush {}, { 0, 0 }, getSize());
}

void FractalView::setSize(glm::ivec2 size) {
    AView::setSize(size);
    mShader.use();
examples/app/game_of_life/src/main.cpp

Game of Life - Game of Life implementation that uses advanced large dynamic data rendering techniques such as ITexture, AImage to be GPU friendly. The computation is performed in AThreadPool.

    void render(ARenderContext ctx) override {
        AView::render(ctx);
        if (mTexture) {
            ctx.render.rectangle(ATexturedBrush { mTexture }, { 0, 0 }, float(SCALE) * glm::vec2(mCells->size()));
        }
        auto drawGrid = [&] {
            ASmallVector<std::pair<glm::vec2, glm::vec2>, 128 * 2> points;
            for (int i = 1; i < mCells->size().x; ++i) {
                points << std::make_pair(glm::vec2(i * SCALE, 0.f), glm::vec2(i * SCALE, getSize().y));

rectangleBorder#


virtual void IRenderer::rectangleBorder(const ABrush& brush, glm::vec2 position, glm::vec2 size, float lineWidth = 1 . f)

Draws rectangle's border.

Arguments
brush
brush to use
position
rectangle position (px)
size
rectangle size (px)
lineWidth
border line width (px)

rotate#


void IRenderer::rotate(const glm::vec3& axis, AAngleRadians angle)

wrapper for setTransform applying matrix rotation along the specified axis.

Arguments
axis
axis
angle
angle to rotate

void IRenderer::rotate(AAngleRadians angle)

wrapper for setTransform applying matrix rotation along z axis.

Arguments
angle
angle to rotate

roundedRectangle#


virtual void IRenderer::roundedRectangle(const ABrush& brush, glm::vec2 position, glm::vec2 size, float radius)

Draws rounded rect (with antialiasing, if msaa enabled).

Arguments
brush
brush to use
position
rectangle position (px)
size
rectangle size (px)
radius
corner radius (px)

Examples:

examples/7guis/circle_drawer/src/main.cpp

7GUIs Circle Drawer - Undo, redo, dialog control.

        AView::render(ctx);

        for (const auto& circle : *mState->circles) {
            if (&circle == mHoveredCircle) {
                ctx.render.roundedRectangle(
                    ASolidBrush { AColor::GRAY }, circle.position - *circle.radius, glm::vec2(circle.radius * 2.f),
                    circle.radius);
            }
            ctx.render.roundedRectangleBorder(
                ASolidBrush { AColor::BLACK }, circle.position - *circle.radius, glm::vec2(circle.radius * 2.f),

roundedRectangleBorder#


virtual void IRenderer::roundedRectangleBorder(const ABrush& brush, glm::vec2 position, glm::vec2 size, float radius, int borderWidth)

Draws rounded rectangle's border.

Arguments
brush
brush to use
position
rectangle position (px)
size
rectangle size (px)
radius
corner radius (px)
borderWidth
border line width (px)

Examples:

examples/7guis/circle_drawer/src/main.cpp

7GUIs Circle Drawer - Undo, redo, dialog control.

                ctx.render.roundedRectangle(
                    ASolidBrush { AColor::GRAY }, circle.position - *circle.radius, glm::vec2(circle.radius * 2.f),
                    circle.radius);
            }
            ctx.render.roundedRectangleBorder(
                ASolidBrush { AColor::BLACK }, circle.position - *circle.radius, glm::vec2(circle.radius * 2.f),
                circle.radius, 1);
        }
    }

setBlending#


virtual void IRenderer::setBlending(Blending blending)

Sets blending mode.

Arguments
blending
new blending mode

Blending Modes and Effects

The rendering engine supports multiple blending modes for advanced visual effects:

enum class Blending Blending mode.

Terminology used in this documentation:

Source color (S)
Source color is a color of the brush (i.e. texture color matching current position) multiplied by the current renderer color, i.e. when drawing a black rectangle onto the white canvas the source color is black.
Destination color (D)
Destination color is a color of the framebuffer you're drawing to, i.e. when drawing a black rectangle onto the white canvas the destination color is white.
S.rgb
Source color without the alpha component.
S.a
Source's alpha component without the color itself.
D.rgb
Destination color without the alpha component.
D.a
Destination's alpha component without the color itself.
Alpha-based
Alpha-based blending mode is a blending mode that uses the alpha component in it's formula.
Color-based
Color-based blending mode is a blending mode that does not use the alpha component in it's formula.
Constant Description
Blending::NORMAL Normal blending.
Formula
S.rgb * S.a + D.rgb * (1 - S.a)
Type
Alpha-based
Behaviour

When S.a is 0, NORMAL does not drawElements anything.

When S.a is 1, NORMAL ignores D.

Blending::ADDITIVE Simply sums S and D colors.
Formula
S.rgb + D.rgb
Type
Color-based
Behaviour

When S is black, ADDITIVE does not drawElements anything.

When S is white, ADDITIVE draws white.

Blending::INVERSE_DST Inverses destination color and multiplies it with the source color.
Formula
S.rgb * (1 - D.rgb)
Type
Color-based
Behaviour

When S is black, INVERSE_DST does not drawElements anything.

When S is white, INVERSE_DST does full inverse.

Blending::INVERSE_SRC Inverses source color and multiplies it with the destination color.
Formula
(1 - S.rgb) * D.rgb
Type
Color-based
Behaviour

When S is black, INVERSE_SRC does not drawElements anything.

When S is white, INVERSE_SRC draws black.

setColor#


void IRenderer::setColor(const AColor& color)

Sets the color which is multiplied with any brush. Unlike setColorForced, the new color is multiplied by the previous color.

Arguments
color
color

Examples:

examples/app/minesweeper/src/CellView.cpp

Minesweeper Game - Minesweeper game implementation driven by ass.

                    color = 0x808080ffu;
                    break;
            }

            context.render.setColor(color);
            context.render.string({getWidth() / 3, (getHeight() - fs.size) / 2 + fs.getAscenderHeight()}, AString::number(count), fs);
        }
    }
}

setColorForced#


void IRenderer::setColorForced(const AColor& color)

Sets the color which is multiplied with any brush.

Arguments
color
color

setRenderScale#


void IRenderer::setRenderScale(float render_scale)

Controls the rendering scale of images for display only. Does not affect the actual visual appearance or geometry of shapes. Only impacts the sharpness and clarity of rendered images on screen.

setTransform#


void IRenderer::setTransform(const glm::mat4& transform)

Sets the transform matrix which is applicable for any figure. Unlike setTransformForced, the new matrix is multiplied by the previous matrix.

Arguments
transform
transform matrix

setTransformForced#


void IRenderer::setTransformForced(const glm::mat4& transform)

Sets the transform matrix which is applicable for any figure.

Arguments
transform
transform matrix

setWindow#


virtual void IRenderer::setWindow(ASurface* window)

Sets the window to render on.

Arguments
window
target window

squareSector#


virtual void IRenderer::squareSector(const ABrush& brush, const glm::vec2& position, const glm::vec2& size, AAngleRadians begin, AAngleRadians end)

Draws sector in rectangle shape. The sector is drawn clockwise from begin to end angles.

Arguments
brush
brush to use
position
rectangle position (px)
size
rectangle size (px)
begin
begin angle of the sector
end
end angle of the sector

The method can be used as mask to ctx.render.roundedRect, creating arc shape.

string#


virtual void IRenderer::string(glm::vec2 position, const AString& string, const AFontStyle& fs = { })

Draws string.

Arguments
position
string baseline
string
string to render
fs
font style (optional)

This function is dramatically inefficient since it does symbol lookup for every character is the string and does GPU buffer allocations. If you want to render the same string for several times (frames), consider using the IRenderer::prerenderString function or high level views (such as ALabel) instead.

Examples:

examples/app/minesweeper/src/CellView.cpp

Minesweeper Game - Minesweeper game implementation driven by ass.

                    break;
            }

            context.render.setColor(color);
            context.render.string({getWidth() / 3, (getHeight() - fs.size) / 2 + fs.getAscenderHeight()}, AString::number(count), fs);
        }
    }
}

stub#


void IRenderer::stub(glm::vec2 position, glm::vec2 size)

Draws stub (i.e., gray rectangle)

This can be used if implementation does not support or can't draw complex effects (i.e., blur)

translate#


void IRenderer::translate(const glm::vec2& offset)

Wrapper for setTransform applying matrix translate transformation.

Arguments
offset
offset in pixels to translate.

Examples:

examples/app/fractal/src/FractalView.cpp

Fractal Example - Fractal viewer application demonstrating usage of custom shaders.

void FractalView::onScroll(const AScrollEvent& event) {
    AView::onScroll(event);
    auto projectedPos = (glm::dvec2(event.origin) / glm::dvec2(getSize()) - glm::dvec2(0.5)) * 2.0;
    projectedPos.x *= mAspectRatio;
    mTransform = glm::translate(mTransform, glm::vec3 { projectedPos, 0.0 });
    mTransform = glm::scale(mTransform, glm::vec3(1.0 - event.delta.y / 1000.0));
    mTransform = glm::translate(mTransform, -glm::vec3 { projectedPos, 0.0 });

    handleMatrixUpdated();