Tuesday, February 18, 2020

Ridiculously cheap depth of field effect for lines

I'm working on PewPew's sequel, for which I've revamped the graphics.
Instead of drawing lines directly using OpenGL, each individual line segment is made up of two triangles whose vertexes are computed with shaders. Getting lines in 3D space to be properly displayed on a 2D screen is not trivial. In PewPew's sequel I use the screen-space projected lines, a technique very well described in the Drawing Lines is Hard post.

The upside of drawing the lines yourself is that you are fully in control, which allows you to implement nice things such as joints, perspective, and even simulate depth of field.

https://en.wikipedia.org/wiki/Depth_of_field

Usually depth of field (DoF) in video games is implemented using a post-processing step that blurs the pixels with an intensity that is a function of the depth of the pixels. When we are rendering lines, we can approximate DoF directly when rendering the lines by having the vertex shader increase the width of lines and reduce their opacity proportionally to the distance they are from the plane of focus.
Left: without DoF
Right: with DoF

On top of that, we can make the lines appear blurry by adding a gradient along the lines in the fragment shader.

Left: DoF with sharp lines
Right: DoF with blurred lines

As long as there are not too many overlapping lines, the whole effect is very cheap in terms of processing power and runs very well on mobile devices.
In addition to that, it also properly handles transparency (unlike standard post-processing based DoF), which in the case of PewPew is very important since almost everything is rendered with additive blending.

Possible improvement

The technique does not work well when one end of a line is in the far plane while the other end is in the near plane. In that case, because the shader interpolates between the two ending of the line, the center will be wide and with a low opacity while it should actually be narrow and crisp.
I reduced the impact of this problem by splitting the geometry.

Sunday, April 21, 2013

Pacifism

So!
Since my last post I got a new awesome job and thus worked less on PewPew and Rollin' Droid. An update for PewPew is in preparation though. It will feature basic maintenance stuff (iphone 5 support, sound improvements, small optimisations, etc...), and more importantly a new game mode:

Pacifism

It is inspired copied from Geometry Wars' Pacifism game mode, and even in its unfinished form it's really a lot of fun. It will be available only in PewPew 2 when you finish the 3rd Campaign (in any difficulty).

Concerning Rollin' Droid, I've expanded my ambitions and need to re-do a part of the engine because I feel that my creativity is limited. I can't simply think of a feature and quickly implement it like I could do in PewPew. The hard part about RD's engine is that I have randomly generated levels that are potentially infinitely wide and height so I can't just alloc enough memory in advance. Also, I absolutely want to maintain 60 fps with no hiccups when loading a new area, so I have to create and stream it chunk by chunk to the GPU. To top it off, I can only use integer to have a deterministic game because I want people to be able to replay each other's games across different CPUs.

Monday, September 3, 2012

Rollin Droid

I have been working on prototypes for games for a while now. I tried doing:
  • a game where you rotate a shape and avoid projectiles
  • a game where you race in between planets
  • an isometric-real-time-chess game on an infinitely large board where you move a knight
but there was always something in the gameplay that didn't feel right.

Luckily, after playing Line Runner I finally did a prototype that deserved to be turned into a complete game. Line Runner is incredibly addictive, but there are several things that I would have done differently:
  • the player isn't allowed to make mistakes: one mistake and it's an immediate Game Over.
  • you play on a horizontal line. It would be better if you could move up or down.
Here's what Rollin Droid (my interpretation of Line Runner) currently looks like:


During the development I realized that I could implement wall jumps which allowed players to climb up tunnels and change direction.
Wall jumping unfortunately creates a big problem: if the player mistakenly wall jumps somewhere he's not supposed to, he ends up going in the wrong way and is very frustrated of not being able to change his direction until he finds a place where he can wall jump again. This problem isn't yet entirely solved, but can be mitigated with smart level design.



The main character is a little bugdroid that skates and collects donuts. In the game, he's a ragdoll animated using box2D, so his body/head/arms/accessories correctly reacts to his movements :-)
I doubt Apple would be very happy if I released the game on the App Store with a bugdroid as the main character, so the game on iOS (and the other non-android OS) will probably feature an other character.

Friday, June 29, 2012

"as seen at the Google IO"

I was watching the live broadcast of the Google IO when I got the pleasant surprise of seeing PewPew 2 as the (currently displayed) recommended app.

Completely unrelated, and much more importantly, Sébastien Huss has ported PewPew 2 to the Pandora console. I've been meaning to port it to this console for a long time because it has 2 physical joysticks.
I really want to thank him as he did all the work quickly, and without any of my help.


It should be noted that porting PewPew to the Pandora would have been totally impossible had I used any closed component (Unity 3D, UDK, Marmelade, ShiVa3D...) ;-)

Thursday, April 12, 2012

Memcaching the right stuff

I am hosting PewPew's scores on the Google App Engine. I chose the GAE because it was free for small websites that stay under a free quota. Unfortunately for me, they recently lowered the free quota, and I started having to pay the minimum fee of $9/month. It's not much, but I want PewPew to keep on working forever, and $9 per month forever amounts to an infinite amount of money, which I don't plan on having.

There were two areas where I was over the free quota: the database was too large (the free quota is 1GB), and I was using to much CPU for the database requests.

Reducing the database size

The database was taking more than 1GB because I never deleted any of the submitted scores/replay. I wrote an handler that erased the lowest scores. Erasing ~400k scores cost me approximately 4$.
If you have a database with tens of millions of entries, doing operations on them can become expensive!
The handler could only erase 1000 entries at a time before timing out, so I "automatized" its call.
Now, I only have ~100k entries left, taking 792 MB. Out of those, 491 MB are used by the replays, which amounts to 23.5 days of non-stop action.

Reducing the CPU usage

I thought optimizing the CPU usage was just going to be a matter of caching the queries. Turns out, there's a right way and a wrong way to do that.

Initially, the scores for the 8 game modes were generated this way:
    for level in levels:
      query_str = get_query(level)
      scores = db.GqlQuery(query_str)
      for entry in scores:
        #write the score, player_name

And to cache the results, I did this :
    for level in levels:
      query_str = get_query(level)
      scores = memcache.get(query_str)
      if scores is None:
        scores = db.GqlQuery(query_str)
        memcache.set(query_str, scores, 60 * 60 * 24)
      for entry in scores:
        #write the score, player_name


But doing this did not improve my CPU usage, and profiling my app showed that I was still doing a lot of database call, even though none appear in my code. I assume I was not caching the entries, only references to the results. Reading the entries still required doing some database calls:



The correct way to do things is to manually put in the cache the strings and numbers you need to store, not references to the entries in your database.
Once this was done, I got the expected 8 memcache calls and divided the response time by 40:


Now the players can get the scores instantly, and I am back to paying $0/forever.

Wednesday, January 4, 2012

Icons

When writing this post I often wrote "iCon" instead of "icon"... Damn you Apple.
Anyway I got a folder full of different icons for PewPew, and I thought it would be cool to look at the evolution.




The first icon shows the classic ship shooting at an enemy, but when resized to 47x47 pixels (the original iPhone's icon size) it didn't look great. I shipped the first version of PewPew with it back in 2009, but quickly iterated on it.


I simplified it and ended up with this.
[Update from 2016: I still like its purified appearance a lot!]
I was pretty happy with it and shipped quite a few versions of PewPew with it, but at some point I decided I need to make it more eye-catching: after all, I want people to download and play the game!

Up to now I was using Adobe Flash (!) to create the graphics. I decided to learn a bit about Photoshop and was able to add a glowing outline and some gradients.
It's interesting to note that the glowing outline is done the same way in Photoshop and in-game: blur the original image and compose the result with the original using additive blending. 


I later found a Photoshop iOS icon template with which I obtained this icon. However it attracted a lot of (deserved) criticism on the Android market, because the iOS glossy look negatively stood out on Android devices.









So I removed the gloss (but kept the roundness), played with the color balance, and obtained the current PP1 icon.


In parallel I was working on PP2 (and its icon). I considered putting 2 ships on the icon, but it would have suggested multiplayer and I did not want to mislead the customers.


It seems that I attempted to unify the icons of PP1 and PP2, and ended up with this. It was a failure and was never used.


After a while I realized that the PP2's icon actually looked very plain compared to other game's icons and realized the power of adding textures. This is the current (and likely final) PP2 icon.



During my last round of experimentations I tried different color scheme and liked this one very much. I ended up not using it, but it inspired me for the Android Market banner.










Edit (23/01/2012): a reddit post complaining about the lack of coherence with the icons on Android made me discover the Android Guidelines for the application's icons.

These are the two new (and hopefully final) icons.



Tuesday, November 22, 2011

Space War

Today, while doing my daily googling of PewPew-related news, I found a piano version of PewPew's main theme!


I hope an a capella version is coming.

Announcing PewPew and PewPew 2 Remasters

PP (PewPew) and PP2 (PewPew 2) haven't been compatible with modern devices for a couple of years now as I focused on PPL (PewPew Live), ...