DisplacementMapProcessor.cs 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104
  1. #region File Description
  2. //-----------------------------------------------------------------------------
  3. // DisplacementMapProcessor.cs
  4. //
  5. // Microsoft XNA Community Game Platform
  6. // Copyright (C) Microsoft Corporation. All rights reserved.
  7. //-----------------------------------------------------------------------------
  8. #endregion
  9. #region Using Statements
  10. using Microsoft.Xna.Framework;
  11. using Microsoft.Xna.Framework.Content.Pipeline;
  12. using Microsoft.Xna.Framework.Content.Pipeline.Graphics;
  13. using Microsoft.Xna.Framework.Graphics.PackedVector;
  14. using System.ComponentModel;
  15. #endregion
  16. namespace DistortionPipeline
  17. {
  18. /// <summary>
  19. /// Converts height maps into 2D displacement maps for use as a texture on
  20. /// distorters. The height map is first converted into a normal map before becoming
  21. /// a displacement map. See the NormapMapProcessor class for more details.
  22. /// </summary>
  23. [ContentProcessor]
  24. public class DisplacementMapProcessor :
  25. ContentProcessor<TextureContent, TextureContent>
  26. {
  27. #region Processor Parameters
  28. /// <summary>
  29. /// Amount of distortion in the map.
  30. /// </summary>
  31. private float distortionScale = 0.5f;
  32. [DisplayName("Distortion Scale")]
  33. [DefaultValue(0.5f)]
  34. [Description("Amount of distortion.")]
  35. public float DistortionScale
  36. {
  37. get { return distortionScale; }
  38. set { distortionScale = value; }
  39. }
  40. #endregion
  41. /// <summary>
  42. /// Converts a greyscale height bitmap into a distplacement map.
  43. /// </summary>
  44. public override TextureContent Process(TextureContent input,
  45. ContentProcessorContext context)
  46. {
  47. // this processor builds on the output of the NormalMapProcessor, so
  48. // we start by chaining to that
  49. input = context.Convert<TextureContent, TextureContent>(input,
  50. "NormalMapProcessor");
  51. // Perform the conversion to a displacement map
  52. PixelBitmapContent<NormalizedByte4> bitmap =
  53. (PixelBitmapContent<NormalizedByte4>)input.Faces[0][0];
  54. ConvertNormalsToDisplacement(bitmap, DistortionScale);
  55. // Convert to NormalizedByte2 because only the X and Y channels are needed
  56. input.ConvertBitmapType(typeof(PixelBitmapContent<NormalizedByte2>));
  57. return input;
  58. }
  59. /// <summary>
  60. /// Flattens vectors from a normal map into a 2D displacement map
  61. /// and stores them in the RG portion of the bitmap.
  62. /// </summary>
  63. public static void ConvertNormalsToDisplacement(
  64. PixelBitmapContent<NormalizedByte4> bitmap, float distortionScale)
  65. {
  66. for (int y = 0; y < bitmap.Height; y++)
  67. {
  68. for (int x = 0; x < bitmap.Width; x++)
  69. {
  70. // Get the normal from the normal map
  71. Vector4 normal4 = bitmap.GetPixel(x, y).ToVector4();
  72. Vector3 normal3 = new Vector3(normal4.X, normal4.Y, normal4.Z);
  73. // Determine the magnitude of the distortion at this pixel
  74. float amount = Vector3.Dot(normal3, Vector3.Backward) *
  75. distortionScale;
  76. // Create a displacement vector of that magnitude in the direction
  77. // of the normal projected onto the plane of the texture.
  78. Vector2 normal2 = new Vector2(normal3.X, normal3.Y);
  79. Vector2 displacement = normal2 * amount + new Vector2(.5f, .5f);
  80. // Store the result
  81. bitmap.SetPixel(x, y,
  82. new NormalizedByte4(displacement.X, displacement.Y, 0, 0));
  83. }
  84. }
  85. }
  86. }
  87. }