Thursday, 7 May 2015

Self-Reflection Sit-Rep

It's been almost 2 months since I began this blog, and I've evolved from feeling blue to feeling introspective. We've had some fun, we've had some laughs, and we've o so much ranting. But now, it's time to sit back, gaze upon our work and think to ourselves "...What was I thinking...?"

Let the introspection and self-reflection commence!

Disclaimer

Let me start off by saying that any praise I give for myself, is tempered by the fact that I made mistakes more often than I succeeded. I like to consider myself a genius, coding savant, but the truth is that I'm really... not. I've only been at this for a few years and I'm full aware I'm not the best. I have a lot more to learn, and so many areas I need to improve in. So if I come across as arrogant and smug, just know that I'm being facetious. Every good point I raise should be taken with a fistful of salt.


AI

So the first task I tackled was AI programming. This was an aspect of coding that I was always interested in, and it's actually the reason I began programming in the first place. Trying to simulate thinking, breathing human behaviour inside a computer fascinated me. That being said, I had never actually tried to program a proper behaviour algorithm before. So trying my hand at programming AI for bots in a fully-automated tournament seemed like an exciting challenge.

Having said that, however, I think I handled this particular discipline of coding rather well. Although I had never programmed a specific AI system before, I had tried my hand at basic behavior algorithms; collision avoidance, chasing targets, Finite State Machines and the like. In particular, the actual mechanics behind the high concept of 'Heuristics-based pathfinding' was much easier than I had first thought. I was worried that this would be the most difficult aspect of AI, but the dynamic list creation and iterating thorough multiple custom objects was something I was very familiar with. Overall, I believe that having prior understanding and knowledge in how to achieve these algorithms allowed me to progress in my code much more smoothly than I would have otherwise fared.

The downside was, as always, over-scoping and poor time management. I had originally planned to do so much more in the field of AI, including the implementation of a fairly complex finite state machine that enabled / disabled specific AI sub-routines. This concept came from my research into GOAP, and I had planned to create a simplified system that still followed the same basic principles of GOAP. Unfortunately by the time I had managed to perfect my A* pathfinding, my time had run out. I was forced to quickly cobble together a basic FSM that selected the next pathfind destination, and that was all; a farcry from my original vision.

The silver lining here is that this error was not very significant in the grand scheme of things, and only occurred in the first place due to my relative inexperience with AI. Now that I have a much better understanding of what I'm doing and how to get the code working, the time it takes to complete each individual task should be considerably shorter. If I was to try something like this again, I'm confident that I can get more done within the same timeframe.

Game Dev

The other major task I must ruminate upon is the Game Development Project, in which I and several others collaborated to create a game. I was in charge of basic game-play code (movement, collision handling, items, etc), as well as graphical effects; namely the god ray shader. I had originally assumed that developing the scripts in Unity, seeing as how I was familiar with c# and had used Unity's system before. This would have been true had I opted to develop things properly, and not half-heartedly decide to use the Rigidbody physics in conjunction with everything else.

Oh boy, what a mistake that was. In hindsight, I have no idea why I decided to develop ALL game-play related code based in the physics simulation. I seem to recall thinking that since 2D platformers involve gravity, using physics within the code was the logical choice. Of course I realise now that this was definitely not the right way to go, and in future I'll be sure to take note of this valuable lesson.

Now, he shader part of my involvement in the project was very good. As I've stated before, I'm rather proud of what I've managed to achieve with the limitations of Unity Free. I don't think I need to reiterate the positive aspects of my work, and if you, o reader, require a memory refresher you can refer to my earlier blog posts.

However, this is not a self-reflection of the work I did; this is a self-reflection of how I approached the work I did. And i this regard, I may have made yet another mistake. You see, because I was so enveloped in my own work, I sort of uh... neglected, my other duties. I worked on the code within the shader for 4 days straight, barely sleeping or eating. This attitude and style of work was fine in previous projects; since they were solo undertakings, the only consequence was the delay in schedule. Howe3ver, as part of a team I was responsible for keeping in communication, remaining update on current progress, and being available for assistance in various other tasks.

Obviously I failed to tick off any of these requirements, and this I can only attribute to may lack of experience working in a group. Because I am usually only involved in solo projects, I am not accustomed to contantly communicating with others whilst developing. This is something I can only improve on with experience, and I can only attain this epxerience by participating in more group-related projects. However, I will try to keep this aspect of teamwork in mind when a similar opportunity arises once again.



The End

So there we have it, my thoughts on how I behaved during the past 2 months. Overall, I'd say my work ethics and attitude was up to standard, despite the occasional slip-ups. I will make it clear that whatever the mistake was, it was not made intentionally. I approached things with the appropriate attitude, I worked on my tasks diligently, and attempted to assist my development team in any way I could. So  I suppose all the errors, at the end of the day, can be chalked up to inexperience and naivety; I arrive on scene with the right mindset, but I simply do not know enough and have not experienced enough, to get the job done perfectly. It will take time to get it right, but I think that being able to recognise 'I am inexperienced' shows I'm on my way to improving already.

Monday, 4 May 2015

Good News or Bad News?



The past week has been... tumultuous.

On a scale of 1 ~10, I've had a really good moment that brought the week up to 8, only to be followed really bad things that drop it down to 2. At the end of it all, I am currently sitting on a solid 5, a very half-hearted "meh". If you'd be willing, o reader, I shall regail to you the sad sorry tale that is my life so far. Starting with the good news, since I'm such a cheerful optimist.



The Good News

I finally managed to get a God Rays post-processing shader working in Unity, using nothing but the tools and functions available in Unity 4 Free Edition. In the beginning I thought it would be a simple task; simply render the scene to a render texture (a feature that very much exists in Unity), apply a hand-written shader effect to it using Unity's built-in custom shaders, and voila! Pretty visual effects! Of course, I'd failed to read the fine print that stated all this was only possible in Unity Pro. Therefore, I had to get creative.


1. Capture the entire screen display into a texture

 This process is, conceptually, identical to rendering the scene into a texture. The key difference is in the method; 'capture the screen display', not 'render the scene'. Because render textures were unavailable, I was forced to perform another function that produced similar results: ReadPixels. I talked about how this functions works previously, and how expensive it is... No kidding, I'm forcing an extra draw call to be performed entirely by the CPU. I managed to optimise it by running the function in a sub-routine thread, but using this technique still dropped the FPS from 120 to about 50. It pained me, but it was necessary.


The worst part is nothing has seemingly changed (-____-)


2. Run Shader Pass A: 'Occlusion'

Once I'd managed to somehow cobble together an image I could work with, I began my work on actually writing a shader to edit this screenshot texture. The good news here is that Unity's shader language, Shader Lab, supports multiple render passes in a single draw call. This made it much easier for me to layer the separate effects I needed to achieve my end goal of God Rays. Now, the first thing one needs to create a God Ray shader is to create an occlusion pass; essentially, draw every object in the scene as solid black. this allows us to represent everything that will be blocking (occluding) the light as it shines through.

Achieving this in a shader is, to be honest, a cakewalk. Simply sample the base texture, and for every pixel that has an alpha value, render black.


Finally, some visible changes!


This method relies on the fact that the screenshot / render texture will, when drawing the scene, only modify a pixel if it sees that an object occupies that pixel space. If an object exists, it will be rendered to the texture (alpha = 1.0); if not, the render texture will not edit the pixel in any way and leaves it blank (alpha = 0.0). Therefore, if the sampled pixel has an alpha value it must mean there is an occluding object occupying that pixel space.


3. Run Shader Pass B: 'Lighting'

Once the occlusion pass was in, I wrote the next block of shader code: lighting. This is just the simple 3D directional lighting technique used in all languages, so I won't go into too much detail about it here.It should be noted though, that I wrote the standard vertex-based lighting model from scratch. Since Unity already has the phong shading and blinn shading models built-in, it may have been easier to use those instead of writing a model myself. However, as with all pre-built code I dislike not knowing how the logic flows internally. As such, I felt more comfortable writing one I knew would work than trusting Unity.


I see the light! Hallelujah! 


4. Run Shader Pass C: 'Blur'

Last but not least, the radial blur. In order for to simulate the God Rays effect, a radial blur is applied to the whole texture with the blur originating from the light source. Or more accurately, where the light's position is in screen space.  This involves passing in the light's position in-game and translating that into screen space, disregarding the z-pos since we are working with 2D textures. Once the light position is found, we set that as the origin for a radial blur that decays in strength the further from the origin. Something along the lines of:

void main()
{
 pixel_position = texCoord[0];
 delta_pixel_position = pixel_position - light position;
 color = renderTexture.sample(pixel_position);
 
 for(int i=0; i < NUM_SAMPLES ; i++)
 {
    pixel_position -= delta_pixel_position;
    new_sample = renderTexture.sample(pixel_position);
    sample *= godray_strength_decay;
    color += sample;
 }
 
 color out 
}

This site also helped.

 ...It's... it's so pretty...!


I'm rather proud of the results to be honest, and I'll more than likely use the technique again in future.... Actually, no I won't. In future I'll just use an engine that has render textures to begin with, save myself the numerous headaches. I briefly talked about some of these headaches previously, so I won't devolve into another rant here. Needless to say, I still very mush dislike working with Unity. if it weren't for its layout and the relatively intuitive component system, I'd never look at it again.



The Bad News

...Aaaand here comes the downside. So as you can imagine, when I had completed this wonderful project of mine I was ecstatic. I was cheering, I was laughing, I even did a little dance. Best of all, this tech that I had managed to complete was to be displayed to the public in a Games Exhibit! I could see my work proudly displayed, and people would see me for the genius, coding savant that I am!

"This calls for celebration!" I thought, "break out the liquor!"


...Yeah.

Two shots of Tequila and half a bottle of Whiskey later, I awoke to find that the whole world was constantly spinning and my legs had transformed to jelly overnight. I could barely walk without feeling nauseated, let alone making it to an exhibit on the other side of town.

Sigh.

It really is my own stupid fault, and that's why I'm feeling rather blue at the moment. I had a wonderful opportunity to see my own work on display, and I miss out on it being a drunken idiot. I can only hope that the exhibit went well and I didn't screw everyone else over by not being present for the preparations. My apologies if I did.


I think I'll quit drinking.