Monthly Archives: December 2014

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.

So much progress

So much has been done.  I’ve gotten the menu screen (title) finished and it’s beutifal.  I got the early music soundtrack for the title and first two levels in place, and a way to transition between all of these things.

My latest work has been the pre and post status screen in the game showing you how many enemies and bystanders to expect before each level, and how many you correctly or incorrectly killed at the end.

 

Some of the funnest work has been coding up the cutscenes for introducing the environments in the game.  I’m still planning on only doing 3 environments (otherwise I’ll never finish this game), and making the 36 total levels out of different takes on these same environments.

Here’s a tease of the intro into the second environment of the game.

C++11′s take on retain cycles

I’d like to take a brief moment to discuss something rather programmy today.  Namely, the topic of retain cycles.  If you’ve ever programmed in Objective-C before (since the addition of ARC) or Swift, this concept will be very familiar to you.  But if you’re coming from other programming languages such as the older (pre-11) C++, This concept will be new and you might want to read on.

Now before I get started, let me say that this example may not be the most correct way to handle delegation via lambda (block) functions in C++11.  Many will tell you that shared ownership of objects in C++ can get you into trouble, and this is certainly a case of how that can happen.  However it’s the most conceptually compatible with other languages, which I value over “c++ correctness” due to the fact that I’m porting code from another language to start with, and shared ownership allows me to get work done without reasoning around the lifespan of my objects.

Now as many newcomers to C++11 know, concepts such as smart pointers and lambda callback delegation can really save you alot of time when developing new systems.  However, there’s ahidden evil in using these two concepts together, that must be uncovered.

Example 1 :: All is well

Consider this example:

and its output:

What we’ve essentially done here is created an object (via shared pointer), set a callback lambda, and issued a method call which at some point calls our callback.  We see that everything is working as desired.  Most importantly, we see that our object is properly deleted when we are finished our program (when the shared pointer goes out of scope).

Example 2 :: Not so much

Now lets look what happens when I add a slightly more complicated, second case.

Obj2 essentially is the same as obj1 right?  All we do is add a little printout of obj2′s someProperty value from within the lambda… and of course, C++11 dictates that we must explicitly declare all external objects that we access within our lambda (a capture list).

So what is the output then?

Note the alarming lack of “object freed” being displayed for obj2.  That’s right, the above code memory-leaks obj2.  You see, obj2 owns someCallback, and someCallback owns obj2 via a capture. This is a retain cycle and it permanently causes obj2 to be “forever retained” and therefore leaks.  Once a retain cycle is made, you can consider things to be more-or-less, too late.

This type of bug is a dangerous silent killer of the night.  Why?  Because it can be so easy to miss when developing.  Objective-C and swift have evolved over time to add compiler and IDE warnings about this kind of “retain cycle” problem.  C++11 assumes that you just wouldn’t write this type of code.  But when porting code over from Objective-C, this kind of code can pop up ALL the time.

So what do we do?

Solution 1 :: The ObjC way

Well Objective-C handles this problem by introducing the concept of “weak pointers”.  These are special pointers that ensure that they do not own their reference, they only keep track of whether or not it is allocated (if any shared pointers to it exist).  Luckily, C++11 brings the weak pointer to us as well.  A solution that uses them looks like so:

You’ll note now that running this code will solve the leak.  It’s also important to note that, while this is an ugly solution, this is/was the only way to solve a retain cycle of this nature in Objective-C.

However, for this explicitly unique case, in C++, there’s another way.

Solution 2 :: The tempting C++ way

What if I told you there was a way to solve the original problem by adding one character to the original code?  Here it is:

See that little ‘&’ added before obj2 in the capture?  This allows us to capture a reference to the smart pointer and not a value.  Why does this matter?  Well when a smart_pointer value is copied, it essentially increments its retain count of the object in question, and when it finally is destroyed by going out of scope, it’ll decrement the retain count, restoring the natural balance to the universe.  However, as I mentioned before, a retain cycle prevents the retain count from ever reaching zero in this case.  A reference to obj2′s smart pointer value allows us to forego the copy-increment mechanism and essentially stop obj2 from being over-retained.  Its essentially like taking a pointer to a pointer….

However, this solution can be dangerous, as it assumes the coder understands the rammifcations of doing things like capturing a reference to a stack variable, an argument, or anything that may be “dead” by the time the callback is ran.  Almost always, this “solution” may give unintended consequences.

The “correct” way

Here’s where things get somewhat opinionated. The “correct” way to handle this really depends on the situation at hand. I suggest that if you a working with a team, you might want to use the safer and more verbose weak pointer method since it is more explicit in its intentions and helps explain why strong ownership could be a problem.  Furthermore, if you are working in a smaller system where shared pointership is not necessary, you might want to avoid using shared pointers altogether (assuming you fully understand the ownership semantics of the objects being used in the captures).

Either way, the golden rule is to understand the side effects of the code you are writing and when using shared pointers, keep that little retain cycle demon in the back of your mind… always

Parallax Occlusion Mapping – Advances in shader land

Today was cool… at least the first part of it was, before I spend 5 hours tracking down a bug in some of the game code.

I stumbled onto a pretty cool little article geared towards a very awesome technique called “parallax occlusion mapping”. This is essentially bump mapping with some extra samples taken at each pixel to provide a realistic depth (or parallax) effect to the surface. This provides the illusion of realistic surface detail all while shading a single polygon. The article was somewhat dated and targeted for Direct3D instead of OpenGL, but I was able to port it over to GLSL 150 for OpenGL 3.2.

Here’s the original article:
http://www.gamedev.net/page/resources/_/technical/graphics-programming-and-theory/a-closer-look-at-parallax-occlusion-mapping-r3262

And here’s my port of the shader code for anyone who is interested.

 

Some of this code is “massaged” by Verto Studio’s code converter when ran on mobile.  It’s definitely a pretty cool effect!  It requires 3 texture maps to work currently, a standard diffuse (color texture) map, a normal map, and a displacement or height map.  Lucky for me, there’s a sick little program called “crazy bump” for mac that can generate both normal maps and displacement maps from any standard diffuse texture map!

 WebGL demo

For those who want to see the shader effect in action, I got a WebGL demo which runs on chrome and safari (firefox and IE don’t work).

It’s an expensive effect however, so I’m not sure yet if I can work it in for Driveby Gangster.  Either way, it’ll definitely be a nice little addition to the shader arsenal.  If I do actually put it into use, I hope to eventually add self-shadowing effects as well.

What I’ve been doing

Tons of stuff has been accomplished as of late.  I’ll just list a few of em here.

  • I programmed a cool “breaking glass” shader for the street scene shop window so that when you shoot at it, it breaks
  • I made a “spark” particle shader for when you shoot at metal, and also programmed separate bullethole decals to appear depending on the surface you strike.
  • I bit the bullet and grabbed maya for finishing up some of the character animation stuff including animations for aiming the gun and getting hit by bullets
  • I started on and nearly finished a very awesome “beach” scene for the game.  This broke one of my cardinal rules about keeping the stuff simple, but I’m accepting the risk because a game with the same level over and over again is a pretty bad user experience.
I apologize again for the lack of quality updates on here, but I’ve definitely been prioritizing working on and finishing the game over keeping this blog up to date.  It’s a tradeoff I guess.

For the beach scene I modeled a cool sailboat for it entirely from scratch using verto.  I have big plans for this sailboat that I’m going to keep secret for now.

One thing that I’m really excited about was a small effort that took me two days. I managed to compile the entire C++ code base to JS using emscripten.  This means that I can display simple verto studio scenes in the web browser!  A quick demo of this, for people running on webgl enabled browsers, should display below…