Non Euclidean Room – Postmortem

Posted by
December 23rd, 2016 1:33 pm

For Ludum dare 37, I worked on a game about wandering around a strangely connected room. The idea obviously come from the works of Escher on “impossible” geometries. The connection with the theme is to have only one big room, but using portals to make it interesting to visit.
You can play and rate the game here :

At first I wanted to have puzzles, like pointing lasers to open doors. You would use portals to change gravity and walk on the ceiling. I also wanted to have markers for the player to place around and help you navigate the room. In the end, I only had time for portals and a simple room, with a couple of interesting visual tricks. The scope is smaller, but by focusing on smooth portal transition, level design and polishing, the game ended up pretty well.
Here is timelapse recorded during the creation of “Non Euclidean Room” :

Portals :
Making portal feel simple but a lot of things can go wrong. At first I simply wanted to plug a copy of the room at each door and teleport everything around. That can work but it limit what you can do a lot. You cant have two doors close to each other. Basically you can only have doors on the external faces of the room.
Then the next technique is to use a render texture to produce a view from the portal exit with a second camera. An object will use that texture to display it on the main camera.
Here is the code (in Unity C#) I use to place the portal camera according to the main camera and transforms from Enter and Exit portals :

Quaternion Rot180 = Quaternion.Euler(0, 180.0f, 0);
Vector3 LocalPos = EnterPortal.transform.InverseTransformPoint( MainCamera.transform.position);
Vector3 RotatedPos = Rot180 * LocalPos;
PortalCamera.transform.position = ExitPortal.transform.TransformPoint( RotatedPos);
PortalCamera.transform.rotation = ExitPortal.transform.rotation * Rot180 * Quaternion.Inverse(EnterPortal .transform.rotation) * MainCamera.transform.rotation;

You use the main camera location in the local space of the entering portal, you pretend it’s a local position in the exiting portal and get it’s world location to place the portal camera. The rotation by 180 degrees is there because the exiting portal face opposite to the entering portal. You do the same on the rotation of the camera.

Portal camera location

This technique can certainly work, but will need a render texture per door. So I tried something else.
I used only two cameras, and the stencil buffer. The idea is to first mark (in stencil buffer) the portal pixels on the screen by drawing them from the main camera point of view. Then draw the scene through the portal, by placing the camera at the correct position, and using the stencil as a mask. Then rendering the usual camera above that, without overriding the portal door.
For the player motion himself, I just teleport the player when he pass the middle point of a portal to the relative location in the second portal.

Portal Anatomie

A second trick that I needed is to use a clip plane along the portal door. You want only objects from beyond the portal to be visible. For that, you can use an oblique projection matrix. This technique create a near clip plane in an arbitrary orientation by distorting the camera projection matrix. There is some downside though, as some visual glitch can appear when the camera is near the clip plane. If you stop in the middle of a portal, you can sometimes see the screen edge disappear. Another idea, that I didn’t have time to test, is to send the clip plane to the shader, and use the instruction “clip” to discard pixels that are on the wrong side. That way, no need for a custom projection matrix.

Oblique projection matrix

After having that first version working, there was only one visual glitch when going through a portal. You could not see a portal trough another portal. That was very obvious when walking through a portal : every other portal will pop into existence. To fix that, I needed to display portal through portal, at least for the nearest portal from the camera.
The idea is to use the stencil bit masks to read and write two separate portal indexes. That way I could tag a door, and a door inside a door. This did limit the portal count to only 15, as there is only 4 bits left in the stencil buffer for each index. But this was enough for the small game I had in mind for Ludum Dare. I could also take the nearest 15 portals from the camera, but it was already time to start the level design so I limited myself to 15 total. You may notice that there is 16 doors in the game. In fact the final door that let you leave is not a portal, it’s a regular door. The portal transition is smooth enough that you don’t notice. Since the LD, I improved the tech quite a bit in a post-compo version.

Visual style :
I decided quite early on the visual style I wanted for the game. The reference to Escher’s work is obvious : black and white with thick lines and a shading made by changing line density. I choose a style a bit more sketchy and, of course, animated. The strokes are placed on the screen and move with the camera. The animation is there to hide that fact. I blend 3 layers of strokes, and 3 times per second, each one have a chance to pan and rotate. This give an unpredictable animation. Some people found the effect a bit too disturbing after a while. I want to revisit it later.

The second part of the visual effect is the edge lines. The issue with portals, is that I render everything in “forward” so I don’t have a “normal buffer” to run my edge detection on. I don’t have a proper “depth buffer” either because of the way I render portals. So, I needed to use only the color buffer to make my edge detection. To detect normals, I simply render the absolute value of the pixel normal in the color buffer, modulated by the lighting intensity. So to have the luminosity of a pixel, I can use the value of the color (average of red, green and blue). And I can use offsets in hue to detect edges by sampling a pixel to the right and a pixel to the bottom of the current pixel.
I also wanted to detect depth discontinuities, so I had the idea to modulate the pixel color by the depth, making some sort of fog. Surfaces with the same normal but at different distances will then have a slightly different colors, and could be detected by the edge filter. The fog gave a moody atmosphere to the scene but I liked it. To complete the look, I added a Gaussian bloom filter, to give some gradient to the flat blue interactive objects.

Scenes from the game :
– Penrose infinite stairs

– Twin scenes through portals

– Falling through an empty space

Future post-compo version :
As much as I like the game as it is, a simple exploration game where you make your own path, I wanted to do more. In the beginning, I wanted to change orientation when you go through portals, letting walk on walls and ceiling. But I used the Unity Controller. And that controller cannot be rotated around freely. The collision capsule is fixed on the Z axis. So I did with that constraint. But now I started to extend the game in a Post-Compo version. The idea is to make a second room and exploiting everything I couldn’t in the base game.
– Infinite recursive portals :

– Proper puzzle with blocks (and laser later) + walking on walls :

I hope to complete that second room in early January 2017, with interesting puzzles and a longer playtime.

Tags: , ,

2 Responses to “Non Euclidean Room – Postmortem”

  1. Avant-Marde says:

    Find it both amazing and rather disgusting that some people are able to pull stuff off at this level of… everything… in such a short time, from idea to concept to plan to actually coding the darn thing, and with an incredible visual style at that. Thoroughly impressed and immensely provoked at the same time! c;

  2. Leon Möhring says:

    Easily my favorite compo entry! Great work!

Leave a Reply

You must be logged in to post a comment.

[cache: storing page]