This tutorial goes into the workings and quirks surrounding model lighting in Half-Life.
In goldsource (the Half-Life engine), models will only receive one type of lighting. Generally the model grabs its lighting info from the brush below
the origin point of the model.
Monsters such as the Barnacle use the EF_INVLIGHT flag, which inverts the direction of the lighting. The Barnacle will look for its lighting info above
the origin point. As you can see from the screenshot below, the barnacle is lit up in green and it'll ignore the blue light below it.
Lighting info is grabbed from any surface that holds lightmap data. This includes all solid world geometry, but not
brush entities, such as
, etc. Even though those brush entities are affected by lighting, the model lighting will ignore these surfaces and instead look for the next available light info on a world geometry face.
In this example, the surface the player is standing on is clearly blue, but the model is lit red because of the red light below this
To fix this, you either have to revert the brushes back to world geometry or turn them into
technically is not a brush entity, so the model will have no issues taking light info from these surfaces.
Model lighting in outside areas has some special rules. Here is an outside area lit by a
. As you can see, the light in the bright area and in the shadows affect our model in different ways, as expected.
Things become strange once we add more light sources. The blue point light is completely ignored by the model.
What's going on? All surfaces that are affected by the
will override any other light info. This is because of a global light value that's being stored in the game. This global light value has the same light colour and intensity as your
. Whenever you move around on a surface that has a lightmap related to the
, it'll use this global value to light the model.
How do we fix this issue? The ZHLT.fgd has a new entity called
. With this you can set a custom global light value. You could set this and adjust the model lighting. However, there is a better and easier way.
Instead of a
, you can use a
. Make sure you set 'Is Sky' to 'Yes'.
lights your outside area just like the
does but it doesn't tie those faces to the global light value. Therefore it'll use the actual light info below the model again.
Another issue with outside areas is the SKY texture. This texture does not hold any lightmap info. If any model is above it, it'll not receive any light at all.
There is a workaround for this issue. You can create a BLACK_HIDDEN brush. Make a new brush with SKIP on all sides and BLACK_HIDDEN on the top surface. These are tool textures found in zhlt.wad. Place this brush above your SKY texture and turn it into
. Make sure it is non-solid: Passable = Yes (
BLACK_HIDDEN is an invisible brush that will retain lightmap info and enables you to have proper light on models again.
These BLACK_HIDDEN brushes are also great in places where model lighting is unrealistic, such as grates. These are
, so models will not get their light info from the
surface but from the light below in the pit (where it is much darker). By putting a BLACK_HIDDEN brush on top of this grate, you can fix this issue.
You could also place these BLACK_HIDDEN brushes in long elevator shafts to keep updating the player model lighting. Or put them across a chasm or broken bridge where players have to jump across. If used with SKIP and zhlt_noclip 1, this brush cannot affect players and monsters so you can place as many as you like.
BLACK_HIDDEN can also work great for Ospreys and Apaches to make sure they get the right amount of light. In this case, I'm using a large brush to cover the entire area where the Osprey is flying. This makes sure it will not render in full black when it passes over a SKY texture. It will also prevent it from picking up unwanted light info from any other structures on the ground. If you use large surfaces like these. be sure to scale up the BLACK_HIDDEN texture (10 or 20 scale) to improve compile times and lighten the load on lightmap resources.
If your Osprey or Apache still renders fully black, it might be too high up. The engine will stop looking for lightmap info once a model is higher than 2048 units above a surface.
If you want a model to have specific lighting info, you can use the
value. Go into the properties of the model you want to adjust, disable SmartEdit and add the keyvalue
and a targetname (for example:
). Then create an
entity, name it
and place it somewhere where you'd like to copy the lightmap info from. The model will then copy a small patch of that lightmap under its origin point. This can be very useful for static models such a Xen Tree's.
I hope this tutorial helped you understand model lighting and lightmaps better. May you now create properly lit maps and models!
- You can add the
effects keyvalue with a value of
16 to any monster if you want to invert the lighting direction.
- Some models are compiled with the 256 (No shadelight) or 1024 (Force Skylight) flags, such as the Nihlianth.