Fez Viewer v0.2 has been released! This build adds support for background planes and animations.

Fez is probably my favorite game of all time. I love everything about it! I wanted to do some Fez fan art over my most recent vacation. But I wanted to get a better view of the levels. After some digging I found that a few other fans had discovered a way to dump the contents of the game. Someone named “fesh0r” released a tool called fez_parse (link below) that will dump the contents, as well as allow you to view the simple 3D models from the game. However nobody had yet written a level viewer. I decided to write a viewer on my flight back from vacation, and add a few features over the past week.

Please use this tool in good taste. It is possible to see many spoilers from the game, but please avoid posting such spoilers online. Thanks!

Roughly 8 months after my last Ludum Dare entry, I finally got around to posting it here!

Just got back from showing one of my games at POW POW POW and someone encouraged me to upload my code to Github. Here’s the source and assets for my latest two games. They require the library Cinder in order to build.

I’ve recently had a need to simultaneously render using both DirectX and OpenGL. There are a number of reasons why this is useful, particularly in tools where you may wish to compare multiple rendering engines simultaneously. With this technique it is also possible to efficiently perform some rendering operations on one API to a render target, and switch to the other API to continue rendering to that render target. It can also be used to perform all rendering in a specific API, while presenting that final render target using another API. Providing direct access to textures and render targets in graphics memory regardless of API has the potential of efficiently pipelining surfaces through multiple discrete renderers.

I’ve been terribly bad at keeping information on my games posted on my blog, so I’ve created a “Games” section where you can see what I’ve been working on! My latest game was an entry to Ludum Dare 28 called “Aggrogate”. It did extremely well, getting 8th place in innovation! I will do my best to keep the game page up to date with the latest builds of my games, the latest videos, and links to the original Ludum Dare competitions.

Also, GDC is next week! I will work on making a nice informational post about one of the many research projects I did this year, as I’ve been meaning to post more technical information on this blog.

And in another hardware related update, I also posted my recent 120Hz monitor overclock conversion.

Today I showed off Zero Zen, a game I made in 48 hours for Ludum Dare, at the Portland DrupalCon. It went great! For those interested in downloading the game, you can download the original Ludum Dare entries here:

Download Zero Zen for Windows

Download Zero Zen for Mac OSX

The original Ludum Dare page with extra information can be found here:

There will be a proper post discussing a postmortem of the game, but for the time being take a look at this nice gameplay video!

I’ve been interested in making some nice electronic music and sound effects for my games. I tend to find the UI of different VSTs frustrating, so I was interested in getting a MIDI controller that could help speed things up. I’m also interested in the possibilities of rigging the MIDI knobs to variables in the code so I could tweak different parameters in real time. Like any good (over-)engineer, I researched what it might take to put one together myself. For whatever reason I find This sort of controller hardware fascinating.

It’s been too long! Here’s an effect I was taking a look at a few months ago.

So there is this cool technique that had gained significant popularity in the demoscene called “Signed Distance Fields”. There’s a truly excellent presentation by iq of rgba (Iñigo Quilez) posted on his website http://www.iquilezles.org which he presented at nvscene back in 2008 called “Rendering Worlds with Two Triangles”. I wanted to play around with some GLSL and thought this would be a really interesting algorithm to take a look at. You can see some of the power of these types of functions in a presentation that smash of fairlight (Matt Swaboda) gave at GDC earlier this year http://directtovideo.wordpress.com.

So here’s an extremely basic GLSL shader I made to learn exactly how the distance fields work. A frequent question when working with signed distance fields, is why march through the scene if you already know the exact distance from your viewpoint to the surface of an object? Well, if you consider the path of a ray fired into a scene, in order to determine the intersection point of that that ray with the implicitly defined surface of one out of many objects, a great deal of math would be involved to determine the exact intersection point; too much for a real time application. The signed distance fields are a way to describe geometry by providing a distance from a given point in 3d space for the entire scene. Combined with ray marching, we can start at the camera and step at least the distance to the nearest surface, but in the direction of the ray. If the ray pointed directly into that nearest surface, the ray would return the intersection point in 3D space. Otherwise, we can run the equation again given a point in 3D space that is that distance along the ray to find a value for the nearest surface. March again, test for intersection, return if we intersected, otherwise continue marching.

To really solidify the algorithm in my brain, I wrote up this little shader. The only input I use is the window dimensions, which are only used for coloring. I hope to soon add shadow computations to provide a true 3D look.

// Distance functions from:

// http://www.iquilezles.org/www/articles/distfunctions/distfunctions.htm

uniform vec2 resolution;

vec3 translate(in vec3 pos, in vec3 translate)

{

mat4 transform = mat4(1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1);

transform[3][0] = translate.x;

transform[3][1] = translate.y;

transform[3][2] = translate.z;

return vec3(inverse(transform) * vec4(pos,1));

}

vec3 scale(in vec3 pos, in float scale)

{

mat4 transform = mat4(scale,0,0,0,0,scale,0,0,0,0,scale,0,0,0,0,scale);

return vec3(inverse(transform) * vec4(pos,1));

}

vec3 repeat(in vec3 pos, in vec3 repeat)

{

return mod(pos, repeat) - 0.5 * repeat;

}

float sdSphere(in vec3 pos, in float scale)

{

return length(pos) - scale;

}

float udBox(in vec3 pos, in vec3 corner)

{

return length(max(abs(pos) - corner, 0.0));

}

float raymarch(in vec3 ro, in vec3 rd)

{

float epsilon = 0.0001;

float farplane = 30;

vec3 raypos = 0;

vec3 boxCorner = vec3(1.0, 0.2, 0.7);

float sphereScale = 0.7;

vec3 repeatDelta = vec3(5, 5, 5);

for (float t = 0; t < farplane;)

{

raypos = ro + t*rd;

float h = min( udBox(repeat(translate(raypos, vec3(-0.5, 0.5, 0)), repeatDelta), boxCorner),

sdSphere(repeat(raypos, repeatDelta), sphereScale)); // distance to nearest object

t += h;

if (h < epsilon)

{

return t;

}

}

return -1.0;

}

void main()

{

// normalize pixel position

vec2 uv = gl_FragCoord.xy/resolution.xy;

// generate a ray with origin ro and direction rd

vec3 ro = vec3(0.0, 0.0, 2.0);

float aspect = 1.6; // resolution.x/resolution.y

vec3 rd = normalize(vec3((-1.0+2.0*uv)*vec2(aspect,1.0), -1.0));

// fire the ray and intersect with the scene

float t = raymarch(ro, rd);

// draw black by default

vec3 col = vec3(0.0);

if (t > 0.0)

{

// if intersection, draw color

col = vec3(uv.x, 0, uv.y);

}

gl_FragColor = vec4(col, 1.0);

}

// http://www.iquilezles.org/www/articles/distfunctions/distfunctions.htm

uniform vec2 resolution;

vec3 translate(in vec3 pos, in vec3 translate)

{

mat4 transform = mat4(1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1);

transform[3][0] = translate.x;

transform[3][1] = translate.y;

transform[3][2] = translate.z;

return vec3(inverse(transform) * vec4(pos,1));

}

vec3 scale(in vec3 pos, in float scale)

{

mat4 transform = mat4(scale,0,0,0,0,scale,0,0,0,0,scale,0,0,0,0,scale);

return vec3(inverse(transform) * vec4(pos,1));

}

vec3 repeat(in vec3 pos, in vec3 repeat)

{

return mod(pos, repeat) - 0.5 * repeat;

}

float sdSphere(in vec3 pos, in float scale)

{

return length(pos) - scale;

}

float udBox(in vec3 pos, in vec3 corner)

{

return length(max(abs(pos) - corner, 0.0));

}

float raymarch(in vec3 ro, in vec3 rd)

{

float epsilon = 0.0001;

float farplane = 30;

vec3 raypos = 0;

vec3 boxCorner = vec3(1.0, 0.2, 0.7);

float sphereScale = 0.7;

vec3 repeatDelta = vec3(5, 5, 5);

for (float t = 0; t < farplane;)

{

raypos = ro + t*rd;

float h = min( udBox(repeat(translate(raypos, vec3(-0.5, 0.5, 0)), repeatDelta), boxCorner),

sdSphere(repeat(raypos, repeatDelta), sphereScale)); // distance to nearest object

t += h;

if (h < epsilon)

{

return t;

}

}

return -1.0;

}

void main()

{

// normalize pixel position

vec2 uv = gl_FragCoord.xy/resolution.xy;

// generate a ray with origin ro and direction rd

vec3 ro = vec3(0.0, 0.0, 2.0);

float aspect = 1.6; // resolution.x/resolution.y

vec3 rd = normalize(vec3((-1.0+2.0*uv)*vec2(aspect,1.0), -1.0));

// fire the ray and intersect with the scene

float t = raymarch(ro, rd);

// draw black by default

vec3 col = vec3(0.0);

if (t > 0.0)

{

// if intersection, draw color

col = vec3(uv.x, 0, uv.y);

}

gl_FragColor = vec4(col, 1.0);

}

A couple weeks ago was another splendid game jam, this time held at the art institute in Portland, organized by the excellent PIGSquad (Portland Indie Game Squad). I was in the mood to learn a bunch of new technologies, and to experiment with audio visual synchronization, which I intend to use heavily in a lot of my upcoming games. The audio program I’m using is called Renoise, and the graphics framework I’m using is called Cinder.

© 2019 Halogenica | Stumblr by Eleven Themes