Visportals
written by Fidcal. Visportals, Func_statics and Worldspawn Brushes added by Sotha.
What are visportals?
Visportals are a very important part of mapping. They are a kind of brush that helps separate your map into individual areas, which is important for both rendering and sound propagation.
Without visportals, the Doom engine would render the entire map even if the player can only see one small area. This would reduce performance and slow the game down.
Visportals are also very important for sound propagation. Without them, sounds can travel through brushwork and reach areas of the map that they shouldn't (see Sound Propagation at the bottom of the page).
Visportals determine how far the engine should render from the player's position. When a visportal is in the player's view, the engine tests to see if there is a second visportal viewable from the position of the first. If yes then it tests to see if a third one can be seen from the second one. If the third is not viewable from the first then the engine won't waste time rendering the map beyond it. If it is, then the engine tests for a fourth one and so on. So for example, with a long corridor with lots of 90 degree turns in it and visportals at every bend then the engine will only render the section you are in plus the next section which gradually reveals more of itself as you approach the bend. But as you get near to it and can see further down it to the next bend's visportal then it will render the next one too.
The console command r_showPortals 1 shows processed visportals as wireframe in-game for testing - even right through walls they are visible. A green wireframe is an 'open' visportal and renders everything beyond it up to the next visportal. A red wireframe is a 'closed' visportal with nothing rendered beyond it and no further visportals beyond that are even processed so are not visible at all. If a visportal does not show then it is either beyond range of processing or it is not working so check it is set up correctly.
What is rendering?
Rendering might be regarded as the calculating of surface lighting, colour, texture, etc. Not all rendered surfaces are visible in-game but still have to be calculated. Others do not need rendering at all. Processing only takes place in the current portal area, that is, up to the nearest closed visportals. Surfaces are treated as divided into triangles for rendering purposes. The r_showTris console command shows those triangles as wireframes. In the console use r_showTris N where N is...
- 0 - Off - normal gameplay with no wireframes shown.
- 1 - Shows only triangles that are visible in-game (not hidden behind other surfaces.) These visible surfaces are only part of what is rendered.
- 2 - Shows as wireframes, all triangle surfaces that would be rendered in-game. This includes those hidden behind other surfaces BUT ONLY IF they face the player, even slightly. Surfaces facing away from the player are never rendered.
- 3 - Shows as wireframes, all triangle surfaces even if not rendered.
You can see that for the purpose of testing performance use 2 above which shows all that would be rendered (whether visible to the player or not.) You can use 3 to see all triangles up to the next closed visportal but remember not all of it will be rendered so will not affect performance.
You might also use r_useScissor 0 to show geometry outside the visportal wireframe that Doom still sends to the video card but tells it not to render. r_useScissor 1 helps performance but even sending the geometry uses processor time so if you can reduce it by adjusting visportal placement so much the better.
(Remember to return to r_useScissor 1 when you are done with visportal testing.)
Here is a short video with a decent visual breakdown:
Another video:
How and where to create visportals
Visportals are just brushes with one face covered in visportal texture. That is the operative face. Only be concerned with that one surface as the rest of the brush merely carries it. So to create one you just....
- Make a thin brush like a wall. Ideally make it rectangular for best sound propagation (see Sound Propagation later.) It can extend beyond the gap so does not necessarily need to be the same shape - see Where to place your Visportal later.
- Give it textures > editor > visportal to either of the main surfaces facing towards or away from you. It does not matter which except you need to be aware which it is because the visportal will be effective at that one face. (Use Ctrl + Shift + on the face in the Dark Radiant camera view to select one face.)
Thickness
The exact thickness is not important to its effectiveness as it will only be effective from its one visportal-textured face anyway but it makes sense to keep it reasonably thin so you can see it clearly in the editor. Always think of visportals as one flat face and the rest of the brush can be ignored for functional purposes.
Where to place your Visportal
It will eventually be wedged tight like a plug into gaps, doorways, etc. between areas. The edges of the visportal-textured face of visportals should be completely sealed by or in solid worldspawn brush that has no gaps. The brush must be a child of worldspawn and not an entity. This is true even if the visportal is within a door (see next section.) For the visportal to be effective it does not matter if the rest of the visportal brush sticks out into space so long as the edges of the visportal-textured face are surrounded by worldspawn brush and/or another visportal brush (see later) In practice you will probably put most fully within a corridor or doorway, a city street (yes, the sky above is solid worldspawn brush), etc. Irregular shaped gaps must still be plugged with a rectangular visportal which should then overlap into the solid worldspawn and leave no gaps. This will also make sound propagation work correctly (see Sound Propagation later.)
Each area you thus created must be totally enclosed with worldspawn brushes with no gaps of either space else an entity. So a closed building with visportals at the doors but a tiny gap under the eaves of the roof won't work! Also avoid only blocking gaps with entities whether brushes or models. For example, a two-sided window entity that completely fills the opening will not seal the area for portalling purposes. Do not put in a visportal unless the window is either transparent or can be opened (like a door.) Instead put in a worldspawn brush with nodraw texture on it so it will not be visible or collidable just in front of the window. Or if you are using two windows back to back (say a lit one outside and an unlit one inside then a thin caulk brush between them.
Generally you will place visportals on bends in the terrain around which the player cannot see from the current viewpoint. Avoid placing visportals in a line along a corridor or street for example. Since the player can see straight down through them all then they serve no purpose as they will all be open and visportals themselves create extra triangles and complexity (see downside section below.)
With a large building surrounded by a walled open area then try visportals at each corner. If it is a very large building then also add visportals midway along each side. The player standing at one corner might be able to see up two sides, part of a far side, and even a small part of the fourth side so all sides would be rendered. By having extra visportals middway along each side then at least half of each side of the furthest corner need not be rendered (consider also preventing the player reaching such a viewpoint with an obstruction!)
Subject to the above, try to find the smallest gaps where possible to place visportals. The smaller the visportal then the smaller the view aperture and so the less chance of lining up those apertures. Remember, visportals beyond the first one do not open unless they intersect all open visportals in that line of view. Even without a door, an open doorway is a better place for a visportal than a wider corridor or room beyond. Imagine trying to get a straight pole through as many of these visportal apertures as possible; the narrower and less aligned they are then the harder to get the pole very far.
Don't get too hung up on perfect placement of every last visportal. Generally if you follow this guide and use your judgement you achieve a satisfactory game performance. Examine some large maps that you know work well to get some ideas where visportals are placed using the r_showPortals 1 command.
What if you put visportal texture on both main faces of the visportal brush? Only one will be effective. If the visportal brush juts out into space then visportal texture at that end will not work but the one at the other end will be the operative one. If you rotated the brush then it still works and uses whichever one is surrounded by solid. If both are in space it does not work at all. If both are surrounded by solid then only one works. Which one? Hard to tell. It seems to be determined by the local geometry. It is interesting to note that when you use r_showTris 3 to see what is rendered then the triangles are confined to either side of the visportal face. In other words, a long corridor wall rendered as two large triangles would now be split into four triangles. So a visportal might be considered to help with multiple lighting performance as you do not need to visually change the terrain with trim etc.
What if you put visportal texture on all the surfaces of the brush? Only one is effective (must be surrounded by solid brush.) To be certain of optimum performance use nodraw on all surfaces except the one face with visportal texture.
Multiple Joined Visportals
Because visportals are a single face, by their very nature they can only be placed on a single brush. But visportal brushes can be placed or merged together to fill more complex shaped gaps. For example, a wide rectangle might have one side clipped to slope over a roof while the rectangular part of its shape sits on top of another rectangle across the street below. But complexity affects performance so only do this if one rectangular visportal intruding into interior walls might do the same job. Remember, it does not matter if the visportal overlaps into solid so if there is an interior wall on the same plane (or indeed if the building is totally solid) then the visportal can penetrate it and still function. Do not use multiple visportals just to shape nicely around solid building trim and structure but intrude into it so long as the edge does not exit into space at any point it will be fine.
Visportals and doors
A visportal in contact with a door that has an openable property is automatically closed when the door is closed and automatically becomes conventionally operative when the door opens. By 'operative' I mean it is then like a normal visportal and will be open or closed depending on the player's view. So when you first go through a door and leave it open then its visportal will be open as you look immediately back at it. But as you then proceed further through other visportals, the door visportal will eventually close (prevent rendering through it) even if the door itself is left open.
Doors standing in front of but not within a doorway
Note that the visportal only needs to be in contact with the door to be affected by it. Normally you would place the visportal within the door but it actually only needs its visportal-textured surface to touch it. This means that if you have a door that is stood in front of an opening in a wall then you cannot put the visportal inside the door because it will not be surrounded by solid brush. But you can put a visportal just inside the opening and flush with the mouth of the opening and the door immediately in front of that and in contact with the visportal. You can test this by placing the door offset well to one side but part of it still in contact with the visportal. In game you can see the opening as the door is only partially covering it. When the door is closed the visportal closes and stops rendering through the doorway. You will see this as a black panel in the doorway. As the door opens the black panel disappears and you can see through the doorway again. You might think that from the other side the black panel would obscure the door when closed but it doesn't. With the door centred in its normal position, typically you might have an entity frame around the door. If you had a solid brush frame without gaps then the visportal could be inside the door if you wanted as it would then have solid all round its edges. In many cases of course, the door frame, whether entity or brush, would be within the solid brush doorway anyway.
Windows, Doors with windows, bars, etc.
Openable doors that let you see through them such as windows, doors with windows, barred gates, etc. should not be in contact with a visportal. When the door is closed it will automatically close any visportal whose effective surface is in touch with it. The visportal will not then permit any rendering through it and will show as a black panel in the window or between the bars of a gate. Instead, move the visportal away from the door. It will still function effectively as a normal visportal just as if the door were not there. This does not of course apply to simulated windows such as a glazed textured panel on a door texture where you cannot actually see through.
All doors and windows that do not have an openable property can have a visportal in touch with them as it will not be affected by them and it will just function as a normal visportal.
Rev. 2.00:
Starting with Rev. 2.00, you can touch a see-through door or window with a visportal, and the portal will not close when the door/window is closed, as long as you use the following spawnarg on the door/window (not the info_portalsettings entity):
- transparent "If set to 1 (0 by default), a see-through door can touch a visportal and the visportal won't close when the door is closed."
This is useful when you want the opening or closing of the door to affect the sound loss across the portal, but not affect visibility through the door/window. Imagine a closed window that muffles a sound beyond it, and as the window opens, the sound gets louder.
Visportal switches: func_portals
The preceding section Visportals and doors makes clear that doors can function like switches to enable and close visportals in contact with them. func_portals can be used to enact further control over portals. You can place a func_portal entity so that it intersects with a visportal, and then trigger the func_portal to close or open the visportal. A second control method is had by using the portal_dist and distcheck_period properties on the func_portal. They control the distance to the player and how frequently (in seconds) this distance should be checked, respectively, and make explicit triggering of the func_portal unnecessary. As with doors, even if enabled, the visportal will not be open even if it is in the player's view. Note, if you have a mover (door/window) in contact with the visportal, it will affect it as well, so typically a visportal controlled by func_portal is placed away from the mover, or use spawnarg "transparent" set to 1.
Another clever trick exists with regard to func_portals: you can also build a func_static over the visportal, and target it with the func_portal as normal. Now, in addition to opening and closing the portal, this will also toggle the drawing of the func_static. This means you could place an appropriate texture (perhaps a low resolution image of a room's interior, drawn over a window) and have it turn on or off based on the player's distance away.
One way to make this work is to create a patch, make it a func_static. Texture it, and then target the func_portal at that func_static. You must then add "hide" "1" to the func_static patch. There may be other ways to make this work, but I had a lot of trouble until I took these steps. -- Springheel
Need I design, even compromise my map to make best use of visportals?
You need to design your map from the start as a series of connected boxes (brushes) with the player's view, sound propogation, and visportals in mind. And yes, sometimes you might need to add a bend you don't want or obstruct a view in some way so you can put in another visportal if you are having or expecting slow down in a large and/or complex area. This is a matter of experience. If you have large complex areas and are experiencing frame lag but can see no obvious place to put a visportal then you might need to compromise your terrain and add some solid brush barriers to block certain views with visportals in the access round or through them.
Note that it is not essential that visportals be only at the actual joins between brushes; they still work even if they are half way down a corridor so long as they are wedged in tight without gaps. But you will mostly place them at joins.
For rendering considerations, the player's view is everything and every room and street in front of you even if there are walls, etc. in the way. Imagine what you would see with X-Ray vision. What is behind you or just out of range of the screen does not matter. But visportals restrict the view to what can be seen through the aperture of the visportal.
It is not necessary to put visportals at every tiny bend in the map; in fact that should be avoided in smaller areas because visportals themselves create extra triangles and complexity (see downside section below.) Try to keep in mind what will be rendered through the visportals and judge what would not cause frame lag slowdown if the player could actually see that view. Three or four bends without visportals in a restricted air duct is not going to cause any problem if the duct is correctly visportalled at the ends for example.
Is there a downside?
One downside to visportals is that is extra work for the mapper! Another is that they split the geometry and create extra triangles and batches. This will not normally cause a problem unless your map has a very large number of areas. The advantages in performance of using visportals far outweigh the downsides!
Sound Propagation
Correct propagation of sound (both to AI and to the player) relies on visportals.
Think of vis-portals as sealing off separate "areas" in a map. A sound that occurs inside a sealed "area" will travel in a straight line to anyone inside the same area, even through walls. If you are not in the same area, however, the sound will travel in a straight line to the first visportal between you and the sound source, then to the next one, etc, until it reaches the area you are in.
If the sound happens in an area that is not sealed, it essentially considers the whole map its "area", and will go straight to the player, through walls, floors, or other brushwork. This can result in confusion for players, as they will hear AI on the other side of a massive wall as if they were standing beside each other.
In the following examples, "P" is the player and "S" is the sound source. The Visportals are red lines. The green lines show how the sound would travel.
Without any visportals, the sound goes in a straight line to the player, even through solid walls. It will sound like the player is in the same room as the sound.
One visportal is an improvement--it will sound further away, but the sound travels straight to the visportal and then straight to the player, so it will still sound like it is coming through the wall.
Two visportals are best in this case, however. The sound will seem like it is coming from the opening to the room, which is where you would expect it to come from.
Sound going to the AI travels the shortest distance through a visportal, passing at any point on the visportal surface. Mappers should always use rectangular visportals unless you have no choice with an awkwardly shaped gap or if the gap is out of range of AI, for example along a sloping roof where AI never go. It also still assumes that when you do have four sides, they are perpendicular. If you have some non-90 degree angles between the sides, some wierdness may ensue. For example, an AI that is alerted in the dark (or facing away) by hearing a sound from the player that passes through an irregular visportal might run to the center of the visportal rather than directly to where the player made the noise. Irregular visportals large enough to make this effect noticeable are likely to be uncommon.
This will be okay for smaller irregular visportals, but the error (path difference from the minimal path) will get more noticeable the larger the visportal.
Visportals function individually even if joined together into complex shapes. So a rectangle at ground level topped by an angled visportal above it tilting out over a roof will be treated separately, not as one aperture.
The bottom line is, with any non-rectangular visportals keep the above in mind and if in doubt then consider early testing of AI's alert to player sound.
Visportals do NOT need to be closed to correctly channel sound to the player. Sometimes it is worth adding visportals even if they will not help with rendering (because they will always be open) in order to make sound travel the way it should.
To make less sound go through a visportal (through a small hole, for example): Soundprop can use info_locationSeparator or info_portalSettings to make sound incur a certain loss when going through the portal it's touching. The key/value pair is the following:
sound_loss "Soundprop: Loss in dB incurred when a sound travels through this portal. Cumulative with door loss if a door is present."
The loss must be a positive number, and negative numbers will automatically be converted to positive.
Rev 2.00:
Prior to Rev 2.00, sound_loss affected the sound propagation to AI only. Sound propagation to the player was not affected.
Starting with Rev 2.00, sound_loss is also used in determining sound volume to the player. This aligns what AI hear with what the player hears. It also allows sound coming through the door to increase as the door opens, or decrease as the door closes, making for a more realistic experience.
For details study: Sound Propagation: Part 1 and Sound Propagation: Part 2
Trouble-shooting
There are two possible problems I can think of: the visportal doesn't work at all or it works yet there is too much being rendered giving poor performance and frame lag. The latter problem is a matter of experience and experimentation. Often much ingenuity is needed to place visportals to reduce the size of areas being rendered at any one time. There is probably a different solution for every situation. Ultimately you might be forced to change the terrain to help visportalling.
If a visportal doesn't work at all (eg, does not show as either red or green while you are directly in its area and looking at it and you have r_showPortals enabled) then that means there is a "leak" in that area. It does not necessarily mean the visportal itself is the problem.
Try the following to track down the problem.
Check the visportal itself:
- Check which face of the visportal is facing which way. It sometimes happen one clones a visportal and rotates it the wrong way without realizing. So the wrong face is in the right place but the visportal face is not in contact with worldspawn.
- Make sure the visportal hasn't been assigned to an entity but is worldspawn.
- Search for gaps anywhere around the edges of the visportal face. Check for grid snapping not only of the visportal but the surrounding brushes. A tiny difference might not be visible in the Dark Radiant grid if you are not zoomed in sufficiently.
- Check all surrounding items to see if any are entities. Remember, the visportal face must only be surrounded by worldspawn brushes. It seems to be mostly OK if the visportal cuts through an entity so long as it meets worldspawn at its edges.
Check the area for internal leaks:
There is a way to test an individual area for leaks. It sounds more complicated than it is.
1. Filter off all entities. Make sure visportals are NOT filtered.
2. Select your entire visible map (which will now be only brushwork).
3. Copy and paste into a new blank map.
4. Put the player start into the area where you think you have an internal leak.
5. Take the visportals sealing that area and texture them with a solid texture.
6. Open a hole in a distant corner of the map.
7. Run dmap. If you do not get a leak, then the area with the player start is properly sealed.
8. If you do get a leak, open the pointfile in DR. Because the player entity is the only entity in the map, the red line will always start there and will show you where the gap is.
9. Go back to your original map and fix the gap. Repeat as needed.
If all else fails, try:
- Clone the visportal and drag one edge to one side, that is, reduce its size to say half.
- Select the original and drag its opposite edge the other way so you now have two visportals pressed together and which together fill the gap. Guess which side unless you suspect one side particularly (see later.)
- Change one of the visportals to any normal visible simple texture, stone, wood, whatever so that now the original gap is smaller and filled by just one smaller visportal. (with hindsight, I think this would probably work anyway and might even be better just leaving it as visportal so you can see which one works but I'll continue with what I did!)
- Check it in game.
- If it still does not work then reduce it further, perhaps by half as much again. In particular, go past edges of surrounding brushes (eg, if working downwards with two brushes on the left then maybe it's the top brush that is the problem so reduce the top of the visportal below its bottom edge.) Obviously as you reduce the visportal you increase the solid temporary brush you made equally to keep up so there is never a gap.
- If the visportal still does not work even when reduced to a slither then try the same for all four sides noting that the three sides against the slither of visportal are obviously first suspects.
- If eventually the visportal starts to work then you know the error is in the other section where you have the solid temporary brush. Use a process of elimination to track down exactly where the error is.
- You might even have to create a third temporary brush or even a fourth but you must eventually force the visportal to work even if you surround it with four new brushes! Once working, then reduce, remove, gradually until the error re-appears - that must be where the error lies. So by a process of elimination you should track down the source of the problem.
- The result might make not seem to make sense but at least if you locate the error you can try things to solve the problem. I had a visportal up to the sky and on its left against the top of a triangle of bricks on which rested a roof. The visportal seemed to be perfectly surrounded by worldspawn but I reduced it slightly with just a slim temporary solid test brush only one unit high above it pressing against the top of this triangle. The visportal was now working yet if I removed that slim test brush and raised the visportal to the top again then it would not work. Made no sense to me unless mathematically the very top pixel of the triangle might be regarded as infinitely thin and therefore a gap. So, I left the thin test brush and gave it sky texture so it's completely invisible and everything works.
(Note: Some mappers at Doom3world reported that cloned visportal brushes can cause problems in a map. This was reported in an earlier Doom 3 build.)
See also
There are other good visportal tutorials to be found under: http://www.iddevnet.com/doom3/visportals.php and http://www.modwiki.net/wiki/Visportal
Visportals, Func_statics and Worldspawn Brushes
Sometimes a visportal (VP) looks just fine in-game, but AI's behave erratically near them: cannot walk through the portal, walk into walls near the portal, can patrol through the portal but cannot chase the player through the portal. This may be due to worldspawn brushes penetrating the visportal.
Image shows scenarios A-D of different VP placement.
- Scenario A, when VP is snugly placed in the worldspawn corridor, it always works.
- Scenario B, where a worldspawn brush penetrates the VP has often caused problems. It will fail with very high probability if the worldspawn brush is a monsterclip brush. Never do this scenario! [Springheel -- I'd like more confirmation on this...I'm certain I've done this on a regular basis in uneven city streets without causing any obvious problems]
- Scenario C is what could be used if the scene absolutely requires somethings going through the VP and scenario A or D cannot be used. Usually this must be done for big outdoors VP's as seen in Knightons Manor exterior behind the manor (it is the hedge, which goes through the VP there). Note how the worldspawn brush is cut just at the VP and it is only func_static which penetrates the VP. This has worked without issues. Note that no monsterclipping is required if the func_static segment of the VP penetrating brush is short enough. The blue worldspawn brushes could also be monsterclipped func_statics as well. If so, mapper must be certain monsterclip brushes do not penetrate the VP!
- Scenario D where the VP is penetrated by func_static detail work, has not been reported to break visportals. Usually this kind of case is used in vaulted corridors etc. Works just fine. If the FS detail work is in reach of AI, special care to monsterclipping should be paid and it must be absolutely sure the monsterclip does not penetrate the VP as this will always cause trouble. In this scenario it is recommended that each side of the visportal have their own func_statics and one func_static brush should never penetrate more than one visportal.
Conclusion
Mappers should favour scenario A when possible. If detailwork requires, scenario D is okay, as well as scenario C. Never, ever use scenario B.
If mapper has some issues with their AI pathfinding, they should check the portal isn't broken as in scenario B. It is really easy to forget wall trims etc which could pass through the VP. Also typical mistake is to automatically surround a model near the VP with monsterclip, which results monsterclip brush which penetrates the VP. It is recommended that the mapper tests every visportal (which an AI is likely to pass) in their map before the map is released. Firstly the mapper should check in DR and make sure visportals are correctly set. Ingame testing should be done both with non-alerted path_corner patrolling AI's and with an alerted AI chasing the player.