Rendering Portals in OpenGL

 

Overview

In my final project I developed and implemented portals capable of transporting the player between different environments. My goal was to create a portal class that could be placed in any direction, angle, or allowed to move without breaking smooth visual continuity.

Key Graphics Technologies

Rendering

To create a portal effect in OpenGL, there are two main strategies:

As far as implementation goes, I placed a lot of effort in reading through the OpenGL documentation on stencil buffers as they are hard to debug. But once I understood what each component was doing, I was able to follow the invaluable step by step instructions Thomas Rinsma provides in his write up of his attempting to render portals using OpenGL. His blog post continues and provides source code for recursively rendering the portals inside each other to simulate the endless portal effect seen in the Portal games.

I took this screenshot in test chamber 14 in Portal 1, on my 4k display at home I was able to count the eight recursive rendering calls before the portal is displayed as a white circle. As the game came out in 2007 I doubt they thought it was necessary to go any deeper. In Portal 2 however they used a different strategy altogether and used a recursively drawn texture past the first portal that intentionally curves to the side to obscure the vanishing point, I'd be very interested in how they made this effect as it can be disabled in the games "shader" settings, meaning that it’s probably computed as a texture being repeated passed to the GPU and then drawn inside itself.

Demo Scene

To demonstrate what my portal code can and cannot do, I built 3 test chambers, one green, one red, and one blue. Through the green portal I used only axis aligned portals, as their virtual camera and position matrices are by far the easiest to set up as they rely on just inversing the player's position over the plane dividing the two portals. In the red portal is where things change, to get views to rotate along with the portals as well as work for all horizontal orientations of portals, I had to rewrite the code that constructs the virtual view matrix. My algorithm utilizes the players position and angle relative to the position and angle that defines the source portal, and maps it virtually to where it should be in the destination portal's space. This works great I was unable to break it even in some of my more lag-inducing tests. The final blue test chamber is my nemesis, these portals all have vertical rotations which threw my virtual camera look direction and position out of whack. Due to time constraints/mental frustration I was unable to solve this final twist. (The Portal games limit portals to only PI/4 angles which I have a hunch allows them just to enter a simple switch statement with only 8 possible transforms, far simpler that what I was implementing.)

Bonus Ideas

My implementation utilizes near plane clipping that was just brought up to the edge of the portal directly out from the player, which makes weird artifacts if you turn sideways as parts of the scene through the portal get cut. However, after speaking with Scott K, who had a great implementation of axis aligned portals in his cool "Not AntiChamber" project this quarter, I learned that you can do Oblique View Frustum Clipping which can allow you to align the near plane in the projection matrix to a plane (in our case the portal). In Scott's implementation this looks great.