Saturday, October 27, 2012

HTML5 Canvas and the Cracked Glass Effect - Revisited

After much toiling and tinkering, I think I have found a reasonably good method to produce a cracking glass effect. While not absolutely perfect, you can achieve some pretty interesting results. I used the same path construction as described in my original attempt. However, I broke the rendering into five different layers. Each layer adds a different dimension to the effect. These include refracting the image, adding reflections, the main cracking lines, fracture points, and some noise. In the demo I created, you can tinker with all the input options. The demo is on my sandbox and below are some examples I created with it.

The default settings will create something that looks like this first image. Since everything is random, you might have to draw the cracks a few times to find a variation you like.



I added a solid background to see what it would look like. Most of the samples out there have a black background so I wanted to see something to compare.



The white background is fun for playing with colors.



Most of the algorithm is finding places to draw lines.  All of the parameters of the lines are precalculated and each layer uses parts of those calculations to guide it in placing various canvas elements (lines, gradients, and curves) around those lines that were calculated as part of the path generation logic.

From a performance perspective, its not too bad.  Chrome seems to render the fastest.  The Noise layer can really slow it down because of the amount of tiny lines it can draw (depending on the decay and frequency selected).  Each layer can be completely disabled by turning the opacity all the way down (the show/hide button will render the layer but its just not visible).  Overall, there's a lot of Canvas API calls being generated and the rendering times are not unacceptable.   Its not something you'd want to try calling over and over again, but it can function in a real time setting.

I suppose the next task is to package it up into something that can actually be called on an image.  Maybe make it a jQuery plugin.  However, that's another project for another day ...