Photon Lighting Engine: Cinematic Emergency Vehicle Lighting

Photon is a mock lighting-engine that uses HDR rendering techniques to create cinematic lighting for cars. While the primary focus is on emergency lighting, it also has some basic support for general car lighting.


So detailed feature information is available on the addon page (click the banner) if you’re interested. This thread is geared towards the more advanced users of Garry’s Mod.

This project actually just started as a way for me to add emergency lights to cars in about September of 2013. I sporadically worked on the project until about June, when I moved away, got a job and had to lose my dedication to Garry’s Mod. After periodic video comments of people asking about it, I figured I would go ahead and push to release it. So for the past month I’ve been working on it regularly.

So there are indeed other mods that do similar things, and I think work reasonably well. Notably VCMod. Also Acecool created his own emergency lighting system for Crime City. And as a matter of fact, Photon is just stolen code from Acecool*. Thanks, buddy. All I need now is a picture from my prom night on the banner. Anyways, I actually spent a great deal of time studying the effects of light on cameras to make this work.

Photon, at its heart, is designed for enthusiasts of actual emergency vehicles. Why we love flashing lights and sirens, I truly don’t know. My dad was a cop and somehow that made it into my blood, but lots of other people just have a fascination with this. Photon is designed for us, by allowing people to customize, share and spawn vehicles with unique specifications.

For example, part of this release was a Seattle Police Taurus. The vehicle, light colors, siren and skin are all based on what the actual car looks like. I happen to live near Seattle so for me it was something I wanted to make. Someone in Los Angeles can take the car specification file and modify it to behave like an LAPD cruiser, by using some maps that I made and some they created.

Photon itself is a standalone “engine.” I say “engine” because really it’s a unique system that uses layered colors to mimic how lights would actually look through a camera. It uses HDR strategies of hue shifting, but ultimately is not a special redo of Source lighting (which is just terrible, by the way).

Cars have to be individually downloaded if people want to actually use the mod. I thought about packaging them together, but decided that it seems stupid to force people to use the NYPD Impalas and Seattle police car I made (nonetheless people are downloading the cars without the engine and wondering why it doesn’t work – you can never win).

Each car uses a “specification” file (I was calling them “definitions” at first but decided it was inappropriate word usage). Everything that makes the car unique is mapped out in that file.

As of writing this, you can specify the following:

  • Props to parent to the vehicle
  • Skin
  • Bodygroups
  • Color
  • Vehicle script (if you want to adjust handling for some reason)
  • Basic lighting parent (it will inherit the lighting information for basic cars, ie the Impala, but only if you want it to)
  • Positions for each light (it has more complexity to it than it sounds)
  • Colors (LED white, halogen soft white, halogen cool white, LED blue, LED amber, LED red, darker LED/halogen red)
  • Light behavior (flashing LED, rotating light, fading/pulsing light [usually halogen])

All of that sounds complex. And yeah, it actually is. Even as the sole developer of this, doing everything is a bitch. Making your own car is not for the faint of heart. There is no simply little GUI tool right now, everything has to be manually mapped out. But while it is really difficult to grasp at first, there is tremendous freedom in what can be done. For the most part, any kind of lighting you see in real life can be closely imitated by this mod (with the exception of lights that change positions).

The point is that virtually any emergency vehicle has the ability to be replicated (as long as you have the models, which I have yet to know much about).



If you don’t like to watch videos and want to read, here is everything in the above videos in text.

This is something I will need to write a lot of documentation for to fully explain. Being at work, I don’t have access to the Lua files, so this is what I know until I get home and verify.

Expanding on what was said above, each vehicle has its own specification file. This allows the car to appear in a player’s spawn menu. Without the Photon addon, all you’re doing is adding another car. If someone tries to spawn an NYPD Impala without Photon (as at least literally 16 people have done) the car will just be a blank LW Impala. The specification file adds a table to the car before it’s inserted into the Vehicles list (in my specs it’s called EMV). That file is shared, so both client and server will get it. (As a side note, this was colloquially called Emergency Vehicle Upgrade by me before I formally named it in the last few weeks, so the EMV and EMVU table names appear often in the code as just a legacy carryover).

When the game starts, that table information is queued up into the master Photon table, indexed based on the car’s name (so it’s important you give cars a specific, unique name). When a car is spawned, it’s checked against the Vehicles list. If it’s flagged as being either EMV or Photon compatible (which it currently needs to be both in order to work) then functions will basically add a bunch of meta information onto the entity. As another side note, the basic lighting and emergency lighting are separate systems. The only real thing they have in common is an identical render process. This is so non-emergency vehicles can use car lighting without needing to behave like an emergency vehicle.

With emergency vehicles, upon spawning, the skin, bodygroups, color and addon props are applied instantaneously, so it will appear as if the car is packaged the way it looks. Also, just so my boy Acecool knows, I am aware that the addon props are currently actual entities, and that they should be clientside props to be more efficient. That will be fixed with time, my love.

The aforementioned table properties are pretty straightforward to understand. If you just want to change a skin on an existing car, it’s very easy to do.

The lighting is where it gets tricky. Here I will go over the different tables of lighting info:

The Metatable contains templates that the specific lights reference. The templates define source sprite, size, width multiplier, rotation behavior, relative angle offset and all sorts of other shit. Basically I tried to keep shared properties of lights in a template that can be referenced by the render function. For example, LED nodes on the lightbar facing the front will be different than the back, because front facing lights generally use a -90 degree offset. This is so the specific lights can use Angle(0,0,0) to face forward, then if rear-facing lights use 90 degrees, they can also be an empty angle to face absolutely backward. In case it wasn’t clear, the offset angles are relative to the direction of the vehicle. From what I’ve seen, -90 is almost always forward and 90 is backward. Tweaking that to a more unusual angle can aid when making lights that sit at a really complex or bizarre angle.

Also important, the template defines the light “source,” which is basically a sprite that appears at the core of the light. Over time I have accumulated a wide variety of source sprites I made that can help. Most Whelen props have a matching sprite, so I would recommend pulling them from existing cars I made to help out. Also to understand what any of this is talking about, I would recommend unzipping the addon and going through the code for a little bit.

By the way, rotating lights use Angle = “R”. This will cause the rendering function to ignore the yaw angle and instead make the angle based on the current time. To offset them you can specify how many degrees different you want the light to be. I employ this technique on the NYPD Impala RMP, and it’s easier to just look at that.

This is typically more straightforward. The position table defines every single light that the emergency lighting system uses. There is a relative position to the vehicle, relative angle after being offset by template, then a string for the template index. In my vehicles, I now add indexes before each table line, ie [1] = {}, that way you can see the index of each light all lined up. Knowing the index is important in order to make the light work, and commenting them leads to the numbers not being lined up visually.

With my vehicles I tend to show them in groups of two. This is because those lights are are basically siblings. They will only share opposite X positions and yaw angles (ie 10 and -10). On well-done models these numbers will be exactly opposite because the model is completely symmetrical. On cars that are a little rough, you can have lights that are .01-.5 points off relative to their sibling, and you can easily account for that. It’s helpful to keep this pattern so red/blue lights are generally easy to identify, for example red could be all odd numbered lights and blue could be even.

Now it’s back to being tricky. A component is like a wrapper for similar lights. It’s more mirroring of how emergency lighting works in real life.

For example, if you have grille lights, you can group them all together in a component called [“grille_lights”]. Within that component, you specify every possible frame the lights can be in within a table.

If light positions 21, 22, 23 and 24 are all in the grille, you want to make a table with each possible combination you want to use. Each table will have separate light-tables that define the color, index (ie 21-24) and optional brightness parameters. If you want to make a light at 50% standard brightness, your brightness parameter would be .5. If you want pulsing lights, you make a table in place of the brightness integer with three parameters { speed, minimum, offset } (I think). This is fed into a sin function that calculates it based on the current time. The speed is how fast the pulsing happens. The minimum is the minimum brightness you want (doesn’t look stellar right now, though) (ie .2 means it won’t drop below 20% brightness). The offset allows you offset a light relative to another. It also really fucking confuses me, because I think pi should be a complete offset, meaning it will always be opposite to 0 offset, but something is bad in my math so 10 seems to create an opposite offset. This is primarily used by me in the wig-wag effect of headlights (see Taurus).

The outline of this table should be identical to Components or else you’ll get spammed with errors. In patterns you specify the component, modes, then the sequence of that component mode.

The name you use for each mode will be referenced in the final Sequences table I’ll discuss below. For example, in [“grille_lights”], say you want a mode called [“code1”]. In Code 1, you might just want a subtle alternating pattern, for example right to blue slowly. Within the [“code1”] table you would specify the sequence of that using the indexes of the Components table. Say index 1 is red and index 2 is blue. To make them flash back and forth, you could do { 1, 2 } and it will loop like that forever. However only doing { 1, 2 } will cause the lights to flash very fast, as the frame time is only .06 seconds. It would be more appropriate to do { 1, 1, 1, 2, 2, 2 } to create a slower alternating effect.

If you want to have a period of darkness for a flashing effect, use 0. It does not need to be defined. Zero is coded as basically a dead-frame, so no lights in that component will turn on. In LED light bars it is common for the lights to go blue, flash, go red, flash and go back. In our grille lights example, this can be done like { 1, 0, 1, 0, 2, 0, 2, 0 }. That will cause each red/blue set to flash twice before switching. But ultimately there are all sorts of patterns you can create in any way you want.

This is basically the highest-tier in completeness. This is what the the end result will render. In here you define the name of each light sequence, then go through and assign a component to a pattern. For example, for a code 1 sequence we would want an entry like [“grille_lights”] = “code1”.

These are kept separate to avoid really complex patterns that require you to highlight each on point in each frame. You can also have components that manipulate the same lights. The prime example of this would be in a traffic advisor. If you want a code 1-3 pattern for a lightbar, but in other sequences want a traffic advisor, you can have the traffic advisor reference the rear-facing lights and only turn it on in the appropriate sequences.

On some cars there is a Disconnect entry. This is for disconnecting basic car lights. The main purpose of this is to turn off the headlights so you can create a wig-way effect. You can also apply it to any light position, however you might have to dig into the Photon vehicle library to find the positions.

A few people have asked about spawning Photon-supported vehicles under their specific circumstances. This is possible to do, and literally done as easily as I can.

When you spawn a vehicle, you need to make sure you tack on the VehicleTable (as in car.VehicleTable). This little gem is from Sandbox and the Vehicles list (list.Get(“Vehicles”)). In Sandbox, when you spawn a car, .VehicleTable is appended to the entity and includes all the info from Vehicles list. The VehicleTable includes all the precious information Photon needs to initialize. Before, you needed to call some internal functions if you were spawning cars outside the Q-menu. Now, when you create an vehicle entity, Photon will check to see if you add the .VehicleTable and then automatically do the initialization procedures.

If you, your addon, or your gamemode spawns vehicles without referencing the Vehicles list, my first question is: why…? Shortly followed up by: fuck you. The Vehicles list is where vehicle addons have to live. Without the VehicleTable there is simply no way to tell if a vehicle is supposed to have Photon or not, as no identifier is tacked on by default, and multiple specifications can match with a model. VCMod, for example, gets cleverly around this by using the model (afaik) and applying itself that way. That is not something I can support, because, as I said, you can have two different cars that base of the same model.

I would strongly suggest you always spawn cars by referencing the Vehicles list. All the information needed to spawn the car correctly is held in that list, and at the very least, have it pull the VehicleTable when someone spawns a Photon car.

To get a vehicle from that beloved table, all you need to do is:

local _____carInfo = list.Get("Vehicles")["vehiclename"]

I’m just kidding about the underscores. If you have underscores in front of your variables, then go fuck yourself. There’s no way around that. You’re just a jackass who has never coded in a professional environment. Try pulling that shit in the .NET industry and see how fast your ass gets kicked out.

I digress.

For Photon, I personally (and urge others) to make the appearance name the same as the index name. As long as there aren’t any quotes in the name it should index just fine. So to get the Photon vehicle info from the Vehicles list, just right-click>copy on the Sandbox menu over any Photon car, and that should work as a correct index.

So for a quick snippet of what it might look like if you don’t use the Vehicles list:

local ent = ents.Create("prop_vehicle_jeep")
-- all your entity setting up goes here
if youWantThisAsAPhotonCar then
 ent.VehicleTable = list.Get("Vehicles")["photonnameyouwant"]

From there Photon should pick up on it and apply the correct modifications.

For any further dev questions, please reply to this thread so I can help you out better.



local A = "AMBER"
local R = "RED"
local DR = "D_RED"
local B = "BLUE"
local W = "WHITE"
local CW = "C_WHITE"
local SW = "S_WHITE"
local G = "GREEN"
local RB = "BLUE/RED"

local VehicleName = ""

local EMV = {}

EMV.Siren = 3
EMV.Skin = 0
EMV.Color = Color(255,255,255)

EMV.BodyGroups = {}

EMV.Props = {}

EMV.Auto = {}

EMV.Sequences = {
	Sequences = {
		{ Name = "STAGE 1", Stage = "M1", Components = {}, Disconnect = {} },
		{ Name = "STAGE 2", Stage = "M2", Components = {}, Disconnect = {} },
		{ Name = "STAGE 3", Stage = "M3", Components = {}, Disconnect = {} }
	Traffic = {
		{ Name = "LEFT", Stage = "L", Components = {}, Disconnect = {} },
		{ Name = "DIVERGE", Stage = "D", Components = {}, Disconnect = {} },
		{ Name = "RIGHT", Stage = "R", Components = {}, Disconnect = {} }

local V = {
	Name = VehicleName,
	Class = "prop_vehicle_jeep",
	Category = "Where do you think?",
	Author = "You",
	Model = "",
	KeyValues = { vehiclescript = "" },
	IsEMV = true,
	HasPhoton = true,
list.Set( "Vehicles", VehicleName, V )

if EMVU then EMVU:OverwriteIndex( VehicleName, EMV ) end

Photon has its own group now which has discussions for bug reports and requests and information relating to our server. The latest update information will be posted on the front page as soon as information is available. Unfortunately, information regarding future updates won’t be released unless otherwise intended which is usually Schmal uploading pictures of new lightbars, features, or even cars that are coming.


2016 Ford Police Interceptor Utility (Schmal)
Seattle Police 2010 Ford Taurus (SentryGunMan)
NYPD RMP 2012 Chevrolet Impala (LoneWolfie)


Several people have suggested selling this script. While I am sincerely humbled and appreciate their thoughts, I think it would go against the spirit of creativity. Seeing people, use, share and modify my work is worth more to me than I would get out of selling something because there is a market.

If you have money that you wish to spend on this, please consider donating it to one of my favorite charities instead:

American Red Cross
Brain & Behavior Research Foundation
Autism Speaks


LCPD:FR community for inspiration.

Photon Development Team:

Full credits list can be found here.

More Additional Information
*this is not a true statement.
I = Schmal

***Since the old thread died ever since VCMod v. Photon, we thought it’d be a good idea to start fresh so here you go!

Can we see the source code?

The full GitHub page can be found here.

I love the presentation. Sleek, clean, and simple

This is so cool :slight_smile: