Showing posts with label opengl. Show all posts
Showing posts with label opengl. Show all posts

Sunday, June 23, 2013

Linux Mint, several hours in

Overall, the experience has been pretty positive.  I took a couple hours fiddling with the system settings, preferences, and all that jazz (of course!).  Of note, I'm now using the proprietary Nvidia graphics driver as opposed to the FOSS version (that was selected by default).  There was noticeable improvements to the rendering/responsiveness speed right away.

I snagged Steam and will be trying out one of my games (X3: Albion Prelude) as it is my *only* game that works on Steam Linux.

I also immediately grabbed some of Nehe's code for setting up opengl programs since I hadn't done windowing/graphics code on Linux in the last decade or so and I've completely forgotten what I was doing and I'm anxious to start porting game engine tech to the platform.

I did crash the window manager once trying to run "glxinfo | grep OpenGL".  To be fair, I think I did this command in a terminal while I was changing the graphics driver... so fair deal.

Firefox was noticeably glitchy and generally unpleasant, so I put Chrome on here, much better.

The only really annoying thing so far I've noticed is that I can't seem to middle/wheel click a webpage in Chrome and scroll around by moving the mouse (like you can in Windows)... so that's kind of annoying.

All in all, if it wasn't for several Windows-only games, I'd probably ditch Win7 completely.  I'm pretty impressed where Linux has come from in the last 15 years or so in terms of the general desktop (aside from the amazing tech fueling the OS itself of course).

Wednesday, May 8, 2013

Game Programming and 2d Art

If you're a game developer, specifically working on 2d games, you will probably want some sort of graphics sooner or later.

Suffice to say, graphics aren't an easy topic for a programmer to really "get" aside from binary values for R G B A.  Yet, for art people, it's all about hues, lighting, perspective, and all that other non-programmer-technical stuff...

Why am I rambling about all of this?  Because if you want to incorporate 2d graphics, you will likely need to interact with artists (unless you're the artist, but you should still take heed!), and likewise, they will have to interact with you... and this is where things can get interesting.

Through some miracle, programmers and artists are working together, but how exactly does all this neat 2d art actually work and get in to a game?  Texture atlases.

Well, let's rewind a bit, the most basic thing is a single graphic.

Now, how you take a single graphic and display it in a game is dependent on your environment, game engine, and all that other stuff.  For the sake of this article, I will not be delving in to any technical examples of how to use any graphics libraries (you won't be seeing any code!) -- I'm more going to focus on *methods* of putting art in to a game.

Now, some programmers might think "methods" and think of programming -- well, reminder, not everyone thinks the same words mean the same things... "methods" can also mean the process of how you accomplish some task... like an artist might use a certain method to create your art, but that has nothing to do with your actual programmatic method used to display that art in your game... or your method of how to implement your method to display the art...

Anyways, back to graphics!

There are some technical issues that you and/or your artist should know right at the get go.  First, some terminology.

Raster Graphics - This refers to graphics that are pixel data.  Stuff like png files, raw RGBA binary data, bitmaps, things that are defined by pixels.  All of this stuff is collectively called "raster graphics".  This is as opposed to...

Vector Graphics - These graphics are a bit more complicated and usually not useful to implement directly in to games.  However, there are some pretty huge perks to having an artist use this format as opposed to raster graphics.  With vector graphics, the artwork is now a collection of mathematical shapes assigned various colors.  This means that, like all math, the original will always remain true, regardless of "zoom level" or how much you scale it; unlike raster graphics which use filters to "approximate" when scaling.

The issue of scaling graphics is complex and is worthwhile to research, but the skinny version is that raster graphics lose quality every time you scale up or down from the original until you will just end up with a blob.  With vector graphics, you can essentially scale up, down, shear, or do anything else to it without losing quality, as much as you want to.

Now, I mentioned vector isn't directly useful to games.  This is true, rendering vector graphics is a massively difficulty task for even today's hardware.  Sure, you could render a couple dozen vector graphics, but you need to realize that the graphic being displayed is generated by math, and if that needs to be refreshed (like during a screen redraw!), it could potentially need to be regenerated; so if the shape is complex enough, it will ruin your game's performance.

Ok, now that we got all that out there, it is really only practical to use raster graphics in games!  Graphics programming is all about using pixel data to feed directly in to some framebuffer, or use as texels for polygons, or things like this.  Someone will need to convert vector in to raster before it can be directly useful in a game.  Thankfully, most (all?) vector programs have an export feature and will allow someone to export vector art (which is flawless!) in to a rasterized version of that art.  What's even better is that you can essentially export to some given scale right away!

I was once confronted with the idea that an artist could "just give me a really large original" from photoshop and then I could just scale it down based on my need at the time.  While this may sound "ok", this is not ok.

Let's talk about graphics scaling some more to hopefully highlight why this isn't acceptable.

We're living in a day and age of thousands of devices, smartphones, tablets, computer monitors, etc.  All of them have different display sizes and capacities (what a nightmare!).  If you want to deploy your game to some/any/all of them, you will need different sizes for all of your art... meaning a LOT of scaling up and down.  But, how do you know what size art you need, or rather, what size would look the best on some given device?

The lazy answer is "just use a big version and scale down", but this actually isn't a good answer at all for 2 reasons.  One, you use excessive amounts of memory/cpu/gpu when you scale it in your game engine.  Two, the scaled version will look much worse regardless if you did the scaling in-engine or pre-rendered the scaled version (ie, you scaled it down ahead of time in gimp/photoshop).

The correct answer is you have to have an exact pixel match for your art to any given display size (read: not feasible).

Anyways, if those 2 lazy reasons don't scare you away, then consider this: scaling graphics up or down too much will always look bad regardless of the originals' size.  I believe the magic cutoff is about 50% up or down before it really starts looking terrible.

Example time.  Let's say I have a 5000x5000 original, which should be considered excessive.  Yet, it does fit the artists' idea of a very large original, and if we can just scale it down to fit our needs, what's the problem as long as we scale it down before we actually use it?

Think like an artist here.  a 5000x5000 original will look absolutely amazing, and the art going in a game should look amazing, so what's the problem?  Well, aside from the obvious memory issue (5000x5000 = 25 million pixels, at 4 bytes per pixel... 100 million bytes to even open that graphic in game!), the appearance will be very terrible if you have to scale it down to something like 128x128.  Go ahead and try it in your favorite raster art program, make a doodle at 5000x5000 and scale it to 128x128 and look what happens, especially around the edges!

Now, this issue is actually more problematic, not only will this scaled version look horrendous, it will actually likely get scaled again when you go to display it in game!  A scaled version of an already bad scaled version will look catastrophic at best.

We could take some less absurd examples, but hopefully you get the idea that a scale of a scale is bad... with larger scaling happening anywhere meaning exponentially bad results.

Vector art sort of fixes this (it's not a panacea though).  The original export will get you a more or less "perfect" raster version at your specified dimensions during the export process.  There isn't any scaling of a raster, there is just a mathematically generated piece of art.  This doesn't work too well with very small graphics (like exporting to say under 32x32ish), so if you're dealing with very small graphics, it is probably best to start doing pixel art.

This generated/exported art will still probably get scaled when it comes time to use in your game and this is the reason why you will likely want various versions of each art asset for different display densities (which is a whole other topic).  Long story short though, you will want to export new originals from the vector art at different pixel sizes rather than scaling your already generated raster art.  The result will likely be much sharper looking art in the end product!  I said likely because there are other steps that can mess up your art all along the way.

Next article I'll cover more about finally putting some of these graphics to work and texture atlases.

Check out part 2

Tuesday, January 29, 2013

Why I didn't use Unity

I was recently asked why I didn't go with Unity when developing games for smartphones.  This answer is a bit complicated and I'll have to rewind the clock a little bit, so bare with me here.

Back in mid-2011 or so when I decided to get in to Android and iOS games, I, like many other people, had to figure out what the "best" way forward was.  A lot of Googling happened.  By a lot, I mean *a lot*.

My background was pretty heavily solidified with C and C++ and I was pretty distraught over the idea that to make games on Android, I'd "have to use Java".  Initially, that was my researched impression anyway... sort of like my initial impression that "any serious and portable game needs to use Unity".

I'm going to skip the side story here on why I decided to develop for Android first here rather than iOS, maybe I'll come back to this in another post.  So, I started dabbling on a "Hello World" program for Android, just to get a basic foothold with what the heck I was doing.  It didn't take long to realize that Android was an immensely complicated and complex undertaking to even make a basic app for.  Sure, the xml, business-like app, was relatively straightforward and easy, but implementing game stuff, using OpenGL, and just drawing something to the screen was not a trivial task.

But, you may say, that drawing anything to the screen shouldn't be too hard; and that was true, until I found out that there are way too many screen sizes, resolutions, densities, and all that other jazz to make any sort of easily designed graphics and retain any sort of semblance of consistency between all these graphical problems.

I had read a couple places that Unity "just works" and my god that would have been nice.  I spent an enormous amount of time piecing together tutorials on how all this worked in the Java world.

Anyways, I always like knowing how things work, that way when something goes wrong, I know why and I can ideally can find a better alternative.  Plus, I was planning on 2d games at this point anyways, so something overly complex like Unity was starting to lose weight here as it was seemingly geared for 3d games -- and possibly 3d games only... though of course you could simulate a 2d game experience.

So, while I had Unity "on hold", I kept plowing through some pretty nightmarish lessons learning about the internal issues with Android.  My first harsh lesson hit when I realized calling an opengl function in java to render a fairly large texture ate 60% of my phone's CPU clock cycles just sitting there idle.  Needless to say, when I tried to play the game itself, the frame rate was horrendous.  The background was killing the game play -- turning that off made my game much more playable; yet all these other games out there in the world don't seem to have this problem -- was it because they were using Unity?

No?  I quickly found out that the *only* real way to make good, smooth games on Android was to use native code.  Thankfully, my C background ate this up.  After a begrudging time "porting" my Java code to native code, the game ran a ton faster, background and all!

So, would Unity have helped with all of this?  Definitely maybe.

So, I finally did crack open Unity to see what all the hubbub was about.  It was completely different.  It takes a much more, uh, designer-friendly approach to making games.  You can drag and drop files in to its project file system and things just load for you -- which is a true godsend as that code in my own engine (yes I ended up making my own portable engine) took a long time.

I see that to make things more game-like in Unity, I more or less have to (or at least should) use C#.  Now, I'm not a master with C#, but I have a couple production level projects done with it, so I can dust that skillset off and start working with it.  Right away, I'm almost devastated with some of its inefficiencies that reminded me immediately of Java on Android.

Right away, the fact that C# *forced me to instantiate new Vectors* when I wanted to manipulate thing's locations made me sick.  This will be happening a whole heck of a lot in games and in code, object instantiation, even on something simple like Vectors, will translate (haha, pun) to a lot of wasted CPU time.

Though don't get me wrong, I was very impressed with the "all in one" idea and visual aspect of Unity.  I loved the idea of "attaching" scripts to objects and I didn't have to worry about writing complex update functions, or render threads, or even game state objects while accounting for time deltas to make my game frame rate independent -- nay, all of this was taken care of by Unity; which *really* could speed up development time of any game made using Unity.  The only trade off now is that I'd have to trade in my freedom of design to make only whatever I could using this cookie cutter engine thing.

Unfortunately for game programming, part of the job *is* to do exactly those things that Unity does for us.

For example, in my own engine, I recently finished code to analyze an arbitrarily large array of pixel data.  The code would then "find" the bounding boxes around all graphics found in the pixel data.  The idea here is that it would automatically find all objects so that I can use them as textures in my game via a texture atlas.  Doing this in C# and Unity, though possible, would likely take a much longer processing time to accomplish.  Even using unsafe code.

Don't believe me?  Ok, that's fine, but remember that C# compiles to an Intermediate Language similar to Java, and that adds extra processing overhead at runtime.  Additionally, if you use unsafe code in C#; you're throwing one of the main reasons why you're using C# out the window.  Additionally, the .Net/Mono framework, again like Java, has to make assumptions about your code; usually trading performance for accuracy.  While this is usually A Good Thing (tm), in game development this can be a disaster wrapped up in the inability to be explain why "your game runs like garbage and nobody knows how to fix it".  For example, not all Android devices have a floating point unit.  Yes, that's right, no hardware floats.  Meaning your game is going to run like terrible.  In C/C++, I can detect this lack of FPU then use function pointers to perform binary coded decimal (fixed) operations using integer operations instead of floats.

In a 3d game, like many that would be made with or without Unity, this has massive implications in terms of performance.  If you try to use ANY floats without a FPU (especially multiply or divide operations), the device will use an fpu emulator of sorts and that is *not* something you want happening when trying to render at 30+ frames a second for any sizable amount of vertex data.

While this sounds like a headache, and believe me it is, this would be difficult and maybe even impossible to avoid with C# or Unityscript (javascript gone Unity).

Fast forward a bit of time and we've released 2 fairly "simple" games on Android, 1 of which was ported to iPhone.  The development process had a lot of bumps and rocks in the road.  Unity probably would have saved me a ton of headaches, but I'm still glad I didn't use it.

I now have a portable game engine that works on both Android and iOS using C and now I can just drop my game logic code in to this engine, regardless of platform, and it just works on both.  For fun, I even have a windows port of my games now all using the same code.

Is my way easy?  Definitely not.  Is it visual?  No.  In fact, on several occasions I ended up diving through zlib and libpng's source code to track down errors (all of which were my fault of course).

If I had to do it again would I use Unity?  No.  While the initial development costs would likely be less and the technical requirement of a programmer be eased, games demand optimized code.  Especially games in constrained environments.  Yes, phones and tablets are getting to be powerful and everyone "should" be getting new phones every year, but the reality is, that isn't the case.  In fact, even as of this writing, I believe most people using Android are still using Android 2.x.x and on phone models over 2 years old -- of which a sizable portion still don't have fpu's!

Which brings me to another side tangent.  Let's talk about math.  Even in 2d games, a decent amount of math is going to be coming in to play.  Even on devices containing FPUs, there can be substantial math involved with games and they will be using a lot of floating point math.  I ended up implementing a very "hackish" version of various math functions to speed them up (square root comes immediately to mind) due to the frequency in which they are called.  I got an extra couple frames per second using my hack versions of these functions.  Mind you, in something like Unity, not only will you likely NOT be using things like this, but you will be getting in to forced object instantiating issues on top of the raw math.

Next, let's talk about memory.  Doing naughty things in C and C++ have been known for a long time, and in C# you can do some dirty things also using unsafe code.

I can't stress enough that if you're using C#, you should be running unsafe almost always when making games.  Which sort of goes against one of the arguments for using C# in the first place.

I should probably also talk about garbage collection and managed memory.  In short, C and C++ don't have these issues -- for better or worse.  In games though, I can't stress enough that these things are not your friend.  I will have to have a whole other article on just this topic I bet.

Anyways, I finally also ended up googling for "pros and cons of unity".  There was some pretty thought provoking stuff and a lot of "eh, works for some, not for others"... and I kind of have to agree with that position.  I will also admit here that because I'm more comfortable with C and C++, that was also a big sway against Unity for my personal situation.

I'll wrap this lengthy post up with: so, is Unity for you?

Probaby yes if:
* you already know Unity
* you have an extensive background in C#
* you want a streamlined design/development cycle and don't mind the tradeoffs
* you "just want to make something"
* you want a job with a company that uses Unity (for whatever reason)
* you have little programming experience
* you can afford Unity

Probably not if:
* you already make games for computers/consoles with C/C++
* you are a programmer with a lot of programming experience in general, including opengl
* you like working extremely long hours, scouring through library source code, love the idea of squeezing out an extra second of performance per update cycle
* you are comfortable with command line interfaces and your own version control
* you like managing your own memory
* you want to make any kind of game with any sort of capacity you can imagine
* you can handle your own portability issues
* you can't afford Unity

This was a quick brain dump of my experience with Unity and my own development issues for games on Android and iPhone/iPad.  Hopefully this helped some people, or at least got them to rage a little bit about something.  I'm probably not 100% accurate on everything stated above and I'm more than happy to hear out people's input where I'm wrong.

I will likely get more in-depth with a lot of things mentioned here in another post later reinforcing my position, so stay tuned if you're in to that sort of thing, but I warn you, it won't be pretty.

Thursday, March 29, 2012

Android NDK loading resources and PNGs

After following the nice code sample from http://androgeek.info/?p=275 about how to load a PNG file by accessing the Android APK file directly using only the NDK, everything seemed awesome.

It uses libzip and libpng to manually load the APK, then load a png file right from the APK itself without using any Java or the Android SDK.

Why would you want to do this?  Well, aside from liking complicated stuff, it is useful for us because now we can put all of our "portable" resource loading code in c/c++ files so it is more easily moved to iOS, windows, whatever, without being bound to using only the Android SDK, thus having to recode loading logic over and over again for each target deployment architecture.

Everything worked well, until something didn't go quite right.  Some of my textures were corrupted and worse, some actually crashed my app!

It took 4 days to track down what exactly was happening.

Common problems usually indicate I was doing something wrong with opengl and the textures themselves...

* All my textures were perfect powers of two (64x64, 128x128, etc)
* All my textures were 32-bit RGBA files
* I fixed a warning and error from the given sample code to correctly read the libzip'd apk file

So, it was time to dig deeper with what was going on.

First, I noticed that my glGenTextures calls were giving me very large opengl texture ids so I thought this was a huge problem as it was not continuous numbers, and in C, any time you have generating wild numbers, it usually means a bad pointer somewhere.  I spent about a day analyzing and referencing code and started to realize that the generated numbers were always the same (this usually rules out a memory corruption issue if the results are *always* the same).

I noticed that the generated opengl texture ids always followed this pattern on my Droid RAZR:
100271
315638026
534244737
1505553200
-1563003837
...
etc.

Yet, on my Android emulator, the texture id's were:
1
2
3
4
5
...
etc

I had found this thread on google groups that I thought was my problem since it sounded really similar, but it didn't actually help.

Knowing that glGenTextures expects an *unsigned* integer as the data type, I realized that the negative number was an overflowed signed integer and actually nothing to worry about.  In my debugging print code I needed to change "%d" to "%u" to see the actual unsigned value.

Since these numbers repeated on every subsequent run of the program, I decided to test the idea that maybe my code had nothing at all to do with the "corrupt" large texture ids.  Indeed, I made a program that literally only called glGenTextures about 100 times right at startup time and did nothing else.  The result?  The exact same large numbers showed up in my device, and was "normal" on the emulator, as expected.  This left me with the conclusion that whatever logic is in my Motorola device in terms of picking a unique texture ID that this was normal - next.

Yet, this didn't answer my question as to why I was seeing an app crash occur and seemingly only when loading a certain texture or two.  My first order of business was to rule out if my other code was at fault, or was it somehow related to ONLY those sets of textures (somehow). Strangely, dozens of tests indicated that it was only the problem of 3 specific textures being loaded as I added lots of additional textures, even loaded some textures multiple times, then finally ONLY loading one of those 3 problematic textures.  The app would only crash at loading any of the 3.

Frustrated, I ended up putting a ton of extra debugging code all over my apps trying to track down what in the world was wrong.  All indicators were pointing to the idea that a problem was with either libzip or libpng since libc.so itself was crashing in a call to a libpng function -- great, time to track down potential bugs in those libraries.

Now, let me put a disclaimer up here, it is almost never a good idea to assume a mature code library has a bug in it; especially one this severe, yet here I am with a consistent crash always calling a specific line of code that libpng was using leaving me to believe this could be the case.

First, I downloaded the most recent version of each library and replaced the old versions that were provided in the linked post above.  I was now using libzip 0.10.1 and libpng 1.5.9.  This had promise since each of those had a bit of fixes/enhancements along the way.  I was hopeful that this would magically fix my problems.

Well, it did - sort of.

Whatever wizardry was happening internally in those libraries helped indicate that libpng was crashing specifically on this line:

png_read_info(png_ptr, info_ptr);

Great, all this work only to help reinforce the idea that libpng was broken for my special case.  Yet, I still couldn't rule out that libzip somehow corrupted my image data while decompressing my APK so libpng might not be at fault trying to load corrupted data.  Worse, all error checking came up empty for all libzip and libpng calls!  I even checked my opengl calls for errors using glError -- NOTHING!

Well, the next step was to dive in to those library's source code and start tracking stuff down, the last resort I guess was to find the problem in one of these libraries and fix it myself and give the respective team a patch!

One of my testing tangents included making a stand alone C project to test very specific sets of code to completely rule out any Android Java JNI mysticism causing problems.  Everything was pointing to only those textures being a problem in the libpng loading code.  So I ran the libpng test program on those 3 test pngs and the only thing that sounded remotely threatening was:

Files aaaa.png and pngout.png are different
Was aaaa.png written with the same maximum IDAT chunk size (8192 bytes), filtering heuristic (libpng default), compression level (zlib default), and zlib version (1.2.5)?


It certainly sounded menacing and I was convinced that somehow my textures were corrupted.  I ended up regenerating those textures using the latest version of Gimp (2.6.11 at the time) -- plugged those in to my app in excitement; and they still crashed.

Strangely, the libpng test program generated pngout.png which was seemingly the same exact copy of my original texture, but a different filesize; something was different, and different was good at this point.  For giggles, I put that pngout.png file in to my Android's APK res/raw folder in place of my original texture and much to my surprise the texture loaded!!!  Ah-hah, the answer finally!

Unfortunately, things weren't over yet, the texture loaded completely corrupted.  Everything was misaligned, the colors were wrong and the texture was completely garbled with random colors all over it.  Basically, I've gone nowhere.

3 days in and I'm still struggling with what is wrong here.  I'm still baffled, why is it that my 10 other textures work fine, yet these 3 don't want to work at all?!  I decided to write my own texture loading function from scratch to ensure I understood exactly every step of logic that was taking place.  The same result happened.  I did all sorts of strange additional tests, hex dumps, you name it.  I was at the end of my rope on this one, I was getting angry.

Finally, I saw an interesting article somewhere that said I needed to rename my png files to mp3 files.  I thought to myself, that's the dumbest thing I ever heard - why would I ever want to do that?!  Well, if you're programming for Android, you might be crazy enough to hear this out.

Apparently, during the APK packing process *SOME* of your png textures are automagically compressed and others are not.  Renaming your png files tells the apk packing process to not mangle/compress that file, and my happy 3 textures were some of the lucky selected ones for this process; which completely broke the texture loading code.  In a move of desperation, I did rename my files to mp3 to verify this was the case, and they worked perfectly.  I was enraged and ecstatic at the same time.

On the bright side I got a better understanding of both libpng and libzip (we got a little familiar with each other, if you know what I mean).

Alright, so the magic bullet answer is that I need to rename all my PNG files to MP3 (test.png.mp3 if you will) or simply dump them all in to a game data file of sorts (probably the better idea).

So, I make a quick resource packing program (using zlib) and I find out that during the APK packing process again, my GZ files are also modified!!!

I quickly found this link explaining it a little bit.

I wonder what other goodies are in store for me to discover by accident!?

Hope this article is found by anyone else stuck in my situation and save you all a couple days of madness.