Repository navigation
DMX Lighting Configuration #784
Replies: 1 comment
|
This may be just restating what you’ve said, but conceptually I think there are two layers involved in a lighting setup like this. Your explanation didn’t quite land in my head for the mapping between channels, fixtures, and logical lighting setups that are portable between bridges. So, at risk of saying what you’ve just said but differently, this is what I understand from your approach and how I’d frame it. Physical mappingsLet’s start at the bottom of the stack. A lighting device has one or more channels. The semantic meaning of what a channel is doesn’t exist down here. It’s literally just binding that channel X in a DMX universe belongs to a specific device. This information is not portable between sets. It is bespoke and custom. It may even vary if a lighting effect is a one off for a specific flight. Channels carry some metadata about the device, its placement on a physical set, the color or purpose it serves in the device, etc. Even so, it is too granular and too specific to carry the intent of what the light means in a flight. It’s just a byte of data without any meaning. As you add devices, channels, and construct a universe, you end up with a pile of metadata tied to an output buffer. That buffer is the target for the rendering pipeline, and that rendering pipeline is where human authors need to work at the level of intent rather than device. Intent is the meaning making: “red alert” means channels like this and channels like that should look like X. Intents mean we need to have a library of verbs we can deploy against our recently declared pile of channels - essentially the nouns in this whole lighting system. Layers of intentYour layering approach makes sense. I think having scenes within “banks” (I will call them layers) is helpful. The layer metaphor here is apt: if a buffer of values is the target, conceptually that’s no different than a grayscale bitmap. You’re building photoshop for DMX, and the layers even have blend modes. I’m split on if a layer (which is a collection of scenes, a blend mode, and a z-index) should internally manage its own transitions between scenes or if that should live outside of it. I’m inclined to treat it as pure data and to have something else handle transitions (see below). At the end of the day, each frame consists of applying the layers in successive order to produce a new buffer for output. Scenes in this model may be a bit different from what you’ve written, I didn’t quite map it over to what I’m about to say. The split between intent and execution seems like a primary design feature in a system like this. I would handle that mapping by having scenes not be collections of channels by index, but collections of channels by tags and/or groups. Any bridge sim set is going to have a set of typical lighting groups. This is maybe where I’d use the word “bank” or “slot” or call them groups. I haven’t noodled enough on if tagging channels is good enough here, since there’s a benefit to having indexed channels for pixel LED strips and numbering each channel by index would be more tedious than ordering them in a list. A good UI could smooth that over, but functionally the goal is that we are able to select channels based on predicates that map them into logical intent groups. Things like “these lights are on the left side and these are the right” or “these are the work lights” and “these are primary” and “these are accent”. This is what abstracts your hardware from your lighting model. This adds one more piece to a layer: a selector that draws channels in by predicate. This keeps the lighting model separate from the rendering model in the same way that the HTML DOM is an abstraction that eventually turns into a render buffer. At a high level, it’s the same thing: abstract building blocks, modified by styles, and rendered into discrete pixel values. ShadersViewing it all this way, and a layer is a kind of shader. I don’t have much experience with shaders to speak more here, but it feels to me like there is an opportunity for composing layers and even rendering them using a GPU pipeline if available. The output certainly fits, so if there are ways to design all of this to be GPU optimized, I can see that really being a win. One last note on premature optimization: a flight could bake bitmaps so that lighting computations are cached. I wouldn’t start here but trying to keep this as an option could be a sign that the architecture is right. State transitionsThis is where I’d need to start modeling in code to get a better feel for the right design. I’m biased towards purely functional data structures so everything above would be just that. You’d feed it into a render pipeline and it would produce an output buffer deterministically. You could then use context like the current frame number to handle things like chasing lights or other fluxes in light (modulo arithmetic over the count of lights in a group). Logic for this would live in the layer or scene. The state machines that govern changes to layers and scenes and all of this ought to probably live outside the render pipeline. They should change the inputs to the pipeline (changing which scene is active in a layer for example), and they would react to game state to move to legal states for lighting purposes. The pipeline itself remains a pure data structure that you replace when state machines react to changes in the game. SummaryA DMX device has channels. Channels are tagged or maybe grouped with metadata that makes them visible to scenes. Scenes select for channels based on those tags, and output values for each channel. Layers have one scene active at a time and group them together with a z-index and blend mode. Intent state machines describe the valid state transitions between lighting modes and modify which scenes and layers are active. External game state feeds into lighting intent state machines to drive reactive changes. A rendering loop (maybe in the GPU) computes each frame and writes it into the draw buffer. The hardware driver reads from that buffer (or the read buffer since you probably want this thing double buffered) to drive physical devices. Multiple DMX universes are fine because you’re just selecting by tags from channels. The final render output would emit each universe buffer in order. How close is that to what you’ve described? Did I just restate what you did? I feel like the channel tags to map intent and state machines were missing, but could help with making this happen? |
Uh oh!
There was an error while loading. Please reload this page.
Let's talk about lighting effects. If you aren't familiar with how DMX works, Thorium Classic's docs have a short primer that will get you up to speed.
Lights are difficult. For starters, every bridge could have a different configuration of lights. Each light could have several channels. Lights are affected by alert condition, ship power, explosions, jumping to warp, and a whole host of other things. Coordinating what channels turn on and off at different times gets really complicated really fast.
Thorium Classic has basic DMX lighting controls with two parts.
The first is the DMX Config which indicates what color lights should be at certain alert conditions, so the lights automatically switch when the alert condition changes.
The second is an effects layer, which applies explosion or pulse effects to all of the lights (with the option to opt out some lights by marking them as "no effects").
This setup works well enough for simple setups with just a handful of lights. But for more complicated or theatrical setups, it falls short in a bunch of ways:
Prior Art
Three of the other bridge simulators (Artemis, Empty Epsilon, Starship Horizons) operate on similar principles:
This works great for small setups with only a handful of lights. The problem is, you have to configure every event trigger against every light, which adds up to a lot of configuration. And since lights are configured individually, it can be difficult to understand how all of the lights will work together at different points in the flight. This makes it hard to create predictable lighting setups.
As always, I want Thorium Nova to be simple enough for someone with a single DMX light in their living room, but scale to a location-based brick-and-mortar bridge.
The Voyager, a ship I built in 2015, has 40 lights and 222 channels — hardly maxing out the 512 channels in a DMX universe, but still plenty. Some are dimmers, some are RGBAW+UV spotlights (the ultraviolet is an awesome effect), some selectively turn on and off for a decontamination field or brig force field, and some must stay illuminated at all times for safety. It even has a DMX controlled smoke machine!
Some day I'd love for them to have addressable strip lights with individually controlled lights along the length of the LED strip — something that would require multiple DMX universes to support. This is the kind of set that I want to make sure Nova's lighting setup works for.
So, how do we do that without ballooning complexity? We take a cue from the Professionals.
Professional Lighting Design
The best DMX control software I can find all work about the same:
They have a lot more features than this, but these are the ones that are most helpful for us.
How Thorium Nova will do Lighting
My plan for Thorium Nova is to combine aspects of all three — Thorium Classic, other bridge sims, and professional lighting software.
We'll take basically everything I listed above from pro software, particularly scenes. Scenes provide a predictable way to configure your lighting at any given time, with direct control over each channel, flexibility to configure multiple channels at once, all while still understanding how all of the channels are working together at any given time.
The auto-play feature of banks make it trivial to set up a lighting animation across all of the lights, like a dramatic flicker and fade down and up effect when the Main Computer activates, or a swoosh of the lights when the ship jumps to warp speed.
And since scenes are basically snapshots of every channel, it makes it much easier to take advantage of some of the other channel types, like strobe or intensity, on a granular level.
Thorium Classic's great idea is having multiple layers that stack on top of each other. In Nova, this translates to being able to stack scenes on top of each other. A base scene provides the permanent lighting. Another scene provides the alert condition colors. Another scene adds to that by changing the lights slightly when the shields are raised or turning on a warning light when there's something the crew needs to address.
Effects, like a subtle pulse when the engines are on or the full-on explosion shake when the ship is taking damage, would also be on their own scene, but that scene would be defined as a multiplier scene. Instead of just setting the lights, this scene multiplies the value of each channel from the base scene by its own channel values. This makes it trivial to make the explosion effect affect some lights while leaving others alone. It also allows for some explosions to shake the lights a little bit while some shake a lot, by having the big explosion effect scene have a large multiplier and the small effect scene have a small multiplier.
I also intend to have an "additive" scene type, which increases (or decreases, for negative numbers) the output of the base layers.
That said, we don't want every scene stacking on top of all the other scenes. If the Red Alert scene stacked on the Green Alert scene, you'd find yourself in a Yellow Alert situation. When a scene is activated, it automatically deactivates any scenes in its bank — only one scene from an individual bank can be active at a time.
Finally, the other bridge sims have identified the best way to define light changes: Just listen for events and change the lights that way. Thorium Classic got this wrong, by trying to automatically set the channel values based on the state of the ship with very little configuration options. It was tedious, complicated, but also inflexible and limited. It's possible a bridge might prefer to do an explosion effect using their light's strobe effect by setting a single channel, but that's not possible with Thorium Classic. That is possible with this design.
Thorium Nova will have "DMX: Activate Scene" and "DMX: Deactivate Scene" actions which can be activated from any trigger or timeline. I'm going to discourage using this action in mission timelines, since I want missions to be portable and every bridge is going to have different lighting scenes. But it's still possible, so long as the mission warns that it needs certain lighting scenes to be configured.
The "DMX: Activate Scene" action will include options for overriding the crossfade time, making it easy to quickly jump between scenes or have the scene channel values change a little slower.
Adjusting lights via events and triggers has another added benefit: it provides the same mechanism for changing lights across any lighting controller. This DMX setup will be built in, so you won't need any other services or programs. But it doesn't eliminate the possibility of using the same events to send messages to Phillips Hue lights, an MQTT broker, or an HTTP API. There's nothing special about how the lights are changed.
One more small detail — before you create your fixtures, you'll define at least one universe. Each universe gives you 512 channels, and you define whether it is accessed via USB on the server, WebUSB on a specific client (you pick the client when you define the universe and the DMX is controlled by that client's web browser), or the IP address of the ArtNet or sACN controller. This allows you to have a positively huge, and extensible, lighting setup if you have the need and budget.
So setting up lights looks like this:
It will be a little bit tedious, but also very clear — an event happens, the lights change to a set scene. Previewing how scenes work together will be trivial. And there will be plenty of tools to make configuring it all easier.
That's basically it. One thing I haven't figured out yet is how best to create the "State" listeners that pass values from the simulation to the lights, which might be useful for some shield indicator lights that cycle through the colors of the shields as the shields increase or decrease in intensity. We'll save that for sometime in the future.
Another thing I hope to do is display the light fixture's positions on a map of the bridge set, which could enable some interesting effects like fading lights in and out as you move the cursor across the bridge map. That won't happen for a while though.
I believe this covers everything. Let me know if you have questions, comments, or notice anything missing.
All reactions