/// <summary> /// This function encodes a new texture based on the list of key frame matrices /// </summary> /// <param name="keyFrameMatrices"></param> /// <returns></returns> static private PixelBitmapContent <Vector4> GetEncodedTexture(List <Matrix[]> keyFrameMatrices, int bones) { //We need 4 pixels per bone. We can store each row of the transform matrix in one pixel. int width = bones * 4; //Create a new bitmap content object PixelBitmapContent <Vector4> animationTexture = new PixelBitmapContent <Vector4>(width, keyFrameMatrices.Count); int y = 0; //Now, we'll write all the rows foreach (Matrix[] animationRow in keyFrameMatrices) { int x = 0; foreach (Matrix transform in animationRow) { // Pretty trivial - we just right out the matrix data as pixels. Instead of R, G, B, and A, we write matrix values. // However, as mentioned in the article, this could be optimized. We really only need 3 pixels to describe a matrix, // because in a transform matrix, the fourth row is always (0, 0, 0, 1). Thus, we could use the RGB values to describe the 3x3 // matrix, and then use the A values to describe the translation values in the 4th column. During runtime, this would save // us a vertex texture fetch per transform! animationTexture.SetPixel(x + 0, y, new Vector4(transform.M11, transform.M12, transform.M13, transform.M14)); animationTexture.SetPixel(x + 1, y, new Vector4(transform.M21, transform.M22, transform.M23, transform.M24)); animationTexture.SetPixel(x + 2, y, new Vector4(transform.M31, transform.M32, transform.M33, transform.M34)); animationTexture.SetPixel(x + 3, y, new Vector4(transform.M41, transform.M42, transform.M43, transform.M44)); x += 4; } y++; } return(animationTexture); }
public override TextureContent Import(string filename, ContentImporterContext context) { using (FileStream file = new FileStream(filename, FileMode.Open)) { byte[] bytes = new byte[file.Length]; file.Read(bytes, 0, (int)file.Length); bool bit16 = false; // Figure out file size if (Width <= 0 || Height <= 0) { Width = (int)Math.Sqrt(file.Length); Height = (int)(file.Length / Width); if (Width * Height != file.Length) { Width = (int)Math.Sqrt(file.Length / 2); Height = (int)(file.Length / 2 / Width); bit16 = true; } if (Width * Height * 2 == file.Length) { context.Logger.LogWarning(null, new ContentIdentity(filename), "Input texture not a raw grayscale texture, or the specified width and height do not match."); } } // Create texture int i = 0; PixelBitmapContent <float> bitmap = new PixelBitmapContent <float>(Width, Height); for (int y = 0; y < Height; ++y) { for (int x = 0; x < Width; ++x) { if (bit16) { bitmap.SetPixel(x, y, 1.0f * (ushort)((bytes[i++] | bytes[i++] << 8)) / ushort.MaxValue); } else { bitmap.SetPixel(x, y, 1.0f * bytes[i++] / byte.MaxValue); } } } Texture2DContent result = new Texture2DContent(); result.Mipmaps = new MipmapChain(bitmap); return(result); } }
/// <summary> /// Using height data stored in the alpha channel, computes normalmap /// vectors and stores them in the RGB portion of the bitmap. /// </summary> static void ConvertAlphaToNormals(PixelBitmapContent <Vector4> bitmap) { for (int y = 0; y < bitmap.Height; y++) { for (int x = 0; x < bitmap.Width; x++) { // Look up the heights to either side of this pixel. float left = GetHeight(bitmap, x - 1, y); float right = GetHeight(bitmap, x + 1, y); float top = GetHeight(bitmap, x, y - 1); float bottom = GetHeight(bitmap, x, y + 1); // Compute gradient vectors, then cross them to get the normal. Vector3 dx = new Vector3(1, 0, (right - left) * bumpSize); Vector3 dy = new Vector3(0, 1, (bottom - top) * bumpSize); Vector3 normal = Vector3.Cross(dx, dy); normal.Normalize(); // Store the result. float alpha = GetHeight(bitmap, x, y); bitmap.SetPixel(x, y, new Vector4(normal, alpha)); } } }
/// <summary> /// Process converts the encoded normals to the NormalizedByte4 format and /// generates mipmaps. /// </summary> /// <param name="input"></param> /// <param name="context"></param> /// <returns></returns> public override TextureContent Process(TextureContent input, ContentProcessorContext context) { Texture2DContent result = new Texture2DContent(); if (input.Faces[0][0] is PixelBitmapContent <Alpha8> ) { return(input); } input.ConvertBitmapType(typeof(PixelBitmapContent <Vector3>)); PixelBitmapContent <Vector3> source = input.Faces[0][0] as PixelBitmapContent <Vector3>; PixelBitmapContent <Alpha8> bitmap = new PixelBitmapContent <Alpha8>(source.Width, source.Height); for (int y = 0; y < source.Height; ++y) { for (int x = 0; x < source.Width; ++x) { Vector3 src = source.GetPixel(x, y); bitmap.SetPixel(x, y, new Alpha8( 0.3f * src.X + 0.59f * src.Y + 0.11f * src.Z)); } } result.Mipmaps.Add(bitmap); return(result); }
public override TextureContent Import(string filename, ContentImporterContext context) { // load raw data FileStream reader = File.OpenRead(filename); int width = 257; int height = 257; byte[] bytes = new byte[reader.Length]; reader.Read(bytes, 0, bytes.Length); reader.Close(); // import into standard XNA bitmap container PixelBitmapContent <Color> bitmapContent = new PixelBitmapContent <Color>(width, height); for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++) { bitmapContent.SetPixel(x, y, new Color(bytes[(y * width) + x], 0, 0)); } } // create and return one-mipmap-level Texture2DContent content = new Texture2DContent { Identity = new ContentIdentity(filename) }; content.Mipmaps.Add(bitmapContent); return(content); }
protected string BuildTexture(Color color, IDictionary <string, object> processorParameters = null) { PixelBitmapContent <Color> bitmap = new PixelBitmapContent <Color>(1, 1); bitmap.SetPixel(0, 0, color); return(BuildTexture(bitmap, processorParameters)); }
/// <summary> /// Applies a single pass of a separable box filter, blurring either /// along the x or y axis. This could give much higher quality results /// if we used a gaussian filter kernel rather than this simplistic box, /// but this is good enough to get the job done. /// </summary> static void ApplyBlurPass(PixelBitmapContent <Vector4> source, PixelBitmapContent <Vector4> destination, int dx, int dy) { int cubemapCenter = cubemapSize / 2; for (int y = 0; y < cubemapSize; y++) { for (int x = 0; x < cubemapSize; x++) { // How far is this texel from the center of the image? int xDist = cubemapCenter - x; int yDist = cubemapCenter - y; int distance = (int)Math.Sqrt(xDist * xDist + yDist * yDist); // Blur more in the center, less near the edges. int blurAmount = Math.Max(cubemapCenter - distance, 0) / 8; // Accumulate source texel values. Vector4 blurredValue = Vector4.Zero; for (int i = -blurAmount; i <= blurAmount; i++) { blurredValue += source.GetPixel(x + dx * i, y + dy * i); } // Average them to calculate a blurred result. blurredValue /= blurAmount * 2 + 1; destination.SetPixel(x, y, blurredValue); } } }
static PixelBitmapContent <Color> CreateAlphaChannel(PixelBitmapContent <Color> input) { int width = input.Width; int height = input.Height; PixelBitmapContent <Color> result = new PixelBitmapContent <Color>(width, height); for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++) { Color color = input.GetPixel(x, y); // Adds/Replaces Alpha channel with the "Brightest color channel value // A better way would be to average all three colors and use that for alpha. // This will work just fine for grey scale textures and is simpler... byte resultAlpha1 = (byte)(color.PackedValue & 0xff); byte resultAlpha2 = (byte)(color.PackedValue & 0xff00); byte resultAlpha3 = (byte)(color.PackedValue & 0xff0000); byte resultAlpha = Math.Max(Math.Max(resultAlpha1, resultAlpha2), resultAlpha3); color.PackedValue = (uint)(resultAlpha << 24) + (0x00ffffff); result.SetPixel(x, y, color); } } return(result); }
unsafe private static BitmapContent ConvertToColor(BitmapContent input) { var width = input.Width; var height = input.Height; SurfaceFormat format; input.TryGetFormat(out format); var formatSize = DDSImporter.GetBitmapSize(format, width, height); var blocks = formatSize; var inData = input.GetPixelData(); var output = new PixelBitmapContent <Color>(width, height); fixed(byte *p = &inData[0]) { DXT1Block *block = (DXT1Block *)p; //convert DXT1 to color for (int y = 0; y < height; ++y) { for (int x = 0; x < width; ++x) { int blockIdx = (x / 4) + (y / 4) * (width / 4); int colorIndex = x % 4 + (y % 4) * 4; Color color = block[blockIdx].GetColor(colorIndex); output.SetPixel(x, y, color); } } } return(output); }
public override TextureContent Import(string filename, ContentImporterContext context) { // load tiff data m_pReader = new BinaryReader(File.OpenRead(filename)); int nOffsetFirstIFD = ReadHeader(); ReadAllIfds(nOffsetFirstIFD); m_pReader.Close(); // import into standard XNA bitmap container PixelBitmapContent <float> bitmapContent = new PixelBitmapContent <float>(m_nWidth, m_nHeight); for (int y = 0; y < m_nHeight; y++) { for (int x = 0; x < m_nWidth; x++) { bitmapContent.SetPixel(x, y, m_pImageData[(y * m_nWidth) + x]); } } // create and return one-mipmap-level Texture2DContent content = new Texture2DContent(); content.Mipmaps.Add(bitmapContent); return(content); }
protected virtual void BuildNormalMap(PixelBitmapContent <Single> bm, PixelBitmapContent <Color> n) { unchecked { int ww = n.Width; int hh = n.Height; for (int y = 0; y < hh; ++y) { for (int x = 0; x < ww; ++x) { float v00 = bm.GetPixel(x, y); float v01 = bm.GetPixel(x, y + 1); float v10 = bm.GetPixel(x + 1, y); float v11 = bm.GetPixel(x + 1, y + 1); // 80 meters up/down for the renderer // two dx-es means divide by 2 (to average) // two meters per triangle side means divide by 2 to normalize to meters // That is crappy resolution. I should probably use floats instead of bytes // for the underlying storage pixmap... float ddx = (v10 + v11 - v00 - v01) * Page.DynamicRange * 0.5f * 0.5f; float ddy = (v01 + v11 - v00 - v10) * Page.DynamicRange * 0.5f * 0.5f; Vector3 v = new Vector3(-ddx, -ddy, 1.0f); v.Normalize(); v = v * 0.5f + new Vector3(0.5f, 0.5f, 0.5f); Color c = new Color(v); n.SetPixel(x, y, c); } } } }
/// <summary> /// Flattens vectors from a normal map into a 2D displacement map /// and stores them in the RG portion of the bitmap. /// </summary> public static void ConvertNormalsToDisplacement( PixelBitmapContent <NormalizedByte4> 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)); } } }
public override TOutput Process(TInput input, ContentProcessorContext context) { input.ConvertBitmapType(typeof(PixelBitmapContent <Vector4>)); PixelBitmapContent <Vector4> bm = (PixelBitmapContent <Vector4>)(((Texture2DContent)input).Mipmaps[0]); for (int y = 0, ym = bm.Height; y != ym; ++y) { for (int x = 0, xm = bm.Width; x != xm; ++x) { Vector4 v = bm.GetPixel(x, y); float w = 1 - v.W; if (v.Z > w) { v.Z = w; } w -= v.Z; if (v.Y > w) { v.Y = w; } w -= v.Y; if (v.X > w) { v.X = w; } System.Diagnostics.Debug.Assert(v.X + v.Y + v.Z + v.W <= 1.001f); // it's OK for w to be > 0 here, as that means the base layer weight bm.SetPixel(x, y, v); } } input.ConvertBitmapType(typeof(PixelBitmapContent <Color>)); input.GenerateMipmaps(true); return(input); }
public static void setData(this PixelBitmapContent <Color> self, Color[] data) { var i = 0; for (var y = 0; y < self.Height; y++) { for (var x = 0; x < self.Width; x++) { self.SetPixel(x, y, data[i++]); } } }
/// <summary> /// Our source data is just a regular 2D image, but to make a good /// cubemap we need this to wrap on all sides without any visible seams. /// An easy way of making an image wrap from left to right is simply to /// put a mirrored copy of the image next to the original. The point /// where the image mirrors is still pretty obvious, but for a reflection /// map this will be good enough. /// </summary> static PixelBitmapContent <Color> MirrorBitmap(PixelBitmapContent <Color> source) { int width = source.Width * 2; PixelBitmapContent <Color> mirrored; mirrored = new PixelBitmapContent <Color>(width, source.Height); for (int y = 0; y < source.Height; y++) { for (int x = 0; x < source.Width; x++) { Color color = source.GetPixel(x, y); mirrored.SetPixel(x, y, color); mirrored.SetPixel(width - x - 1, y, color); } } return(mirrored); }
/// <summary> /// Worker function for folding and stretching a flap from the source /// image to make up one quarter of the top or bottom cubemap faces. /// </summary> static void ScaleTrapezoid(PixelBitmapContent <Color> source, int cubeSide, int cubeY, PixelBitmapContent <Color> destination, int destinationX, int destinationY, int xDirection1, int yDirection1, int xDirection2, int yDirection2) { int size = destination.Width; // Compute the source x location. int baseSourceX = cubeSide * source.Width / 4; // Copy the image data one row at a time. for (int row = 0; row < size / 2; row++) { // Compute the source y location. int sourceY; if (cubeY < 0) { sourceY = source.Height / 3; } else { sourceY = source.Height * 2 / 3; } sourceY += cubeY * row * source.Height / 3 / (size / 2); // Stretch this row from the source to destination. int x = destinationX; int y = destinationY; int rowLength = size - row * 2; for (int i = 0; i < rowLength; i++) { int sourceX = baseSourceX + i * source.Width / 4 / rowLength; Color color = source.GetPixel(sourceX, sourceY); destination.SetPixel(x, y, color); x += xDirection1; y += yDirection1; } // Advance to the start of the next row. destinationX += xDirection1 + xDirection2; destinationY += yDirection1 + yDirection2; } }
/// <summary> /// Process converts the encoded normals to the NormalizedByte4 format and /// generates mipmaps. /// </summary> /// <param name="input"></param> /// <param name="context"></param> /// <returns></returns> public override TextureContent Process(TextureContent input, ContentProcessorContext context) { // convert to vector4 format, so that we know what kind of data we're // working with. input.ConvertBitmapType(typeof(PixelBitmapContent <Vector4>)); Texture2DContent output = new Texture2DContent(); // expand the encoded normals; values ranging from 0 to 1 should be // expanded to range to -1 to 1. // NOTE: in almost all cases, the input normalmap will be a // Texture2DContent, and will only have one face. just to be safe, // we'll do the conversion for every face in the texture. int mmIndex = 0; foreach (MipmapChain mipmapChain in input.Faces) { int bmpIndex = 0; foreach (PixelBitmapContent <Vector4> bitmap in mipmapChain) { // Copy original bitmap to the new texture output.Faces[mmIndex].Add(bitmap); PixelBitmapContent <NormalizedByte4> normalizedBitmap = new PixelBitmapContent <NormalizedByte4>(bitmap.Width, bitmap.Height); for (int x = 0; x < bitmap.Width; x++) { for (int y = 0; y < bitmap.Height; y++) { Vector4 encoded = 2 * bitmap.GetPixel(x, y) - Vector4.One; normalizedBitmap.SetPixel(x, y, new NormalizedByte4(encoded)); } } // now that the conversion to -1 to 1 ranges is finished, convert to the // runtime-ready format NormalizedByte4. output.Faces[mmIndex][bmpIndex++] = normalizedBitmap; } mmIndex++; } // Overwriting mipmaps isn't needed here. output.GenerateMipmaps(false); return(output); }
/// <summary> /// Copies greyscale color information into the alpha channel. /// </summary> static void ConvertGreyToAlpha(PixelBitmapContent <Vector4> bitmap) { for (int y = 0; y < bitmap.Height; y++) { for (int x = 0; x < bitmap.Width; x++) { Vector4 value = bitmap.GetPixel(x, y); // Copy a greyscale version of the RGB data into the alpha channel. float greyscale = (value.X + value.Y + value.Z) / 3; value.W = greyscale; bitmap.SetPixel(x, y, value); } } }
PixelBitmapContent <Rgba1010102> Encode2(PixelBitmapContent <Rgba1010102> bmpMipMap) { // Create Color Bitmap of Equal Size PixelBitmapContent <Rgba1010102> bmpColor = new PixelBitmapContent <Rgba1010102>(bmpMipMap.Width, bmpMipMap.Height); // Convert each pixel to gamma encoded color for (int y = 0; y < bmpMipMap.Height; y++) { for (int x = 0; x < bmpMipMap.Width; x++) { // Get Input Pixel Rgba1010102 CmipMap = bmpMipMap.GetPixel(x, y); // Set Output Pixel bmpColor.SetPixel(x, y, GammaEncodeColor2(CmipMap.ToVector4())); } //for (x) } //for (y) return(bmpColor); }//method
public override Texture2DContent Import(string filename, ContentImporterContext context) { Bitmap bitmap = Image.FromFile(filename) as Bitmap; var bitmapContent = new PixelBitmapContent <Microsoft.Xna.Framework.Color>(bitmap.Width, bitmap.Height); for (int i = 0; i < bitmap.Width; i++) { for (int j = 0; j < bitmap.Height; j++) { System.Drawing.Color from = bitmap.GetPixel(i, j); Microsoft.Xna.Framework.Color to = new Microsoft.Xna.Framework.Color(from.R, from.G, from.B, from.A); bitmapContent.SetPixel(i, j, to); } } return(new Texture2DContent() { Mipmaps = new MipmapChain(bitmapContent) }); }
}//method public PixelBitmapContent <Rgba1010102> Decode2(PixelBitmapContent <Color> bmpInput) { // Decoded Bitmap PixelBitmapContent <Rgba1010102> bmpDecoded = new PixelBitmapContent <Rgba1010102>(bmpInput.Width, bmpInput.Height); // Convert each pixel to gamma decoded float for (int y = 0; y < bmpInput.Height; y++) { for (int x = 0; x < bmpInput.Width; x++) { // Get Input Pixel Color Cinput = bmpInput.GetPixel(x, y); // Set Output Pixel bmpDecoded.SetPixel(x, y, GammaDecodeColor2(Cinput.ToVector4())); } //for (x) } //for (y) return(bmpDecoded); }
private Texture2DContent BuildTextureContent(byte[] buffer) { var bitmap = new Bitmap(new MemoryStream(buffer)); var bitmapContent = new PixelBitmapContent <Color>(bitmap.Width, bitmap.Height); for (int i = 0; i < bitmap.Width; i++) { for (int j = 0; j < bitmap.Height; j++) { System.Drawing.Color from = bitmap.GetPixel(i, j); //System.Drawing.Color to Microsoft.Xna.Framework.Color var to = new Color(from.R, from.G, from.B, from.A); bitmapContent.SetPixel(i, j, to); } } return(new Texture2DContent { Mipmaps = new MipmapChain(bitmapContent) }); }
public override TextureContent Process(TextureContent input, ContentProcessorContext context) { input.ConvertBitmapType(typeof(PixelBitmapContent<Color>)); foreach (var mipmapChain in input.Faces) { for (int i = 0; i < mipmapChain.Count; i++) { var bitmap = mipmapChain[i] as PixelBitmapContent<Color>; int newWidth = (int) ((float) bitmap.Width * Scale); int newHeight = (int) ((float) bitmap.Height * Scale); var newBitmap = new PixelBitmapContent<Color>(newWidth, newHeight); for (int y = 0; y < bitmap.Height; y++) { for (int x = 0; x < bitmap.Width; x++) { for (int scaleY = 0; scaleY < Scale; scaleY++) { for (int scaleX = 0; scaleX < Scale; scaleX++) { newBitmap.SetPixel( (int) (x * Scale) + scaleX, (int) (y * Scale) + scaleY, bitmap.GetPixel(x, y)); } } } } mipmapChain[i] = newBitmap; } } return base.Process(input, context); }
public override TextureContent Process(TextureContent input, ContentProcessorContext context) { input.ConvertBitmapType(typeof(PixelBitmapContent <Color>)); foreach (var mipmapChain in input.Faces) { for (int i = 0; i < mipmapChain.Count; i++) { var bitmap = mipmapChain[i] as PixelBitmapContent <Color>; int newWidth = (int)((float)bitmap.Width * Scale); int newHeight = (int)((float)bitmap.Height * Scale); var newBitmap = new PixelBitmapContent <Color>(newWidth, newHeight); for (int y = 0; y < bitmap.Height; y++) { for (int x = 0; x < bitmap.Width; x++) { for (int scaleY = 0; scaleY < Scale; scaleY++) { for (int scaleX = 0; scaleX < Scale; scaleX++) { newBitmap.SetPixel( (int)(x * Scale) + scaleX, (int)(y * Scale) + scaleY, bitmap.GetPixel(x, y)); } } } } mipmapChain[i] = newBitmap; } } return(base.Process(input, context)); }
public override TextureContent Process(TextureContent input, ContentProcessorContext context) { TextureContent texContent = base.Process(input, context); texContent.ConvertBitmapType(typeof(PixelBitmapContent <Color>)); for (int face = 0; face < input.Faces.Count; face++) { MipmapChain mipChain = input.Faces[face]; for (int mipLevel = 0; mipLevel < mipChain.Count; mipLevel++) { PixelBitmapContent <Color> oldImage = (PixelBitmapContent <Color>)input.Faces[face][mipLevel]; PixelBitmapContent <Color> grayImage = new PixelBitmapContent <Color>(oldImage.Width, oldImage.Height); for (int x = 0; x < oldImage.Width; x++) { for (int y = 0; y < oldImage.Height; y++) { Color oldColor = oldImage.GetPixel(x, y); float grayValue = oldColor.R * 0.299f / 255.0f; grayValue += oldColor.G * 0.596f / 255.0f; grayValue += oldColor.B * 0.211f / 255.0f; float alpha = oldColor.A / 255.0f; Color grayColor = new Color(grayValue, grayValue, grayValue, alpha); Color newColor = Color.Lerp(oldColor, grayColor, interpolation); grayImage.SetPixel(x, y, newColor); } } input.Faces[face][mipLevel] = grayImage; } } return(texContent); }
public override TextureContent Process(TextureContent input, ContentProcessorContext context) { string[] strs = context.OutputFilename.Split('\\'); /* // If assigning this processor to all textures, use something like this to only apply to certain folders * if (strs.Length > 2 && strs[strs.Length - 2] == "Animations") * { } */ //write_debug(context.OutputDirectory); //write_debug(context.OutputFilename); Dictionary <Color, int> palette = new Dictionary <Color, int>(); Dictionary <string, Color[]> palette_data = context.BuildAndLoadAsset <string, Dictionary <string, Color[]> >( new ExternalReference <string>(@"Face_Palette_Data.xml"), ""); string filename = Path.GetFileNameWithoutExtension(context.OutputFilename); string doop = filename; // If palette data for the face exists if (palette_data.ContainsKey(filename) && palette_data[filename].Length > 0) { // Add the colors to a dictionary for (int i = 0; i < palette_data[filename].Length; i++) { if (!palette.ContainsKey(palette_data[filename][i])) { palette.Add(palette_data[filename][i], i); } } } // The process for getting to this point has changed, so now if there is no palette entry for a texture it shouldn't be edited at all else { return(base.Process(input, context)); } // Otherwise we have palette data and the image will be remapped to color indices on the red channel input.ConvertBitmapType(typeof(PixelBitmapContent <Color>)); int base_count = palette.Count; int new_colors = 0; foreach (MipmapChain image_face in input.Faces) { for (int i = 0; i < image_face.Count; i++) { PixelBitmapContent <Color> mip = (PixelBitmapContent <Color>)image_face[i]; Color original, edited; for (int y = 0; y < mip.Height; y++) { for (int x = 0; x < mip.Width; x++) { original = mip.GetPixel(x, y); // Checks for new colors not in the palette data // Why would those exist? //Yeti if (!palette.ContainsKey(original)) { // Gets the smallest whole number that is not already in the palette values int index = 0; while (palette.Values.ToList().Contains(index)) { index++; } // Adds a new color palette.Add(original, index); // Keeps track of how many new colors have been added new_colors++; } edited = new Color((palette[original] * 1) % 256, 0, 0, original.A); mip.SetPixel(x, y, edited); } } } } if (false) { //write_debug(doop + ", " + palette.Count.ToString()); write_debug(doop + ", " + new_colors.ToString() + "/" + palette.Count.ToString()); for (int i = base_count; i < palette.Count; i++) { foreach (KeyValuePair <Color, int> entry in palette) { if (entry.Value == i) { if (entry.Key.A > 0) { write_debug(entry.Key.ToString()); } break; } } } } return(base.Process(input, context)); }
public override Texture2DContent Process(Splatter splatter, ContentProcessorContext context) { var input = splatter.Layers.Select(layer => layer != null ? layer.Filename : null).ToArray(); if (input.Length > 4) { context.Logger.LogWarning(null, null, "SplatterTextureProcessor supports at most 4 textures. Additional textures will be discarded"); } int width = 0; int height = 0; Texture2DContent texture = null; PixelBitmapContent <float> bitmapR = null; PixelBitmapContent <float> bitmapG = null; PixelBitmapContent <float> bitmapB = null; PixelBitmapContent <float> bitmapA = null; if (input.Length > 0 && !string.IsNullOrEmpty(input[0])) { texture = context.BuildAndLoadAsset <TextureContent, Texture2DContent>( new ExternalReference <TextureContent>(input[0]), null); texture.ConvertBitmapType(typeof(PixelBitmapContent <float>)); bitmapR = (PixelBitmapContent <float>)texture.Mipmaps[0]; width = bitmapR.Width; height = bitmapR.Height; } if (input.Length > 1 && !string.IsNullOrEmpty(input[1])) { texture = context.BuildAndLoadAsset <TextureContent, Texture2DContent>( new ExternalReference <TextureContent>(input[1]), null); texture.ConvertBitmapType(typeof(PixelBitmapContent <float>)); bitmapG = (PixelBitmapContent <float>)texture.Mipmaps[0]; width = bitmapG.Width; height = bitmapG.Height; } if (input.Length > 2 && !string.IsNullOrEmpty(input[2])) { texture = context.BuildAndLoadAsset <TextureContent, Texture2DContent>( new ExternalReference <TextureContent>(input[2]), null); texture.ConvertBitmapType(typeof(PixelBitmapContent <float>)); bitmapB = (PixelBitmapContent <float>)texture.Mipmaps[0]; width = bitmapB.Width; height = bitmapB.Height; } if (input.Length > 3 && !string.IsNullOrEmpty(input[3])) { texture = context.BuildAndLoadAsset <TextureContent, Texture2DContent>( new ExternalReference <TextureContent>(input[3]), null); texture.ConvertBitmapType(typeof(PixelBitmapContent <float>)); bitmapA = (PixelBitmapContent <float>)texture.Mipmaps[0]; width = bitmapA.Width; height = bitmapA.Height; } // In case no alpha texture is specified. width = Math.Max(1, width); height = Math.Max(1, height); PixelBitmapContent <Vector4> bitmap = new PixelBitmapContent <Vector4>(width, height); for (int y = 0; y < height; ++y) { for (int x = 0; x < width; ++x) { var color = new Vector4( bitmapR != null ? bitmapR.GetPixel(x, y) : GenerateBaseLayer ? 1 : 0, bitmapG != null ? bitmapG.GetPixel(x, y) : 0, bitmapB != null ? bitmapB.GetPixel(x, y) : 0, bitmapA != null ? bitmapA.GetPixel(x, y) : 0); color.Z = Math.Min(color.Z, 1 - color.W); color.Y = Math.Min(color.Y, 1 - color.W - color.Z); color.X = Math.Min(color.X, 1 - color.W - color.Z - color.Y); bitmap.SetPixel(x, y, color); } } Texture2DContent result = new Texture2DContent(); result.Mipmaps = new MipmapChain(bitmap); result.ConvertBitmapType(typeof(PixelBitmapContent <Color>)); return(result); }
PixelBitmapContent <Color> CreateNormalMap(PixelBitmapContent <Color> input) { int width = input.Width; int height = input.Height; PixelBitmapContent <Color> result = new PixelBitmapContent <Color>(width, height); float h1, h2, h3, h4; for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++) { if (x < width - 1) { h1 = ((float)input.GetPixel(x + 1, y).R / 255.0f); } else // wrap x to other side of texture. { h1 = ((float)input.GetPixel(0, y).R / 255.0f); } if (x > 0) { h3 = ((float)input.GetPixel(x - 1, y).R / 255.0f); } else // Wrap x to other side of texture. { h3 = ((float)input.GetPixel((width - 1), y).R / 255.0f); } if (y < height - 1) { h2 = ((float)input.GetPixel(x, y + 1).R / 255.0f); } else // Wrap y to other side of texture { h2 = ((float)input.GetPixel(x, 0).R / 255.0f); } if (y > 0) { h4 = (float)(input.GetPixel(x, y - 1).R / 255.0f); } else // Wrap y to other side of texture { h4 = (float)(input.GetPixel(x, (height - 1)).R / 255.0f); } Vector3 v1 = new Vector3(1.0f, 0.0f, (h1 - h3)); Vector3 v2 = new Vector3(0.0f, 1.0f, (h2 - h4)); Vector3 normal = Vector3.Cross(v1, v2); normal.Normalize(); normal.X = (normal.X + 1.0f) * 0.5f; normal.Y = (normal.Y + 1.0f) * 0.5f; normal.Z = (normal.Z + 1.0f) * 0.5f; result.SetPixel(x, y, new Color(normal)); } } return(result); }
public override TextureContent Process(TextureContent input, ContentProcessorContext context) { string[] strs = context.OutputFilename.Split('\\'); /* // If assigning this processor to all textures, use something like this to only apply to certain folders * if (strs.Length > 2 && strs[strs.Length - 2] == "Animations") * { } */ //write_debug(context.OutputDirectory); //write_debug(context.OutputFilename); bool battler = (strs.Length > 2 && strs[strs.Length - 2] == "Battlers"); Dictionary <Color, int> palette = new Dictionary <Color, int>(); Dictionary <string, Color[]> palette_data = context.BuildAndLoadAsset <string, Dictionary <string, Color[]> >(new ExternalReference <string>(@"BattlerPalettes.xml"), ""); string filename = Path.GetFileNameWithoutExtension(context.OutputFilename); if (!palette_data.ContainsKey(filename)) { filename = filename.Split('-')[0]; } if (palette_data.ContainsKey(filename)) { for (int i = 0; i < palette_data[filename].Length; i++) { if (!palette.ContainsKey(palette_data[filename][i])) { palette.Add(palette_data[filename][i], i); } } } // The process for getting to this point has changed, so now if there is no palette entry for a texture it shouldn't be edited at all else { return(base.Process(input, context)); } // Otherwise we have palette data and the image will be remapped to color indices on the red channel input.ConvertBitmapType(typeof(PixelBitmapContent <Color>)); foreach (MipmapChain image_face in input.Faces) { for (int i = 0; i < image_face.Count; i++) { PixelBitmapContent <Color> mip = (PixelBitmapContent <Color>)image_face[i]; Color original, edited; // Go through the whole image for (int y = 0; y < mip.Height; y++) { for (int x = 0; x < mip.Width; x++) { original = mip.GetPixel(x, y); // If this color isn't already in the palette, /leave the color alone/ // This is a new change to leave unpaletted colors alone if (original.A > 0 && palette.ContainsKey(original)) { edited = new Color((palette[original] * 1) % 256, 0, 0, original.A); mip.SetPixel(x, y, edited); } } } } } /* * if (false) * { * //write_debug(originalFilename + ", " + palette.Count.ToString()); * write_debug(originalFilename + ", " + new_colors.ToString() + "/" + palette.Count.ToString()); * for (int i = base_count; i < palette.Count; i++) * foreach (KeyValuePair<Color, int> entry in palette) * if (entry.Value == i) * { * if (entry.Key.A > 0) * write_debug(entry.Key.ToString()); * break; * } * }*/ return(base.Process(input, context)); }
/// <summary> /// 文字グリフからテクスチャを生成する /// </summary> /// <param name="layouter"></param> void ProcessTexture(BoxLayouter layouter) { // レイアウト、複数の矩形を1つの矩形内に並べる int width, height; layouter.Layout(out width, out height); // 配置後のグリフを画像へ書き込む var bitmap = new PixelBitmapContent <Color>(width, height); for (int i = 0; i < layouter.Items.Count; ++i) { // グリフ位置情報の追加 var rc = fontContent.Glyphs[i]; rc.X = layouter.Items[i].Bounds.X; rc.Y = layouter.Items[i].Bounds.Y; fontContent.Glyphs[i] = rc; // 個々のグリフ画像をひとつの画像へ追加する var pixels = layouter.Items[i].Tag as uint[]; int idx = 0; for (int y = 0; y < rc.Height; ++y) { for (int x = 0; x < rc.Width; ++x) { int r = (int)((pixels[idx] & 0x00ff0000) >> 16); int g = (int)((pixels[idx] & 0x0000ff00) >> 8); int b = (int)((pixels[idx] & 0x000000ff) >> 0); int a = (int)((pixels[idx] & 0xff000000) >> 24); bitmap.SetPixel(rc.X + x, rc.Y + y, new Color(r, g, b, a)); ++idx; } } } // 文字画像をまとめた画像をテクスチャへ変換する fontContent.Texture = new Texture2DContent(); switch (TextureFormat) { case WpfTextureFormat.Auto: if (UseGradient) { // グラデーション使用していればColorフォーマット fontContent.Texture.Mipmaps = bitmap; } else if (OutlineThickness > 0) { // アウトラインのみ使用していればBgra4444フォーマット fontContent.Texture.Mipmaps = bitmap; fontContent.Texture.ConvertBitmapType( typeof(PixelBitmapContent <Bgra4444>)); } else { // それ以外の単色フォントであれば単色に特化したDXT3圧縮をする fontContent.Texture.Mipmaps = SingleColorDxtCompressor.Compress(bitmap, FontColor); } break; case WpfTextureFormat.Bgra4444: fontContent.Texture.Mipmaps = bitmap; fontContent.Texture.ConvertBitmapType( typeof(PixelBitmapContent <Bgra4444>)); break; case WpfTextureFormat.Color: fontContent.Texture.Mipmaps = bitmap; break; } }