M MGFX Modern GMod FX

Garry's Mod shader UI renderer

Modern GMod FX

MGFX gives GMod UI shader-level edge quality and efficient immediate draw calls: antialiased masks, rounded primitives, rings, glow, gradients, progress widgets, and composed text without relying on binary stencil edges.

GPU antialiasing Stencil-free shape masks Immediate shader fast paths
GPU AA one-pixel shader coverage edges
No stencil masks that are not hard binary cuts
Fast path shader draws and cached text runs
Renderer composition 14 targets
Squad overlay 0.62 ms
TextEx glow + shadow + gradient face
82
RingEx stroke, pattern, inner glow
MGFX.Mask(kind, spec) rounded, chamfer, circle, capsule, texture
StartPanel ImageEx ProgressBarEx Supports
frame mask paint glow text

Why not just draw/surface?

Built for polished GMod UI, not just pixels on screen

Vanilla Garry's Mod APIs such as draw.RoundedBox, draw.SimpleText, surface.SetMaterial, and surface.DrawTexturedRect are useful primitives, but they leave quality and state management to your panel code. MGFX keeps the immediate mindset while moving edge coverage, masks, glow, strokes, gradients, rings, bars, and composed text into explicit shader-backed records.

Antialiased shader coverage No GMod stencil edge stair-steps Fewer manual passes for rich UI Cached composed text effects
Vanilla GMod draw/surface manual layering
MGFX single style record
ImageEx + TextEx mask, glow, gradient, stroke

Vanilla path: compose effects by hand

render.SetStencilEnable(true)
-- configure a circular stencil mask here
-- the mask edge is still binary, not shader-antialiased

surface.SetDrawColor(255, 255, 255)
surface.SetMaterial(avatarMat)
surface.DrawTexturedRect(x, y, size, size)

render.SetStencilEnable(false)

draw.RoundedBox(8, x, y + 62, w, 8, track)
draw.RoundedBox(8, x, y + 62, w * hp, 8, fill)

for ox = -1, 1 do
    draw.SimpleText(name, font, x + 60 + ox, y, stroke, 0, 0)
end
draw.SimpleText(name, font, x + 62, y + 2, shadow, 0, 0)
draw.SimpleText(name, font, x + 60, y, color_white, 0, 0)

MGFX path: declare the visual result

MGFX.ImageEx(x, y, size, size, avatarMat, {
    fit = "cover",
    mask = MGFX.Mask("circle"),
    outerGlow = {color = accent, width = 12},
})

MGFX.ProgressBarEx(x, y + 62, w, 8, hp, {
    radius = 4,
    fill = MGFX.LinearGradient(0, 0, 1, 0, hpA, hpB),
})

MGFX.TextEx(name, font, x + 60, y, nil, 0, 0, nameStyle)
Concern Original GMod API MGFX
Edge quality GMod stencil masks are binary. They can cut a shape, but they cannot produce soft shader antialiasing at the mask edge, so circles and diagonal cuts stair-step. MGFX shape and image masks use pixel-shader coverage, so rounded boxes, circles, capsules, chamfers, rings, and strokes can keep a stable one-pixel antialiased edge.
Efficiency Rich vanilla UI often means repeated draw.SimpleText offsets, stencil setup, several rounded-box passes, custom geometry, or render-target work for glow-like effects. MGFX pushes supported masks, gradients, strokes, rings, bars, patterns, and text composition through immediate shader fast paths, while stable text runs are cached in atlas pages.
Surface state You set global state with surface.SetDrawColor, surface.SetMaterial, font calls, and render state. A missed reset can leak into the next draw. Each call carries its own fill, stroke, pattern, mask, and effect records. The visual state is local to the primitive.
Advanced image shapes Texture draws are naturally rectangular. Circles, capsules, cut corners, and texture masks usually mean stencil setup, custom materials, or repeated helper code. ImageEx and IconEx accept MGFX.Mask(kind, spec) for circle, capsule, chamfer, rounded, and texture masks without owning stencil plumbing at the call site.
Text effects Shadows, strokes, glow, and fake gradient text usually become several draw.SimpleText calls per label, plus duplicated offsets in every panel. TextEx resolves fill, stroke, glow, shadow, tracking, and line height into a reusable style while the text renderer caches composed runs.
Paint and progress UI Bars, segmented meters, rings, arcs, striped fills, and soft glows are custom geometry or several draw passes that must be kept in sync. ProgressBarEx, SegmentBarEx, RingEx, ArcEx, SectorEx, and gradient or pattern records keep those effects named and repeatable.
Panel and HUD boundaries Vanilla code has no shared frame convention. Panel-local coordinates, screen-space HUD coordinates, clips, and deferred text are each handled manually. StartPanel, StartScreen, PushClip, and the matching end calls define the frame and flush queued text at a predictable point.
Reusable visual language The original API is intentionally low-level, so teams often copy small drawing helpers across scoreboards, HUDs, and Derma panels. MGFX names the reusable pieces: Solid, gradients, patterns, masks, text styles, and *Ex style tables. The same record can drive many panels.
Feature fallbacks When a shader path or visual feature is optional, your code owns every branch and every degraded version. GetCapabilities and Supports let demos and gamemodes gate optional polish explicitly before drawing.

Start here

Quick Start

Install the addon at garrysmod/addons/mgfx. The server loader sends client files and runtime resources, while the client loader includes the shaderpack and demos. Gamemodes should call public MGFX.* functions after the addon has loaded.

function PANEL:Paint(w, h)
    MGFX.StartPanel(self, w, h)

    MGFX.BackdropEx(0, 0, w, h, {
        blur = 8,
        tint = Color(0, 8, 12, 170),
        vignette = 0.35,
        radius = 8,
    })

    MGFX.RoundedBox(
        16, 16, w - 32, 72,
        6,
        Color(5, 18, 26, 185),
        Color(70, 160, 220, 60),
        1
    )

    MGFX.ProgressBarEx(24, 104, w - 48, 10, 0.72, {
        radius = 5,
        track = Color(10, 18, 24, 190),
        fill = MGFX.LinearGradient(0, 0, 1, 0,
            Color(30, 130, 255, 230),
            Color(60, 200, 255, 230)
        ),
    })

    MGFX.EndPanel()
end

Panel frames

StartPanel(panel, w, h) converts the panel origin once. Keep coordinates local to the panel.

Screen frames

StartScreen(w, h) is for HUDPaint or other screen-space rendering.

Flush point

Shape calls render immediately. Text and clip commands are captured during the frame and replayed at EndPanel or EndScreen; draw text after the layers it should appear above.

Mental model

Core Ideas

01

Immediate draw arguments

MGFX does not own layout, input, focus, transitions, component state, or panel lifecycle. Callers compute the current visual state and pass it directly every frame.

02

Name(...) and NameEx(...)

Short positional functions are hot-path helpers. Advanced effects live in the matching table-based Ex call. Positional signatures should stay compact.

03

Explicit paint slots

fill is a color or gradient. Shape patterns use pattern. Progress and segment bars use fillPattern and trackPattern. There is no global fill or stroke state.

04

Shader masks, rectangular clips

Masks are per-primitive shader coverage. PushClip and PopClip are rectangular scissor clips, not general shape-mask stacks.

05

Immediate paths are primary

Shape rendering stays on direct shader/fallback paths. The retired batch prototype is documented as a postmortem, not a runtime feature.

Working patterns

Usage Recipes

These recipes show how MGFX expects callers to compose UI without hidden renderer state.

Hover or selected state

Animate in your panel or UI layer, then pass the current values into MGFX.

local t = self.HoverAmount or 0
MGFX.RoundedBoxEx(0, 0, w, h, {
    radius = 6,
    fill = Color(5 + t * 4, 16 + t * 12, 22 + t * 20, 220),
    stroke = Color(80, 180, 230, 40 + t * 80),
    strokeWidth = 1,
    outerGlow = t > 0 and {
        color = Color(70, 190, 255, 90 * t),
        size = 16,
        opacity = t,
    } or nil,
})

Masked image avatar

Use shader masks for rounded, chamfer, circle, capsule, and texture-mask coverage.

MGFX.ImageEx(x, y, size, size, avatarMaterial, {
    mask = MGFX.Mask("circle"),
    fit = "cover",
    outerGlow = {
        color = Color(76, 190, 255, 70),
        width = 16,
        opacity = 0.7,
    },
})

Reusable text style

Register the font face when MGFX needs to make composed variants such as weight, italic, and CJK-safe effects.

MGFX.RegisterTextFont("ScoreTitle", {
    mode = "composed",
    face = "Bahnschrift",
    size = 34,
    weight = 650,
    lineHeight = 42,
})

MGFX.DefineTextStyle("ScoreTitleGlow", {
    fill = MGFX.LinearGradient(0, 0, 1, 0,
        Color(104, 210, 255),
        Color(255, 204, 112)
    ),
    stroke = {width = 0.9, softness = 0.55, color = Color(2, 9, 12, 185)},
    glow = {size = 7, color = Color(66, 188, 255, 64), opacity = 0.58},
})

MGFX.TextEx("ROUND 4", "ScoreTitle", x, y, nil, TEXT_ALIGN_LEFT, TEXT_ALIGN_TOP,
    MGFX.GetTextStyle("ScoreTitleGlow"))

Capability check

Capabilities describe implemented render slots for immediate shader and fallback paths.

if MGFX.Supports(MGFX.TARGET.RING, "outerGlow") then
    MGFX.RingEx(cx, cy, 44, {
        width = 8,
        fill = Color(80, 210, 170),
        outerGlow = {color = Color(80, 210, 170, 80), width = 18},
    })
end

What MGFX draws

Render Families

Shapes

Rounded boxes, chamfer boxes, circles, capsules, convex polygons, lines, backdrop blur, strokes, patterns, inner glow, and outer glow.

Paint

Solid colors plus linear, radial, conic, multi-stop, and ring/sector-local radial or angular gradients. Pattern records support stripe and smoke fields.

Images

Image and icon drawing with tint, alpha, UV/crop, object fit, background fills, strokes, masks, and mask outer glow.

Widgets

Progress bars, segmented bars, rings, arcs, and straight-edged sectors. These are render widgets, not stateful UI components.

Text

Native-raster composed text with fill, gradient face, outline, glow, shadow, tracking, line height, boxes, and CJK support.

Diagnostics

Console commands expose shader status, immediate draw counters, text cache health, profiler rows, and demo surfaces.

Public surface

API Reference

All coordinates are local to the active frame. Stroke argument order is always fill, stroke, strokeWidth. A nil stroke, nil width, or non-positive width means no stroke.

Frame Scope

MGFX.StartPanel(panel, w, h)Begin a panel-local frame and install the panel base clip.
MGFX.EndPanel()Finish the panel frame and flush queued text commands.
MGFX.StartScreen(w, h)Begin a screen-space frame, typically for HUDPaint.
MGFX.EndScreen()Finish the screen frame and flush queued text commands.
MGFX.PushClip(x, y, w, h)Push a rectangular scissor clip inside the current frame.
MGFX.PopClip()Pop the last rectangular clip.
MGFX.DebugOverlay(x, y)Draw an internal stats overlay for renderer debugging.

Primitives

MGFX.RoundedBox(x, y, w, h, radius, fill, stroke, strokeWidth)Hot-path rounded rectangle.
MGFX.RoundedBoxEx(x, y, w, h, style)Advanced rounded rectangle with radius, fill, stroke, shadow, glow, and pattern.
MGFX.ChamferBox(x, y, w, h, cuts, fill, stroke, strokeWidth)Hot-path chamfered box. Cuts may be scalar or corner table.
MGFX.ChamferBoxEx(x, y, w, h, style)Advanced chamfered box using style.cuts.
MGFX.Poly(points, fill, stroke, strokeWidth)Convex polygon draw. Points are copied at call time.
MGFX.PolyEx(points, style)Advanced convex polygon with fill, stroke, and pattern.
MGFX.Line(x1, y1, x2, y2, width, fill)Line helper. Fill may be solid or gradient.
MGFX.LineEx(x1, y1, x2, y2, style)Advanced line using style.width, caps, radius, and fill/color.
MGFX.Circle(cx, cy, radius, fill, stroke, strokeWidth)Circle helper backed by rounded-box coverage.
MGFX.CircleEx(cx, cy, radius, style)Advanced circle style.
MGFX.Capsule(x, y, w, h, fill, stroke, strokeWidth)Pill/capsule helper with automatic radius.
MGFX.CapsuleEx(x, y, w, h, style)Advanced capsule style.
MGFX.Backdrop(x, y, w, h, blur, tint, vignette)Framebuffer blur/tint/vignette helper.
MGFX.BackdropEx(x, y, w, h, style)Advanced backdrop using blur, tint, vignette, and radius.

Images

MGFX.Image(x, y, w, h, source, radius, tint)General image helper with rounded radius and tint.
MGFX.ImageEx(x, y, w, h, source, style)Advanced image path with fit, crop, uv, mask, outerGlow, background fill, and stroke.
MGFX.Icon(x, y, w, h, source, tint)Icon helper. Defaults to contain fitting.
MGFX.IconEx(x, y, w, h, source, style)Advanced icon path. Defaults to contain if fit is omitted.
MGFX.Mask(kind, spec)Create a mask record for rounded, chamfer, circle, capsule, or texture masks.

Widgets

MGFX.ProgressBar(x, y, w, h, value, radius, track, fill, stroke, strokeWidth)Hot-path progress bar. Value is clamped from 0 to 1.
MGFX.ProgressBarEx(x, y, w, h, value, style)Advanced progress with padding, fx, fillPattern, trackPattern, gradients, and stroke.
MGFX.SegmentBar(x, y, w, h, value, segments, fill, track)Segmented value bar helper.
MGFX.SegmentBarEx(x, y, w, h, value, style)Advanced segments, gap, radius, background, patterns, glow, and stroke.
MGFX.Ring(cx, cy, radius, width, fill)Ring helper.
MGFX.RingEx(cx, cy, radius, style)Advanced ring using style.width, fill, stroke, pattern, innerGlow, and outerGlow.
MGFX.Arc(cx, cy, radius, startDeg, endDeg, width, fill)Arc helper. Angles are degrees.
MGFX.ArcEx(cx, cy, radius, startDeg, endDeg, style)Advanced arc with ring-style paint and effects.
MGFX.Sector(cx, cy, radius, startDeg, endDeg, innerRadius, fill)Straight-edged sector helper for wheel menu wedges.
MGFX.SectorEx(cx, cy, radius, startDeg, endDeg, style)Advanced sector with innerRadius, ring-style paint, stroke, pattern, and glow.

Text

MGFX.RegisterTextFont(name, spec)Register a composed font alias. Include face, size, weight, and lineHeight when effects need variants.
MGFX.DefineTextStyle(name, style)Store a reusable text style record.
MGFX.GetTextStyle(name)Fetch a defined text style.
MGFX.ResolveTextStyle(style)Normalize a text style for reuse.
MGFX.MeasureText(text, font)Measure a single text run.
MGFX.MeasureTextBox(text, font, w, style)Measure wrapped or ellipsized text for a box width.
MGFX.PrewarmText(text, font, style)Bake stable text into the composed atlas before first paint.
MGFX.Text(text, font, x, y, color, ax, ay)Simple text draw.
MGFX.TextEx(text, font, x, y, color, ax, ay, style)Advanced text effects, gradient face, stroke, glow, shadow, tracking, and dynamic route controls.
MGFX.TextBox(text, font, x, y, w, h, color, alignX, alignY)Simple text box draw.
MGFX.TextBoxEx(text, font, x, y, w, h, style)Advanced text box with wrapping, alignment, line height, and effects.

Paint, Patterns, Capabilities

MGFX.Solid(color)Create a solid fill record.
MGFX.LinearGradient(x1, y1, x2, y2, colorA, colorB)Two-stop linear gradient. Coordinates are normalized inside the primitive.
MGFX.LinearGradient(x1, y1, x2, y2, stops)Equivalent to LinearGradientStops for linear ramps.
MGFX.LinearGradientStops(x1, y1, x2, y2, stops)Multi-stop linear gradient. Other gradient helpers also accept stops tables.
MGFX.RadialGradient(cx, cy, radius, colorA, colorB)Radial gradient fill.
MGFX.RingRadialGradient(colorA, colorB)Ring-local radial fill from inner edge to outer edge.
MGFX.SectorRadialGradient(colorA, colorB)Sector-local radial fill from inner edge to outer edge.
MGFX.ConicGradient(cx, cy, rotationDeg, colorA, colorB)Conic gradient using degree rotation publicly.
MGFX.ShapeAngularGradient(colorA, colorB, rotationDeg)Shape-local angular fill mapped over the current arc/sector span.
MGFX.RingAngularGradient(colorA, colorB, rotationDeg)Ring-local angular fill.
MGFX.ArcAngularGradient(colorA, colorB, rotationDeg)Arc-local angular fill from startDeg to endDeg.
MGFX.SectorAngularGradient(colorA, colorB, rotationDeg)Sector-local angular fill from startDeg to endDeg.
MGFX.StripePattern(spec)Stripe pattern. Also accepts positional color, spacing, width, angle, offset.
MGFX.SmokePattern(spec)Procedural smoke pattern with color, scale, density, softness, angle, offset, speed, warp, and seed.
MGFX.GetCapabilities(target)Return implemented style keys and metadata for a target.
MGFX.Supports(target, key)Check whether a target supports a public render slot.

Detailed usage

How to read and combine the API

The short functions are small hot-path helpers. The Ex functions take a style table so new fields can be added without growing positional signatures.

Signature rules

x, y, w, h values are active-frame local pixels. Optional stroke always means fill, stroke, strokeWidth. Advanced calls copy and normalize style records, so keep caller-owned tables mutable on your side only.

  • Name(...)compact helper for common draw paths
  • NameEx(..., style)table API for effects, per-corner values, masks, and patterns
  • nilomit optional paint, stroke, or effect fields cleanly

Frame scope

Call StartPanel / EndPanel inside panel paint, or StartScreen / EndScreen inside HUD paint. Shapes draw immediately; text commands are recorded and flushed at the frame end.

function PANEL:Paint(w, h)
    MGFX.StartPanel(self, w, h)
    MGFX.RoundedBoxEx(0, 0, w, h, {
        radius = 10,
        fill = Color(20, 24, 32, 230),
    })
    MGFX.Text("Loadout", "DermaLarge", 16, 14, color_white)
    MGFX.EndPanel()
end

Primitive styles

Use RoundedBoxEx, ChamferBoxEx, LineEx, and shape Ex calls when the draw needs glow, shadow, pattern, per-corner radius, or named fields.

  • radiusnumber or corner table: tl, tr, br, bl
  • cutsnumber or corner table clamped to half the smaller side
  • fillColor or MGFX gradient record
  • patternStripePattern or SmokePattern for supported shape paths

Image sources and fitting

source may be a material path, Material-like object, or texture-like object. Use fit for layout, crop or uv for source region, and position for cover/contain alignment.

fitfill/stretch, cover, contain
position{x = 0.5, y = 0.5}, or alignX/alignY
cropnormalized {x, y, w, h}, or pixel crop with pixels = true
uv{u0, v0, u1, v1}; aliases x0/y0/x1/y1 and array values work

MGFX.Mask(kind, spec)

MGFX.Mask returns a copied mask record. The renderer normalizes it when used as style.mask in ImageEx or IconEx. Pass false or "none" to disable masking; omit mask and set style.radius for a rounded image shortcut.

rounded spec.radius is a number, true, "circle", percent string, or px string. Aliases: round, roundedbox, roundrect.
chamfer spec.cuts is a number or {tl, tr, br, bl} table. Default is 0. Alias: bevel.
circle No spec required. Uses half of the smaller rendered side after fit/crop layout.
capsule No spec required. Uses automatic pill radius across the rendered rectangle. Alias: pill.
texture Uses source, material, texture, or image as the mask texture. channel accepts a/alpha, r/red, g/green, b/blue, or luma/lum/luminance/rgb. Aliases: alpha, image.
false / "none" Disables mask normalization even when the surrounding image style has a radius.

Circle avatar

MGFX.ImageEx(x, y, 48, 48, avatarMat, {
    mask = MGFX.Mask("circle"),
    fit = "cover",
})

Rounded card image with stroke

MGFX.ImageEx(x, y, w, h, material, {
    mask = MGFX.Mask("rounded", {radius = 10}),
    fit = "cover",
    stroke = Color(255, 255, 255, 40),
    strokeWidth = 1,
})

Texture-channel mask

MGFX.ImageEx(x, y, w, h, source, {
    mask = MGFX.Mask("texture", {
        source = maskMaterial,
        channel = "a",
        invert = false,
        uv = {u0 = 0, v0 = 0, u1 = 1, v1 = 1},
    }),
})

Text and dynamic values

Use RegisterTextFont for font aliases, DefineTextStyle for reusable effect records, and PrewarmText for stable labels. dynamic = true keeps changing values on the composer route.

MGFX.TextEx(scoreText, "MGFXScoreStat", x, y, nil,
    TEXT_ALIGN_RIGHT, TEXT_ALIGN_TOP, {
        fill = MGFX.LinearGradient(0, 0, 1, 0,
            Color(255, 255, 255), Color(130, 210, 255)),
        glow = {size = 4, color = Color(80, 170, 255, 110)},
        dynamic = true,
    })

Paint values

Paint records are plain values passed into explicit slots. Shapes use fill and optional pattern; progress widgets split visible paint into track, fill, trackPattern, and fillPattern.

local fill = MGFX.LinearGradientStops(0, 0, 1, 0, {
    {0.00, Color(80, 170, 255)},
    {0.55, Color(90, 220, 180)},
    {1.00, Color(255, 210, 110)},
})

MGFX.ProgressBarEx(x, y, w, 10, value, {
    radius = 5,
    track = Color(255, 255, 255, 22),
    fill = fill,
    fillPattern = MGFX.StripePattern({
        color = Color(255, 255, 255, 42),
        spacing = 10,
        width = 1.5,
    }),
})

Per-function reference

Dedicated Usage For Every API

Each public function below has its own section with parameters, behavior notes, return value where relevant, and a practical Lua example.

Table-based calls

Style Keys

Advanced APIs normalize styles early, then immediate shader and fallback paths consume the same canonical data.

Common shape keys

{
    fill = Color(...) or MGFX.LinearGradient(...),
    stroke = Color(...),
    strokeWidth = 1,
    radius = 8,
    shadow = {...},
    innerGlow = {color = Color(...), size = 10, opacity = 0.6, softness = 0.55},
    outerGlow = {color = Color(...), size = 18, opacity = 0.6, softness = 0.55},
    pattern = MGFX.SmokePattern(...),
}

Image keys

{
    radius = 8,
    tint = Color(...),
    alpha = 0.9,
    fit = "cover", -- fill, contain, cover
    position = {x = 0.5, y = 0.5},
    crop = {x = 0, y = 0, w = 1, h = 1},
    uv = {u0 = 0, v0 = 0, u1 = 1, v1 = 1},
    mask = MGFX.Mask("chamfer", {cuts = {tl = 8, tr = 0, br = 8, bl = 0}}),
}

Progress keys

{
    radius = 8,
    padding = 2,
    track = Color(...),
    fill = MGFX.LinearGradient(0, 0, 1, 0, Color(...), Color(...)),
    stroke = Color(...),
    strokeWidth = 1,
    fx = {
        glow = true,
        sheen = true,
        marker = true,
        ticks = 6,
    },
    fillPattern = MGFX.StripePattern(...),
    trackPattern = MGFX.SmokePattern(...),
}

Text keys

{
    fill = Color(...) or MGFX.LinearGradient(...),
    stroke = {width = 0.6, color = Color(...), softness = 0.6},
    glow = {size = 5, color = Color(...), opacity = 1, softness = 0.58},
    shadow = {x = 0, y = 2, blur = 3, color = Color(...)},
    surface = {strength = 0.1},
    weightAdjust = 0.4,
    bold = true,
    thin = true,
    italic = true,
    tracking = 0,
    lineHeight = 24,
    alignX = TEXT_ALIGN_LEFT,
    alignY = TEXT_ALIGN_TOP,
}

Postmortem

Retired Shape Batch

MGFX no longer exposes shape batching controls. The retired shape/data-texture prototype is documented as a design record for future experiments, while current shapes render through immediate shader and fallback paths.

Why it was removed

shape/data batch enabled:
  FPS roughly 50-90
  commandLoop up to ~10 ms
  actual batchDraws near zero

shape queue disabled:
  FPS roughly 130-140
  commandLoop ~0.0075 ms

Lua-side scheduling, rules, barriers, data texture prep, material state work, and broad shader coverage outweighed the draw-call reduction in representative GMod UI.

Lessons preserved

  • Measure data texture upload cost separately before adding a data path.
  • Avoid expensive per-command candidate detection on frames with no useful batch.
  • Assume real UI streams are heterogeneous and frequently interrupted.
  • Keep visual parity mandatory for AA, stroke, gradient, alpha, and clip.
Runtime batch hooks removed Batch shaders removed Text composer unchanged Future work must prove real-frame wins

Composer-only route

Text Renderer

MGFX removed the old runtime SDF route. Current text uses native GMod glyph rendering baked into persistent 2048x1024 atlas pages, then composes effects through mgfx_text_compose.

1

Text, TextEx, TextBox, and TextBoxEx record text commands during a frame.

2

The renderer resolves native font and style into a cache key.

3

On a miss, the whole text run is rasterized once into an atlas page with transparent gutter.

4

Normal frames blit cached atlas regions through a shader that composes shadow, glow, outline, and face fill.

Best fit

Stable or moderately changing text: scoreboard labels, player names, headings, status labels, and repeated table cells.

Dynamic values

dynamic = true forces glyph-composer rendering. dynamic = "auto" observes churn but currently stays on the whole-run route until glyph batching exists.

Health checks

mgfx_text_status should show fallback, evicts, fallbackBatches, fallbackRecords, prewarmFails, and prewarmRestarts near zero for a healthy stable frame.

Build and package

Shaders & Packaging

Rebuild shaderpack

python .\shadersrc\mgfx\build.py

The script compiles the shader list, packs generated *.vcs files into an in-memory GMA, and writes lua/mgfx/cl_mgfx_shaderpack.lua. The shaderpack version is a Unix timestamp.

Runtime resources

lua/autorun/client/mgfx_loader.lua
lua/autorun/server/mgfx_loader.lua
lua/mgfx/*.lua
materials/mgfx/scoreboard_atlas.png
resource/fonts/notosanssc-vf.ttf

Shader source, tools, Markdown docs, and this docs website are excluded from addon packaging.

GMod shader rule: generated materials need explicit UV care, and shader fast paths must match immediate/fallback output instead of approximating it.

Maintenance map

Architecture

cl_mgfx.lua is the client composition root. It wires modules together and keeps rendering implementation in focused files.

cl_mgfx_materials.luaShaderpack mount, render targets, material creation, and shader status.
cl_mgfx_style.luaPublic style normalization, fills, gradients, patterns, radius, stroke, and glow helpers.
cl_mgfx_capabilities.luaTarget capability matrix and paint-slot normalization.
cl_mgfx_commands.luaReader boundary for queued text and clip commands.
cl_mgfx_frame.luaText command capture, clip stack, and frame flush.
cl_mgfx_roundrect.luaRounded boxes, circles, capsules, immediate fill/stroke/glow/pattern paths.
cl_mgfx_primitives.luaChamfer boxes, lines, convex polygons, and backdrops.
cl_mgfx_widgets_*.luaBars, rings/arcs, images/masks, and text draw-call bridge.
cl_mgfx_text.luaComposer-only text renderer and atlas cache.
cl_mgfx_demo.luaPublic API demos and dev-facing examples.

Runtime diagnostics

Commands & Cvars

Commands

mgfx_status mgfx_selftest mgfx_reload mgfx_hot_reload mgfx_demo mgfx_demo_close mgfx_scoreboard_demo mgfx_scoreboard_demo_close mgfx_text_status mgfx_text_cache_clear mgfx_text_composed_clear mgfx_text_demo mgfx_profile_status mgfx_profile_reset

Client cvars

mgfx_force_fallback 0/1 mgfx_profile 0/1 mgfx_draw_counts 0/1 mgfx_profile_window 120 mgfx_profile_top 18 mgfx_text_composed 0/1 mgfx_text_composed_budget 6

Field notes

Troubleshooting

Shader fallback

Run mgfx_status. Confirm shaderpack version, mount name, and material statuses. Use mgfx_force_fallback 1 to compare fallback output.

Immediate hotspots

Use mgfx_profile 1, optionally mgfx_draw_counts 1, and mgfx_status to compare round.*, image.*, line.*, and paintBuild timings. Disable both cvars for real FPS checks.

Text first-paint cost

Prewarm stable strings and watch mgfx_text_status. Increase mgfx_text_composed_budget carefully if too many strings miss at once.

Package validation

Use gmad.exe create -folder "garrysmod/addons/mgfx" -out "%TEMP%/mgfx.gma". Runtime contents should stay Lua, the scoreboard atlas, and the lowercase bundled TTF.