Go to content Go to navigation Go to search

Correct use of anaglyphic, in XNA

Wed, 16 Sep 2009

Help with correctly implementing an anaglyphic 3D effect, especially in XNA.When searching for an example implementation of an anaglyphic effect in XNA, I found a neat little example by Javier Ferrero here. Unfortunately, it needs modification to implement anaglyphic correctly.The problem lies with how anaglyphic actually works. Ferrero's code keeps the user's view fixed in position, while moving the world one way and tinting it cyan (green+blue), and the other way and tinting it red, showing both at once. Where the worlds collide, you get a full colour image.

Screenshot of Ferrero's implementation and my own diagram showing how it works.

Red/cyan spacing can be changed, but note how since the spacing is a set value, spacing in the distance appears less. This is similar to a true implementation with a focal point infinitely far away. Trying it with 3D glasses, the effect is okay, but doesn't always work well.True anaglyphic is based on having two eyes each seeing either the red of cyan view. The view is spaced apart (as opposed to the world) since your eyes are spaced apart, and then each view is angled inward to a focal point. The two colours should get closer together as we approach the focal point, with no red/cyan disparity at the focal point, and then start to space out the opposite way past the focal point (so if red was on the left, cyan will be now).

Fully correcting the example would take some editing of the StereoMode effects file, but basically, in StereoEffect.cs we see the Red pass code:

private void SetParametersRedPass(ICamera camera, float factor)
{
  stereo.Parameters["View"].SetValue(camera.View)
  stereo.Parameters["Projection"].SetValue(camera.Projection)
  stereo.Parameters["Translate"].SetValue(Matrix.CreateTranslation(-factor, 0, 0))
  stereo.Parameters["mask"].SetValue(new Vector4(1, 0, 0, 1))
}

And opposite for the GreenBlue pass. We can see this translates the world by the chosen factor. I suggest something like this:

private void SetParametersRedPass(ICamera camera, float factor)
{
  stereo.Parameters["View"].SetValue(camera.View);
  stereo.Parameters["Projection"].SetValue(camera.Projection);
  stereo.Parameters["TranslateView"].SetValue(Matrix.CreateTranslation(-1f, 0f, 0f)); //Eye spacing
  stereo.Parameters["RotateView"].SetValue(Matrix.CreateRotationY(-factor)); //Rotate view
  stereo.Parameters["mask"].SetValue(new Vector4(1, 0, 0, 1))
}

The quoted words are directly editing StereoEffect.cs, so you'd need to modify that too, but this is the basic idea (sorry, I don't have a fully working implementation). I've made the spacing between eyes fixed at a reasonable distance, while factor now controls the focal point.