How Last-gen Games Do Lighting?

I’d first like to start by saying I’m interested in developing games using Unity on limited graphics platforms (read: mobiles)
Especially the upcoming OUYA and Gamestick platforms.

Over a long period of time I’ve been developing an itch of curiosity at the back of my brain, and it’s been getting worse.
If you watch any gameplay of Mech Assault 2: Lone Wolf for the original Xbox, you can see some serious visuals. Missiles and lasers fly back and forth, casting realtime lights on the scenery and characters with surprising visual fidelity for being an Xbox 1 title. The more surprising thing is watching huge numbers of them flying around, considering that in Unity the max pixel light count by default is a mere 2, and on mobiles can slow the game down more than a bicycle with flat tires stuck in molasses.
How do games like MA2 get away with such impressive realtime lighting given the limitations of the system they perform on? I know Xbox 1 had quite limited fragment shader support, so I’d be surprised if it was just a naive pixel lighting implementation.

They fake it. A lot of folks get stuck on the details, reality is, doesn’t matter how it works on the back end, if it looks good on the front end.

There are several ways I can think of, all of them doable in Unity luckily enough. First of all, as far as I know, the whole 2 pixel light thing in Unity doesn’t mean you can only have two lights in your scene or two lights on screen at a time, it means only a maximum of two lights will affect a single object. You could have lots of lights in your scene, it’s just that individual objects wouldn’t be affected by more than two (or whatever you set your limit to). A lot of the time, this isn’t even all that noticeable. In Unity, lights can also be set to switch from vertex to pixel automatically depending on how many lights are affecting an object.

As to Mech Assault, I don’t think I’ve played it before but here are some of the more common ways. One is by using vertex lighting, which is quite performance friendly and a lot of older games used that. But the main way is using lightmaps, bake out the lighting for the environment and all static objects…and then have the dynamic lights (which you used to bake the lightmapping) ONLY affect dynamic objects that move around. So instead of the dynamic lights affecting the whole environment, it’s only a handful of moving objects. Lights from things like projectiles have a small range so they can be set to affect everything. This way, you could have lots of lights on screen at a time, but if each one is only affecting a couple of objects at a time, the performance hit isn’t too bad. The fact that the environments and objects themselves aren’t too detailed also helps.

For further performance, you could limit the number of lights on screen at a time, or you could also set it so that if a light is too far away, it turns off. Since the world is using lightmapping, when the lights get turned off from being too far away, the only objects that would be affected would be dynamic ones, the environment would remain lit. Or maybe instead of turning the lights off, switch them to vertex mode. Or do a combination.
So for example, lets say at range 20, all pixel lights switch to vertex lighting, and at range 40 they get turned off entirely.

Another shortcut too is to use fog to hide lit/unlit objects that are far away. Which is great for performance anyways, lots of games from that time used fog to hide the fact that they had low draw distances, allowing for better performance.

If you’re feeling really stingy, one trick to fake lighting is to create objects with self-illumination or additive shaders and have them not cast any actual light at all. This way you can have really bright laser blasts and explosions and magic attacks and stuff like that which look bright, but don’t actually cast light. A lot of the time if the player notices at all, they won’t care all that much since they’re busy looking at the big shiny effect, and if they do notice…well you’re working with limited hardware, the rest of the actual game probably isn’t that much more detailed.

And one last thing, in the case of Unity, you have a massive advantage that the older games didn’t. And that is the lightprobes. Using lightprobes in Unity you can eliminate almost all lights entirely and dynamic objects will basically be lit by the lightmapping. That’s how Shadowgun on iOS was done and I believe they managed to not use a single actual light in the game or something crazy like that, while at the same time having characters and stuff lit by the environment.

Hahah you young’uns! :smile:

All of those tricks I already know about. None of which are what I’m talking about.
Look at Mech Assault 2. It’s not just casting light on characters, it’s casting light onto a static environment.
I know they must be using some kind of wizardry, but I would love to know what that particular brand of wizardry is, unless it’s just a particularly high-poly terrain with vertex lighting - I kind of doubt it though.

I might have to try that with my game…and the levels have a lot going on…

OK, I’m trying to brainstorm ways to light the environment the way MW2: Lone Wolf does (MW1 doesn’t, because it uses a fixed function pipeline, but MW2 added fragment shaders and pixel lighting to the environment so that lasers would actually cast lights on the terrain… it looks really good for being an Xbox 1 game)

Perhaps I could figure out some kind of limit system. So perhaps 10 lights at any given time can be active. I would also specify that dynamic objects use noforwardadd, so only the directional light is per pixel but point lights are per-vertex (the quality loss is negligible IMHO)
So essentially lights are perhaps sorted by a combination of both distance and priority (a light could have some priority set on it, so an explosion light is more important that the light cast by a laser for example), and the first 10 lights are set to per-pixel, and the rest are all forced to per-vertex.

I would also perhaps split my game levels into many modular pieces. The idea is to keep many small meshes instead of one giant mesh (or a few big meshes), so that two lights across the map from each other don’t affect the entire map as a whole, instead they might affect, say, a few pieces of the street corner they are cast on. This could also help in being able to use blob shadows, since having a blob shadow only draw a small section of the level is obviously far superior to having it draw the entire map (I might also enforce a similar system for blob shadows, where the nearest 5 or so are enabled and the rest are set to use a plain old quad, since the artifacts wouldn’t be so noticeable at a distance)

You’re trying way too hard. Vertex lighting + additive textures will give you everything you need.

There are other hacks, like floating shadows slightly above the terrain similar to Resident Evil 4, but that requires a lot more time and effort. Plus, you don’t need to do that in Unity.

The real key to great lighting is the artist.

Could you please elaborate on this?

I suppose if I tell my artist (whenever I find the time to get an artist >.<) to make sure surfaces are sufficiently tesselated, I suppose. Which I need to do anyway, I already put the light LOD system together (max 5 lights can be per-pixel, and the rest per vertex) and sufficient tessellation can prevent distant or unimportant lights from looking downright awful and instead elevate it to just looking a little bit off.

Use additives for glows and light sources to show the motivation for your lighting. They will affect everything behind the texture and this gives the illusion of the environment being affected by the light. Cheaper than alpha blended too. I even used additive textures to fake window glass on a PS2 game.

Tessellation or polycount should change with distance. This means you’ll need to match the impression of the lighting at different distances and with different polycounts. This is a full-time job if you are working on an open-world game.

Well I’m not so there’s that.
Shoot, I might just avoid realtime lighting altogether, or possibly very limited (basically, the look of early 1st gen Xbox games, and many PS2 games). And just wait until mobile hardware gets better for more complicated effects XD

Funny this topic is coming up… what if I have surfaces that have gloss/specular and light probes? I was thinking of baking my scenes with everything I want in the lighting and set the lights in the distance to Not Important just to retain the specular highlights after the bake. With the shadows baked in, the only thing casting shadows are the characters and dynamic objects