#region File Description
//-----------------------------------------------------------------------------
// DisplacementMapProcessor.cs
//
// Microsoft XNA Community Game Platform
// Copyright (C) Microsoft Corporation. All rights reserved.
//-----------------------------------------------------------------------------
#endregion
#region Using Statements
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Content.Pipeline;
using Microsoft.Xna.Framework.Content.Pipeline.Graphics;
using Microsoft.Xna.Framework.Graphics.PackedVector;
using System.ComponentModel;
#endregion
namespace DistortionPipeline
{
///
/// Converts height maps into 2D displacement maps for use as a texture on
/// distorters. The height map is first converted into a normal map before becoming
/// a displacement map. See the NormapMapProcessor class for more details.
///
[ContentProcessor]
public class DisplacementMapProcessor :
ContentProcessor
{
#region Processor Parameters
///
/// Amount of distortion in the map.
///
private float distortionScale = 0.5f;
[DisplayName("Distortion Scale")]
[DefaultValue(0.5f)]
[Description("Amount of distortion.")]
public float DistortionScale
{
get { return distortionScale; }
set { distortionScale = value; }
}
#endregion
///
/// Converts a greyscale height bitmap into a distplacement map.
///
public override TextureContent Process(TextureContent input,
ContentProcessorContext context)
{
// this processor builds on the output of the NormalMapProcessor, so
// we start by chaining to that
input = context.Convert(input,
"NormalMapProcessor");
// Perform the conversion to a displacement map
PixelBitmapContent bitmap =
(PixelBitmapContent)input.Faces[0][0];
ConvertNormalsToDisplacement(bitmap, DistortionScale);
// Convert to NormalizedByte2 because only the X and Y channels are needed
input.ConvertBitmapType(typeof(PixelBitmapContent));
return input;
}
///
/// Flattens vectors from a normal map into a 2D displacement map
/// and stores them in the RG portion of the bitmap.
///
public static void ConvertNormalsToDisplacement(
PixelBitmapContent bitmap, float distortionScale)
{
for (int y = 0; y < bitmap.Height; y++)
{
for (int x = 0; x < bitmap.Width; x++)
{
// Get the normal from the normal map
Vector4 normal4 = bitmap.GetPixel(x, y).ToVector4();
Vector3 normal3 = new Vector3(normal4.X, normal4.Y, normal4.Z);
// Determine the magnitude of the distortion at this pixel
float amount = Vector3.Dot(normal3, Vector3.Backward) *
distortionScale;
// Create a displacement vector of that magnitude in the direction
// of the normal projected onto the plane of the texture.
Vector2 normal2 = new Vector2(normal3.X, normal3.Y);
Vector2 displacement = normal2 * amount + new Vector2(.5f, .5f);
// Store the result
bitmap.SetPixel(x, y,
new NormalizedByte4(displacement.X, displacement.Y, 0, 0));
}
}
}
}
}