[Tutorial] Optimisation - Stairs

NoodleCollie

Stoat fiend
aa
Jul 30, 2009
383
335
After recently delving into Valve's mapping world in order to make a L4D campaign out of Half-Life: 2, I've gained some valuable experience. What better time then, I thought, than to write some of the optimisation tutorials I've been thinking about? Some of this is what I've picked up from Valve's maps; some, including this tutorial, are what I've come up with myself. I hope they come in useful. :)

Stairs
When making your arbitrary bits-and-pieces for a map, your goal should always be to make the best structure you can while creating the least polys (triangles) you can for the engine to have to render. Before I go any further, I want to make a point which should NEVER be disobeyed, regarding the tools/nodraw texture: whenever you make a new brush, ALWAYS create it with the nodraw texture and then texture the faces you're able to see. This minimises the faces the engine will have to draw, since the ones you'll never see in-game aren't even compiled into the map.

That aside, we move on to stairs. They can be pesky little things if you don't get them right, and in my experience this is the best way I've found to do it.

Enclosed Stairs
These types of stairs are ones that reach completely from one wall of a corridor to the other. You cannot see the sides of them or go underneath them, so the number of faces drawn should be minimal.

First, choose your size of step. My recommended size is either 8 units high, 12 units deep (the general standard) or 8 units high, 16 deep (which I'm inadvertently used to), and wide enough to go the width of your hallway. Create one step in nodraw, place it at the top of your staircase and then shift-clone it in a stair-like fashion until you reach the floor. Note that you can texture the step before you clone it, but make sure not to have Texture Lock enabled (unless you're using a specially aligned step texture) otherwise your stairs' textures will look strangely identical from in-front, which can ruin the realism a tiny bit. :)

stairs01.png


To quicken compile times, we want to get the simplest brush structure possible. A rectangle shape must be split into two triangles, whereas a triangle shape is obviously only one, so select all your steps and cut them at once to leave them just as triangular prisms. This isn't so important for enclosed stairs but is more important for others, as you'll soon see.

stairs02.png


Now, tie all your stairs to a func_detail with Ctrl-T. Stairs make masochistical visleaf cuts unless they're func_detail, so don't forget this step.

stairs03.png


You may also notice that there's a lot of empty space underneath the stairs. This won't matter as, since the stairs meet each other's edges, the player won't be able to see underneath. Do not fill the space with a brush, even a func_detail one, as it's completely unnecessary. Remember the Tesco motto: “Every little helps”. :)

Finally, the clip. Ever tried to jump on stairs? Isn't it annoying when you ricochet off them at an angle? Creating a clip brush like so solves this problem while also allowing Engineers to build properly on the stairs. If you have large, tall stairs and want Engies to be able to build on each individual step, make the clip brush a player clip and it won't affect the buildables. Also, don't func_detail the clip as it prevents it from being put into the correct visgroup and clips don't cut visleaves anyway.

stairs04.png


Textured, things should look like this:

stairs05.png


Open Stairs
Open stairs are still very simple and are where the stairs don't take up the entire width of a room but cannot be crawled under. They look like this:

stairs06.png


Firstly, make the basic slope your stairs will be on. Once again, I'd recommend a 2:3 or 1:2 (rise:run) ratio.

stairs07.png


Now, make your top step and cut the oblong into a triangular prism. This will reduce the amount of triangles the engine will have to draw for the end product, as shown below:

stairs08.png


This is the main thing people get wrong with stairs: while the right may seem the simplest way to make them, it's by far more taxing on the game engine than the left.

Now, texture the stairs. You shouldn't end up texturing the base slope's face as it's covered by the rest of the stairs and so is unseen.

stairs09.png


Finally, func_detail and add the clip:

stairs10.png


If you want, you can add a bit of detail. Firstly, select the entire stairs and press "Apply Current Texture" with nodraw as the texture to get rid of all the previous textures. We will re-texture the stairs at the end.

Now, shrink the width of the stairs by one unit either side and create another ramp that runs along the full slope of the stairs, like so:

stairs11.png


stairs12.png


Split the ramp and shrink both new ones to become one unit wide. Then, sit them on either side of your stairs.

stairs13.png


Delete the triangular ramp underneath, since it can no longer be seen and so is not needed.

stairs14.png


Finally, re-texture, func_detail and clip.

Framework stairs
These are stairs that can be crawled under, like so.

stairs15.png


There are two main types, either with or without gaps.

Without Gaps
Follow the Open Stairs method so that you have a base ramp with stairs on top, then delete the base ramp to leave the stairs. If you left them like this, imagine how many unnecessary polys you'd get on the underside:

stairs16.png


To combat this, and make the stairs look generally nicer, create a nice brush that follows the slope of the underside of the stairs, like so:

stairs17.png


Now, we have two polys underneath with our one rectangular face, instead of loads with our many stairs.

Shrink the stairs by a unit each side, then add the detail like in the Open Stairs method:

stairs18.png


Finally, texture, func_detail and clip.

stairs19.png


With Gaps
Stairs with gaps in-between require a little different setup. Firstly, create the outside guides for your stairs (which you could just clone from having done the Without Gaps method):

stairs20.png


Next, put in your stairs. For this example they're one unit high.

stairs21.png


Now, texture the rest of your stairs and func_detail them. Make the clip a player clip this time, as a normal clip may stop small objects from being able to drop through the gaps in the stairs.

With a little practice, Framework Stairs With Gaps can look pretty stylish. Check out the details on these:

stairs22.png


stairs23.png


stairs24.png


If you'd like to use any of these stairs, the VMF is here: http://www.mediafire.com/?5gwuzmltztt. Note that the frames of some stairs, like grazr said below, should be made func_lod and are not currently in the VMF. I'll reupload once I've fixed them.
 
Last edited:

grazr

Old Man Mutant Ninja Turtle
aa
Mar 4, 2008
5,441
3,814
func_lod your frame otherwise you may overload your t-junction limit if you have a lot of func_detail work that touches the edges of world geometry or other func_detail geometry.

stairs21.png


In this image for example.

func_detail steps with func_detail frame = 56 func_detail based t-junctions and 4 world geometry t-junctions.

func_detail steps with func_lod frame = 0 func_detail based t-junctions and 2 world geometry t-junctions.
 
Last edited:

NoodleCollie

Stoat fiend
aa
Jul 30, 2009
383
335
Standard ratio is actually 2:3 (8x12 units).

Ah, OK. I only came to 1:2 a long time ago because I was sticking to a grid size of 8 and found that that worked well. I'll update the post.

func_lod your frame otherwise you may overload your t-junction limit if you have a lot of func_detail work that touches the edges of world geometry or other func_detail geometry.

stairs21.png


In this image for example.

func_detail steps with func_detail frame = 56 func_detail based t-junctions and 4 world geometry t-junctions.

func_detail steps with func_lod frame = 0 func_detail based t-junctions and 2 world geometry t-junctions.

OK, I had no idea about T-junctions. I'll update that stuff when I'm back on my own computer.
 

grazr

Old Man Mutant Ninja Turtle
aa
Mar 4, 2008
5,441
3,814
T-junctions

It's something that becomes an issue in the later development of a map, regarding detail, and it's prime suspects are protruding wall trims and stair cases.

Luckily for Valve's development team most of their stuff can be converted to models and thus removes this problem altogether. But in other cases, such as badwater, which has excessive use of stairs, Dario Casali simply func_lod's the stair frame's. Quite clever really.
 

gamemaster1996

L13: Stunning Member
Sep 30, 2009
1,064
134
I dont think you HAVE to nodraw everything and then texture brushes on faces i just nodraw faces that are not needed it is alot easier.
But thanks for the info about stairs very useful.
 

NoodleCollie

Stoat fiend
aa
Jul 30, 2009
383
335
I've had this debate before. :D

I'd rather start out with nodraw and then texture/align the faces I need to than start out with a texture, align it and then go back and nodraw all the ones I can't even see. If we're looking at it from an optimisation viewpoint, you'll eliminate 99% of unneeded faces if you start out with nodraw, the only exceptions being if you clip a brush and a random texture gets applied to the new faces, or if you change/add geometry so that a face that was textured gets covered and is unseen. While flush world brush faces (faces that are pressed together) get ignored by BSP, flush func_detail ones, as far as I know, do not, and this is especially important for stairs which are both func_detail and have a lot of faces.

Sorry about that, lecture over. :D
 

Stormcaller3801

L5: Dapper Member
Jul 5, 2009
249
28
1) Wouldn't making all of the parts of the stair one func_detail reduce or eliminate the t-junction issue? I've been trying to grab logical groups and then func_detailing them all at once for this reason.

2) Nodraw vs textures: my feelings on the matter are guided by laziness. How many faces will I have to change later on for each method? The one that requires the least amount of work is the one I'll use for a given situation. Thus my water and displacements start out as nodraw brushes, whereas my open staircases and fence posts get textures.
 

NoodleCollie

Stoat fiend
aa
Jul 30, 2009
383
335
1) Wouldn't making all of the parts of the stair one func_detail reduce or eliminate the t-junction issue? I've been trying to grab logical groups and then func_detailing them all at once for this reason.

Same here, and it's how I did the staircases. I like to keep things all under one func_detail to act as a "group" if I want to clone the thing. I don't tend to use actual groups as much, since I usually tell whether or not something's tied to an entity by whether it selects other brushes when I click it.

However, I don't think making the whole thing a func_detail would work since it all seems to depend on what vertices touch what surfaces. If they're flush, they get turned into T-Juncts whatever the weather.
 

Tapp

L10: Glamorous Member
Jan 26, 2009
776
215
All func_details are un-grouped during compile. This taught me a LOT about optimising stairs, I will make a note to use your tips whenever I can.