Solitaire

Around 2006, a friend mentioned that I should port my Windows Forms-based solitaire game to OpenGL. I had only a vague notion of what OpenGL was around this time, and cautiously journeyed into what would become my primary area of interest for many years to follow. The timing could not have been more perfect; I entered the graphics API scene right around the time when GPUs were transitioning from fixed-function register combiners to programmable vertex and fragment shaders. This allowed me to experiment with shaders long before geometry, hull/domain and compute shaders materialized and allowed me to learn the concepts incrementally. In 2008, I expanded my horizons by learning Direct3D 10 and was able to master it thanks to my experience with OpenGL. I partly attribute my strong interest in computer graphics to the fact that one of my favorite mathematical topics is linear algebra.

Details

I started simple. I had already implemented the actual solitaire engine and just wanted to get some cards to render to the framebuffer, while handling mouse events. As can be seen in the screenshot, I started out with immediate mode.

Solitaire

To add a bit of realism, I threw in some random per-card rotation to reflect the fact that life isn't perfect.

Solitaire

This didn't feel 3D enough for me, so I experimented with some different perspective transformations next.

Solitaire

Next, I experimented with bump mapping, lighting and attenuation.

Solitaire

I learned about image-based lighting (IBL) and couldn't resist throwing that in.

Solitaire

Now it was time to add a bit of polish. I added a background and refined the card borders, lighting and bump mapping.

Solitaire

That didn't stop me from experimenting, though. I couldn't resist mixing multiple textures together in the fragment shader to create a "paint-splattered cards" effect.

Solitaire

I generalized the code to support other games too, such as escalator.

Solitaire

At the idea of a friend, I implemented a real-time sketch effect with Gabor filters in the fragment shader. Around this time, I also ported the game to Direct3D to expand my horizons.

Solitaire

Why not add some dynamic fingerprints for realism?

Solitaire

All fun aside, this is what I ended up with. As stated earlier, I used immediate mode when I first started out, but evolved to instanced rendering, texture arrays and buffer objects.

Solitaire

Complete with a win effect:

The raw card bitmaps were generated from an SVG design created by David Bellot. The tablecloth bitmap comes from a royalty-free texture pack.