in Uncategorized

The Secret Behind Valve’s Flickering Lights

This article will explore the origin of the popular flickering light effect, seen across many of their titles including “Quake”, “Half-Life”, “Half-Life: Alyx” and “Portal”. A Unity package to use this very effect can be download at the end of the article.

Not long ago the Internet has gone crazy upon discovering that Valve has been using exactly the same flickering effect for over 25 years. The discussion quickly trended on Reddit, bringing an old piece of code back from 1996.

While the code was indeed used in many Valve games, it actually predates the company. The flickering light effect was likely written by none other than John Carmack for “Quake” in 1996. That was part of a library of flickering presets compiled by John Romero in 1993 while working on “DoomED”:

  • 0 : “Normal”
  • 1 : “Flicker A”
  • 2 : “Slow, strong pulse”
  • 3 : “Candle A”
  • 4 : “Fast strobe”
  • 5 : “Gentle pulse”
  • 6 : “Flicker B”
  • 7 : “Candle B”
  • 8 : “Candle C”
  • 9 : “Slow strobe”
  • 10: “Fluorescent flicker”
  • 11: “Slow pulse, noblack”

Luckily for us, “Quake” source code was actually made available by id-Software on their GitHub page. It is thanks to that that we can find out how the flickering light effect actually works.

Before we do that, it should be noticed that a lot of “Quake” code was written in QuakeC, a C-like compiled language developed exclusively to facilitate the creation of mods and content. The piece of code we are interested on is inside a function called worldspawn in the file world.qc, which has the responsibility of setting up and world settings and precaching sounds.

The function initialises a light animation table, with 12 different styles. They are defined using strings: the one shown in the Reddit post is "mmamammmmammamamaaamammma", which is referred in the code as “fluorescent flicker“. The string represents how the brightness of the light changes over time, with 'a' being total darkness, 'm' being full brightness and 'z' being double brightness.

//
// Setup light animation tables. 'a' is total darkness, 'z' is maxbright.
//

// 0 normal
lightstyle(0, "m");

// 1 FLICKER (first variety)
lightstyle(1, "mmnmmommommnonmmonqnmmo");

// 2 SLOW STRONG PULSE
lightstyle(2, "abcdefghijklmnopqrstuvwxyzyxwvutsrqponmlkjihgfedcba");

// 3 CANDLE (first variety)
lightstyle(3, "mmmmmaaaaammmmmaaaaaabcdefgabcdefg");

// 4 FAST STROBE
lightstyle(4, "mamamamamama");

// 5 GENTLE PULSE 1
lightstyle(5,"jklmnopqrstuvwxyzyxwvutsrqponmlkj");

// 6 FLICKER (second variety)
lightstyle(6, "nmonqnmomnmomomno");

// 7 CANDLE (second variety)
lightstyle(7, "mmmaaaabcdefgmmmmaaaammmaamm");

// 8 CANDLE (third variety)
lightstyle(8, "mmmaaammmaaammmabcdefaaaammmmabcdefmmmaaaa");

// 9 SLOW STROBE (fourth variety)
lightstyle(9, "aaaaaaaazzzzzzzz");

// 10 FLUORESCENT FLICKER
lightstyle(10, "mmamammmmammamamaaamammma");

// 11 SLOW PULSE NOT FADE TO BLACK
lightstyle(11, "abcdefghijklmnopqrrqponmlkjihgfedcba");

// styles 32-62 are assigned by the light program for switchable lights

// 63 testing
lightstyle(63, "a");

It should be now clear what "mmamammmmammamamaaamammma" does is to rapidly set the light on ('m' = 100% brightness) and off ('a' = 0% brightness).

The same code can literally be found in both “Half-Life” and “Half-Life 2“. And there are hints that the same presets are available in the level editor and even in “Counter-Strike“. Looking through “Quake” source code, it is also possible to find the function which parses those strings. It is called R_AnimateLight in r_light.c:

void R_AnimateLight (void)
{
	int i,j,k;
	
	//
	// light animations
	// 'm' is normal light, 'a' is no light, 'z' is double bright
	i = (int)(cl.time*10);
	for (j=0 ; j<MAX_LIGHTSTYLES ; j++)
	{
		if (!cl_lightstyle[j].length)
		{
			d_lightstylevalue[j] = 256;
			continue;
		}
		k = i % cl_lightstyle[j].length;
		k = cl_lightstyle[j].map[k] - 'a';
		k = k*22;
		d_lightstylevalue[j] = k;
	}	
}

From that, we can also see that the string is parsed at 10 frames per second.

⭐ Suggested Unity Assets ⭐
Unity is free, but you can upgrade to Unity Pro or Unity Plus subscriptions plans to get more functionality and training resources to power up your projects.

Download Unity Package

Become a Patron!

You can add these very light effects to your game, using the Unity package available on Patreon.

All of the above-mentioned light effects are included, with the possibility of writing your own pattern.

💖 Support this blog

This website exists thanks to the contribution of patrons on Patreon. If you think these posts have either helped or inspired you, please consider supporting this blog.

Patreon Patreon_button
Twitter_logo

YouTube_logo
📧 Stay updated

You will be notified when a new tutorial is released!

📝 Licensing

You are free to use, adapt and build upon this tutorial for your own projects (even commercially) as long as you credit me.

You are not allowed to redistribute the content of this tutorial on other platforms, especially the parts that are only available on Patreon.

If the knowledge you have gained had a significant impact on your project, a mention in the credit would be very appreciated. ❤️🧔🏻

Write a Comment

Comment