Built nearly from the ground up in C++ using OpenGL and SDL, Aperture is my most technically impressive game by far. In it, the player explores a small island, taking pictures of the native flora and fauna. In a team of three, I was the primary graphics programmer, as well as a gameplay and UI programmer and the sound designer. This game was created for CMU 15-466 Computer Game Programming, a class about creating games and game engines.

Itch.io GitHub

Occlusion Queries

Our main mechanic, picture-taking, required object detection. However, we wanted to find a better way than just raycasting from the camera. So, I used OpenGL's hardware occlusion queries to count the number of fragments that get rendered from each object, which was then used for scoring and other mechanics. I implemented occlusion culling using the same queries - each object would be drawn and queried each frame, and if its query returned zero, it would not render to screen with our more intensive shader. I also made a queue of queries per object, so that we would query each frame but only use the fragment count of the most recent finished query to prevent the game from freezing until each query finishes.

Custom Shaders

In addition to shaders described elsewhere, I implemented distance-based fog that changed color with the sky, color grading, integrated a teammate's animation code, and wrote my favorite shader, the camera depth-of-field effect. That shader renders a blurred texture of the screen, then blends it with the normal screen texture based on focus calculated via a depth texture. This worked, but had issues when foreground blurred objects' edges overlaid in-focus objects. With more time, I would fix this by instead computing focus amount for each pixel along with the depth, then generating a blurred texture that, when sampling neighbors' colors, weights those colors by the focus amount. This should fix the issue and is more efficient as it renders each object three times instead of four.

Pictures

I wrote the code to store, export, and grade pictures. Each picture stored data about the fragment count of each object in the picture as well as the creatures in the photo and their focus, relative position, and other state. I also implemented the photo grading system, which grades each creature in the picture based on fragment count, invisible "focal points" included in the model, creature angle (closeness to an authored best angle), position in frame, how in focus it is, and whether it's displaying a bonus behavior. The highest scoring creature is the "subject", and the rest are reduced and given as bonus points. Plant variety is also detected and given bonus points.

Lighting

Using OpenGL, I implemented forward lighting in-game. There were only two real light sources in the game - the sun/moon and ambient light from the sky. Because of the day/night cycle, we could not bake shadow maps, so I also implemented shadow mapping to both add immersion and emphasize the passage of time. I used a very simple blurring algorithm to tone down the pixelated edges of the shadows. I also wrote code to change the angle and color of the lighting based on time of day and modified my teammate's sky color code to add sunrises and sunsets.

Pipelines

Given we had no engine, it was important to build some tools to allow us to quickly add content to our game. When I integrated textures into the main shader, I also programmed a small pipeline to automatically assign textures to objects based on name. I also wrote some CSV parsing code to allow us to easily add creature descriptions, point values, names, et cetera to the game. Finally, I also wrote a small audio pipeline, although it required the user to type in the name of the file.

Sound

I was the solo sound person on the project, and as such, I made all the sound effects and music for the game. Much of the sound engine code was given as part of our starter code, but I went in and implemented the ability to play sound at variable speed. This let me play sound effects with random pitching, preventing them from getting stale. In addition, some of the starter code was implemented by us earlier in the year. The music and all 12 sound effects except one were made from scratch with a synth. The music also syncs to the time of day, being bright and cheery during the day and getting more eerie at night.

Game Logic

In addition to graphics, sound, and other responsibilities, I also programmed much of the general game logic. For instance, I wrote unique behaviors for each of the six creatures in the game, such as the meepers, who fly around a set home location, the snalers, which hide in their shell if you get too close, or the tantrus, which emerges from the sea around sunset, flies around a set path over the island, and returns to the sea. Some creatures also have behaviors triggered by picture-taking, such as the floaters, who float away into the sky if you take a picture of them.I also wrote the code to keep track of what creatures you've taken pictures of, the number of times you've seen them, your best picture of them, et cetera to emulate a "pokedex" pause menu. I also did the UI for this menu.

Optimization

Finally, I worked a bit on optimization. Due to the small scale of the game, not much was necessary, provided I built the shaders somewhat efficiently. After we finished the game, the main optimization issue was loading, which took about 30 seconds on my computer. However, I went back in and implemented multithreaded resource loading and optimized our texture resource sharing, which brought the time to 10 seconds, three times faster. During development I decided to implement occlusion culling mostly for educational purposes, but after I finished building it, I measured the FPS and realized that the game was 1-2 frames faster per second without it on. Occlusion culling required an extra pre-pass, and the game visuals weren't complex/big enough that the saved shading time offset the occlusion culling overhead.


willowpet ยท Strange New World - Aperture OST