|
This tutorial will teach you how to improve
the performance of your map by placing effective portals and
anti-portals.
This
tutorial assumes that you understand the basics of UnrealED
and know how to manipulate brushes, build map geometry,
generate terrain, and load custom maps into Raven Shield. If
this is not the case, I recommend you start with my first
tutorial, Building
Your First Raven Shield Map, and work through most of my
other tutorials before coming back to this one.
Zones
The most
important step in optimizing the performance of your map is to
divide it into multiple zones. This frees the engine from
having to render all geometry at all times, and enables it to
focus on just the areas that the player is viewing at the
time. To be a distinct zone, a room or area must contain a
single ZoneInfo actor, and it must be sealed off
completely--with a combination of geometry brushes and zone
portal sheets—from the rest of the map.
Let’s walk
through a simple example. Pick any texture and carve out two
unconnected rooms of any size, with around 64 units of space
between them. Rebuild the map. Select the 3d perspective view
and switch to “Zone/Portal” view ([Alt+2]). Notice that each
room displays as a different color, indicating that there are
two distinct zones. Now carve out a simple hallway between the
two rooms. Open the Actor Classes browser, expand “Info” and
select “ZoneInfo”. Right click and place a ZoneInfo in the
center of each room. Rebuild the map. Notice that—uh oh—both
rooms are the same color now. Even though we have placed two
ZoneInfos, the rooms are no longer sealed off from each other.
We need to add a zone portal to seal the connecting passage.
Switch to “Texture” view ([Alt+6]) and make sure you
have “Realtime Preview” turned off in the 3d viewport or you
won’t be able to see the portal sheet that we place. (Press
[P] or click the Joystick icon to toggle “Realtime Preview” on
and off.) Right click the “Sheet” primitive button (below
Linear Staircase on the left toolbar). Select “AX_YAxis” and
build a sheet to the same height and width as your hallway.
Position the sheet as if it were a door, so that it perfectly
seals the middle of the hallway (you may need to rotate the
brush). Open the texture browser and open the “R6_Common.utx”
package. Select the “Portal” texture. (this is not important
to the functioning of the zone portal, but will clearly
identify it in the editor). Click the “Add Special Brush”
button (below Intersect on the left toolbar). Select “Zone
Portal” from the dropdown list. Select the “Two Sided”
checkbox and click the “OK” button. Click the “Close” button.
Now switch back to “Zone/Portal” view and rebuild the map
again. If you placed the portal sheet properly each room will
display as a different color again. If both rooms are still
the same color, check the size and positioning of the sheet to
make sure there aren’t “leaks” on any side; the passageway
must be completely sealed.
Now when the player is
looking from one room into the next, the engine will render
both rooms. However, when the player is looking in the other
direction, the 2nd room won’t render at all. If you place your
zones intelligently, the engine will never need to render more
than a few zones at the same time, and will result in better
performance on your map. The most common placement of zone
portals will be in doorways and window frames since these are
the most common openings into an otherwise sealed room. Note
that dividing your map into zones offers a few benefits in
addition to performance: you can assign different ambient
sounds, EAX effects, weather effects, and ambient light levels
to each zone. (I’ll cover each of these in future tutorials.)
Anti-portals
In the case of large rooms
and outdoor areas, it doesn’t make sense to try to break the
area into multiple zones. In these situations you should
attempt to place some large physical objects (hills, huge
rocks, stage curtains, etc.) to cut down the line-of-sight
distance, and then place anti-portals inside these objects.
Let’s walk through an example. Start a new map,
subtract a large area (at least 4096x4096), and build
mostly-flat terrain with two sizable hills, each near an
opposite corner of the map. Leave some room to hide in the
corner behind each hill. (If you’ve never worked with terrain
before, this is no small task. You’ll want to read my Terrain
Tutorial and come back to this part at a later date.)
Scatter a few static meshes around the middle of the map
(above the terrain of course). Place few BSP cubes and spheres
as well. Place the necessary insertion zone, lighting, and
path node actors; then rebuild and save the map.
Load
the map in-game from the Custom Missions menu. Press [~] to
open the console. Type “ghost” and press [Enter]. Type “rmode
1” and press [Enter]. Press [~] to close the console. Now, fly
around the map a bit in wireframe view. Note that even when
you are completely behind one of the hills, you can still see
the wireframe models of the entire map, indicating that all of
the objects are being rendered at all times. Let’s go back to
the editor and try to change that.
There are two types of
anti-portals you can use. The editor is a bit inconsistent
with the naming, but I’ll refer to them as anti-portal brushes
and anti-portal volumes. There isn’t a whole lot of difference
between them, and I tend to prefer using anti-portal volumes.
I’ll show you how to place both types.
First, we’ll
place an anti-portal brush inside the first hill. Make sure
you have “Realtime Preview” turned off and “Show Volumes”
turned on in each viewport, or you won’t be able to see the
anti-portals that we place. (Press [P] and [O] to toggle these
on and off.) Select the cube primitive and size and position
your red builder brush so that it ‘fills’ the hill as well as
possible without any corners sticking up out of the terrain.
The best way to check for proper positioning, is to show
terrain (Press [T]) in 2d viewports. If we wanted to, we could
break out the 2d editor and brush clipping tools and try to
sculpt the brush to resemble the shape of the terrain hill,
but it’s really not worth the effort. (Plus, it could cause
major problems if it resulted in an anti-portal with any
concave surfaces). A cube primitive will work fine, just keep
it thin so that it can sit pretty high under the terrain
without sticking out the sides.
Open the texture
browser, open the “R6_Common.utx” package, and select the “AP”
texture (the texture is not important in any way to the
functioning of the anti-portal, but it will help differentiate
the anti-portal brush from other brushes on the map). Click
the “Add Special Brush” button on the left toolbar. Choose
“Anti-Portal” from the dropdown list, and click the “OK”
button. Click the “Close” button and move the builder brush
out of the way. At this point, with the camera positioned
above the terrain in the 3d view, you should not be able to
see any part of the purple ‘Anti Portal’ texture sticking out
of the terrain. If you do see any corners sticking out, you
should reposition the anti-portal brush to bury it completely.
Do not, however, resize the anti-portal or it will no longer
function correctly.
Note that you can also use a
sheet for anti-portal brushes. This can be useful for
situations where you want to occlude the individual sides of a
building. You would place the anti-portal brush the same way
we did above, just starting with a sheet rather than a cube
primitive (and when using a sheet, I recommend creating the
special brush as “two-sided”).
Now, let’s place an
anti-portal volume inside the second hill. Move the red
builder brush to the other side of the map and size and
position it so that it ‘fills’ the second hill as well as
possible. We don’t need to bother with a texture this time,
since volumes don’t have any surfaces. Once the builder brush
is positioned, click the “Add Antiportal” button on the left
toolbar. (In case you’re curious, the “Add Antiportal” option
in the “Brush” menu does the exact same thing. And once the
anti-portal volume is created, the editor actually refers to
it as an ‘AntiPortalActor’. Try not to get confused by the
inconsistent terms. It really is a volume, I swear.)
Move the builder brush out of the way and make sure no
corners of the volume are sticking out of the terrain. If you
accidentally leave part of an anti-portal outside of an
object, it could cause objects to disappear from view even
when a player is looking right at them. Worse still, if you
ever allow a player to walk into your anti-portal, they will
see a hall-of-mirrors effect.
Now that our
anti-portals are in place, rebuild and save the map. Load the
map in-game and enter ghost and wireframe mode, just as we did
earlier. Fly around the map, staying mostly low to the ground,
and positioning yourself at different angles behind each hill.
Make sure that you keep yourself inside the subtracted area
and outside of the terrain, or you’ll get a false impression
of how the anti-portals are functioning.
Notice now, that objects and
terrain disappear when hidden behind either of the
anti-portals. As you move around the edge of the anti-portals,
you may notice that different types of actors are occluded
(hidden) a bit differently. BSP geometry is occluded one BSP
node at a time, terrain is occluded in 16x16 blocks, and a
static mesh is only occluded if every polygon on that mesh is
behind the anti-portal. With just one anti-portal in each
hill, you’ll find that there are a lot of angles where no
occlusion occurs. You could improve this by adding additional
connected anti-portals sitting at different angles, all placed
under your hill or mountain range. However, use your
anti-portals intelligently and sparingly. If you place too
many, the engine will have to work so hard to calculate the
occlusions, that it will negate the performance benefit of
having the areas occluded at all.
The methods for
placing an anti-portal inside a static mesh are exactly the
same as those we used for the terrain hills. If the object
blocking the player’s vision is a BSP brush, the method is
almost the same, however in that situation the anti-portal
should not be placed completely ‘inside’ the BSP brush, it
should be roughly the same size. It is essential that the
anti-portal touches the subtracted area outside the brush, or
it will not function properly. (This isn’t an issue with
terrain or static meshes, since even when you are under
terrain or inside a static mesh, you are technically in
subtracted space).
Conclusion
The
‘rmode 1’ wireframe view works great for testing zones as well
as anti-portals. Always run through your entire map in this
mode and make sure objects are not being rendered when they
should be occluded. Note that objects in adjacent zones will
be rendered as long as the player can see through a window or
doorway into any part of that zone. Note also that an
anti-portal will only hide objects in the same zone, so if you
place an anti-portal/dividing wall, then a crate, then a
window/zone portal, then a bookcase--all in a single line of
sight--the anti-portal will hide the crate but not the
bookcase in the next zone. We used ghost mode in this tutorial
so that you could get a feel for exactly how anti-portal
occlusion works. However, when testing portals and
anti-portals in your own maps, it’s probably better to stay
out of ghost mode so you see the exact same angles that the
player will see.
Important note: It is possible to switch the 3d
viewport to wireframe mode right in the editor. Other
tutorials indicate that if you turn on “Realtime Preview” and
“Show Volumes”, you can test if your anti-portals are working
right from the editor. This worked occasionally for me, but it
appears to be very inconsistent. I spent a lot of wasted time
trying to figure out why my anti-portals weren’t occluding
properly, when in fact they were working fine in-game. So, I
recommend that you always test your zones and anti-portals
in-game, using the “rmode 1” view as described above.
I hope you found this tutorial helpful. If there's
anything I've gotten wrong, please let me know and I'll
correct the information. Email me if you have any questions or
mapping issues you'd like to discuss. -Beckett
|