To jump straight to the video, go here: http://youtu.be/bRJPddYX7m4
In this post I’ll talk about how I am making a lightning effect. No, not a lightning bolt itself – that’s somewhat interesting and perhaps worth a post in and of itself – but a lightning flash effect accompanied by thunder. The sudden bright-as-day flashes that light everything up in the night, perhaps revealing something unexpected in the corner of your eye.
One of the first things I do before trying to simulate some natural phenomenon is to study it a bit. I’d recently taken some video footage of a lightning storm. I loaded it into my video editor to look through it frame by frame. What do things look like when lit up by the brightest flash?
One thing that stands out is that there aren’t any shadows. That makes sense, since the light is coming from all over the sky – the lightning bolt is back-lighting the entire cloud deck I suppose. During a prior attempt at simulating lighting, I had done it by “borrowing” the global directional light (used for sunlight and moonlight) for a few frames and temporarily positioning it at high noon and making it very bright. Looking at this image though, it seems like a flatter ambient light might be more appropriate. So I thought I would try that instead (not to mention the code was simpler).
The other thing I wanted to study was how the brightness of the flash varied with time. During my previous attempt, I had haphazardly come up with some programmatic logic that made a few frames full brightness, then a few more back to normal, then a few frames bright again, then back to normal… repeat that a few times and call it good.
Carefully stepping through my video footage though, I noticed that the flashes started abruptly but tapered off more slowly. And of course, there tended to be a few dimmer flashes following the main one.
A quick check on youtube for some lightning videos showed a similar pattern. I briefly scoured the internet for some research on “lightning flash brightness over time”, to see if any college students had done a study on this – but after a few minutes I decided it was a waste of time. I had the info I needed.
I decided to make a texture in photoshop with gradients that indicate brightness over time. 256 values over time, and, in this case, 4 rows corresponding to different variations.
Here’s an example of a night scene (where I artifically dim the surrounding area) showing what it looks like both with and without flash.
The next step in making a convincing (not necessarily realistic, mind you) simulation is to incorporate audio. I downloaded a bunch of lightning sounds from soundsnap, chopped them up how I like, and put them into my XACT project.
I didn’t find any lightning sounds I really liked, but these will do for now. I have 4 different variations that XACT plays randomly when the sound is triggered. I also have a volume variable. The one thing I am missing are some more pure rumbling sounds – the ones I have all sound like the crack-and-rumble of close-by lightning.
Since sound takes time to travel, I delay the thunder by anywhere from 0 to 3 seconds. Longer times would probably be more realistic (you can experience very loud thunder that is much more than 3 seconds away), but shorter times make for a more pleasurable, cohesive experience.
I finally got around to hooking up the wind and rain noises too (the ones in my previous weather video were faked in post-processing). Helpful note to people using XACT: the xWMA compression option results in looped sounds having a terrible gap on the PC. So use one of the other (unfortunately less effective) compression methods.
The result is here (do you see something unexpected in one of the lightning flashes?):
I’ll go over a few other gotchas. I want to ensure that my engine seamlessly supports quick travel – one frame you may be in location X, the next you may be on the other side of the map. This could happen if there is actually “real” teleporting in the game, or simply due to a cut scene, or entering a cave or area that is actually implemented elsewhere on the map.
So in these cases, the logic that drives the lightning flashes and noises needs to know that our position has changed so it can shut them off (or not).
Well, this seems like a nice fit for a component in the game entity framework. The lightning visuals and sound could be tied to an entity When the entity is dehydrated (because we left the area), it is removed. We detect this, and shut off the lights and sounds associated with various components of the entity. It could even be modeled as an entity existing at a particular location – and our proximity to that location would determine the loudness/brightness. Maybe there would even be a lightning bolt model associated with it, so we would see the bolt if we were in range. Heat damage! Who knows?
In the end I decided this was overkill. I couldn’t fit the necessary logic nicely into Components I already had, and things seemed to require too much special-casing. On top of that, the area of the world map that is currently hydrated is smaller than lighting would have visual/aural effects – so it doesn’t necessarily fit nicely.
So as of now I just have it as part of the weather system (which isn’t tied to the entity-component framework at all), and a lightning burst is described simply as an intensity and a “relative proximity” that has no relation to real distance.
I still need to determine the weather conditions that lead to lightning (currently I am triggered it manually just for show). Something like a warm enough weather system, and with enough wind. And I still need to come up with a solution for silencing the lightning flashes when we move a large distance.