AXE Lens replaces Maya's standard VP2 renderer with a custom MRenderOverride that runs a multi-pass post-process pipeline on top of the normal scene render. Click ACTIVATE to swap the renderer; click again to revert. Every parameter change updates in real time — no toggle required after activation.
The C++ plugin axe_lens_override.mll registers an override named AXELensOverride with VP2. Activation routes modelPanel4 through this override via setRendererInModelPanel. Deactivation routes it back to vp2Renderer. The override intercepts the full render loop — scene render, HUD, and present.
All 18 post-process parameters live as Maya optionVars (prefixed axeLensPost_). Every UI interaction writes to optionVars first, then calls axeLensSetParams — a custom MEL command registered by the C++ plugin — which flushes the current optionVar values into the override's uniform state. This means settings survive Maya restarts and can be set from any Python or MEL script without opening the UI.
Each post-process pass runs as a full-screen quad render using an OGSFX (OpenGL Shading Framework) shader. The shaders are loaded from a shaders/ folder alongside the plugin and are hot-reloadable without a Maya restart. Six shader files handle distinct passes: the main grade, bloom threshold, bloom blur (Gaussian), bloom composite, geometry outline (Sobel edge detection), and the final blit to the viewport.
A permanent scriptJob fires on PostSceneRender and calls push_params() in the bridge. This ensures parameters are re-pushed to the C++ side after every scene render — catching edge cases where VP2 resets its override state (e.g. after a panel focus change or a hardware renderer reset via ogs -reset).
setRendererInModelPanel "AXELensOverride" yourPanelName;Passes execute in a fixed order each frame. Each pass reads from an off-screen render target and writes to the next. The bloom and outline passes are skipped entirely when their respective enables are off — zero shader cost when not in use.
| Parameter | Range | Default | What it does |
|---|---|---|---|
| Filmic Tonemapping | On / Off | On | Applies the Hable filmic curve (the same curve used in Uncharted 2 and widely adopted in games/film pipelines). Compresses bright highlights into a pleasing roll-off rather than hard clipping. Leave On unless you need a purely linear comparison pass. |
| Exposure | 0.1 – 4.0 | 1.0 | Linear multiplier applied before tonemapping. Scales the entire image up or down in linear light. 1.0 = no change. Boosting exposure before a filmic tonemap is the correct way to brighten a scene without losing highlight detail. |
| Contrast | 0.5 – 2.0 | 1.08 | S-curve pivot at 0.5 applied after tonemapping. Values above 1.0 push darks darker and brights brighter. Values below 1.0 flatten the image toward grey. |
| Saturation | 0.0 – 2.0 | 1.08 | Mixes between greyscale (0.0) and full colour (1.0) and beyond to hypersaturation (2.0). Uses luminance-preserving interpolation so brightness doesn't shift with saturation changes. |
| Sharpen | 0.0 – 3.0 | 0.0 | Unsharp mask. Subtracts a 4-tap blur from the original and adds the difference back, scaled by this value. Runs pre-tonemap. Higher values increase perceived crispness but will exaggerate compression artefacts on noisy geometry. |
| Color Temp | −1.0 – +1.0 | 0.0 | Shifts the RGB balance toward warm (orange-red) at positive values or cool (blue) at negative. Implemented as a channel offset: positive boosts R/G slightly and reduces B; negative does the inverse. More subtle than saturation — good for mood without obvious hue shifts. |
| Vignette Strength | 0.0 – 1.0 | 0.5 | How dark the vignette gets at the corners. 0 = no vignette, 1 = fully black corners. |
| Vignette Radius | 0.0 – 0.7 | 0.35 | How far the vignette extends inward from the edges. Smaller values push the dark area closer to the centre. Values above ~0.5 begin to encroach noticeably on the image. |
| Parameter | Range | Default | What it does |
|---|---|---|---|
| Enable Bloom | On / Off | Off | Activates three additional render passes (threshold → blur → composite). No cost when off. |
| Threshold | 0.0 – 1.0 | 0.75 | Luminance cutoff for the bright pass. Only pixels brighter than this value contribute to the bloom. Lower thresholds create broad, diffuse glows across mid-tones; higher thresholds restrict bloom to only the brightest specular or emissive areas. |
| Strength | 0.0 – 2.0 | 0.35 | Additive blend weight of the blurred bright pass. Higher values make the glow more intense. Values above 1.0 can cause noticeable overbright halos — useful for neon/fantasy looks but not for naturalistic rendering. |
| Radius | 0.5 – 4.0 | 1.5 | Controls how far the Gaussian blur spreads the bright-pass pixels. Larger values create wider, softer glows. Higher values also carry a proportionally higher GPU cost on large viewports. |
| Parameter | Range | Default | What it does |
|---|---|---|---|
| Enable Outline | On / Off | Off | Activates Sobel edge detection on the geometry buffer. Runs on the pre-grade scene output so edges are always crisp. |
| Thickness | 1.0 – 8.0 | 2.0 | Pixel width of detected edges. |
| Strength | 0.0 – 1.0 | 1.0 | Opacity of the outline over the scene. Lower values give a ghosted, subtle line; 1.0 is fully opaque. |
| Color | RGB swatch | AXE cyan | Line colour. Click the swatch to open the colour picker. Each look preset overrides this with its own paired outline colour where applicable. |
push_params() calls 50ms apart. This is intentional — the first call sets the enable flag, and the second ensures the C++ override has fully recalculated its pass routing before VP2 draws the next frame. You may see a single dropped frame on toggle. This is expected.Looks are one-click preset combinations of all 18 post-process parameters. Selecting a look updates every slider and checkbox in the UI and immediately pushes to the override. You can then tweak individual parameters freely after applying a look — it's a starting point, not a lock.
The Quality accordion section controls Maya's hardwareRenderingGlobals node — the VP2 renderer settings that govern SSAO, MSAA, HDR buffer, and line anti-aliasing. These are independent of the post-process pipeline and apply regardless of whether AXE Lens is activated.
| Preset | SSAO | MSAA | HDR Buffer | Best for |
|---|---|---|---|---|
| PERFORMANCE | Off | Off (1×) | Off | Blocking, quick turnaround, low-spec GPU, playback scrubbing |
| BALANCED | On (16 samples) | On (4×) | On | Day-to-day animation work — good quality without heavy SSAO cost |
| QUALITY | On (32 samples) | On (8×) | On | Presentation screenshots, review sessions, hero shot work |
hardwareRenderingGlobals and to axeLens_* optionVars. On next launch, restore_from_optionvars() (called from userSetup) reapplies the last-used preset. If you want to go back to Maya's factory defaults and stop auto-restoring, click RESET ALL in the status bar — this removes all axeLens_* optionVars.Saved Lenses are named snapshots of all 18 post-process parameters. They persist via Maya optionVars and survive across scenes and restarts. Use them to save a calibrated look for a specific show, shot type, or playblast style.
| Action | How it works |
|---|---|
| Save | Type a name in the text field and click SAVE (or press Enter). The current values of all 18 post-process parameters are written to individual optionVars keyed as axeLensSaved_{name}_{param}. The lens name is added to an index optionVar (axeLensSaved__index) as a ||-delimited list. |
| Load | Click the lens name in the list. Values are copied from the saved optionVars into the live axeLensPost_* optionVars, the UI is refreshed, and push_params() fires twice (50ms apart) to ensure the outline routing recalculates. Any active look button is deselected. |
| Delete | Click the ✕ next to a saved lens. Removes all 18 param optionVars for that name and updates the index. This cannot be undone. |
axeLensSetParams() with your studio-approved values directly.The most common cause is that axe_lens_override.mll is not loaded. The ACTIVATE button calls bridge.activate(), which loads the plugin if needed — but if the module path isn't on Maya's plugin search path, the load will silently fail.
Check the Script Editor for a warning like AXE Lens Bridge: could not load plugin. If present, ensure the axeLens.mod file is in a directory Maya scans for modules (Documents/maya/modules/ on Windows) and that it correctly points to the build folder for your Maya version.
Also confirm VP2 is the renderer in modelPanel4 before activating. AXE Lens replaces the VP2 renderer — if the panel is running Legacy Viewport, the override assignment has no effect.
The PostSceneRender scriptJob in the bridge is designed to catch exactly this. If it gets killed — by a Maya crash recovery, a forced scene load, or another tool that clears all scriptJobs — the params won't be re-pushed automatically.
Fix: call from axe_lens_override.python import axe_lens_bridge as b; b.install() from the Script Editor to reinstall the scriptJob. Or simply close and reopen the AXE Lens panel, which reinstalls the bridge on open.
Bloom is additive on top of the grade pass output, so there must be pixels bright enough to survive the threshold filter. In a typical VP2 scene with default lighting and a gamma-corrected output, many surfaces are below 0.75 in luminance even if they look bright — especially with the Hable tonemap engaged, which compresses highlights.
Try lowering the Threshold to 0.4–0.5, or temporarily boosting Exposure above 1.5 to push more pixels above the threshold. Once you can see the bloom, adjust back to taste.
Also check that the HDR float buffer is enabled (Quality → HDR float buffer). Without floating-point precision the bright pass has limited dynamic range to work with and bloom will be weak or absent.
The Sobel edge detection reads from the depth and normal buffer. In VP2 every geometric edge produces a depth or normal discontinuity, so all visible edges get detected — including internal edge loops and flat-shaded faces.
To get cleaner silhouette-only outlines: lower the Strength slider (0.3–0.5) so interior edges are less visible, and keep Thickness at 1.0. This mimics a silhouette-only look without actually changing the detection algorithm.
For rig review, the RIG look uses exactly this approach — thin cyan outlines at reduced strength give a clean structure read without mesh clutter.
On activation, the bridge reads Maya's current background colour with displayRGBColor("background") and pushes it to the override's clear colour via axeLensSetParams(bgR, bgG, bgB). If your background is a gradient or uses a different colour path (e.g. a background plane, image plane, or gradient background setting), the clear colour may not match.
Workaround: after activation, call the bridge directly with the correct colour:from axe_lens_override.python import axe_lens_bridge as b; b.push_params()
Or set the background colour before activating so it can be read correctly.
Saved Lenses are stored in Maya's optionVar store, which is version-specific on most systems. Upgrading from Maya 2024 to 2025 means a fresh optionVar store and your saved lenses won't carry over automatically.
To migrate: before upgrading, use the Script Editor to dump your lens values:import maya.cmds as cmds; print([cmds.optionVar(q=k) for k in cmds.optionVar(list=True) if k.startswith("axeLensSaved")])
Save the output, then recreate your lenses in the new version by entering the values manually and re-saving.
RESET ALL does two things: resets hardwareRenderingGlobals to Maya factory defaults and clears all axeLens_* optionVars. It calls cmds.ogs(reset=True) to force a VP2 reinitialisation.
What it doesn't do: deactivate the AXE Lens override. If the post-process is still active when you reset, the grade parameters are cleared (back to NEUTRAL values) but the MRenderOverride is still routing the panel through the custom pipeline. Click DEACTIVATE first if you want to fully return to standard VP2.
Each active pass adds a full-screen quad render. The grade pass is always active once the override is on. Bloom adds three passes; outline adds one. At 1080p the total overhead is low on a modern GPU (typically <2ms per frame for grade-only). At 4K or with many passes active it becomes more significant.
Reduce cost: disable Bloom when not needed (the biggest single cost). Disable Outline. For playback review, consider switching to the NEUTRAL look (which minimises all effects) or deactivating the override entirely during heavy scrubbing.
SSAO note: the Quality settings affect VP2's own SSAO, which is separate from the post-process pipeline. If playback is slow, PERFORMANCE preset (no SSAO, no MSAA) will give the biggest framerate improvement independently of whether AXE Lens is active.
The bridge hardcodes modelPanel4 as the target. To route the override to a different panel, run the MEL directly from the Script Editor after clicking ACTIVATE:
setRendererInModelPanel "AXELensOverride" yourPanelName;
Replace yourPanelName with your panel's name (e.g. modelPanel1). You can query which panels exist with cmds.lsUI(editors=True) filtered for modelPanel.
Note that deactivation via the UI button will still target modelPanel4. To deactivate from a custom panel: setRendererInModelPanel "vp2Renderer" yourPanelName;
Yes — if AXE Lens is active when you run a playblast from modelPanel4, the playblast captures the post-processed output exactly as you see it in the viewport. All effects (grade, bloom, outline) will be baked into the playblast frames.
For clean production playblasts you may prefer to save a NEUTRAL lens and load it before blasting, then reload your working look afterward. The saved lens workflow makes this fast.
One gotcha: cmds.playblast() with the viewer=True flag sometimes opens its own panel which may not have the override active. Use viewer=False and review the output file directly for reliable results.
After a valid activation the license key is cached to a Maya optionVar. If the dialog reappears, the most likely cause is that the optionVar store is being cleared on launch (e.g. by a studio pipeline script that resets prefs) or the cached key has expired.
You can also set the key via environment variable to bypass the optionVar entirely: set AXE_LENS_LICENSE=your_key_here in your shell or Maya.env before launching Maya. The license module checks this environment variable first before reading the optionVar.