Skip to content

Character Rim Overlay

Summary: An unlit additive overlay material that draws a light-facing Fresnel rim on enemy characters so they stay readable in dark zones without lifting the scene's chiaroscuro. The rim is gated and tinted by the scene's directional light, so it auto-tracks each zone's sun/moon instead of needing a per-zone tuning pass. Applied through the mesh overlay material slot — a single-valued slot it shares with aura gameplay cues.

Table of Contents


Why a Rim Overlay

The painterly chiaroscuro direction deliberately crushes shadow detail, and enemies in unlit forest and interior zones dissolved into the background — a readability problem, not an art problem. Lifting ambient light or adding fill lights would have fixed the silhouette by flattening exactly the contrast the art direction is built on.

An overlay pass is the cheap, surgical alternative: it leaves the base material and the scene lighting untouched and adds one unlit additive edge highlight on top. Because the overlay slot is per-mesh and set from the Blueprint, it costs nothing on characters that don't use it.


How It Works

┌────────────────────────┐
│ Scene directional light │
│  • SkyAtmosphereLight   │──── direction ───┐
│    Direction            │                  │
│  • …LightIlluminance    │──── color ───┐   │
│    OnGround             │              │   │
└────────────────────────┘              │   │
                                         │   ▼
┌──────────────────┐   Fresnel    ┌──────┴───────────────┐
│ Mesh normal + V  │─────────────▶│ rim = fresnel        │
└──────────────────┘  RimExponent │     × wrap(N·L)      │
                                  │     × RimIntensity   │
                                  │     × illuminance    │
                                  │     × RimTint        │
                                  └──────────┬───────────┘
                                             │ Emissive, unlit, additive, two-sided
                                   SetOverlayMaterial(mesh)

Three ideas do the work:

  1. Fresnel for the edge. A view-dependent Fresnel term hugs the silhouette, which is precisely the contour the eye needs to separate an enemy from a dark background.
  2. Light-gated, not omnidirectional. The Fresnel is multiplied by a wrapped N·L against SkyAtmosphereLightDirection, so only the lit-facing edge glows. An ungated rim reads as a cheap uniform outline; gating makes it read as a real bounce off the key light. The wrap (soft-clamped rather than hard saturate) keeps the falloff from terminating abruptly at the terminator.
  3. Auto-tinted by the zone. The result is tinted by SkyAtmosphereLightIlluminanceOnGround, so a cold moonlit forest rims cold and a warm interior rims warm with no per-zone material instances.

The material is unlit (it contributes emissive only), additive (it can never darken the base), and two-sided so thin silhouette geometry still catches the edge.


Asset Set

Role Asset
Rim overlay material /Game/MaterialLibrary/Characters/M_CharacterRim_Overlay
Assigned on BP_Cultist, BP_Cultist_Ranged, BP_Cultist_ShieldBearer, BP_Skeleton_Archer

Assignment is per-Blueprint via the mesh component's Overlay Material property — there is no C++ path and no data asset. Characters without the assignment render exactly as before.


Parameters

Exposed on M_CharacterRim_Overlay:

Parameter Purpose
RimExponent Fresnel falloff power — higher = tighter band hugging the silhouette, lower = broad wash across the body
RimIntensity Overall additive strength before the illuminance tint
RimTint Color bias on the rim, multiplied on top of the scene light color rather than replacing it

Tune per-character with a Material Instance if a unit needs to read differently; the master's defaults are the shared enemy baseline.


Critical Wiring Details

These are the parts that are easy to get wrong:

  • Unlit + additive, not translucent-lit. A lit overlay would be re-shaded by the very darkness it is compensating for and disappear in the zones it exists to serve.
  • Light direction, not a light vector guess. SkyAtmosphereLightDirection is the authoritative scene sun/moon direction; hardcoding a direction desyncs the rim from the zone the moment the light is rotated.
  • Illuminance for color, tint for bias. Multiplying by SkyAtmosphereLightIlluminanceOnGround is what makes the rim zone-aware. Treat RimTint as a bias on that product, not a replacement — an absolute tint reintroduces the per-zone tuning the material exists to avoid.
  • Wrapped N·L, not saturate(N·L). A hard clamp puts a visible hard terminator on the rim itself.
  • Two-sided. Capes, blades and other thin geometry otherwise drop the rim on backfacing shells.

The Shared Overlay Slot

SetOverlayMaterial is one slot per mesh component. The rim overlay is not its only occupant: aura gameplay cues (AGameplayCueNotify_Aura) write the same slot when a buff aura is active.

The cue notify resolves the conflict on the aura's side, not the rim's:

Phase What the aura notify does
Spawn Records each visible mesh's current overlay in an FAuraOverlayTarget before writing its own
Active The aura overlay replaces the rim — intentionally, since the aura is the more urgent read
Teardown Writes each recorded material back, restoring the rim

So the rim survives auras, but only because the aura saves and restores it. Any future system that writes the overlay slot must follow the same save/restore discipline, or it will permanently delete the rim on every enemy it touches. Full detail: Gameplay Cue Visuals.

Because the slot is single-valued, the rim and an aura cannot be shown simultaneously — layering them would require folding the rim into the aura overlay materials themselves.


Applying to New Characters

  1. Open the enemy Blueprint and select its visible body mesh component.
  2. Set Overlay Material to M_CharacterRim_Overlay (or a per-character MI of it).
  3. Assign it only to visible meshes — the hidden ALS driver mesh renders nothing, so an overlay there is dead weight (the aura notify skips hidden meshes for the same reason).
  4. Check the character in the darkest zone it spawns in, not in the editor's default lighting.

Tuning Guide

Symptom First thing to check
Rim visible on the unlit side of the character N·L gate lost or the wrap widened too far — the rim should die on the shadowed edge
Rim reads the wrong color for the zone Illuminance multiply bypassed, or RimTint set as an absolute color instead of a bias
Rim washes across the whole body RimExponent too low
Enemy still lost in a dark zone RimIntensity too low, or the overlay landed on the hidden driver mesh instead of the visible one
Rim vanished permanently after a buff expired An overlay writer that didn't save/restore — see The Shared Overlay Slot
Rim missing on capes/blades only Two-sided disabled on the material

  • Gameplay Cue Visuals — aura body-overlay layer; shares this slot and owns the save/restore contract
  • Tonemapping — the tone curve the additive rim is graded through
  • Enemy AI — the enemies this material is assigned to

Recent Changes

Date Change Impact
2026-08-06 Documented the rim overlay pattern M_CharacterRim_Overlay assigned on the cultist family and the skeleton archer for dark-zone readability; overlay-slot sharing with aura cues written down as a contract