Skip to content

Fixture Configuration Reference

towneh edited this page Oct 16, 2026 · 19 revisions

Fixture Configuration Reference

Setup and authoring for VRSL realtime lights on Unity 6 URP. For installation and a first-run walkthrough, see Getting Started. For pipeline architecture, struct layouts, and tuning internals, see Architecture.

This guide covers two paths:

  • DMX: fixtures driven by a desk's channel values, arriving as a video grid or as bytes (see DMX Channel Sources).
  • AudioLink: fixtures driven by AudioLink's audio analysis texture, no DMX needed.

The two paths share most authoring concepts; differences are noted per section.


Quickstart

The three URP-only shaders (Hidden/VRSL-URP/DeferredLighting, Hidden/VRSL-URP/VolumetricLighting, Hidden/VRSL-URP/SurfaceProperties) ship at Runtime/Shaders/Surface/ inside this package. URP is a hard dependency, so the shaders compile unconditionally and the Light Manager menu utilities resolve them via Shader.Find.

VRSL never changes the URP asset or renderer asset settings; those belong to your project. It reads them in one place, Validate Renderer Setup, which reports what it finds and says what to change; making the change is yours. The realtime light path is implemented entirely through runtime pass injection and a VRSL-owned surface prepass, so it co-exists with whatever URP renderer configuration the project uses.

Three menu utilities under VRSL → URP cover scene-level setup. All are idempotent: safe to re-run, and the third only ever reads.

Menu Effect
VRSL → URP → Add Light Manager to Active Scene Creates a VRSL DMX URP Light Manager GameObject in the active scene with the compute, light-cull, lighting, surface-properties and volumetric shader references assigned.
VRSL → URP → AudioLink Config → Setup AudioLink Realtime Lights in Scene Adds VRSLAudioLinkRealtimeLight to every AudioLink mover spotlight in the active scene and wires up pan/tilt transforms.
VRSL → URP → Validate Renderer Setup Reads the active pipeline asset, its renderers and the open scene, and reports which renderer each camera uses, the rendering and depth-priming modes, whether the prepass layer mask covers the layers your fixtures sit on, and any opaque shader here without both depth passes. Read-only: it changes nothing.

The managers inject their render passes at runtime via RenderPipelineManager.beginCameraRendering, so there is no ScriptableRendererFeature to add to the URP Renderer asset. That lets the package work where the client owns the renderer asset, as in Basis worlds.

VRSLSurfacePrepass (enqueued automatically by the manager) captures the surface data the lighting pass shades against. Authored normals come from the same DepthNormals / DepthNormalsOnly shader tags URP's built-in depth-normals prepass uses, so any opaque shader with a URP DepthNormals pass (URP Lit / Poiyomi URP / lilToon URP / Mochie URP) contributes automatically; surfaces drawn by shaders without one fall back to depth-derivative normals. Albedo, smoothness and metallic come from a second draw using the SurfaceProperties shader as an override, which keeps each renderer's own material values, and that is what lets a lit surface keep its texture colour. Third-party shader authors do not need to add anything VRSL-specific for either.

The remainder of this document describes the per-fixture fields exposed in the inspectors.


Manager Setup

DMX: VRSL_DMXURPLightManager

Field Asset
dmxInput DMX Input: where the lights take their DMX from. Horizontal grid, Vertical grid or Legacy grid reads that layout from the video; Stream data reads the channel source and is dark without one. Drawn above Quality. SetDmxInput(int) changes it while the world runs, 0 to 3 in that order (see DMX Sources).
gridTextures A Grid Textures asset: for each layout, the CRTs that decode it (main, movement, strobe output, strobe timings, spin timer), and the raw grid as the video arrives, before smoothing, which shaders of your own read unsmoothed values from (DMX in Your Own Shaders). Fills in with the package's own, Runtime/Textures/RTs/VRSL-DMX-GridTextures.asset. To decode through CRTs of your own, make one (Create → VRSL → URP → Grid Textures, or duplicate the package's) and point the manager at it; never edit the package's.
computeShader VRSLDMXLightUpdate
lightCullShader VRSLLightCull. Builds the per-tile light list. Leave empty to disable tiled culling.
lightingShader Hidden/VRSL-URP/DeferredLighting
surfacePropertiesShader Hidden/VRSL-URP/SurfaceProperties. Drives the albedo / smoothness / metallic prepass. Leave empty to light every surface as a neutral mid-grey dielectric.
volumetricShader Hidden/VRSL-URP/VolumetricLighting
goboTextures Optional Texture2D[] packed into a shared Texture2DArray; DMX channel +11 selects the slot.
discoballCubemap The dot pattern every Discoball fixture throws. The prefab carries the stock mirror-ball cubemap; empty means a discoball lights as a plain point light.

On enable, under a grid input, the manager publishes its layout's CRTs as the _VRSLU_DMX* globals the fixture bodies sample, and the layout as _VRSLU_DMXGridLayout, so no control panel is needed. It switches that layout's CRTs to Realtime and stops any other layout's left running; under Stream data it publishes black in their place and stops them all. It puts every update mode back when it lets go, so Play mode leaves the package's CRT assets as it found them. disableStrobe is published as _VRSLU_StrobeDisabled, which the strobe output decode reads, so holding strobe open reaches the fixture bodies on every layout as well as the cast light.

A manager saved with its five grid textures as separate fields is moved onto a Grid Textures asset when it is opened in the editor or its scene is built: it comes up in the layout its main texture belonged to, on the package's Grid Textures. One whose textures were its author's own keeps them and warns until it has a Grid Textures asset made from them. A manager seen by the editor for the first time in a scene that holds an enabled channel source comes up on Stream data; otherwise it keeps its grid.

AudioLink: VRSL_AudioLinkURPLightManager

Field Asset
computeShader VRSLAudioLinkLightUpdate
lightCullShader VRSLLightCull. Builds the per-tile light list. Leave empty to disable tiled culling.
lightingShader Hidden/VRSL-URP/DeferredLighting
surfacePropertiesShader Hidden/VRSL-URP/SurfaceProperties. Drives the albedo / smoothness / metallic prepass. Leave empty to light every surface as a neutral mid-grey dielectric.
volumetricShader Hidden/VRSL-URP/VolumetricLighting
goboTextures Optional Texture2D[] for the shared gobo wheel.
discoballCubemap The dot pattern every Discoball fixture throws, as on the DMX manager.
samplingTexture Optional Texture2D or RenderTexture sampled by every fixture in ColorTexture / ColorTextureTraditional color modes. Per-fixture textureSamplingCoordinates UVs pick the colour. Leave empty when no fixtures use those modes.

The AudioLink manager auto-discovers _AudioTexture from the global shader property; no texture references are needed.

Scene-wide controls (both managers)

Field Effect
quality What the package may spend: Off, Standard or High. See Volumetric tuning below and the quality table in Architecture.
prepassLayers Which layers keep their own colour, gloss and normal maps when lit. A layer left out is still lit, as a plain mid-grey surface. Defaults to everything. With a DMX manager and an AudioLink manager in one scene, the DMX manager draws the prepass for the cameras it renders and its mask applies there.
lightIntensity How bright the light every fixture casts is, all of them at once, on top of what each fixture is set to. 1 leaves the scene as authored. The beams follow it, since they are the same light seen in the haze; volumetricIntensity then scales the beams on their own. The control panel drives this for the local user.
contactShadowStrength Screen-space contact shadows, 0 to 1. Off at 0, which is the default: each fixture traces the depth buffer towards itself from every lit pixel, the most expensive term in the surface pass. Shadows come only from geometry the camera can see, within the level's trace distance.
secondaryCameraMode What cameras rendering into a texture get: Match, Reduced (default), SurfaceOnly or Skip. Reduced lights them one level below the scene, with Standard stepping down to a mirror-only Low level. The Camera Selection section of Architecture has the table.
forceOwnNormals Draw VRSL's own normals prepass even where URP's could be read instead. Costs an opaque draw per camera; for diagnosing lit surfaces that look wrong in a way that changes with the camera angle.
outputDebugLogs Log fixture collection and DMX publishing to the Console on enable.

Strobe and movement (DMX manager)

Apart from disableStrobe, these apply where DMX arrives as stream data. On a grid the CRT chain does its own strobe and damping, and its materials set those.

Field Effect
strobeRate StaticFrequencies (the default): three fixed rates, picked by the channel at 0.2 and 0.5. Dynamic: the rate follows the channel value up to maxStrobeFrequency.
strobeMedFrequency / strobeHighFrequency The static rates between 0.2 and 0.5, and above 0.5.
maxStrobeFrequency The dynamic rate at full.
disableStrobe Holds every strobing fixture fully on, on every input. The control panel's strobe toggle sets it.
movementSmoothingMax / movementSmoothingMin Pan and tilt smoothing when a fixture's smoothing channel (+12) reads 0 and full. Lower snaps sooner.

Volumetric tuning (both managers)

The volumetric pass runs when the level draws beams and volumetricShader is assigned. Emptying the shader and setting quality to Off both stop it being recorded.

Field Effect
volumetricDensity Base scattering density.
volumetricAnisotropy Henyey–Greenstein g (default 0.2; 0 = isotropic; positive forward-scatters).
volumetricTint / volumetricIntensity Colour tint and global multiplier.
coupleToSceneFog Multiply density by unity_FogParams.x and tint by unity_FogColor so a URP VolumeProfile drives shaft brightness globally.

Everything above changes the look at a fixed price, so it is yours to set. Step counts, trace lengths and render resolutions set frame time directly and can't be judged by eye, so the quality level sets them.

To take the cones out of the air without touching the shader assignment, drop volumetricIntensity to 0, or set quality to Off, which also stops the pass being recorded and the targets being allocated.

The control panel

VRSL-LocalUIControlPanel is an optional in-world panel for the local user, and nothing in a scene depends on it. It finds the scene's managers on start and adjusts quality, volumetricIntensity, lightIntensity and disableStrobe on them, each as a share of what the scene was authored to. It also acts on the fixture materials for the body glow, the lens flares and the lasers, and on each discoball's Global Intensity. Those materials are shared assets, so a change reaches every fixture using them. Nothing the panel sets leaves the local client. What each control on the panel does is in Performance and Quality.


Fixture Authoring: Shared Fields

These fields appear on both VRSLDMXRealtimeLight and VRSLAudioLinkRealtimeLight:

Field Notes
fixtureType MoverSpotlight, MoverWashlight, StaticBlinder, StaticParLight, StaticPointLight (DMX only), Discoball, Custom. Drives inspector field visibility and sets the wash-vs-spot inner-cone ratio (wash 0.65 = flat-bright with long feather; spot/static 0.5 = falloff over the outer half). StaticPointLight emits omnidirectionally: the manager forces point mode for it and the inspector hides the spot, cone, pan/tilt, and gobo fields. Discoball is a point light whose dots come from the manager's cubemap; see Fixtures.
maxIntensity Output at full DMX / full amplitude, on the same scale as a URP spot light's Intensity value. A fixture at full output with Final and Global Intensity at 1 matches a URP spot set to the same number, so you can calibrate against a reference light instead of by eye.
range Attenuation range in metres.
spotAngle (AudioLink) / minSpotAngle & maxSpotAngle (DMX) Outer cone angle in degrees. DMX channel +4 lerps between min and max.
isPointLight Emit as a point light instead of a spot.
emitterDepth (m) Pushes the cone apex back along the light direction so the cone arrives at the lens with finite radius emitterDepth × tan(halfAngle). Default 0 reproduces a point source. As a starting point: an LED-bar fixture with a 30° outer half-angle reads well at emitterDepth ≈ 0.3–0.5 m.
lensTransform Optional child Transform. When assigned, the cone's apex projects from the lens position, which matters on a hung mover whose root sits at the truss clamp. The DMX mover prefabs ship with a LensTransform child. Left empty, a DMX light comes from the centre of its first body renderer, or its root if it has none; an AudioLink mover takes its origin from panTransform while pan/tilt is on, and other AudioLink lights from their root. On a Discoball it is the ball: the dots come from its centre and it turns with them. The discoball prefabs set it to their sphere.
fixtureShellRenderers The fixture's body and, on a blinder, its lens flare. The Realtime light pushes a MaterialPropertyBlock to each so it lights from the same DMX or AudioLink data as the light. The block carries the fixture's tint and intensities as well, which replace the material's own on those renderers. Every stock realtime fixture lists its body except the discoball, whose sphere has nothing to drive. A body left off the list glows however its material says, which for a par or blinder body is full brightness whatever the desk sends.
enablePanTilt Enable for moving-head fixtures. DMX movers take pan and tilt from the desk and rotate on the GPU. AudioLink movers read tiltTransform's direction each frame, so animate those transforms.
discoballSpinSpeed How fast a discoball's ball and dots turn, in degrees per second; negative turns the other way.
discoballBeams Draw a discoball's dots in the haze as well as on surfaces, at a cubemap fetch per raymarch step across its range. Off by default.

DMX-Specific Authoring

VRSLDMXRealtimeLight:

Field Notes
enableDMXChannels Enable DMX control.
dmxChannel / dmxUniverse Industry-standard channel and Artnet universe (1-based).
useLegacySectorMode / sector Legacy sector addressing for older patches. Sector 0 = channels 1–13, sector 1 = 14–26, etc.
enableFineChannels 16-bit pan/tilt via the +1 / +3 channels.
use5ChannelMode Read DMX using the compressed 5-channel static layout (intensity +0, RGB +1/2/3, strobe +4) instead of the standard 13-channel layout. For fixtures patched 5 channels apart. Match this to the channel mode of the fixture-body surface shader so surface and light read the same data; the stock 5-channel par, blinder and point bar set it.
enableStrobe Allow the DMX strobe channel to gate the light on/off.
enableConeWidth Allow ch+4 (motor speed / zoom) to modulate the cone between minSpotAngle and maxSpotAngle. Disable on par cans and blinders so unrelated traffic on ch+4 does not flicker their cone width.
enableGobo Allow ch+11 to select gobos.
enableGoboSpin Allow ch+10 to drive gobo spin speed.
finalIntensity / globalIntensity User-side intensity caps (0–1).
curveMod How the cast light and the body glow ramp with the dimmer: 2 matches the stock body surface, 1 is the gentlest curve. Sent to the body as _CurveMod in place of its material's.
shellEmissionTint How brightly the body and flare glow, multiplying the colour the desk sends. The stock pars and blinders use 2, the movers 1. On a discoball it is the colour of the dots.
maxMinPan / maxMinTilt Total pan and tilt travel in degrees (±half from centre).
panOffset / tiltOffset Per-fixture aim offset.
invertPan / invertTilt Reverse direction.
lightOriginOffset World-space offset added to where the light comes from, e.g. (0, -0.5, 0) to drop a ceiling strip's light below it.
localLightDirection The local axis the light shines along. Forward (+Z) by default, as on the movers; up (+Y) for a body whose lens faces local +Y.

To re-patch a fixture while the world runs, set any of the four address fields from a script and then call ApplyAddress() on the fixture. The beam and the fixture body both move to the new address from the next frame. VRSLDMXStatic has the same call for shader-driven fixtures. Calling it with the address unchanged changes nothing.

The full per-fixture channel layout (offsets relative to dmxChannel):

Offset Channel
+0 Pan coarse
+1 Pan fine
+2 Tilt coarse
+3 Tilt fine
+4 Motor speed / cone width
+5 Dimmer / intensity
+6 Strobe gate
+7 / +8 / +9 Red / Green / Blue
+10 Gobo spin speed
+11 Gobo selection

With use5ChannelMode enabled this collapses to the 5-channel static form (dimmer at +0, Red / Green / Blue at +1 / +2 / +3, strobe at +4), and the motor, pan/tilt, and gobo channels are unused. Patch those fixtures 5 channels apart and set the fixture-body surface shader to its matching 5-channel mode.


AudioLink-Specific Authoring

VRSLAudioLinkRealtimeLight:

Field Notes
enableAudioLink When enabled, intensity is driven by AudioLink amplitude. When disabled, the light runs at full maxIntensity × finalIntensity regardless, which is how a static fixture lives in an AudioLink scene.
band Bass / LowMids / HighMids / Treble.
delay History delay (0 = most recent, 127 = most delayed). Useful for chasing effects across a row of fixtures.
bandMultiplier Sensitivity multiplier: increase it if amplitude reads too low for your audio levels.
colorMode Emission (fixed emissionColor), ThemeColor0–3, ColorChord, ColorTexture (modern, HSV-normalised), ColorTextureTraditional (raw sample).
emissionColor Active when colorMode == Emission. Author in HDR for bright fixtures.
textureSamplingCoordinates Active in the ColorTexture modes: the UV in the manager's samplingTexture (AudioLink's own texture when that is empty) to read the colour from.
goboIndex Selects a slot in the manager's shared gobo wheel, from 1 (1 = open beam, 2–8 = shaped gobos).
goboSpinSpeed Rotation speed for the projected gobo (negative = anticlockwise, positive = clockwise).
panTransform Transform rotated on Y for pan. Its world position becomes the light origin.
tiltTransform Transform rotated on X for tilt. Its world forward becomes the light direction.
targetToFollow Optional aim target. When set, the fixture's tilt transform tracks this object from Start; call ApplyTargetToFollow() after changing it later.
finalIntensity / globalIntensity User-side intensity caps.

Tuning maxIntensity

AudioLink amplitude is normalised (0–1), so maxIntensity directly controls peak output. Calibration:

  1. Play a loud section so the target band is near full amplitude.
  2. Adjust maxIntensity until illumination on a lit surface matches your artistic intent.
  3. Use bandMultiplier to control sensitivity (how quickly the light reaches maxIntensity from quiet audio) independently of peak brightness.

Writing a fixture shader: depth passes

A shader that draws in the opaque queue needs DepthOnly and DepthNormals passes whose vertex stage matches its forward pass (pan and tilt, alpha clipping, any collapse to hide the fixture), or it vanishes under depth priming. Depth requirements in Architecture says why. Validate Renderer Setup names any opaque shader in the open scene missing a depth pass; it can't tell whether a depth pass's vertex stage matches, so check the fixtures with priming on.

Runtime API

// DMX: after changing a fixture's address (sector, dmxChannel, dmxUniverse, useLegacySectorMode)
fixture.ApplyAddress();

// DMX: after changing any other fixture config field
VRSL_DMXURPLightManager.Instance.MarkConfigDirty();

Fixtures switched on or off, added or removed, need no call: both managers follow them by the next frame. A realtime fixture whose component is switched off casts no light, and its body keeps glowing with the show. RefreshFixtures() on either manager still works and is never needed.

AudioLink's per-frame fields (band, delay, bandMultiplier, colorMode, emissionColor, maxIntensity, finalIntensity, enableAudioLink, goboIndex, goboSpinSpeed) are read every frame and do not require a refresh call.


Prefabs

The prefabs ship under Runtime/Prefabs/:

Path Contents
Runtime/Prefabs/DMX/ The DMX manager and every DMX fixture: the 13-channel movers, par and blinder, the 5-channel par, blinder and point bar, the flasher, laser, light bars, 6x4 strobe, discoball and example surface. One set serves every grid layout: set the manager's DMX Input to the one the world uses
Runtime/Prefabs/AudioLink/ The AudioLink manager and fixtures (movers, par, blinder, discoball, laser, flasher, light bar), and an example audio source

Movers, pars, blinders, the point bar and the discoballs carry a realtime light and nothing else to author; the volumetric pass draws their beams. The flasher, laser, light bars and 6x4 strobe are shader-driven and carry VRSLDMXStatic, or on AudioLink VRSLAudioLinkStatic / VRSLAudioLinkLaser.


Example Scenes

Scene Path
VRSL-ExampleScene-AudioLink-URPRealtimeLights Runtime/Example Scenes/AudioLink-Scenes/
VRSL-ExampleScene-EditorViaOSC-Horizontal-URPRealtimeLights Runtime/Example Scenes/DMX-EditorViaOSCScenes/

Each ships with the manager pre-populated.

Clone this wiki locally