Faking lighting through vector evaluation compositionI recently needed to apply a fake lighting effect for the green goo in Nytro's scrapyard level's crypt. The effect needed to fade out toward the ceiling, the back of a side room, and around an exit door, with the shape of the light volume varying as needed to fade believably and smoothly with the player's position.
In addition, I wanted the freedom to affect both Nytro's shadow and light color—defined in a shader—along with a custom light direction. And, with how often games need to respond to a position, I wanted the system to be generic enough to be potentially useful elsewhere.
So, I basically made a shader for positions.
The core concept is to input a Vector3 (the player's position, in this case) and receive a Vector4 as an output. Anything between the input and output acts much like a shader or layer in an image editor would, modifying an existing value in an arbitrary manner in response to an input. This potentially allows position-driven fake light to be colored procedurally. And, the system can be reused for anything else that needs to produce a value from a position.
For the crypt's light, I first defined a set of scripts inheriting from an abstract VectorLayer class. These include a solid box volume, a cylinder volume (with a radial gradient), and a linear gradient. These classes override a function that returns a Vector4 for a given Vector3 and existing value. And, the VectorLayer base class contains a blend mode property that defines how a layer is applied to the existing value (e.g., the value produced by the previous layer). For example, the solid box volume simply returns one value if a box contains the given position and another value if it doesn't.
A MultiVectorLayer class (which also inherits from VectorLayer) then simply loops through a list of layers, passing the output of one layer into the input of the next (along with the player's position). This class acts as a layer group and also as a layer in and of itself, allowing a system to make use of an arbitrary hierarchy of shape and modifier layers.
For example, in the crypt, I have defined one solid box for the main chamber and a second solid box for a side room. These are applied additively to form a volume. A horizontal linear gradient is applied on top of the side room to fade the light out toward the dark back. A cylinder sits at the exit with a radial gradient that smoothly fades light around the doorway. And, because the light is coming from the pool in the bottom of the main chamber, a vertical linear gradient is applied multiplicatively over the whole thing to fade it from bottom to top.
Here's a GIF of the system directly modifying Nytro's lighting values in response to position:
https://gfycat.com/BlindDefinitiveChupacabraAnd, finally, here are a couple of screenshots taken before (left) and after (right) applying the simulated lighting while very close to the green goo: