V2 · LICENSED
Viewport onion skin renderer for Maya 2022–2026 · Long Winter Studios

How It Works

AXE Onion hooks into Maya's VP2 renderer at a low level. It does not bake meshes, create display layers, duplicate geometry, or write anything to the scene graph. Every frame that passes through the viewport is quietly stored in a GPU-side render target, and those stored frames are composited back over the live viewport in real time as you scrub.

1
MRenderOverride Registration

On Toggle Renderer, a custom MRenderOverride named axe_onion is registered with VP2 and assigned to the active model panel. From this point Maya routes its entire render loop through AXE Onion's pass stack instead of the default renderer.

2
Per-Frame Capture (onionSkinPass)

Each time the timeline moves, the tracked objects (those in the axe_onion_objects Maya set) are rendered into a dedicated off-screen RGBA render target keyed by frame number. This is the "buffer fill" step — it's how the tool learns what your geometry looks like at any given frame.

3
Standard Scene Render (standardPass)

The live scene is rendered normally into the main render target, exactly as VP2 would without the override. This gives you your normal working view.

4
Ghost Blend Passes (OSQuadRender)

For each visible ghost frame (e.g. −2, −1, +1, +2), a full-screen quad pass composites the stored buffer target for that frame back over the current view. The OGSFX/FX shader handles the tint colour, opacity, and the outline/solid display mode. Passes farther from the current frame receive lower opacity automatically (stepping down ~15% per step, floored at 20%).

5
Current Frame Outline (OSCurrentFramePass)

A separate quad pass renders an orange outline of the current frame's geometry on top of everything — useful as a registration marker when scrubbing through dense ghost stacks.

6
HUD + Present

Maya's normal HUD (frame counter, camera info, etc.) is re-composited on top, and the result is presented to the viewport. From the user's perspective the viewport looks and behaves normally — just with ghosts overlaid.

Clean slate on every Toggle. The override is fully destroyed and rebuilt each time you press Toggle Renderer. This prevents stale GPU state, leaked render targets, or orphaned callbacks from accumulating across sessions. If anything looks wrong, toggling off and on is always the first fix.

UI Reference

Control What it does
Target Objects list Shows every mesh being tracked. Greyed-out entries mean the node no longer exists in the scene. Internally backed by a Maya object set (axe_onion_objects) so it survives scene saves within a session.
Add Selected Adds the current Maya selection to the tracking set. Works with transforms, shape nodes, or mixed selections — the tool flattens everything to DAG paths internally.
Clear All Removes all tracked objects and clears the render buffer. The Maya set is deleted. Equivalent to starting fresh without ending the session.
Onion Skin Frames (bracket slider) Two-handle slider. Drag the pink left handle to set how many past frames are shown. Drag the green right handle to set future frames. Range is 0–8 in each direction. Default ±1.
Display Mode — Solid / Outline Toggles the OGSFX shader between a filled alpha blend (Solid) and a silhouette outline only (Outline). Outline mode is cleaner for dense scenes; Solid is more readable for large, simple geometry.
Outline Width slider Controls the pixel width of outlines (both ghost outlines and the current frame orange ring). Active in both display modes. Default 3px.
Draw Behind When enabled, ghost outlines are composited behind the current frame's shaded geometry rather than on top of it. Useful when you want the live mesh unobscured while still seeing motion trails in negative space around it.
Toggle Renderer Activates or deactivates the VP2 override on the currently active model panel. On activation: fully destroys any previous instance, builds a fresh one, re-applies all settings, and re-syncs the object list. On deactivation: tears down the override and restores the panel to default VP2.
End Session The correct way to close the tool. Saves settings, clears the viewport override, destroys the renderer, deletes the Maya object set, and closes the window. Use this instead of the OS window close. The window intentionally has no OS close button for this reason.
⚙ → Clear Buffer Manually releases all stored render targets and resets the frame cache. Use this if ghosts are showing stale data after a major scene change (e.g. a large move of the camera rig).
⚙ → Auto Clear Buffer When enabled (default), the buffer automatically clears whenever the active camera's world matrix changes — i.e., when you move or tumble the camera. Prevents ghosts from "floating" in world space if you reframe. Disable it if you're on a locked shot and want to preserve the buffer across tumbles.
⚙ → Preferences Opens a dialog with: Maximum Buffer Size (max frames stored before oldest entries are evicted, default 200), Tint Seed (offset for randomised tint palette).
⚙ → Save Settings Writes current UI state to settings.txt in the tool folder. Settings are also saved automatically on End Session and on frame range changes.

Colour Coding

Ghost colours are fixed and intentional — they encode temporal direction so you can read motion at a glance without counting frames.

Cyan-Green
rgb(18, 255, 188)
Future frames — where the pose is going.
Hot-Pink
rgb(255, 50, 140)
Past frames — where the pose came from.
Orange
rgb(255, 123, 74)
Current frame outline — your live position.
Ghost opacity decreases with distance from the current frame. Frame ±1 renders at 75%, ±2 at 60%, ±3 at 45%, and so on down to a floor of 20%. This falloff is automatic and cannot currently be adjusted per-frame in the UI.

The Buffer System

AXE Onion stores one GPU render target per visited frame. Each target is a full-resolution RGBA texture matching your current viewport dimensions. The buffer is a key-value map: frame_number → render_target.

F1
past
evicted
F10
past
F11
past −1
F12
current
F13
future +1
F14
future
?
not yet
visited

Unvisited frames show no ghost. A frame only enters the buffer the first time the timeline lands on it and the renderer is active. If you jump to frame 100 without scrubbing through 50–99, those frames are unknown to the tool and no ghost will appear.

The buffer cap (default 200 frames) evicts the oldest entry when full, using a simple FIFO queue. At 1080p an RGBA target is roughly 8 MB, so 200 frames ≈ 1.6 GB of VRAM. Reduce this number in Preferences if you're on a constrained card. Increase it for long shot scrubbing workflows.

Buffer is camera-aware. With Auto Clear enabled, any change to the camera's world matrix flushes the buffer. This is necessary because the captures are screen-space composites — a camera move would make old ghosts appear to drift relative to the new view.

Viewport resize clears the buffer. Render targets are sized to the current viewport resolution at the moment they were captured. If you resize the viewport (including docking/undocking panels) the existing captures become the wrong size and the buffer auto-clears on the next scrub.
Buffer does not survive across Toggle cycles. When you click Toggle Renderer off and back on, the entire renderer is rebuilt from scratch and the buffer starts empty. This is intentional — it guarantees a clean GPU state.

Display Modes

Two modes control how the OGSFX shader renders ghost frames onto the viewport. The choice affects readability depending on your geometry's complexity and how dense your frame stack is.

Mode How it renders Best for
Outline Renders a silhouette edge ring around the ghost geometry. The interior is transparent. Uses the Outline Width value to set pixel thickness. Dense scenes, many objects, overlapping character parts. Much easier to read when you have 4–8 ghost frames active.
Solid Renders the ghost as a filled, alpha-blended silhouette. No edge detection — the entire mesh area is tinted and composited at the layer opacity. Simple geometry, large-limbed characters, broad motion arcs. Easier to see mass and volume at a glance.
The Draw Behind toggle works with both modes and is independent of display mode. In Solid mode, Draw Behind is often desirable to prevent the ghost fill from obscuring your current mesh. In Outline mode it matters less since the ghost interior is already transparent.

FAQ

I scrub the timeline but no ghosts appear

Three things to check in order:

1. Is the renderer active? The Toggle Renderer button must be pressed (lit) and the override must be assigned to the panel you're looking at. If you have multiple viewports, the override is only on the panel that was active when you clicked Toggle.

2. Are objects in the list? Ghosts only render for objects explicitly added via Add Selected. An empty target list means the capture pass has nothing to record.

3. Have those frames been visited? The buffer only contains frames you've actually scrubbed through. Jump to the current frame, then scrub backward and forward one frame at a time — you should see ghosts appear on the first pass. Future frames won't have data until the timeline reaches them.

Ghosts show old poses, not the current animation

The buffer caches captures by frame number. If you've edited the animation since those frames were buffered, the stored captures are stale. Use ⚙ → Clear Buffer to flush the cache, then scrub through the affected range again to rebuild it with current data.

This also applies after any rig change, mesh edit, or constraint modification — anything that changes the visible shape of the tracked objects at frames that are already in the buffer.

Ghosts are floating / not aligned with the geometry

The most common cause is camera movement. AXE Onion composites stored screen-space images, not 3D geometry — so if the camera moved between the time a frame was captured and now, the ghost will appear offset from the actual pose's world position.

With Auto Clear Buffer enabled (default), any camera matrix change automatically flushes the buffer. If you disabled this, re-enable it, or manually clear the buffer after repositioning the camera.

If the camera hasn't moved and ghosts are still misaligned, check if the mesh itself is parented under something that has been repositioned (e.g. a character rig root). The buffer captures world-space projections, so reparenting or moving the root after capture will create drift.

Performance drops noticeably with the renderer active

Each active ghost frame adds one full-screen quad render pass to the VP2 pipeline. At ±4 frames (8 ghosts + current frame outline) you have 9 extra passes per viewport refresh. This is by design and is usually fast, but a few things can compound the cost:

High viewport resolution. Render targets are full-resolution. Drop your viewport to a smaller size if performance is critical during a scrub session.

Large buffer size. The buffer cap doesn't affect runtime performance (passes are keyed to the visible range, not the buffer size), but a large cap means more VRAM allocation over a long session. This can cause indirect slowdowns via VRAM pressure on lower-spec GPUs.

Too many ghost frames. Keeping the bracket at ±1 or ±2 rather than ±8 cuts pass count significantly. Use the minimum range that gives you the motion read you need.

The renderer gets stuck / viewport goes black after a crash

If Maya crashes or the tool's UI is force-closed without going through End Session, the VP2 override can be left registered with no UI to control it. On next launch the tool should clean this up automatically. If it doesn't, or if the viewport is black mid-session, use the emergency kill script below.

See the Emergency Kill section for the exact Python snippet to run from the Script Editor.

Adding objects to the list clears my existing ghosts

This is expected and intentional. When the object list changes, the tool clears the buffer to prevent a mismatch between what's stored (captures of the old object set) and what will be rendered as ghosts going forward. Adding a new mesh and immediately seeing ghosts of only that mesh would be confusing and incorrect.

After adding objects, scrub through your range again to rebuild the buffer with the updated set.

I have multiple viewports — which one gets the override?

Whichever panel is the active view at the moment you press Toggle Renderer. Click inside the panel you want first to make it active, then toggle on. The override is applied to exactly one panel at a time.

You can verify which panel has the override by checking modelEditor -q -rendererOverrideName in the Script Editor — the panel running axe_onion is the active one.

If you want to move the override to a different panel, toggle off, click the new panel to activate it, then toggle on again.

End Session vs. just closing the window — does it matter?

Yes, significantly. End Session is the safe shutdown path: it saves settings, explicitly deregisters the MRenderOverride from VP2, deletes the Maya object set, and cleans up all callbacks before the Qt window is destroyed.

The window is deliberately designed without an OS close button (the × in the title bar) to prevent accidental bypasses. If you do find a way to close the window without End Session (e.g. via Python), the override may stay registered in VP2 even though the UI is gone, potentially causing issues on the next launch. If this happens, use the emergency kill script to clean up.

Will my settings persist between Maya sessions?

Yes. Settings are saved to settings.txt (JSON) inside the axe_onion/ folder whenever you click Save Settings, change the frame range, or use End Session. On the next launch the tool loads this file and restores: Draw Behind, Auto Clear Buffer, display mode, outline width, frame range (past/future), buffer size, and tint seed.

The buffer itself is never saved — it lives only in VRAM for the duration of the session. Object list membership also resets between sessions since the Maya set (axe_onion_objects) is deleted on End Session.

Does it work with referenced characters / namespace objects?

Yes. The tool tracks objects by full DAG path, which includes namespaces. Select the geometry normally in the viewport (not via the outliner necessarily) and click Add Selected — the full path including any namespace: prefix is stored correctly.

Be aware that if the reference is reloaded or the namespace changes, the stored path becomes stale. The item will appear greyed-out in the list. Remove it and re-add with the new path.

Can I use it on deforming geometry (blend shapes, skin)?

Yes — this is the primary use case. The capture is a render of the evaluated mesh at the moment of capture, so deformed shapes, blend shapes, skin deformation, and cloth simulations are all captured correctly. What you see in the viewport is exactly what gets stored.

What about GPU memory — how much does it use?

Each stored frame is one RGBA render target at your current viewport resolution. Rough sizes:

1280×720 → ~3.7 MB per frame
1920×1080 → ~8.3 MB per frame
2560×1440 → ~14.7 MB per frame
3840×2160 → ~33.2 MB per frame

At the default cap of 200 frames, 1080p usage tops out around 1.65 GB VRAM. If you're on a card with 8 GB or more this is comfortable. On a 4 GB card you may want to reduce the cap to 50–80 frames via Preferences.

VRAM is reclaimed immediately on Clear Buffer, Toggle Off, or End Session.

The license dialog appears every time I open Maya

After a successful activation the token is cached to disk automatically. If the dialog reappears, the most likely cause is that the axe_onion/ folder is in a read-only location and the token file can't be written. Move the folder somewhere your user account has write access (the default scripts directory is fine) and activate again.

You can check where the token is stored by inspecting axe_onion/license.py — look for the TOKEN_PATH variable.

Emergency Kill

If the renderer becomes stuck — viewport rendering incorrectly, tool UI missing but override still active, or Maya complaining about a duplicate override on launch — run this from the Script Editor (Python tab). It is safe to run at any time.

Run this only if the tool is misbehaving. Under normal operation, End Session handles all cleanup. This script is a manual override for edge cases.
# AXE Onion — emergency kill # Paste into Script Editor → Python tab → Execute All import maya.cmds as cmds import maya.api.OpenMayaRender as omr # Step 1 — clear the override from every model panel for panel in (cmds.lsUI(editors=True) or []): if 'modelPanel' in panel: try: if cmds.modelEditor(panel, q=True, rendererOverrideName=True) == 'axe_onion': cmds.modelEditor(panel, e=True, rendererOverrideName='') except: pass # Step 2 — destroy the renderer instance try: import axe_onion.core as core if core.OSR_INSTANCE is not None: core.OSR_INSTANCE.deleteCallbacks() omr.MRenderer.deregisterOverride(core.OSR_INSTANCE) core.OSR_INSTANCE.destroy() core.OSR_INSTANCE = None print("AXE Onion: override cleared.") except Exception as e: print("AXE Onion kill error: %s" % e)
After running the kill script, you can relaunch normally with import axe_onion.controller as osr; osr.show() from the Script Editor.

Requirements

Maya Version
2022, 2023, 2024, 2025, 2026
Renderer
Viewport 2.0 (VP2) — default in all versions
Python
Python 3 (bundled with Maya 2022+)
Qt Binding
PySide2 (Maya 2022–2024) or PySide6 (Maya 2025+) — auto-detected
GPU
Any VP2-compatible card. 8 GB VRAM recommended at default buffer settings.
OS
Windows, macOS, Linux — any platform that runs VP2