Building a 3D Portal Engine - Issue 09 - 2D Portal Rendering by (26 February 1999) Return to The Archives
 Introduction
In this article we'll start the investigation of the portal technique for fast visible surface determination. We'll start again with the basics, and proceed to the darker corners of technology as we explore portal-related features like mirrors, shadows and warps...

A few years ago, I wrote a little 3D engine in Pascal. It was more or less portal based, as I used a technique that I now call '2D Portals'. That isn't the perfect name to give it, I know, but suggestions are always welcome...

Anyway, before I explain what '2D Portals' are, I will try to explain the basics of portal rendering in general.

Imagine a large room. In the middle of this room there is a floating thing that looks like a mirror at first, but when you look closer, you can see that it actually shows a completely different scene... It's a link to another location, a window in space... Or, to be exact, a geometrical discontinuity.

This is what Unreal (and I assume Prey also) calls a 'Portal'. In my opinion, a portal is much more. It can also link two rooms in a perfectly normal way, for example. So, what's its benefit in that case? Simple, if you return to the floating portal example. Everything that you can see through the floating portal is 'clipped' against the portal. And even better, it's very easy to determine if everything beyond the portal is visible, simply by determining if the portal itself is visible. The first thing I mentioned reduces overdraw to almost zero, if you would place portals all over your scene. The second cuts of whole parts of your world in an incredible efficient manner. Besides that, the algorithm is very simple and intuitive, and generally applicable.

Just to be sure that you grasp the general idea of portals, one more example. Imagine you are in a room, with three windows, and a single door. Outside this room, there is a huge world, with lots of large polygons. In short, the exterior is a disaster for the average software renderer, because the walls will be drawn right over it, causing massive overdraw. But if you would place portals in the windows, and one where the door is, you could actually clip the exterior to these areas, and reduce the overdraw to zero. If you would turn away from the door, you wouldn't even have to consider the scenery beyond the door. So, no matter how many polygons you could see through the door, it's processed in no time. That's a 3D coder's dream: No extra penalty for geometry that is not visible. Visible complexity counts, not total complexity.

The data structures needed for this stuff are extremely simple. There are two things that you need to know about:
• Portals
• Sectors
• Sectors are areas in your geometry, completely sealed off by a combination of portals and solid polygons. So, in the example above, you have two sectors: The room the camera is in, and 'outdoor'. Portals link two sectors. So, each window links to the sector 'outdoor'.

Now that the basic ideas are clear, I shall wet your appetite with some little ideas.

A world is usually rendered by the following pipeline:
• Determine set of visible polygons
• Rotate coordinates
• Perform perspective
• Draw polygons
• The rotation of coordinates is usually performed using a matrix. Now wouldn't it be cool to use different matrices on different coordinates? (no, I hear you think) Yes! Imagine, you look out of one of the windows of the hypothetical room I mentioned before. All the coordinates in the room are rotated and translated using the usual matrix. But then you encounter a portal. The portal alters the matrix, and links to a different sector than the one that is physically behind the window, for example by changing the translation vector. All polygons that you see through the portal are rotated and translated by the new matrix, so effectively, you are looking at a different position... One window could for example link to another window, so if you try to look out of the window, you see yourself, looking out of a window, and so on...

This way, a portal could also be used as a mirror: You can easily determine the mirror matrix for a viewpoint and a plane, and render the sector that the portal is in using that matrix. I'll get back on all those nice features later.

So, how do you implement your portal engine? Here's some pseudo code:

 ``` Frustum fr; function renderSector (sector) { for (each polygon in current sector) { if (!facing (polygon)) continue; if (clip (polygon, fr) == NULL) continue; if (polygon != PORTAL) markVisible; if (polygon == PORTAL) { Push fr; fr = adjustFrustum (fr, polygon); renderSector (polygon.sector) Pop fr; } } } ```