This is not about how to use Hammer itself. This is about how to efficiently model levels.

  1. Setup
  2. Fast Testing
  3. Level Blocking
  4. Optimization
  5. Lighting
    1. HDR
    2. Constructing Lights
    3. Other Tips
  6. Sound
  7. Advanced Modeling

img ttt_pigisland_nightswim

I used these resources to learn Hammer:

This tutorial is focused on making TTT maps, but it can be generalized.

Setup

  • Mount Counter-Strike: Source into Hammer. This lets you use textures and models from Counter-Strike.

Fast Testing

I use CompilePal instead of running the map compilation through Hammer. It’s faster, lets you save different configurations, and doesn’t lock up your computer.

Other tips:

  • Keep Gmod running as you model, with a TTT game going. When you compile a new version of the map, you can immediately open the console (~) and run changelevel ttt_yourmap, or hit Enter to rerun it. You may have to enable the dev console in settings > keyboard > advanced.
  • Set these in the console, they’ll make it easy to get to a round start when you reload the map:
    • ttt_debug_preventwin 1
    • ttt_preptime_seconds 1
    • ttt_firstpreptime 1
  • Use ttt_roundrestart as needed.
  • Compile with vvis -fast for testing, but be aware that it will produce strange lighting artifacts and shadows where there shouldn’t be.

Level Blocking

  • Add a skybox immediately. It looks better than the black nodraw cube around your level geometry, plus you’ll start getting an intuitive sense of how the light will fall and which parts will be in light and shadow. I always throw in a light_environment entity after setting the sky name in the map properties.
  • Start with dev textures, but add some variance. I like orange for buildings you can enter, the white/gray reflectivity indices for large walls and background objects, and the dark gray grid for floors.
  • When making displacements, don’t select the entire brush when you click Create Displacement. Use ShiftA to only select the face you want to convert into a displacement. Otherwise the compiler will squawk about stitching errors and face alignents.
  • All vertices in Hammer need to be aligned to a 1-inch grid. If they’re not, they’ll move around when the map is compiled, and you’ll end up with a roof full of seams that get you stuck if you walk on them.
  • Use visgroups to sort level geometry into categories you can show/hide at will.

Optimization

The main thing: Understand how visleaves work, and how complicated shapes will slice the air around them. This can be avoided by converting them into func_detail entities (shortcut: select them and press CtrlT).

img

Above: two eight-sided cylinder brushes, with the right marked as a func_detail.

Pretty much every brush that doesn’t make up the backbone of the world should be marked as a func_detail. Different visleaves should only reflect different areas, like different rooms or floors.

The map in the cover image, ttt_PigIsland_nightswim, takes less time to compile on high-quality settings than my first and smaller map, ttt_ManHouse, does on extra-low. That’s because I didn’t know how visleaves worked when I made it.

Fun fact: I can’t even compile ManHouse, GroverHaus or OldChurch on anything but FastVis because the visleaves are so screwed up.

General optimization reference

Lighting

HDR

I’ve never compiled a map with HDR, but I recommend against using it. It’s very easy to misconfigure, which results in eye-watering bloom in areas where it shouldn’t be.

image

ttt_ApeHouse

Constructing Lights

If there’s a chance players will be looking at the bulb head-on, I add an env_sprite with the default sprite. Just make sure you set the render mode to “World Space Glow.”

image

A typical stack for a ceiling light: the light model, a sprite inside of it (since it will show outside the model) and the actual light a distance away. I could have moved it further away because the patch of ceiling right around it is very bright.

image

Other Tips

  • Never use a pure white light unless you’re making a hospital or something.
  • Read Valve’s lighting psychology post.
  • Named sprites always start invisible, unless you check the “Start On” flag.
  • Named lights will generate versions of baked lighting for if they’re on or off. Hammer assumes they’re referenced in the IO system, will be switched on and off at runtime, and generates all variants.
  • If you have multiple differently named lights hitting the same surface, your lightmap sizes and compile times will grow at O(nn) from calculating all permutations. Be very careful.

Sound

ambient_generic is what every game sound uses, and it’s busted. Some sounds, despite having “loop” at the end of their name, do not loop. In ttt_PigIsland, waterlap_loop has to be manually repeated every 14 seconds with a logic_timer. More info in the docs, as always.

Advanced Modeling

or, how I learned to stop worrying and love the carve tool

Everyone always says don’t use Carve, it’s bad. But they never say why. It’s because if you carve something other than an axis-aligned box, it does terrible things to the geometry, messing up visleaves and potentially misaligning vertices. But it can be very useful.

img

Say I want to make a pipe through this wall, and I want it to be hollow so people can walk through it, like in ttt_PigIsland.

image

The naive approach: stick the pipe through the wall and hit Carve.

image

Looks fine, until we look at what it’s done to that wall.

image

bad

If we want that wall to split visleaves, we’re out of luck. Recall how objects cut space around them. We can make it a func_detail, but there’s a better way.

image

  1. Carve a square into the wall the size of the cylinder
  2. Carve that with the cylinder
  3. Mark the Bad Square as func_detail

image

Much better. The cut geometry is isolated and you can move around the rest of the level as you wish.