Aimless on a cloudy saturday…
As I had to do some icons for Sim (my instant messenging software) and for the upcoming kick-ass Thoughtz (more info to come soon), I started realizing how much of a pain it was to create these fancy Aqua-styled icons for non-circular shapes.
Unless I missed something, it’s all about faking 3D by adding nice effects in Photoshop or in Illustrator / Inkscape. I just dunno how icon makers manage to do anything else than circle shapes without turning crazy (there must be some trick or dedicated software, please someone tell me which one !).
But hey, why should we have to fake 3D when we can get some real one ?
The issue is that we typically get some sort of flat-looking 2D arbitrarily-shaped image (by shaped, I mean : with an alpha layer that gives it a shape), which has nothing 3D in it.
Here begins the fun stuff : I wrote an ugly algorithm that computes, for each pixel, the distance to the closest transparent pixel. The algo is fast, but still has some glitches (because I actually cheat, I don’t test all the pixels to get the smallest distance). Antialiasing is taken into account in the process (a pixel with alpha A is considered “A / 255f”-away from a transparent pixel).
The main idea of the algorithm is to scan the image horizontally (row by row) then vertically (column by column), each time in both directions. When scanning a line / column, I keep the current distance to a transparent pixel and I update it as I walk along the line. Doing it in both directions ensures correctness along X and Y axes.
At the end, I try to smooth things a bit, but I still need to improve this step.
Once I get this distance for each pixel, I normalize it for the whole image and I apply a smoothing function (something in x ^ 3). I magically get a bumped height map of the image.
Follows some painful mesh generation (which still has some glitches) with normals averaging, and I get a 3D mesh that represents my original picture. As an added bonus, I texture it with the picture.
Now the magic glossy finish : a tiny bit of environment mapping brings the reflective effect into shape.
To try the demo, click on the “Launch” link above. If all goes well, you will be able to drag-and-drop images and text on the window. The bottom slider lets you control the extrude height.
And dropping text on the window looks like :
Speaking of 3D text, JOGL now features some very cool classes (TextRenderer and TextureRenderer) that let you draw 2D and 3D text in OpenGL in a snap… I did not use them for this demo, but I will certainly do soon…
Here are some things I would like to add to the demo :
- choice of different reflection maps (predefined ones, custom ones)
- control steepness of the borders of the extrusion
- blur edges (blur would grow with distance to border)
- export functionality, to save a translucent image. I will have to switch the display component from a GLCanvas to a GLJPanel in order to grab the image easily, but this might be a lot slower (especially before Java 6 and its magic Java2D-JOGL bridge).
- add some control on the text generation : font family and size, color… Maybe even some HTML editor to have some rich text
- add some buttons (with cool icons :-D) to expose functionalities : open file, generate text, export
- add copy-paste functionality