Reference · Updated 2552.08.12.15.56
System Link Hard-Light Bridge Material
The reusable material set lives in:
The reusable material set lives in:
/Game/SystemLink/Environment/HardLightBridge/Materials
M_SL_HardLightBridge— primary translucent, unlit surface.
MI_SL_HardLightBridge_Default— tuned cyan-blue default instance.
M_SL_HardLightBridge_Edge— optional additive edge layer.
MI_SL_HardLightBridge_Edge_Default— brighter default edge instance.
The source references were used only for broad visual qualities: a projected cyan surface, strong longitudinal rails, moving construction bands, restrained geometric detail, and a brighter activation front. The pattern is original, procedural, and uses no third-party textures.
#Material settings
| Setting | Surface | Edge |
|---|---|---|
| Domain | Surface | Surface |
| Blend | Translucent | Additive |
| Shading model | Unlit | Unlit |
| Two Sided | On | On |
| Refraction | None | None |
| Main outputs | Emissive, Opacity | Emissive, Opacity |
Keep the primary material translucent. Additive alone loses too much definition in moderately lit spaces. Use the edge material on a second, slightly expanded mesh only when the main surface does not provide enough rail separation.
#Graph implementation
Run the idempotent generator while Unreal Editor is open with Python Remote Execution enabled:
python Tools\create_hard_light_bridge_materials.py
The generated graph is organized into these groups:
- Coordinates —
TextureCoordinatesupplies UV0 andTimedrives all motion. U is bridge length;
world position is projected onto the bridge's normalized local X/Y axes for the pattern, noise, flow, and scanlines. Scaling the mesh therefore adds energy repeats instead of stretching the detail. V is width.
- View/intersection response — a standard
Fresnelnode supplies grazing-angle glow and a standard
DepthFade softens intersections with the projector housing and nearby geometry.
- Procedural pattern — standard
Frac,Min,OneMinus,Divide, andSaturatenodes create an
original rectangular/diagonal energy lattice. Crossed Sine chains provide low-cost distortion; additional Sine, Power, and Frac chains create directional flow and thin scanlines.
- Activation — U is optionally reversed, compared with
ActivationProgress, and softened at the
construction boundary. A narrow triangular band around the boundary becomes the hot leading edge. ActivationProgress = 0 explicitly multiplies visibility to zero.
- Layer composition — central energy, pattern, flow, scanlines, noise, side rails, Fresnel, pulse, and
construction-front energy are combined, tinted between the primary and secondary colors, then written to Emissive. A quieter version drives Opacity.
- Edge material — reuses the coordinate, animation, noise, and activation logic but restricts output
to wider V-edge bands and uses Additive blending.
The graph contains no Custom HLSL and no texture samples. It deliberately follows the layering approach used by SystemLinkCore's M_Textured_Fresnel_01: shape masks with Frac/Saturate, animate scalar fields with Time/Sine, and compose color using Lerp, Power, Fresnel, and final output multipliers. If profiling shows the texture-free lattice is a material bottleneck, replace only that group with one small tiling grayscale texture; preserve Fresnel, Depth Fade, activation, and output layering.
#Default parameters
| Parameter | Default | Purpose |
|---|---|---|
SL_HardLight_Color | (0.015, 0.42, 1.0) | Main energy color |
SL_HardLight_SecondaryColor | (0.12, 0.85, 1.0) | Hot lines and activation front |
SL_HardLight_EmissiveIntensity | 10 | Overall HDR emissive |
SL_HardLight_SurfaceOpacity | 0.24 | Central surface readability |
SL_HardLight_EdgeIntensity | 2.75 | Long-edge brightness |
SL_HardLight_RailFlipV | 0 | Flip inside/outside rail UV direction |
SL_HardLight_RailInnerCoreWidth | 0.10 | Hard inside-edge core width |
SL_HardLight_RailInnerIntensity | 1.35 | Hard inside-edge brightness |
SL_HardLight_RailOuterIntensity | 0.70 | Soft outward glow brightness |
SL_HardLight_RailOuterFalloffPower | 1.65 | Inside-to-outside softness |
SL_HardLight_FresnelPower | 4 | Grazing-angle falloff |
SL_HardLight_FresnelIntensity | 1.5 | Grazing-angle brightness |
SL_HardLight_PatternScale | 18 | Cells along U |
SL_HardLight_PatternIntensity | 0.55 | Longitudinal filament brightness |
SL_HardLight_PatternTexture | 512x512 generated mask | Optional custom circuitry mask |
SL_HardLight_UseTexturePattern | 1 | Enables the texture-pattern layer |
SL_HardLight_TexturePatternScale | 1 | Physical texture tiling multiplier |
SL_HardLight_TexturePatternScaleX | 1.75 | Extra longitudinal tiling/aspect correction |
SL_HardLight_TexturePatternScaleY | 1 | Extra width tiling/aspect correction |
SL_HardLight_TexturePatternIntensity | 0.65 | Texture-pattern brightness |
SL_HardLight_TextureFlowSpeed | 0.025 | Texture travel speed along local X |
SL_HardLight_TextureWorldSizeCm | 400 | Square physical size of each texture tile |
SL_HardLight_ReferenceLengthCm | 1200 | Unscaled local-X mesh length |
SL_HardLight_ReferenceWidthCm | 400 | Unscaled local-Y mesh width |
SL_HardLight_FlowSpeed | 0.35 | Flow cycles/second |
SL_HardLight_FlowDirection | 1 | Use -1 to reverse flow |
SL_HardLight_ScanlineScale | 72 | Scanline count along U |
SL_HardLight_ScanlineSpeed | 0.55 | Scanline travel speed |
SL_HardLight_PulseSpeed | 1.25 | Pulse cycles/second |
SL_HardLight_PulseStrength | 0.10 | Pulse amplitude |
SL_HardLight_NoiseScale | 9 | Procedural noise cells |
SL_HardLight_NoiseStrength | 0.18 | Noise/distortion amount |
SL_HardLight_DepthFadeDistance | 24 cm | Intersection fade |
ActivationProgress | 1 | Construction state, 0–1 |
ReverseConstructionDirection | 0 | Reverse U construction at 1 |
SL_HardLight_ActivationEdgeWidth | 0.035 | Construction-front width |
SL_HardLight_ActivationEdgeIntensity | 5 | Construction-front brightness |
For bright daylight, first raise opacity to 0.42–0.5; only then raise emissive. Excessive emissive can bloom into a flat white slab. For dark interiors, opacity around 0.25–0.34 retains layered detail.
#Material instance setup
Duplicate MI_SL_HardLightBridge_Default for each visual family, not for every placed bridge. Suggested instances are MI_SL_HardLightBridge_ArenaBlue, MI_SL_HardLightBridge_Dim, and MI_SL_HardLightBridge_Warning. Runtime activation should use a Dynamic Material Instance (MID), leaving the shared constant instance unchanged.
If using the optional edge mesh, create MIDs for both material slots and set ActivationProgress and ReverseConstructionDirection on both in the same update.
#Blueprint activation
On BeginPlay:
- Call
Create Dynamic Material Instanceon the surface mesh (element 0) and cache it asSurfaceMID.
- If present, do the same for the edge mesh and cache
EdgeMID.
- Set
ReverseConstructionDirectionto0or1on both.
- Set
ActivationProgressto the initial state.
For activation, play a Timeline from 0 to 1 over roughly 0.65–1.0 seconds using a smooth ease curve. On Update, call Set Scalar Parameter Value (ActivationProgress) on both MIDs. Reverse the Timeline for deactivation. Collision is gameplay state, so enable it on the server at a deliberate threshold (usually near 0.9 while activating) and disable it immediately when deactivation starts. The MID itself is cosmetic and does not replicate.
For multiplayer, replicate bBridgeActive (and optionally a server activation start time), then let each client animate its local MIDs in OnRep_BridgeActive. Late joiners should derive progress from replicated server time or receive the final value.
#C++ activation example
// Members: UMaterialInstanceDynamic* SurfaceMID; UMaterialInstanceDynamic* EdgeMID;
// float ActivationProgress = 0.0f; float ActivationTarget = 0.0f;
void ASLHardLightBridge::BeginPlay()
{
Super::BeginPlay();
SurfaceMID = SurfaceMesh->CreateAndSetMaterialInstanceDynamic(0);
EdgeMID = EdgeMesh ? EdgeMesh->CreateAndSetMaterialInstanceDynamic(0) : nullptr;
SetVisualProgress(bStartsActive ? 1.0f : 0.0f);
}
void ASLHardLightBridge::SetVisualProgress(float NewProgress)
{
ActivationProgress = FMath::Clamp(NewProgress, 0.0f, 1.0f);
if (SurfaceMID) SurfaceMID->SetScalarParameterValue(TEXT("ActivationProgress"), ActivationProgress);
if (EdgeMID) EdgeMID->SetScalarParameterValue(TEXT("ActivationProgress"), ActivationProgress);
}
void ASLHardLightBridge::Tick(float DeltaSeconds)
{
Super::Tick(DeltaSeconds);
const float Rate = 1.25f; // ~0.8 seconds end-to-end
SetVisualProgress(FMath::FInterpConstantTo(ActivationProgress, ActivationTarget, DeltaSeconds, Rate));
}
Prefer a replicated target/state over replicating ActivationProgress every frame. If all clients must match a one-shot activation precisely, replicate the server start time and evaluate the same normalized curve locally.
#Mesh and UV layout
- Primary mesh: a long rectangular plane or a 2–5 cm thin box. UV0 must run U=
0..1along the complete
length and V=0..1 across the width without mirroring.
- A plane is cheapest; a thin box reads as more volumetric from below and at oblique angles. With a box,
give the top and underside their own full 0..1 UV islands and keep side faces in a separate material slot or very narrow UV bands.
- Keep bridge length on local X and width on local Y. The material projects world position onto those
local axes. Set SL_HardLight_ReferenceLengthCm and SL_HardLight_ReferenceWidthCm to the unscaled mesh dimensions (the sample defaults are 1200 and 400 cm).
- Actor-scale animation is supported. UV-based activation and edge masks remain normalized, while pattern,
flow, noise, and scanline density remain visually stable as the bridge extends or retracts.
- The custom pattern texture uses one shared world-size divisor for local X and Y, following the projection
behavior of MF_WorldAligned. A square mask stays square; a 1200x400 cm bridge shows three 400 cm tiles along its length instead of stretching one tile across the full bridge.
- Add longitudinal subdivisions only if future world-position offset is required; this material does not
deform vertices.
- Gameplay collision should be a separate simple box. Never rely on a translucent render plane for
player collision.
- Optional edge geometry: two narrow strips, 1–3 cm above or outside the main plane, with U along length.
Offset enough to avoid z-fighting but not enough to look detached.
- Put small opaque projector/end-cap meshes at both ends. They sell the projection origin and hide Depth
Fade intersections.
#Performance
- The material uses no textures, refraction, pixel depth offset, or world-position offset.
- Translucent overdraw is the main cost. Keep layers to one surface plus one optional edge layer; avoid
stacking several coplanar shells.
- Use tight mesh bounds and do not disable depth testing. Avoid large invisible quads around the bridge.
- Translucent emissive does not automatically illuminate the world. Use restrained baked/static lights or
a few local lights at projectors rather than many movable lights along the span.
- Niagara and activation are cosmetic. Do not replicate particles or per-frame MID values.
- Profile in Shader Complexity and Quad Overdraw views. On distant bridges, disable the edge component or
use a simpler instance with lower scan/pattern contrast.
#Optional Niagara effects
Create NS_SL_HardLightBridge_Activation only after the base material reads well:
- A thin GPU ribbon or sprite sheet at the construction front, moving from one projector to the other.
- Sparse cyan sparks emitted from the leading edge, lifetime
0.15–0.4 s, with low spawn counts.
- Very faint upward mist sprites near the surface, depth-faded and camera-softened.
- A short projector burst at each end on activation/deactivation.
Drive Niagara with a user float named User.ActivationProgress and the same reverse-direction flag. Spawn the system once for a transition, not continuously for every bridge. Audio should carry much of the power: a low projector hum, a short charging sweep, and a clean lock-in transient cost less than more overdraw.
#Suggested folder structure
/Game/SystemLink/Environment/HardLightBridge/
Blueprints/BP_SL_HardLightBridge
Materials/M_SL_HardLightBridge
Materials/MI_SL_HardLightBridge_Default
Materials/M_SL_HardLightBridge_Edge
Materials/MI_SL_HardLightBridge_Edge_Default
Meshes/SM_SL_HardLightBridge_Surface
Meshes/SM_SL_HardLightBridge_Edges
Meshes/SM_SL_HardLightBridge_Projector
VFX/NS_SL_HardLightBridge_Activation
Audio/SC_SL_HardLightBridge_Activate
The bridge actor should own the render meshes, separate collision box, MIDs, authoritative active state, and client-side transition playback. That keeps the material reusable and the multiplayer contract clear.