Advanced Terrain Creation
Mmm, landscape :3 Terrain is one of the more challenging things in GoldSrc mapping. There are many ways to make terrain, and not just with terrain generators, but by hand. It sounds complicated, but making terrain by hand is actually kind of easy if you know how to do it. I won't show how to use a terrain generator, since they probably don't need a guide how simple they are.
Combining certain methods, you can get a landscape such as this:
ts_untergrund In this tutorial I will show certain methods and how to combine them.
Triangular Prisms
Let's start with a method which is fairly easy to understand.
It's similar to Source's displacements.
Triangular prisms (a.k.a. wedges) are a popular way of adding terrain into your map. A triangular prism is basically a 3D shape which, when looked from above, looks like a triangle.
Let's see how to create terrain with triangular prisms:
1. Create a brush like this:
2. Cut it diagonally:
3. Disable the Texture Lock:
This is important for texturing. If you don't turn it off, the textures will 'stick' to the brushes and the terrain will have seams everywhere.
4. Texture the top faces:
5. Make copies of the 2 brushes, forming a grid:
This is why I told you to disable the texture lock, otherwise it would look like this:
6. Manipulate the vertexes in the top view: (with the Vertex Manipulation tool, of course)
Now you can select the middle vertices and in the front or side view, you can pull them down. You can either nudge them with the arrow keys, or click and drag them.
Sometimes, you'll end up with this:
The triangle seems to be too "thin". Usually, you can retriangulate the part by either deleting the few brushes and aligning them, or you can rotate them by 90° and align the vertices:
What's after 6th step has two variations:
Variant 17. Now let's do the walls.
Repeat the same process, and make it like this:
8. Raise the vertexes upwards:
Variant 27. Create a wall and cut it like this:
8. Copy it and align it to the floor:
9. Copy it vertically:
10. Do the same for the other side:
11. Give it a shape:
This was done by selecting a line of vertices in the front view, and then I pushed them away from the centre.
12. Simply apply the textures, and give the shape some more variation:
When some faces are stretched like this:
Open the Texture Application tool, select the faces, and tick
World:
If some faces don't align properly like here:
Then pick one face that aligned correctly:
Press
Shift+F6:
And left-click the other faces which should've
obeyed, so you can force their orientation:
Sometimes, setting it to
World won't work, so you'll have to set the "parent" face to
Face.
Final step:
Press
Alt+P.
This will usually happen to some faces that are invisible in-game.
It's usually caused by vertex manipulation, and sometimes improper usage of the texturing tool.
Here's a quick explanation of it.
The white frames represent the projection planes, and the arrows represent the normals. This is perfectly fine. If the face is parallel to the projection plane, it's not stretched.
In this scenario, we rotate the projection plane by 90° and thus it becomes perpendicular to the face. Actually, the projection was copied from the top face. This causes infinite stretching and a "Bad surface extents" error when compiling, as well as the "Texture axis perpendicular to face" error in the map editor.
You should not make the cliffs too detailed, otherwise you'll hit the clipnode limit pretty quickly (32 767). There are 3 clipnodes generated per face, so be careful.
Alternatively, you can use the -nohull2 parameter in CSG, so you'll end up saving a third of your clipnodes.
Basically, hull2 is for big monsters. Counter-Strike 1.6 doesn't have any monsters except the hostages.
This method can have a few tricks. If you've followed Variant 2 of this method, then you can do this:
You can essentially use your triangular prisms for not just the wall, but also the floor which is on that wall.
With some smoothing, triangular prism terrain like this is surely a delight.
Tetrahedra
While this method is very messy for the 2D views, it's really useful in a lot of situations.
Let's see how to create tetrahedrons and how to make something with them.
1. Create a cube and cut it diagonally:
2. Pull these 3 vertices up:
3. Apply a texture, disable
texture locking, and clone the tetrahedron pair:
You'll mostly use the 3 top vertices. Those vertices will define that visible, textured face you see in-game.
But there's a 4th one. (highlighted in red)
Consider it as a "root" vertice. If the root vertice is sticking out like this:
... then it's concave. It's simply inside-out. So you should always look out for this.
Now, when do we sometimes use tetrahedra instead of prisms?
With tetrahedra, it's impossible to get the "face not planar" error.
A tetrahedron is made of triangles, while a triangular prism is made out of two triangles, and three squares.
Those squares' planes get bent if you're not careful:
You could triangulate it via Ctrl+F, but it could lead to problems later on since it's not easily reversible.
4. Clone it into walls and the ceiling:
5. Shape it like a cave with the VM tool:
6. Copy the segments and twist it a bit more:
As you can see, there are 512 brushes.
In theory, that should be 1536 clipnodes (1024 with -nohull2). This is why you have to be careful with such terrain.
And another reason is VIS. It can take VIS a LONG time to process a map of this complexity.
We could've used regular, old wedges for this part, but it wouldn't be ideal for the following part.
7. Copy the whole part and rotate it 90°:
8. Copy a few segments and align the vertices in the top view:
These vertices are now aligned on the XY plane, but now we need to align them vertically as well.
Now you can polish the brushwork a little bit, and texture it.
Cave entrance/exit (combining tetrahedra and triangular prisms)
In this example, we'll use a cliff made out of triangular prisms, and a cave made out of tetrahedra.
1. Start off by preparing the cliff and cave mesh
(note: never do it this detailed, it's just for the sake of this example)
One end is on the bottom, and the other end is on the top.
2. Go to one of the ends, hide everything except this:
3. "Open" the wall with the VM tool (without deleting any brushes)
That step is usually done by selecting one half of the brushes (e.g. left half) and dragging the vertices, effectively un-welding them.
Since the cave mesh end is about 256 units away from the wall, we should copy it a couple of times otherwise there would be stretching.
4. Copy the cave segments close to the wall
To quickly connect the two segments, mirror this one horizontally.
5. In the Vertex Manipulation tool, connect the vertices of the cave to the wall.
For J.A.C.K. users: Select the vertices in the 3D view, and nudge them in the 2D views. If the 2D views are too messy, you can use the blue camera in the 2D views to help you. Wherever the 3D camera is at, it will show up in the 2D views. Just navigate to the point where you want to move your vertices and you'll see where to move the verts in the 2D view.
For VHE users: on my end, it will always select just one vertice unless you enable auto-select IIRC, therefore I suggest you to drag a selection box in the Top view and then drag the vertices around. Sledge selects 'bundled' vertices just fine like J.A.C.K.
.
6. Repeat the same for the other end
However, it doesn't look too great.
In this case, delete these brushes:
Connect these:
Add some brushes to cover it up (and texture it):
I told you not to do it this detailed because of a good reason:
(0fps FTW)It's a mess of wpolys. And VIS would take a lot of time if they were all world brushes.
However, if you really want to, or have to use a lot of triangles, here's a tip: scale all the textures to larger values like 4 or 8, and use a detail texture and downscale it. That way you'll prevent a part of BSP subdivision, although lightmaps will be more low-res (texture scale affects lightmap scales on faces).
The cave, on the other hand, was subdivided nicely:
Combining tetrahedra with triangular prisms was used in ts_untergrund to make a hole going through a cliff.
Toward Gearbox-style terrain
Quads 4 life!
Creating cliffs with a relatively small number of brushes
You start with a "base".
After that, add a few big cubes and start cutting them:
Sledge has a really useful feature in its Clipping Tool. Its clipping plane can be defined by 3 points, not just 2.
Click the edges and connect each edge:
Basically, once you select two edges, press
Ctrl+F.
If you return to the Select mode and the lines get removed, check this:
And repeat it for all of the brushes except the left-most and right-most ones:
Now, this is a more complex part:
Connect the edges like this:
And then merge these two:
With this one:
Do the same for the other end.
And then select the edge vertices:
And move them:
Lastly, make sure to do some minor corrections and then press
Ctrl+Alt+T if needed (if you end up with the "face not planar" error). If you aren't using J.A.C.K., you can always select the brush with that non-planar face, and use
Ctrl+F to cut the face into 2 triangles, thus making it planar.
And then, we have the texturing part. All of the faces should have a common projection plane, so you can either turn on "World" alignment, or use the "Apply (all + copy axes)" mode.
After that, you can keep adding more geometry this way:
The end result will look something like this:
However, there's a problem:
If you would leave these to be world brushes, the compiled map would be messy. It's sort of messy as it is, but that's one of the compromises with GoldSRC terrian.
This is why you should convert these brushes to
func_detail.
Don't forget to cover them with CLIP brushes, of course. We'd rather not want too many clipnodes or funky geometry that can make other players get stuck.
You will, of course, encounter errors while trying to do this:
The brush looks completely fine, but it's really not fine.
Let's take a closer look:
This is where we need to retriangulate our brush. It's fairly simple and it's done in the VM tool.
Make these lines:
And then merge two vertices to make the brush look like this:
After that, you have to pull the middle vertice:
If you scroll up, you would remember that the diagonal line was going from the bottom left to the top right corner.
So, we only need to make it the opposite.
Pull the middle vertice to the bottom-right corner:
If you get the "Point off the face plane" error, I suggest you to move some vertices.
In the end, you'll save many brushes:
56 brushes (not counting the 2 clip brushes)
Imagine how many brushes it would take if you did that with tetrahedrons only.
Tetrahedrons surely give you lots of freedom when you're working on the shape, but that produces a lot of brushes.
This might be the least messiest method for the 2D views. So far, we've mainly used the Clipping tool and the Vertex Manipulation tool for the brushwork. Now let's limit ourselves to not using the VM tool at all.
Firstly, let's disable the texture lock.
Now, create a cuboid like this:
Clone it above:
Click the cuboid multiple times in the 2D view until the skewing mode shows up:
And skew it a little bit. Repeat the two steps until you get to a certain height or a shape.
Now group this entire segment, and clone it sideways.
Select one segment and skew it in a different 2D view.
Lastly, you can skew it again in the Top view.
You can easily make ground this way too.
Just don't overdetail it.
This takes a lot to compile and it wouldn't make much of a difference compared to something more low-poly.
Effectively the same thing can always be achieved with less.
Gearbox-style
When first playing through Opposing Force, the terrain just amazed me. If you're looking for the terrain style that looks so late 90's, look no further. But beware, funky geometry awaits after you compile it.
One approach to this style of terrain is via layers.
First layer.
Second layer.
Third layer.
Fourth layer.
Fifth layer. (optional, also it doesn't have to be in this very order)
Let's do this on another example.
1. Place down the floor brushes
Let's give them a twist. You can either skew them with the Select tool or the Vertex Manipulation tool.
2. Start adding the wall segments.
If you simply started adding walls and skewing them, you'd get this:
It looks boring...
Start off by placing this block.
Cut it and turn it into this.
This is where the magic happens.
After this point, a lot of people could do something wrongly in the VM tool and get a "Face not planar" error.
However, a way to prevent it is to prepare the brush for further operations.
Since these two are relatively simple, only 2 edges needed to be moved.
Now, select the following vertices and move them up:
After that, select the bottom vertices and move them sideways:
We can go one step further and move the vertices in the middle.
We're not finished with this wall segment yet, as it has to be complete.
You can clone one brush and keep skewing it downwards and inwards.
In the end, you'll get a rock like this:
You may cut the rock to later merge it into one brush. (I'd rather not do that, though)
At this point, you might become worried about the off-grid vertices. It won't be too much of a problem. In the final phase we'll convert a lot of things into func_detail and cover what's needed in CLIP brushes.
For now, let's save this rock for later. It's part of the 5th layer.
Let's focus on the 1st layer.
Remember. Always prepare the brushes:
(top view - this is to preserve facial planarity)
That's better. We'll start by lowering these vertices:
And then we can move the vertices to form this:
For some variety, we can nudge some segments closer to the road.
Additionally, raise some segments:
First you do a smooth curve, then the 'pinches'.
You've probably noticed by now that the front view is never really used due to the mess. I've done all my vertex manipulations in the top and side view. That's at least in this situation. Sometimes you won't use the top view, sometimes you won't use the side view.
We'll repeat the same for the other side.
In case you get a hole like this:
Extend the ground to close it, or move the cliff.
I'm extending all the segments in order to preserve the planarity, because the ground will be slanted.
Now we'll make a rock.
3. Create a block, and rotate it:
And just cut it up:
After some more adjustments, we get the final result.
4. Optimise.
Back in the day, if you had terrain like that, you would've had to go through very long compile times. Maps compiled for hours and some took days. Even if you've got a decent PC with a fast CPU, it doesn't mean you shouldn't bother optimising the map. Remember, a lot of people still use (old) laptops and old desktop PCs. I've got a relatively decent PC, but before that one, I had a 2007 Fujitsu laptop.
So, let's begin.
Since I've raised my ground in a specific way:
I can do the following:
Hide everything but the road.
Copy the road on both sides and apply the NULL texture.
And align it to the cliffs while they're unhidden. You can hide them again and place sky brushes.
Time for
func_detail.
The ground -> detail level 1
The cliffs -> detail level 2
The rocks -> detail level 3
If you're familiar with BSP face clipping, this means that you can control it even further. If not, well, I'll explain.
Level 1 can clip level 2 and 3, while level 2 can't clip level 1, but can clip 3. Level 3 can't clip level 1 and 2, but gets clipped by them.
If you look closely, the parts where the rock touches the cliff are cut. This is because I've set all the func_details to the same detail level (1).
If we follow the image I posted above, however:
You can see that we managed to save some wpoly as the rock doesn't cut the cliff, and the cliff doesn't cut the ground.
Additionally, to save on clipnodes, you can turn the rocks into passable func_details and add some CLIP brushes.
Good half-morning. :v
There's one thing to keep in mind, though. You can't always use func_detail for all things. It will lead to huge areas being rendered at once and that means lag. It does sound hard to believe for GoldSrc, but even with a GTX 1080 Ti, the game can drop from 400fps to 40fps if certain things are going on.
So you'll sometimes have to make a compromise.
Also, if you func_detail too much terrain, it will lead to a bigger clipnode count. So be careful. Clipnodes are one of the biggest threats to terrain in GoldSrc.
You might hit the clipnode limit pretty quickly (32 767). There are 3 clipnodes generated per face (one for each hull except hull0, the visual hull), so be careful.
Alternatively, you can use the -nohull2 parameter in CSG, so you'll end up saving a third of your clipnodes.
Basically, hull2 is for big monsters. Counter-Strike 1.6 doesn't have any monsters except the hostages, so compiling with -nohull2 shouldn't cause any issues. Hull1 and hull3 are for standing and crouching players respectively.
Tips & Tricks
Look at the marked brushes. There's something bad.
This one ruins the terrain because there's a noticeable line on it.
To fix this, mirror it horizontally in the Top view:
And align the vertices:
This improves the flow of the terrain by a bit. It looks smoother this way and it looks more natural.
It's a good idea to group the segments because it becomes easier to work with.
When you want to select more specific parts, just turn on Ignore Grouping and turn it off when you're done.
This is a blocky corner.
We need smooth ones. Select these:
Shape them into this:
If you smooth every corner, you can have really nice results.
Let's see how I actually did the smoothing.
We'll perform this on a low-poly mesh.
Grab the corner vertices in the Top view and pull them:
If you come across this kind of segment:
Rotate it by 90°. In J.A.C.K. you can press Ctrl+R to rotate it 90°.
We've finished one part of the smoothing:
Now, make the grid smaller by one step, and start smoothing it even more:
Now, we grab either the ceiling or the floor. Let's start with the ceiling:
And pull!
Do the same with the other edges.
After this, you can either do the same thing with the floor.
If you want to save time, you can just copy the finished half.
And then mirror it:
Then spend some time fine-tuning the mesh:
It doesn't always have to be terrain, though.
Take the bottom half:
And then wrap another segment around it:
And then make a heart shape out of it:
You can decorate your indoors this way. It would surely make a nice addition.
You don't necessarily need to make a heart shape. You could also shape it like a lake:
Or maybe a ball. Anything is possible.
The lake up there doesn't look too natural, so I decided to give it a blend texture.
I basically went up and took 3 screenshots of it.
One with the gravel texture, one with the mud texture, and the last one which is covered in water, so I know how to blend the first two.
This is starting to look more like Source.
However, be careful with 512x512 blend textures, as you can easily make a huge WAD file, and produce more wpolys (assuming you downscaled the texture). Another limit to take into account is AllocBlock.
Another method would be making 4 textures, 512x512 each. However, that would require a strict grid of triangular prisms, which you can only raise up and down. (actually, not entirely true)
Here are the source BMPs.
In a map, it would look like this:
The 'strict grid' I was talking about actually doesn't have to be completely followed.
Moving vertices in the top view here will cause seams:
However, since J.A.C.K. has a UV lock (sometimes doesn't work as intended), this problem can be partially avoided, if we move the vertices in a single direction.
As mentioned, sometimes it does not work as intended, so I suggest you to avoid using this.
If you have faces that share the same texture, and share the same angle, chances are that CSG is going to merge them, like it did in this example. So, you don't have to worry too much if you've got a lot of faces like those in the editor.
On the other hand, BSP cuts some of those faces. CSG merges, BSP cuts.
Either way, out of the potential 128 wpoly or more, only about 97 faces got compiled in my case.
If you wish to use a texture with dimensions like 1024x256, 2048x128 etc., be warned:
In OpenGL, power-of-two textures will be rendered properly, but NPOT textures won't. Instead, they will be rescaled: 1024x256 to 256x256, 2048x128 to 128x128, which will make them look horribly stretched horizontally. So yeah, 96x96 will be 64x64, 48x48 will be 32x32 etc. In Software mode they are rendered exactly as they are.
In most situations, you will want a constant terrain density in your map.
What does this mean, however?
With the first method, triangular prisms, when you're making that first brush, you have to define what dimensions you want to use.
Basically, I made a 64x64x16 block, and cut it into two wedges. These first two dimensions are what matter. If it's 64x64, it means there will be a relatively high terrain density. If you're going for a very open area, you'll want something bigger (less dense) like 128x128, 256x256 or even 512x512 if it's far away.
But nothing prevents you from using a dynamic density. ts_untergrund is the prime example of that. Some parts of the terrain consist of 128x128 pieces, some are 320x224, and a lot of the parts are off the 'strict grid'. This basically means that you can have detailed terrain that's in the nearby playable area, and low-poly terrain in the far away area, which is sometimes good.
Here we have a nice little cliff:
From experience, we know that we will get messy cuts with terrain like this.
We can actually 'tell' the compiler how exactly it should cut that geometry. We do that by using the SOLIDHINT tool texture.
So, after we replace the backfaces with SOLIDHINT (typically textured with NULL or BEVEL), we're gonna get this:
In this scenario, it decreased the wpolys by roughly 40%. Your mileage may vary, but it'll certainly be significant.
In the end
I hope this helped you out at least a bit on terrain in GoldSrc.
It's one of those things that I was fascinated with, when I started mapping.
You could expect me to write a part 2 of this tutorial one day. The first part already took long enough and it's long enough by itself. The next part will focus on certain situations and some extra things I haven't mentioned in this tutorial.
Just remember, watch your r_speeds and keep your compile times reasonable. You can always make it look better with less.
You can find source files (JMF & WAD)
here.
Happy mapping!
Happy mapping on GoldSrc.