Wednesday, November 12, 2014

Amazing Anaglyphs

For today's comic about 3D printers, the final cell has an optional stereoscopic 3D effect. You are probably familiar with this type of 3D imagery, where you have to look at it with those cardboard glasses with the two different colored lenses. Pictures like this are called anaglyphs. The most common form are the red/cyan type. Those two colors are used because red and cyan are opposite each other on the color spectrum.

Red/Cyan Stereoscopic 3D Glasses
Making the 3D version of the comic was not as easy as I initially thought it would be. As you may know, I create my comics by combining multiple SVG images on a web page. My first idea was to apply an SVG filter to create the anaglyph effect.

The first hurdle was to actually create the filter. I mistakenly assumed that Inkscape's filter editor might be usable. Ugh. Poor assumption. I had to edit the SVG file in a text editor, but it was certainly easy enough to apply the filter in Inkscape.

The Anaglyph SVG Filter


Here is the filter I created. Apply it to any element in a SVG document to make it pop off the screen!

<filter
     color-interpolation-filters="sRGB"
     inkscape:label="3d"
     id="filter3895-1-1">
    <feOffset
      result="l1"
      in="SourceGraphic"
      id="feOffset3897-8-2"
      dy="0"
      dx="-5" />
    <feOffset
      result="r1"
      in="SourceGraphic"
      id="feOffset3899-9-3"
      dy="0"
      dx="5" />
    <feColorMatrix
      result="r2"
      values="1 0 0 0 0 0 1 0 0 1 0 0 1 0 1 0 0 0 1 0 "
      in="r1"
      id="feColorMatrix3901-2-3" />
    <feColorMatrix
      result="l2"
      values="1 0 0 0 1 0 1 0 0 0 0 0 1 0 0 0 0 0 1 0 "
      in="l1"
      id="feColorMatrix3903-7-4" />
    <feMerge
        id="feMerge3905-9-1">
       <feMergeNode
           id="feMergeNode3907-5-1"
           in="l2" />
       <feMergeNode
           id="feMergeNode3909-4-3"
           in="r2" />
    </feMerge>
    <feBlend
       mode="multiply"
       in2="l2"
       in="r2"
       id="feBlend3911-3-8" />
</filter>

Here's the before-and-after pictures.

Before the Anaglyph Filter
After the Anaglyph Filter
Let me explain a little about what it does. First, it splits the source graphic into two new graphics. Each one has an X offset. In this case, I use an offset of 5 in each direction. To make the image appear to come further out of the screen, just use a larger value here. The first offset graphic (see the tag starting on line 5) will be the left side because it has the dx value of -5. The second offset graphic (starting on line 11) will be the right side because it has the dx value of 5. The resulting new graphics are called l1 and r1, respectively. The next step is to apply a different color transformation to each of the new graphics. The feColorMatrix tags on lines 17 and 22 perform these modifications. One side gets all the red removed and the other all the cyan. Finally, both of the new graphics get merged back together and a multiply blend is applied. This multiplies the color values together wherever they overlap, which results in the original color being seen again. On the edges, where there is no overlap, you can see a little of the all-red and all-cyan images.

Looks good, right? Put on your 3D glasses and that frog is jumping out at you. There was just one slight problem...This only works on individual graphics. If you try to arrange multiple images on a web page with these filters applied, the colors won't all blend together to create a cohesive scene. It looks weird, trust me.

The Anaglyph CSS


First idea was a failure. Next idea: use the new color-blending features of CSS3 on the images to create the scene! Here's how that works.

First, I created two SVG images of the frog. On one image I applied a filter to strip out the cyan color channel, and on the other I applied a filter to strip out the red channel. That gave me these oddly colored graphics:

frog_cyan_channel.svg

frog_red_channel.svg
I could then use these graphics together as backgrounds for a DIV, blending them together to create the same type of effect seen in the SVG filter. Here is an example of just that:

<!doctype html>

<html lang="en">
<head>
  <meta charset="utf-8">
  <title>Color Test</title>
  <style>

.ana {

  background:
    url(frog_red_channel.svg),
    url(frog_cyan_channel.svg);
  background-position:
    0px 0px,
    10px, 0px;
  background-repeat: no-repeat;
  background-blend-mode: multiply;

}

  </style>
</head>

<body>

  <div class="ana" style="top: 45px; width: 326px; height: 281px;"></div>

</body>

</html>

When you view this page in your browser, it looks like this:

Anaglyph via CSS blending
The CSS involved here is actually fairly simple. The DIV has two background images, the two color-filtered frog graphics. The position of the second background is given as "10px" which moves it 10 pixels to the right of the first background. This offset can be changed to make the frog appear closer to the viewer. The background-repeat is turned off so that we don't see another image along the edge, since the DIV has to be made 10 pixels wider than either image to ensure that there's room for the offset. Finally, background-blend-mode is set to multiply. Just like in the SVG filter, this causes the color values to be multiplied together anywhere the two images overlap - which brings back the original color in most of the image. Only along the edges do you see the all-red or all-cyan versions.

But alas, it's still not that easy. This works great for a single image. However, if you try to put one image done this way on top of another image, like I do in my comic, the colors from the two images won't blend with each other. They only blend their own backgrounds. Plus, this kind of blending still doesn't work on text even in the latest web browsers. That means even if I could figure out a slick way to overcome the first problem, I wouldn't be able to make the frog's words float in front of your face. Foiled again!

Even though this didn't work out either, I did learn quite a bit. You can read the following page to learn more about CSS blend modes: Basics of CSS Blend Modes.

The Classic Approach


In the end, I had to use the old-fashioned way to create the 3D version of the comic. I created two different versions of the cell, each with the individual components (frogs, text, and printer) slightly offset. I used my standard PhantomJS script to turn each one into a PNG image. Then I used GIMP to do the same thing to those two images that I'd been doing in the SVG filter and CSS - strip out the opposite colors from each image and then blend to put them together to form a single image.

After creating your 2 images, one for the right eye and one for the left eye, open them as Layers in GIMP.


You should end up with layers something like this. Make sure the right eye's image is on top. If it didn't end up there, just move it up.


Next, set your foreground color to red. Pure red. #FF0000.


Now create two new layers, with "Foreground color" selected as the fill type. Create one on top of the right side image and one between the right and left side images.


Your layers should now look like this:


Select the lower layer, the one directly above the left-side image, and from the Colors menu, select Invert. That should change the entire fill color to cyan.


And your layers should now look like this:


Next, click on each of the color layers and change their Mode to Screen. The mode selector is at the very top of the layer area above Opacity. Just click on the drop down on the right side and you'll see lots of options. Screen is the one you want.


Now from the Layer menu, select Merge Down on each of the pure color layers. This will combine them with the image layers directly below them.


And you have just two layers remaining and they should look something like the following picture. The one final step is to change the Mode on the top layer (should be the right eye image if you've done everything correctly) to Multiply. You can merge down again if you want to create a single layer, but your image should already look like a red/cyan anaglyph if you have both layers visible. Now you can export it!

Mode on the top layer is "Multiply"
It was quite a journey of discovery that I took to learn and experiment with all this, just to get a single cell in a single comic. I hope you enjoy looking at it as much as I enjoyed making it.

Amphibian.com comic for 12 November 2014