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

SettingSurfaceEdge
DomainSurfaceSurface
BlendTranslucentAdditive
Shading modelUnlitUnlit
Two SidedOnOn
RefractionNoneNone
Main outputsEmissive, OpacityEmissive, 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:

  1. CoordinatesTextureCoordinate supplies UV0 and Time drives all motion. U is bridge length;
  2. 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.

  1. View/intersection response — a standard Fresnel node supplies grazing-angle glow and a standard
  2. DepthFade softens intersections with the projector housing and nearby geometry.

  1. Procedural pattern — standard Frac, Min, OneMinus, Divide, and Saturate nodes create an
  2. original rectangular/diagonal energy lattice. Crossed Sine chains provide low-cost distortion; additional Sine, Power, and Frac chains create directional flow and thin scanlines.

  1. Activation — U is optionally reversed, compared with ActivationProgress, and softened at the
  2. construction boundary. A narrow triangular band around the boundary becomes the hot leading edge. ActivationProgress = 0 explicitly multiplies visibility to zero.

  1. Layer composition — central energy, pattern, flow, scanlines, noise, side rails, Fresnel, pulse, and
  2. construction-front energy are combined, tinted between the primary and secondary colors, then written to Emissive. A quieter version drives Opacity.

  1. Edge material — reuses the coordinate, animation, noise, and activation logic but restricts output
  2. 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

ParameterDefaultPurpose
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_EmissiveIntensity10Overall HDR emissive
SL_HardLight_SurfaceOpacity0.24Central surface readability
SL_HardLight_EdgeIntensity2.75Long-edge brightness
SL_HardLight_RailFlipV0Flip inside/outside rail UV direction
SL_HardLight_RailInnerCoreWidth0.10Hard inside-edge core width
SL_HardLight_RailInnerIntensity1.35Hard inside-edge brightness
SL_HardLight_RailOuterIntensity0.70Soft outward glow brightness
SL_HardLight_RailOuterFalloffPower1.65Inside-to-outside softness
SL_HardLight_FresnelPower4Grazing-angle falloff
SL_HardLight_FresnelIntensity1.5Grazing-angle brightness
SL_HardLight_PatternScale18Cells along U
SL_HardLight_PatternIntensity0.55Longitudinal filament brightness
SL_HardLight_PatternTexture512x512 generated maskOptional custom circuitry mask
SL_HardLight_UseTexturePattern1Enables the texture-pattern layer
SL_HardLight_TexturePatternScale1Physical texture tiling multiplier
SL_HardLight_TexturePatternScaleX1.75Extra longitudinal tiling/aspect correction
SL_HardLight_TexturePatternScaleY1Extra width tiling/aspect correction
SL_HardLight_TexturePatternIntensity0.65Texture-pattern brightness
SL_HardLight_TextureFlowSpeed0.025Texture travel speed along local X
SL_HardLight_TextureWorldSizeCm400Square physical size of each texture tile
SL_HardLight_ReferenceLengthCm1200Unscaled local-X mesh length
SL_HardLight_ReferenceWidthCm400Unscaled local-Y mesh width
SL_HardLight_FlowSpeed0.35Flow cycles/second
SL_HardLight_FlowDirection1Use -1 to reverse flow
SL_HardLight_ScanlineScale72Scanline count along U
SL_HardLight_ScanlineSpeed0.55Scanline travel speed
SL_HardLight_PulseSpeed1.25Pulse cycles/second
SL_HardLight_PulseStrength0.10Pulse amplitude
SL_HardLight_NoiseScale9Procedural noise cells
SL_HardLight_NoiseStrength0.18Noise/distortion amount
SL_HardLight_DepthFadeDistance24 cmIntersection fade
ActivationProgress1Construction state, 0–1
ReverseConstructionDirection0Reverse U construction at 1
SL_HardLight_ActivationEdgeWidth0.035Construction-front width
SL_HardLight_ActivationEdgeIntensity5Construction-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:

  1. Call Create Dynamic Material Instance on the surface mesh (element 0) and cache it as SurfaceMID.
  1. If present, do the same for the edge mesh and cache EdgeMID.
  1. Set ReverseConstructionDirection to 0 or 1 on both.
  1. Set ActivationProgress to 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..1 along 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.