Social Media Icons for Game Developers
I'm working on a few parts of the Wolfire site and one thing that I've been wanting to do for a while is change our list of social networking sites from a laundry list of links to a more friendly group of icons. Sort of like how the amazing DanLab has his set up on the DanLab blog. Fun fact: DanLab made the original design for wolfire.com in exchange for some programming help from David. He is a very talented guy.
It sounds sort of trivial, but I suspect that having icons instead of text will bring more attention to these sites and cause more people to join them. As I mentioned earlier, these sites are actually the most important way people are finding out about us and they work better as more people join them.
Social networking icon sets are absolutely everywhere on the internet, but unfortunately these sets are often not game developer friendly, omitting the important ModDB and Steam. So I asked Iiro Jppinen if he had time to hook me up with some cool icons, and the next thing I knew, he sent me these on Skype!
Feel free to add them to your site. :) It would be nice to mention Iiro somewhere if you do though. If you need any other sizes or other sites, let him know in the comments and he will see what he can do!
Physics Editor ~ Part I
The latest toolset I've been working on for Overgrowth is the physics editor. There are three big pieces to this, and each is now well underway. First, users need to be able to make and manipulate simple physics primitives (such as boxes, capsules, and spheres) that can be inserted into the Overgrowth physics world. Second, we need tools to link these primitives together with joints. And third, we need a way to attach models to the newly formed physics bodies (model rigging). We will go into more detail about each of these steps a bit later, when our tools are more polished. For now, I'd just like to demo some of the fun physics things I've been playing with:
Click here to watch it in HD!
One cool thing about the physics editor is that it will also serve as the back-end for our animation editor. This will ensure that our animations are part of the physical world and can thus react to impacts and uneven terrain.
Do you guys have any questions or thoughts about the video?
Black Shades iPhone Breaks 1000
Wolfire's first iPhone app, Black Shades iPhone, recently broke 1000 sales on the App Store. It's been an interesting journey and in the spirit of open development we thought we'd give you a look at how BSI has been doing.
The graph above shows the BSI sales we've gotten each day since launch. We had a decent start but never made the Holy Grail of the iPhone: the self-sustaining "Top 100" list. So sales tapered off, getting stopped completely for a few days when our account was being transferred. Since then, sales have been modest but continuous. The peak at the end occurred when we got a shout out from Offworld on their list of recommended iPhone games.
The chart above shows cumulative sales over time and illustrates our steady ascent into the land of quadruple digits.
It's easy to get sucked into all the miracle app success stories. However, Simon Carless, Chairman of the IGF, and editor of both Game Developer Magazine and Gamasutra, gave developers a nice dose of reality at the GDC 2009 Indie Games Summit this year. You should definitely check out his slides (slides 22-25 refer to the iPhone).
Simon said that as of March, the app store was averaging 27 new games per day -- that's a lot of competition! He also estimated that 90% of iPhone apps only sell about 200-1000 units, with 7% selling 1,000-5,000 and only 3% are selling more than that. So by this measure I guess we've just made it into the top 10% :) .
Given that BSI sells for 99, it's not exactly a huge success story like the iFart app and other apps highlighted by the media. However, Henry Kropf, the man responsible for porting Black Shades, said he'd console us with some Subway Sandwiches.
It's been an interesting experience and though we don't have any immediate plans to make more iPhone apps, we now have some insights on what we can try differently next time. Do you guys have any questions about our iPhone experience or iPhone development in general?
How to make a seamless tiling texture
What are seams?
Tiling textures are much more efficient than unique textures, which is especially important for large objects. The main cost of this efficiency is that tiling textures can look unrealistic when used incorrectly -- real rocks are not made of repeating tiles. The tiling is most obvious when there are distinct details that repeat, and the worst kind of distinct detail is an edge seam -- a sharp discontinuity between the tiles. Here is an example of a tiling rock texture with seams (highlighted on the left, but still present on the right).
How do we remove seams?
First, let's get our initial texture (with seams). For photosourced textures, I usually start by getting a photo from CGTextures.com, and cutting out a square. I pick an area that looks fairly uniform.
I paste that into a new file, and then use the 'offset' filter to expose the seams. The offset filter lets you shift the image over in a way that 'wraps around', so that the pixels that go off the right edge show up on the left.
Now that I've offset the image by half its size in each direction, the seam shows up as a cross through the middle of the image -- you can see it clearly if you click the image below. I then pick a soft brush, and paint out the seams using the clone (rubber stamp) tool. The rubber stamp tool lets you paint pixels from one part of the image onto another part.
Here is the texture after painting out the seams.
That's really all there is to basic seam removal. Here is the final seamless tiling material in the engine:
This could still use a lot of work though. Even without seams, the tiling is obvious because of the features and colors in the texture. For example, there is one dark shadow underneath a rock which is obviously repeated over and over -- if we end up using this particular texture in the game I will have to fix that! When making tiling textures, we have to walk a fine line between making it tile invisibly, and making it visually interesting.
How do we test tiling textures in the Phoenix engine?
There are a few more details you'll have to know to make tiling texture blocks like this in Phoenix (in the Overgrowth alphas). First you will need to add a normal map and specular map to take full advantage of the lighting system. If you want, you can just use the default 'diffusebump.tga' texture and skip making a normal map, but I'll explain how to use normal maps for anyone who is interested. You can make a decent normal map from a color map very easily using CrazyBump. If you don't have CrazyBump there is a free Nvidia plugin that works in Photoshop.
You will also probably want a specular map (showing how shiny the texture is, from black [matte] to white [chrome]). If you don't want your texture to be shiny at all, leave the alpha channel black. To make my specular map I just grabbed the one calculated by CrazyBump, but you can also just use a darker desaturated version of your color map. Here are the color, normal and specular maps for this texture.
To use fewer textures, Phoenix uses the alpha channel of the color map to store the specular map. To do this, you have to make sure your color map has an alpha channel, and then copy your specular map into it. Here is the 'channels' panel for the color map in photoshop, with the specular in the alpha channel.
Now you can export both the color/specular map and normal map as .tga files, and create the .xml object file to load them in the game. The easiest way to make this file is to copy an existing block object .xml file and just edit the paths to the textures. Here I copied "blackCatRoad.xml" file and edited the
<Type>generic</Type>
<Object>
<Model>Data/Models/box.obj</Model>
<ColorMap>Data/Textures/Buildings/Tiling/GrayRock/GrayRock_color.tga</ColorMap>
<NormalMap>Data/Textures/Buildings/Tiling/GrayRock/GrayRock_normal.tga</NormalMap>
<ShaderName>cubemap</ShaderName>
</Object>
Now I can just load my block in the engine and make walls or floors or whatever I want! My first attempt came out too bright because the specular map was not dark enough -- a bright color map with a bright specular map will just get washed out like this.
I fixed it by just darkening the maps a bit.
Although it seems like a lot of steps, adding materials to the engine is really not too hard. If anyone uses this tutorial, it would be cool to see image links in the comments!
How to project decals
We've been talking a lot about decals recently, showing off our editor and explaining how the shading works. However, we haven't explained how the decals are actually projected geometrically onto complicated objects. We've been getting some questions about that, and I remember how hard it was to find information about decals when I was getting started, so here's an overview of the decal projection algorithm I created for Overgrowth. Let's start with this scene here.
It's a bit too clean for me... I want to add a decal to give it some subtle weathering. To place a decal, I need to first set up the projector. The projector is just a 3D rectangular prism with three properties: size, position, and orientation. Of these, the orientation can be the most confusing. For decal projectors, I represent the orientation as an orthogonal basis, which is a set of three vectors that are all perpendicular to each other. For example as the XYZ axes form an orthogonal basis, as do 'forward', 'up', and 'right'. This gives us a complete orientation in 3D space, and is easier to think about than matrices and quaternions.
The secret to projecting decals is to not think about creating a mesh that conforms to the model. Instead, think of it as starting with the model, and cutting away everything that is not in the projector box. I found that thinking of the problem like this made it easier to figure out what to do. Let's start by checking which triangles in the scene intersect with the decal projector. I first implemented this in a brute force fashion, and once that was working, changed it to work hierarchically using octrees [to bring the runtime from O(n) to O(logn)].
Next is the hardest part: we have to crop the triangles so that they don't extend out from the projector. Why is this important? Think about firing a thousand machine gun shots at a wall that is made of just two triangles. If we don't crop our bullet holes, we will have to draw the entire wall a thousand times! Since the wall is so much bigger on the screen than the bullet holes, this will use up too much fillrate, and bring the framerate to a crawl. However, with decal cropping, I can do this and maintain maximum framerate!
So now that you're convinced that decal cropping is important, how do we actually do it? Cutting arbitrary 3D triangles to fit in an arbitrary 3D box is a daunting task. To make it easier, I thought about it in 2D. We can transform the triangles from world space to projector space, crop them, and transform them back. This makes the problem much simpler. In projector space, the projector box is just a square from (0,0) to (1,1), like this:
A triangle in projector space might look like this:
So now all we have to do is crop the triangle to fit in the square. This seems like a tricky task itself, but we can break it down even more. First, we can start with one border at a time. Let's pick the left border. To crop the triangle, we start by marking every vertex in violation of the rule -- in this case, the leftmost one. Then we look at every line between a marked vertex and an unmarked vertex, and add a vertex at the point at which it crosses the border.
We can then simply remove the marked vertex (or vertices), and move onto the next border.
Once we've checked all the borders, we have a cropped triangle!
After doing this for every triangle, and projecting back into world space, we have a cropped decal mesh.
If we keep track of each vertex's coordinates in projector space, those are also the projected texture coordinates! That's why I set up the projector space to be (0,0) to (1,1) -- that's the range that OpenGL uses for texture coordinates. Here's what the decal looks like using those texture coordinates on a test texture.
Now we can just substitute in our real decal texture, and we're done!
Here's the original camera angle with the finished decal applied. It's a pretty subtle effect, but I think the extra detail helps make the damaged area look more realistic -- nothing would be able to take a huge chunk out of that block without scuffing up the surfaces around it.
So that's an overview of how decal projection works in Overgrowth! If you're not familiar with linear algebra, you might be confused about how to transform triangles from one space to another, and why it's important to have a complete orientation. I could write a blog post explaining vector spaces and transformations in game development terms, but I'm not sure if anybody would be interested. Do you have any other technical subjects you would like me to talk about?