Tightly packed fonts in OpenGL

Work is going well on the line rendering library. Taking a short break to explore some other areas.

LibGDX has a handy freetype extension which allows you to render TTF files to a texture (bitmap font) on-the-fly. Typically each TTF file will be packed into its own atlas; for example, you might end up with one 256×256 atlas for 24 pt font, and another for 16 pt font. If you plan on including many different font sizes and styles (bold, italic, etc) in your game — especially useful for different resolutions — you’re leading to a lot of extra white space.

With a small tweak to LibGDX code, it’s possible to use PixmapPacker to tightly pack your fonts into a single atlas. This also allows you more control over padding and texture size. See an example here, which packs 1,410 glyphs into a 512×256 image. It uses three font styles (Regular, Bold, Italic) and 5 font sizes for each (12 pt – 16 pt), so a total of 15 fonts packed into a single texture atlas. This could then be saved to a file before final release, using only the characters necessary for your game and target language(s), thus making for a very fast load time and nicely scalable, styled text.

If I have time in the future I’d like to contribute a bit to scene2D UI and provide a Label that allows for markup (color, font, etc) to easily produce styled text:

Screen shot 2013-05-03 at 1.40.27 PM

Another cool way of storing multiple levels of text sizes would be to use mipmapping, where each successive mipmap level is uploaded manually (glTexImage2D). The glyphs would need to be packed in the same positions. You could then use nearest sampling when picking the mipmap levels, which would lead to ‘stepped’ scaling without artifacts, or you could use GL_LINEAR for trilinear filtering between mipmap levels. I will have to experiment with this idea a bit further.

For larger sizes, there is of course distance field rendering, but that doesn’t play so nicely with small fonts.

The code changes are pretty minimal. Here is a clone of FreeTypeFontGenerator that shows what is necessary. Next week I may send a pull request to LibGDX to have this feature added officially.

https://gist.github.com/mattdesl/5512218

Advertisements

Per-Pixel 2D Shadows on the GPU

Below is my implementation of per-pixel shadows on the GPU, using far fewer passes and state changes than other current techniques such as Catalin Zima’s soft shadows. This technique also has a lot of room for optimization, as only one channel is currently used. Further, the blur pass is performed only in the horizontal direction, and can be included in the same step as the light rendering. Special thanks to the user “Nego” on the LibGDX forums, who expanded on my previous attempts with some great optimizations. 

Per-Pixel 2D Shadows on the GPU (using LibGDX)

Image

 

Graphics by Kenney from OpenGameArt.org.

Real-Time Backgrounds in GLSL

The beauty of GLSL sandboxes is the real-time visual feedback while coding. I’ve been toying with these to learn a bit more about shader programming, and see whether they would be feasible for use in desktop and mobile games.

Creating a background effect (e.g. for a menu screen or screen saver) in GLSL gives you full control over the fragments. You can handle anti-aliasing, real-time noise displacement, animate hues and colors, and even add 3D effects. Best of all, with some minor changes, the result is resolution-independent, and can be scaled infinitely with no loss in quality. Depending on the GPU, using GLSL might lead to better performance and aesthetics than trying to replicate the effect with textures and multiple blend passes.

The first prototype is an underwater scene, using my previous “Angler Fish Game” doodle as a reference. Here is the resulting background:

Screen shot 2013-03-09 at 3.38.08 PM

If you have a WebGL-enabled browser, you can see the effect and code in real-time below:
http://glsl.heroku.com/e#6052.4

The next prototype is a cartoony space background, using my previous “God of the Universe” doodle as a reference. Here is the resulting background:

Screen shot 2013-03-09 at 3.39.43 PM

You can see the effect in real-time and the code in the following link. The code is much simpler; I was hoping to target mobile with this shader.
http://glsl.heroku.com/e#6607.4

Perhaps in the next few years, as WebGL and consumer GPUs evolve, we will see a shift in understanding of what constitutes a “web image.” Already we have GIF (animated images) and SVG (scalable vector graphics). Maybe in the future we will have small snippets of OpenGL/GLSL, contained in a portable “image” format, and even allowing input such as mouse movement.

Fruit-Ninja Swipes in OpenGL

For a small game project I am working on in LibGDX (an OpenGL-based framework in Java which targets Desktop, Android, iOS, and WebGL), I decided to implement a “finger swipe” effect much like in Fruit Ninja. For reference, here is the effect in Fruit Ninja which I was trying to replicate:

The result of my efforts led to the following effect, which works on iOS, Android, WebGL, and Desktop:

Because I am working in a pure OpenGL setting (i.e. no luxury of HTML5 Canvas), there are a number of graphical hurdles to overcome. What’s more, many Android phones and tablets have poor accuracy on diagonal finger tracking, which leads to wobbly lines. The problem is demonstrated here. So a typical “finger swipe” on many Android devices might look like this:

I was able to minimize this problem with the Radial Distance Path Simplification algorithm. Douglas-Peucker might provide better results, but it is less efficient. In the image below, the gray line shows the raw “zig-zag” input, while the red line shows the simplified path:

The path is then smoothed using 2 iterations of Chaikin’s smoothing algorithm, to remove some of the sharp edges on corners:

Using some basic vector math, you can extrude the path into a 2D mesh. For efficiency, we use GL_TRIANGLE_STRIP to render the mesh. This leads to a pretty nice “swipe” effect:

The problem with this, as we can see, is that OpenGL doesn’t produce reliable polygon smoothing (anti-aliasing). Unfortunately, full-screen solutions like FXAA are often too slow for mobile platforms. I ended up using some OpenGL texturing tricks to produce smooth edges, and the result is extremely efficient (only requires one extra triangle strip per “swipe”). As a bonus, my solution can be easily used in conjunction with a custom fragment shader to produce 3D lighting, glows, and animated colors.

I go into more detail on the algorithms, 2D mesh generation, and anti-aliasing tricks in the following article:
Creating a Fruit-Ninja Style Swipe in LibGDX

Normal Map Lighting in Java4K

While toying with various ideas for the Java4K game programming competition, I looked into the possibility of per-pixel lighting — using the same techniques that advanced 3D games use to give higher definition to their low-poly meshes.

The effect can be seen below. If you look closely, you will see the bricks and player being lit based on their general shape, the position, and the color of the lights in the scene.

You can see some of the code for this effect below. Be warned; as the entire program needs to fit within the confines of 4 KB, it may be a bit hard to read.

NormalMap.java

I write more about normal mapping in GLSL using LWJGL (Java + OpenGL) in the following tutorial:
GLSL Tutorial: Normal Map Lighting in 2D

LWJGL, OpenGL & GLSL Tutorials

Recently I’ve been working on a series of tutorials for beginning with OpenGL in Java (through LWJGL). The tutorials rely on a minimal library I have developed, lwjgl-basics, which minimizes some of the boilerplate associated with GL programming (shader compilation, sprite batching, and so forth). Many of the tutorials also include ports for the popular LibGDX Java game development framework.

You can find the tutorials here:
OpenGL and GLSL Tutorials in Java

Just a few of the subjects covered by the series:

  • Loading OpenGL Textures and using “Sprite Batchers”
  • GLSL and shader programming:
    • Image processing: invert, sepia, grayscale
    • Texture splatting, linear interpolation basics
    • Blurs, bloom and post-processing with Frame Buffer Objects
    • Per-pixel lighting using Normal Maps
  • Creating your own Shader-Based 2D Rendering Engine (WIP)

Java 4K – Limbo-inspired Graphics

Java4K is a game development contest that requires your submissions to be a single JAR under 4096 bytes.

 

I wanted to mimic Limbo’s graphical style using blurs, parallax scrolling, and light scattering. You can test the applet here:

Download (open j4k.html)

 

The trees are created randomly and procedurally using simple Java2D paths. Effects like vignette, blur, light scattering, and film grain are achieved with per-pixel modifications; much as you would with a GLSL fragment shader. More details on implementation to come…