Elysian Shadows

ESTk DevLog 002: Normal Mapping and Lua Debugging

Three days of slow and painful progress culminating in an epic 48-hour substance-fueled devbinge, yielding astounding results. That's pretty much how I would sum up this week. As much as I have tried to distance myself from these "devbinges" after they took their toll on my mental health and sanity during our exhausting Kickstarter campaign, sometimes old habits die hard... and sometimes a little bit of decadent self destruction yields significant progress and is exactly what the doctor ordered. I suppose this blog will inevitably reflect the delicate dance with insanity one must perform in order to succeed with an indie startup company. In the name of my company and my dream, I regret nothing... Judge me.

falcoTylerReested
2 days without sleep? Standard procedure...

In my quest to bestow upon Patryk everything he could possibly need to create an aesthetic masterpiece of a game, taking the entire pixel art concept to the next level, I have continued my obsessive compulsive bugfixing and request-driven feature development for ESTkv1.5.7 "Sex and Candy" Release of the Elysian Shadows toolkit. The majority of the minor bugs and stability issues have been resolved, now I'm tackling far more fundamental issues and am implementing far more complex features, remaining in my beloved low-level R&D land while the rest of my team utilizes my work several layers of abstraction above, creating the actual experience of Elysian Shadows as a game.

Flip/Rotated Normals
If you remember from my previous blog post, I already addressed one fundamental issue with normal mapped tiles not being lit perfectly on orthogonal planes. It turns out we have yet another lighting issue that has been part of our engine since day one and has only now been recognized by Patryk during his latest round of tile and normal map production. The problem stems from reorienting tiles within the engine not resulting in reorienting their normal maps.

lightReest
Patrick's pretty lil' bug submission image. Notice while the tile is flipped correctly, it's corresponding normal map is not.

Our engine allows our artists to arbitrarily flip and rotate every tile to maximize sheet reusability and minimize our VRAM footprint. Unfortunately the act of rotating a tile affects its tangent vector, which is utilized in the fragment shader to convert tangent-space normal map vectors into world space before being fed into the lighting algorithm. Since our engine deals with a preset number of possible texture orientations on a preset number of planes, I have opted to hardcode these tangent vectors to reduce run-time calculations. My solution here was to create a lookup table of these tangent vectors to be indexed by each texture's orientation enumeration. These resulting tangent vectors are then submitted to the fragment shader as uniforms upon changes in texture orientation.

flipRotTangents
Some of our backers will receive my "devnotebook," which looks like a cross between the manic scribblings of a mad scientist and an insane person.

Unfortunately the act of flipping a tile is not so simple. Not only does it affect the tangent vector, but it also affects the normal vector as well as the interpretation of the normal map. When flipping a tile in 3D space, its normal becomes flipped as well, pointing in the opposite direction. For a colormap, this simply means sampling the UV coordinates in reverse to flip the tile. However, you cannot simply sample a normal map in this manner due to the nature of its representation. Along with a 2D lookup table of normal vectors indexed by plane and texture orientation, I have also had to add special logic to our fragment shader to flip certain channels sampled from our normal map when the corresponding textures are flipped. The results are seamlessly lit arbitrarily oriented tiles in 3D space:

flipRotNormals
ESTk auto-adjusting normal maps, tangent vectors, and normal vectors for dynamic lighting of reoriented tiles.

Dynamic Shadows
Dynamic shadows have long been a hallmark of our engine, yet they were never completely integrated within ESTk. Now they're back, and they are toggle-able along with the entire lighting engine itself. These advanced rendering features can be enabled and disabled to optimize performance while designing content or to emulate the engine running on less capable hardware.

dynamicShadows
Dynamic lighting and shadowing are now run-time toggle-able within ESTk.

Dynamic Level and Area Reloading
First we allowed for the artists to refresh texture maps, normal maps, and specular maps at run-time. Then last week I implemented the ability to refresh shaders at run-time for my own debugging and development purposes. This week our Lua scripter, Tyler Rogers, got jealous of our pristine workflows and requested similar functionality for his scripts. As a result, I implemented the ability to fully refresh levels and areas within ESTk at run-time. This serves to refresh all corresponding Lua scripts. It also prevents us from having to exit out of the Toolkit and reload the entire project every time we pull down the latest assets committed by our team mates. 

levelAreaReload
Fucked up a Lua script and need to reload? I got your back, bro.

Lua Table Inspection, Injection, and Run-Time Debugging
This is honestly one of the most abstract, complex, and difficult software feats I have ever attempted. It has required countless rewrites, filled up several walls in our dev studio, and has consumed many pages of notebook paper... In an attempt to allow artists, designers, and scripters to create, modify, and debug every aspect of our engine and Lua behaviors at run-time without requiring programming knowledge, we dreamt up allowing ESTk to serve as a type of run-time Lua debugger, allowing for the access and modification of every table and attribute maintained by the Lua VM.

luaTableInspection
Don't mind me, just browsing and modifying the entire global environment table of the Lua VM while the game is running.

After nearly destroying myself implementing this bitch (that's what I worked on during the binge, haha), the end result is what we're calling the "Visual Studio" of Lua development. An entire IDE/debugging suite for the Lua programming language. We have an interactive prompt for executing Lua code dynamically at any point during the engine's run-time also serving as a log for interpreter output, displaying errors, catching exceptions, offering stack traces, table dumps, memory usage, and even dumps of the virtual C stack for communicating between Lua and the engine.

luaConsole
Full-fledged interactive Lua interpreter running in-game. Script the game while you play it. Modify behaviors at run-time. Dump and inspect tables. Fuck everything up. Whatever.

The most exciting aspect of this entire endeavor for us is that we believe it will essentially allow ESTk to "write itself." Instead of having to develop specialized widgets for every new component or behavior as they are created, we can simply create attribute Lua tables to be modified through ESTk in this manner, removing any need for us to develop specialized GUIs in the future!

To my team: I'm compiling the new Windows build right now and will have it up on Owncloud within the next few minutes. To inspect a Lua table, use estk.inspectTable(luaTable) in the Lua console. Now go forward, brothers. These features will help you on your journey, because it sure as hell isn't safe to go alone.

Falco Girgis
Falco Girgis is the founder and lead software architect of the Elysian Shadows project. He was previously employed in the telecom industry before taking a chance on Kickstarter and quitting his job to live the dream. He is currently pursuing his masters in Computer Engineering with a focus on GPU architecture.
  • 0FF1C3 N1NJ4

    Putting in some major work… I see you team ES!!! Nothing worth a damn is ever easy to obtain… #keepgrinding we’re riding shotgun with you fellas till the wheels fall off…

    • Falco Girgis

      Hell yeah. Thanks for the support and glad to have you along for the ride. 😀

  • Feashrind

    Great work guys, keep it up. I’m so excited for this game!

    • Falco Girgis

      Thanks, we appreciate it!

  • Travis Haselden

    Would this lookup table be a static member of your texture class? Thanks for the update. These posts really help me gain insight into game engine development.

    • Falco Girgis

      It’s actually part of the libGyro framework, which is written in C. So it’s a static global LUT within the video shader .c file.

      • Travis Haselden

        Makes sense. Thanks for taking a break from binge coding to spread enlightenment.