Interior Mapping meets Escher
One cube, six interiors
My program was inspired by a piece of
M.C. Escher's artwork, “Other World” (seen below). In this
viewer looks from the inside of a cube and sees five walls, and each
pair of walls shows a different view angle of the moon's surface.
In my program, I have reproduced the effect of that painting, inverted:
using interior mapping, I have given each face of the cube a different
interior, occupying the same virtual
"Other World", by M.C. Escher
The first piece of logic is in my C++
program: it loads all six cube maps (one “interior” cube map for
each exterior face of the cube). It then draws the 6 faces of the
cube, binding the cube maps in place. The C++ program is also
responsible for feeding the world position into the shader as a
ShaderMy shader implements the following techniques:
- Alpha Blending
- The outer window texture is transparent in the parts where the interior should appear.
- The interior textures allow transparency as well -- this will allow the world background to show through.
- Interior Mapping
- Interior Mapping uses the fragment shader to cast the
incoming view ray (“direction”) into the interior of a cube, and decide which wall it hits.
- Cube Mapping
- The outer world background sphere uses normals to directly use up the cubemap texture.
- The cube interiors use the position of the ray-cube intersection to look up the interior wall texture.
- Diffuse Lighting
- Initially, I computed both the exterior color and the interior color using diffuse
shading from the single light source
- Later, I decided that the interior looks better full-bright, instead of lit from outside. outside
world through them.
I had previously seen an interior
mapping demo created by “Joost 'Oogst' van Dongen”; this demo provided
the base shader code. I fed the provided shader code through
the NVIDIA CG compiler to obtain GLSL code, and then revised from
– Cube Map Textures
– Interior Mapping Demo
I obtained my cubemap textures
from Emil Persson (“Humus”) -- more specifically, I used the following
named cubemaps (note that the camera starts out looking at the "left"
Left: "Interior" (from InteriorMapping demo)
Top: Walls are the window texture; top and
bottom are from the open-source game Nexuiz.
Bottom: "Earth"; exterior bottom is from Nexuiz.
Some of the most challenging aspects of
this program were as follows:
- Obtaining correct “view direction”
vectors in the shader -- I ended up having to feed the world
coordinates into the shader through one set of texture coordinates.
- Dealing with offsets and a cube from
(0,0,0) – (1,1,1) – a cube centered around zero resulted in 4 walls and
broken cubemap coordinates.
- Ensuring that a sideways incoming ray did not immediately collide
with an interior wall -- I eventually had to use a factor of "0.999" in
the wall distances, to ensure that the virtual inside walls were
"behind" the physical walls.
- Using alpha-blending to enable
viewing “through” the cube from outside, as well as viewing the world
from the inside.
Demo and Code AssumptionsI have archived the demo (compiled for
Linux) here: dgoyette_interiormapping_demo.tar.bz2
My demo assumes the following:
If I really wanted to confuse the viewer, I could have made each of the
rooms have a different definition of "up"... but I decided that that
would be a bit too evil.
In addition to the Escher painint, I was also inspired by a level from
the old game Duke
Nukem 3D, "Tier
Drops" [youtube.com], that used the game engine design to awesome
effect: Picture a spiral
staircase with four central landings (also connected via vertical
tubes)... and then flatten it so that all four center areas occupy the
same physical space. This was the effect I was trying to create