New level environment

So I had to make a tough choice recently.  The game originally planned to have 36 levels in sets of 12.  Each 12 would feature a specific art style, decreasing in realism with each set.  A major snag related to my own lack of art skills alongside an increasingly pushed back completion date for this game has lead me to make a change to this plan.

Toonshaded games are not as graphically “simple” as they appear to be.  I quickly realized this while attempting to adapt one of my environments for this look.  A perfect example would be to look at any recent celshaded game such as Zelda Windwaker HD.  You will notice that all the textures are hand painted with a very high attention to detail an artistic quality.  This is an artistic talent that I simply do not possess, and it would be a mistake to pretend that I do.

So what I’m going to do instead is break up the game into two halves of 15 levels each, and bring the total level count down to 30.  This will allow me to do just one alternate art style (an easier to render dark noire style) for the final half of the game.  Combining the dark black and white effect with the recently implemented SSAO effect that I’ve added to the game should look really cool for these last 15 levels.

The only remaining problem with this new plan is that I only had 12 levels done sofar and I would really hate to re-hash the same 3 environments again to fill the last 3 before changing art styles.  This lead me to the decision to make yet another new 3D environment for the game which I’ll use to create 3 more levels.  I initially really didn’t want to do this because I am approaching a burnout risk for the game, meaning I’m starting to get tired of working on it.. which puts the entire project at risk.  So, I decided that It’ll be a simpler level so that I can keep the total game size low (both in disk space and complexity).  I’ve posted a screenshot of what I’ve got sofar for that level.

More on all this soon…

Ambient Occlusion

So I got the ambient occlusion effect implemented in the actual game shader code.  I followed the technique outlined in this article.  I must say, it’s very subtle, but it looks nice.  The real benefit here is that when I turn off the “check depth range” mechanism, I get a very awesome surreal dark outline around all of the models in the scene.  This will be an excellent effect to use when I work on the second half of the game (which will use an artistic black and white noire post processing style signifying the protagonists slowly weakening grip on reality).

I didn’t understand how ambient occlusion worked at all before implementing the effect, but now I must say, I have a pretty reasonable grasp on it.  Basically in one brief description, it takes random samples at every point on the surface to determine how much ambient light from the rest of the scene can reach that point.  In other words, how much of the ambient light is occluded by other nearby surfaces.  This is done by randomly sampling points within a small hemisphere emanating from the surface.  What makes SSAO so nice, is that this technique is approximated entirely in screen space, making it reasonable for real-time rendering in a game.  The downside is it seems to be a little noisy and I see artifacts from time to time on the screen, but hopefully I’ll be able to clean some of that up in time.

Below are some more progress shots showing the kinds of subtle shadowing I can achieve using SSAO in the VGLPP/DrivebyGangster engine.

Ambient Occlusion!

Today was huge!  I am exhausted.  I busted my ass today to get an affect known as screen-space ambient occlusion (SSAO) working in a prototype scene in verto studio.  Right when I was about to give up, I got it working!  I’m too groggy to explain anything about it, so I’ll just post pictures!

This is going to add a huge boost to the visual look-and-feel of the game without a severe performance penalty.  Needless to say, I’m pretty stoked!



Still going…

Too far to turn back now. Progress has been steady. I’ll post some shots this weekend.  Level 8 is done. I’ve added a really awesome new game mechanic (randomly distributed hostile gangsters) for level 7 and up that makes the gameplay a lot more intense.  My initial playthroughs of this new mechanic have been awesome and I find myself almost unable to think I have to react so fast which is exactly the kind of gameplay action that I’m going for.

I’ve decided to try to do one new level of the game per day until it’s done.  If I can do this, I’ll be on track to have the game done by some time in April like I’ve been planning for.  Let’s see how it goes. I still cannot believe that I originally thought this game could be done in a matter of weeks. Granted that I’ve increased the game beyond its original scope, 2 weeks even for a most basic version of this game is way way off.

Playtesting demos!

Here they are, the public play testing demos! These are downloadable and playable on just about any recent computer (recent meaning 2012 ish). Older laptops may struggle and older older laptops will struggle hard. I wouldn’t expect this game to run on any pre-600 series nvidia card or equivalent amd card. Intel HD 4000 was tested but that’s it from the intel family, so I expect that’s the required card for intel.

Feel free to grab these, play the crap out of the demo, and don’t hold back in giving me feedback. This’ll be the first time I get any real feedback for this game so let me have it!

Mac –
Win –

Downloads are a little dodgy from my server so you may have to retry once or twice to get it.

Also, IF IT CRASHES, please email or contact me immediately so I can find out what went wrong. There’s one sound-related windows crash that I haven’t fully nailed down yet but I expect it to be quite rare. Either way, if that happens, please let me know via email or on here.

Pushing for playtest demo

Not a lot of updates here lately because I’ve been working hard to get to the point where I can post a playtest demo and get some early feedback for the game. The demo will feature the first six levels of the game which I’m tying off today.

An early screen shot of the sixth level is below..
It was a pain to convert and simplify all of the “night time” shaders that I had for the night fog scene back into “day mode”. But I got it done. I also noticed that with the fog lifted, the original scene was way to simple so I had to add some desert in the distance and some extra buildings to make it look more presentable.

OpenGL point light shadows & Atomspheric FX hacks

So asset creation in the form of modeling the final environment that’ll be used in the game took the past few days.  It’s amazed how much faster it went this time compared the first scene (the city street).  I chalk this up to experience that I’ve picked up now that I’ve been doing this awhile, and my understanding of things that are very time consuming to model vs things I can quickly grab, import, texture, and place from turbosquid.  The perfect balance of both techniques has led to me being done with the dark night alley street scene after just a few days.

Where I spent the most time this time was in the shaders.  I really wanted to have quality rendering and go out with a bang since this’ll likely be the last environment that I do for the game.  I want the dark alleyway to appear foggy and dark, like its just about to rain.  That includes moist shiny cobblestone rocks, and a damp fog effect that feels very palpable to the player.

This idea of mine posed two major problems that I haven’t had to tackle until now.

Point Light Shadows

The first major problem, is that I could no longer “cheat” using a single directional light source representing the “sun” in the scene.  Instead, I had to place a street lamp every building or so and have these be the only sources of light in the scene.  This means, in order to keep my shadows working, I now had to implement shadows from a point light source.  In some ways this was easier than point lighting (no longer necessary to compute an optimal shadow bounding box to be used for the light’s ortho matrix projection).  However, now I needed render to and utilize cube maps to store the shadow depth information.  Surprisingly, there was very little comprehensive information on the web about how to properly do PCF shadows using cubemaps.

What I found that works is the following.

  • Create a cubemap renderer that is positioned at the exact same position as one of the point lights - this special vgl engine object renders the scene into 6 faces of a cubemap with 90-degree fov angles to properly capture the entire scene from “all angles”.
  • Format the cubemap shader to have each face hold floating point depth-component values and keep the size small (256×256) since there will be alot of these.
  • Define an “override” shader to be used by the above cubemap renderer to ensure a simple specialized “light render” shader was used when rendering the scene into the cubemap faces.  
  • Set the cubemap compare mode (GL_TEXTURE_COMPARE_MODEfor the rendered cubemap texture to GL_COMPARE_REF_TO_TEXTURE which helps with percentage-closest-filtering (PCF) mode to allow smoother linear-interpolated shadow edges.  
  • Lastly, pass a rendered shadow cubemap for each light to the scene shaders in the form of samplerCubeShadow

The “light render” shader mentioned above which is used when rendering the depth information to the cubemaps looks like so:

Basically this encodes the distance from the surface point to the light in the form normalized depth information.  This is done by manually overriding the depth value stored in gl_FragDepth.  Each light has its own cubemap renderer with a custom-tailored shader like this (using the correct light index to compute distance from).

The per-fragment lighting shader code that utilizes the cube shadow maps looks like:

Essentially the highlighted code above compares the distance between the surface point to the light to the stored depth value in the cube texture using the fragment-light vector as a lookup value into the cubemap.  Because we’re sampling using a special “shadow” version of the cubemap sampler, the result will be properly interpolated between shadow texels to avoid ugly edges between shadowed and non-shadowed areas.

Luckily, I was able to build this into the Verto Studio editor and associated graphics system and test this out with relatively little trouble.  Even though I have 4 or 5 statically rendered cubemap shadow textures in the entire scene.  I was able to keep performance high by building versions of the shaders for each side of the street so that each individual shader only has to shade with at most 3 lights at a time.  This worked out better than I had expected.

Light-Fog Interaction (Volume FX)

This part was tricky..  I had an idea in my head of how I wanted this to look.  So I did something that usually leads to trouble;  I tried to come up with a volume rendering technique on my own from scratch and implement it and just kinda see how it goes.

The basic idea stems from what I’ve observed in real life from foggy, dark, damp nights and lighting.  Essentially, fog at night is black… IF there is no light around to interact with the fog.  Naturally, if the water droplets don’t have any light to interact with them, you won’t see them and the fog will appear black.  However, if any light interacts with the water vapor in the air, it’ll create the illusion of a whiter colored and denser fog.  So this is what I set out to emulate with my shader.

Now atmospheric shader effects can often lead to the necessity of raymarching and heavy iteration in the fragment shader to simulate the accumulation of light-atomosphere interaction.  To this I said “hell no” since ray marching of any kind in a shader terribly robs performance.  I quickly realized that I could avoid raymarching entirely if I used a simple model to represent the light-fog interaction that I was going for.

In my case, it turned out I could do the whole effect using something as simple as a sphere intersection test.  Basically, when I’m shading a pixel (a point on the surface), I’m interested in what happens to the light on its way back from the surface to the viewer, the surface-to-viewer vector.  If the atmosphere affects the light at any point along this vector, I’ll need to compute that.  In other words, if the ray from the surface to the viewer intersects a sphere centered at the light, then the fog affects the light on the way back to the viewer.  How much?  Well if I calculate the length of the segment between the entry and exit points of the ray intersection (how much of the sphere the ray pierces), I find that length is proportional to both the perceived increase in density of the fog and the brightening of the fog color.

This algorithm is given below in fragment shader code:


I’m sure I’m not the first one to come up with this idea before, but it still did feel pretty cool to reason my way through a shading problem like this.  The visual result looks amazing.

The progress of this all is below in a gallery.  

How to 3D sound in windows (hint: it’s not OpenAL)

So yesterday and today, I bit the bullet and started working on compiling the game for windows.  I wanted to do this before the project got too much further along so I didn’t write any code that would have serious implications on windows.  I must say, I’m amazed at how much trouble I didn’t have with the rendering system.  The levels/screens load up and look great!  I did have some issues with visual studio that I chalk up to lack of experience in windows dev on my part.  Namely getting the builds to be 64-bit instead of the default 32, SSE3 operator overload stuff, and getting debug builds to forego some of the extremely slow settings that make the engine run at a crawl.  Once I took care of all that, my little game was running on windows like a champ, complete with same stellar OpenGL 3.3 performance I get on mac.  All was well… that is except for one little tiny issue.  The sound.

One thing that became apparent almost right away was that OpenAL support on windows is in a terrible state.  Counting on it to just be there like OpenGL is a no no.. and installing your own via something like OpenAL soft gives pretty poor support.  I realized that I had to do something I’ve never done before, and that’s directly use a DirectX subsystem.  After some quick googling I discovered what I need can be done using a combination of xAudio2 and X3DAudio.  Both of these systems come with DirectX and the DX SDK so I was already set up to use em.

So basically, the plan on windows was pretty simple:  since I already have all my 3D sound calls abstracted out in my SoundManager class, I all I had to do is re-implement the stuff that OpenAL handled using this new xAudio2 stuff.. and pray that it played nice along side SDL_Mixer which I use for mp3 music.  More or less, things went relatively painless and I was able to find an xAudio2/X3DAudio analog for just about everything I was doing in OpenAL EXCEPT for a little issue I had with source playback.

On mac, I’m able to play a source overtop of itself as many times as I want to.  On windows, this seems to be a no-go.  So for win, I had to manually pre-allocate pools of sources for the sounds that I would be playing rapidly such as bullet ricochet sounds and typewriter keystrokes and ensure that I return an available source whenever I ask to play that sound.  That process more or less worked out just fine.

After all that, we have my reworked soundmanager class for windows.  The code is below for anyone who wants to learn from it.

All of the multiple source stuff is essentially handled by my inner MultiSource class which handles the souce pools for sounds that need em.  I found that I never needed more than 8 sources per sound.  I also had to add a new update3D method to update the 3D sound calculations and call it once every other frame or so (which wasn’t needed in OpenAL since it was done automatically).

Not shown here is a Wave class which essentially is a slightly modified version of the one from this tutorial.  That class basically handles wav file loading for me and manages the sound buffer data internally.  

That’s just about it.  Everything else was pretty straightforward.