Mapping 105: Lighting

Unlike newer games, Q3 has a static lightmap. Shadows aren't cast in real time; they are pre-calculated during the compile of the level. This lightmap is rendered onto the textures you apply to your geometry, so in a way, all textures in Q3 are blended shaders. Real time or dynamic lighting isn't also possible in Q3, but Q3map2 give us the option of 'faking' dynamic lighting through shader trickery.

Practical examples and tips on how to use lighting (including the above) can be found in the Advanced lighting page.

## Why care for lighting?

The best answer to this question comes from Sjoerd "Hourences" De Jong:

*"Lighting is one of the most important and influential elements in environments. It has the power to make or break the visuals, theme and atmosphere. Lighting is often forgotten or underestimated. Designers often add it quickly and without much love. While in the past that was partially excusable by the weak hardware and game engines, these excuses just won't hold up anymore. Lighting is just as important as geometry. Without lighting there is no environment but just a group of 3 dimensional objects. Lighting has the capacity to bring life to a group of objects and take them to the next level of quality. Its purpose goes further than just giving the players the ability to see where they are going. It creates atmosphere. It makes places look scary/cozy or warm/cold. It augments the three dimensional feel of objects and it creates composition and balance to lead the player's eyes around. Yet considering all of that there is a very large group of games and levels out there which use nothing more than white ambient lighting everywhere."*

## Lighting sources

For the purpose of these tips, here's a definition of a light source:

*"Light sources can be anything: small or large lamps hanging on walls or from ceilings, the moon or the sun, crystals, lasers and other type of high tech beams, fire, mirrors, magical effects, water surfaces that bounce back light, lava or radioactive slime and so on. Everything is possible as long as there is a noticeable source."*
The most basic rule about lighting is that every light must have a source, and that every light must appear to be cast from that source as well. Also, the lighting a source casts must be balanced with both the size and the brightness of the source. Big light sources are going to illuminate more areas and their area look brighter than small light sources. This should be reflected on the map as well.

The key is the use and positioning of your light sources, whether that be, shader or entity in origin. Try to shine light through interestingly shaped geometry, where it can be cast on to an appropriate surface. After this, increase the resolution of the affected geometry's lightmap. Select the geometry where the light is to be cast and assign it as a func\_group. Bring up the entity editing window (N) then add the key `"_lightmapscale"`, with a value less than 1. Use powers of 2, 0.125 is very high res. Be aware that many high res lightmaps will bump up the size of your .bsp considerably. You also have a limit of 256 lightmaps, so pay attention to your console and if you notice your map lighting getting broken it could be related to this.

## Lighting colors

The most complex rule of lighting is that colored lighting is a must and absolute requirement in almost every situation. Colors can make or break a composition; they shape the atmosphere and emotions associated with an area and they simply make environments more interesting and lively to look at. Most light sources in the world cast lighting that, in one way or another, have color. Therefore it isn't very realistic to place white lighting in the environment.

Due to the way the engine works, it is possible to relay on shaders in order to get the level lit, but 90% of the time, this isn't enough. One must color the lights oneself instead of relying on how the atmosphere or materials might enhance the lighting. If color isn't added, the result will be very bland and fake.

Another aspect of lighting is the light temperature. There's a theory that says light is energy and the stronger the light the more energy it has and thus the warmer it is. In real life we use the Kelvin scale. The temperature influences the strength. 1600K is sunset and sunrise and 1800K is a candle. 2800K is a regular light, 5000K is midday sun and so on. Thus the chance that the light in the game environment would cast pure white lighting is rather small.

Another reason to use colors is the composition. In fact one color is not enough most of the time; at least two colors are needed or else creating contrast will be impossible. If only one lighting color is used, that very important color contrast is lost and the result would again be very bland.

## Understanding the Light Compiling Process

This is the compilation stage where the lightmaps are generated for every world surface in the map. We will learn more about this in the Compiling your Map tutorial, but for now what you need to know is this:

When you compile your map, Q3Map2 (your compiler program) stores lighting data of every 16 units on a brush and is stored in 128x128 pages unless otherwise specified. This all gets stored inside your .bsp file as a simple 2d white-to-black image.

#### What is a lightmap?

A lightmap at it's simplest definition is how the compile process stores and changes the brightness of surfaces. Your easiest way to see how this is gets compiled is to type r\_lightmap (with cheats on) in-game. A lightmap is actually a singular monochrome 2D map representing the amount of light hitting that object which gets put inside your .bsp file (and if you want, it can even be exported into a subfolder outside of your .bsp to be edited.

This advanced video explains lightmaps and lighting/history of compiling in Quake 1/2 (still applicable for our purposes) brilliantly:

https://www.youtube.com/watch?v=bxientPsqRg

Now that we understand some of the basics of how lighting works in the Quake Engine, let's get into the actual tools for lighting our map.

## Light entity

This is your bread and butter for lighting. Placing a light entity is simple. Right click in your 2d or 3d space and click light from the dropdown. If you want to change the power output of your light quickly, simply drag outside of your light's radius to change the power of your light. (note, you can toggle this off in (View->Show->Show Light Radius). Since this is an entity, press N to pull up your available settings. By default think of your vanilla light entity as about the same amount of light as a light bulb. The default condition emits white light in all directions at a value of 300 (`"light" "300"`). The apparent brightness of the light is modeled on "real world" physics, so the falloff in brightness will be an inverse square of distance from the source.

The basic lesson of the Inverse Square law in physics is this: Double the distance, double the power required to light it. Try to think about lighting your areas in terms of this, using powers of 2.

#### Keys

* **light:** value of light intensity (default 300). If you think about the light value as the wattage for an old-style incandescent light bulb, you are not far off target.
* **\_color:** weighted RGB value of light color (default white - 1 1 1, but you could use 255 255 255 or 1005000 100500 100500).
* **target:** point this to an target\_position, info\_null or info\_notnull to create a *spotlight* effect, instead of illuminating in all directions.
* **start\_off**: if set to 1, this light is turned off by default and only turns on if targeted by another entity or script. Just be sure to give your light a targetname / have an outside force targetting it.

#### Spawnflags

* **LINEAR:** light falloff will be linear instead of inverse square of distance from source. Linear fall off will not make much difference on low value lights. Useful on high value lights where the light travels long distances. Useful when you want to fill a room with one light.
* **NOINCIDENCE**: Amplified falloff you have and makes lighting more softer or diffuse. Think about it as if a regular light is sunny light and a noincidence flagged light is cloudy light.

#### Spotlight

If you want your lighting to feel like it is coming from a certain light source or you feel your lighting is filling an area too much and you only really want it in one area. To give your lighting more direction, Give your light entity an info\_null target. This essentially 'focuses' the light in that direction, similar to the effect of a spotlight. Useful if you aren't wanting to get your light spilled around the area evenly but more-so want it focused in one direction. Unfortunately GTK can not show lighting effect in real time, so it is necessary to compile the map in order to observe the effect you have created. Sometimes it may take 3 or 4 attempts to achieve the result you want, adjusting the strength of the light source and the distance and angle from the info\_null.

Key (for spotlight use only):

**radius:** sets radius of light cone *for spotlights* (default 64) in game units. Radius measurement is made at the targeted entity.

#### Coloring lights

There are several ways a light entity can be colored:

* **K:** With the entity window open, select a light entity in either the map or camera window. Press **K**. This brings up the windows color selector. Select a color and choose "OK". The editor automatically normalizes the light colors.
* **Sample Texture:** Select the light entity. Select a texture in either the texture window or the camera window. Hit SHIFT + middle mouse button.
* **Manual Entry:** Type in the value for the key \_color as a 3 numbers between 0 and 1 (inclusive).
* **Copy Existing:** Select another light entity whose color value the user would like to duplicate. In the editor window, lef click on the key "\_color". Now select the light entity to be colored. Hit ENTER.

If the "Light drawing" preference is selected (under Preferences), the editor shows the light entities as diamond shaped pieces the color of the light they cast.

## Shader Lighting

While using shaders to create your lighting may feel like a far more advanced style of lighting your map, consider the skybox. Arguably the skybox lighting is the best, most natural feeling light in the game, when done right. And it's all done using shader properties!

Shaders can be made to emit light from a surface. The amount of light that they give off is determined by two factors: the size of the texture and the value given for its `q3map_surfacelight` parameter. Sky shaders are a specialized subset of this, see: Creating a Skybox

Usually, the color of a shader light is given by the *average color* of the texture specified with q3map\_lightimage parameter, however Q3MAP2 added q3map\_lightrgb keyword to manually specify shader light color; sky shaders can also cast the light of a "sun" (or more) with a manually-specified color.

One of the best ways to learn is to copy, look at other map's shader files and search within for q3map\_surfacelight. You'll get to see what levels or properties were used for those lights to make them work. What you won't know for certain is what compile that map used to achieve them, but you'll have a good headstart on something you can then customize yourself. We'll get more into understanding shaders in the next chapter of this tutorial series: Mapping 106: Shaders.

Here is an example of a shader which has a lot of properties one can customize to great effect. Try using it as a building block

```
shaderexample/light1
{
 q3map\_lightimage shaderexample/light1
 qer\_editorimage shaderexample/light1 //this texture shows up in netradiant, not in game
 q3map\_surfacelight 5000 // power of your light texture
 q3map\_lightsubdivide 60 //defaults to 120 game units, but can be made larger or smaller as needed. Can have an increasingly "darker" effect when used with -fast.
 //q3map\_bounceScale // works like bounce compile but without doing bounce compile, should help soften light - EXPERIMENT WITH ME LAST
 q3map\_backSplash 1 2 //this pushes the light off the texture itself, useful if the light is spilling too close to the light source, try low amounts for starters
 //q3map\_lightStyle 1 // takes the form of a number between 1 and 31, useful for flickering and other effects
 {
 map $lightmap
 }
 {
 map shaderexample/light1
 blendFunc GL\_DST\_COLOR GL\_ZERO
 }
 {
 map shaderexample/light1\_gl //if you want your light to have dynamic glow, you will need to create the glow texture
 blendFunc GL\_ONE GL\_ONE
 glow
 }
}

```

##### Colored shader lights

Colors are expressed in RGB (red-green-blue) values, but not going from 0 to 255 like many programs do: their range is from 0.0 to 1.0. Hence, if you know an RGB color on 255-scale as R 241, G 55, B 100, you have to "normalize" those values by calculating 241/255=0.94509, 55/255=0.21568 and 100/255=0.39215.

For example, `q3map_lightRGB 0.0 0.0 1` would be blue light

##### Advanced technique (invisible shader lighting)

Here is a nice example of a shader of varying power levels which you can use to create an *invisible* area lighting. Play around with the properties of these shaders in your map to get a feel for how these can work compared to light entities. In many ways there is more control with shader lighting compared to light entities due to the shape of the brush.

```
textures/lightyay/lightbrush\_1k
{
 qer\_editorimage textures/colors/white
 qer\_trans 0.7
 surfaceparm nomarks
 surfaceparm nonsolid
 surfaceparm nonopaque
 surfaceparm trans
 surfaceparm nolightmap
 q3map\_lightRGB 1 1 1
 q3map\_nolightmap
 q3map\_surfacelight 1000
 q3map\_backsplash 0 0
 {
 map $whiteimage
 rgbGen const ( 0.000000 0.000000 0.000000 )
 blendFunc GL\_ONE GL\_ONE
 }
}
//twice as much light
textures/lightyay/lightbrush\_2k
{
 qer\_editorimage textures/colors/white
 qer\_trans 0.7
 surfaceparm nomarks
 surfaceparm nonsolid
 surfaceparm nonopaque
 surfaceparm trans
 surfaceparm nolightmap
 q3map\_lightRGB 1 1 1
 q3map\_nolightmap
 q3map\_surfacelight 2000
 q3map\_backsplash 0 0
 {
 map $whiteimage
 rgbGen const ( 0.000000 0.000000 0.000000 )
 blendFunc GL\_ONE GL\_ONE
 }
}

```

### Skybox light

This is one of the best ways to evenly light large portions of your map, but if you want it to look great, it can take a little time to 'dial it in', especially if you want a cloudier/more diffuse light. There are shader properties specific to a skybox, this information is posted in the skybox tutorial.

### Ambient light

Let's give a look to the ways to add some light all around the map, to avoid black spots: **ambient**, **\_minlight**, **\_floodlight** and **"radiosity"**.

Ambient light (key `"ambient"`/`"_ambient"`) is a property of the map's worldspawn entity. By assigning a number value to the ambient key, the overall lighting level of the map is raised. This has the tendency to flatten the difference between light and shadow. It can be effective depending on the 'vibe' of the map. If you are looking for less contrast overall on a map with fog or cloudy weather, this may work quite well for your needs.

To use either of these, add a new key called either ambient or \_minlight. Try very low numbers on your next compile. This will raise the lighting level-wise, but will keeps the light values of entity/sky/shaders intact.

Difference between "ambient" and "\_minlight" should roughly be something like this: in case you have four points (A, B, C, D) of the map which are illuminated like 0, 4, 10, 50 respectively, and then add "ambient 5", they will result as A 5, B 9, C 15, D 55; if you use "\_minlight 5" instead, they will result as A 5, B 5, C 10, D 50. *Note: "\_minlight" is not supported by the old Q3MAP used by Q3Radiant.*

In any case, abuse of this "ambient" and "\_minlight" (and in most cases, also use) *isn't recommended*. The best thing to do regarding lighting is to light the level oneself, placing lights where needed and creating sky shaders with appropriate parameters. Instead, in dark areas try to focus on the next two options available to you, and if that still isn't cutting it, try very low number.

To summarize: \_minlight forces your darkest colors to be raised and ambient forces your brightest colors to be lowered in favor of a global increase/decrease of everything else. Keep this in mind when using either.

In case you decide to use one of them, you can also specify `"_color"` key, which specifies the color of this fill lighting.

#### Floodlight and Radiosity

Floodlight and radiosity tend to look more "natural" than `ambient` or `_minlight`,

Radiosity is not a worldspawn property, but a mix of -*bounce* and other *Q3MAP2 compiling parameters*)

Floodlight fixes the issues minlight/ambient create by faking ambient occlusion - light becomes darker in closed spaces and brighter in wide open spaces.

In **worldspawn** add a new key called **\_floodlight**. The values are, in the order that they are typed:

-RGB color values, in the non-normalized 0 - 255 scale, or in the normalized 0 - 1 scale.

-Distance to trace. Higher values make the light rays travel distance longer, resulting in darker lighting. Lower values produce the opposite effect, light rays travel distance is shorter, resulting in overall brighter lighting. Try to guess the best value based on the overall wideness of your map.

-Intensity. The floodlight's intensity. Float value.

Note that floodlight "floods" the whole map, there is no control over per area flooding.

### Radiosity

To get an object to reflect light similar to how it does in real life, q3map2 fakes radiosity by generating lights right in front of surfaces hit by direct lighting (**-bounce x** parameter sets light bounces). How much bounce you put in your compile settings determines how much radiosity you will get in your lightmaps.

The best way to learn how this works is to create a simple map and try out different levels of bounce. Keep in mind RGB from textures can 'bleed' onto other lightmaps (see images on the left).

To further push things, you can add the **-bouncescale x** switch. It'll multiply the intensity of lights generated by light q3map2's radiosity by x, where x is float. This will "overpower" light bounces, creating strong indirect lighting and strong color bleeding. The side effect is that this will also create overbright spots here and there on corners. There is no workaround those overbright spots because that's how q3map2 generates radiosity in the first place.

If map becomes overbright everywhere you can compensate with **-compensate n.n** in light stage and/or **q3map\_lightmapbrightness n.n** on all surfaces, meaning that you'll have to have shader scripts for every lightmapped texture in your map. In turn, **-compensate n.n** has another side effect, it darkens places that are already dark. To compensate for this last side effect use **-gamma x** in light stage to multiply the lightmap's gamma by x, where x is float. To learn more about how your compile affects the lighting, see: Compiling your Map

### Tips for Lighting:

By preference I suggest using light emitting textures. They usually look better in place then light coming from nowhere. If your map is mainly outdoor, focus on learning how to create optimal skybox shader properties instead of adding a bunch of outdoor light entities. This is done by applying a shader property to a texture which has a light. Easiest way to figure out how this works is to look at maps which employ this method and then examine the textures and shaders of that light source, be it skybox or otherwise.

If you use point lights don’t make the values too big since you will get ugly spots, it’s better to use several small lights.

## Light styles

Although the engine doesn't allow the use of real time or dynamic lighting, thanks to Q3Map2 it's possible to "fake it" by using shader tricks. That can be used for simple flickering/blinking lights like torches. Just be careful in the use of dynamic lighting, as with all shaders, overuse impacts upon performance in terms of a loss of framerate. Also, any surface must not receive light from any more than 4 dynamic light sources.

* Create a light entity.
* Open its properties and add the key `_style` with a value between 1 and 13. Some experimentation is required to achieve the look that is required.

## Triggerable shaders

Q3MAP2 allows "triggerable shaders", having a trigger cause all the shaders with a certain name in the map be switched with another one (e.g. to "turn on" a screen which shows some kind of message), see here.

In case such shaders include a lightmap stage, the lightmap could get corrupted: this Simonoc's article shows how to use triggerable shaders and how to workaround such problems. It also mentions you should prevent players from triggering them repeatedly too fast, or the game may crash.

Next chapter: Creating a Skybox

## Lighting tips

* Use colored lights with care, to emphasis light emitted from flame for example, but let subtlety be your guide.
* For models, check the mapmodels page.
* For brushes and patches to get a more accurate lightmap, group them into func\_group entities and use the key-value pair `"_lightmapscale" "0.125"`.
* OA isn't that good at rendering curved shadows or angled shadows. You can end up with ugly jagged shadows if the light is emitted from or hits geometry at certain angles. Changing light sources can help, also making affected geometry into func\_group entities and assigning the keys "\_rs" or "\_cs" with a value of 0 is a useful trick. The "\_rs" key prevents shadows being cast on to geometry, and "\_cs" prevents it from casting shadows.
* The proper use of light-emitting textures like skies and lava add real moody light. And it's a lot easier to do than tons of light entities.

## Notes

1. ↑ If you run a level in `/devmap` mode and then type `/r_lightmap 1` at the console, you will see the level's lightmap. The geometry, apart from non-lightmapped shaders, will be white, with the shadows, light and colour burnt into it clearly visible. `/r_lightmap 0` returns the map to normal.
2. ↑ LevelDK 4: lighting and curves
3. ↑ LevelDK 6: faking dynamic lighting
4. ↑ Lighting in game environments by Hourences
5. ↑ 5.0 5.1 Lighting in game environments by Hourences
6. ↑ WeMakeMaps.com Shader Lights

## Further reading

* Mapping\_manual/Advanced\_lighting
* Mapping\_manual/Compiling and packaging#The Light stage
* High resolution lightmaps by 0kelvin
* Fake indirect lighting by 0kelvin (Floodlight, Radiosity)
* Fixing overburned pixels by 0kelvin

## External Links

* Wikibooks' Lights
* Worldspawn archive's Playing around with lights
* WeMakeMaps.com Basic Lighting
* WeMakeMaps.com Adding lights to models
* WeMakeMaps.com Sky Lights
* WeMakeMaps.com Ambient light