C#, XNA, How to select image minimalization filter in 2D mode?
The problem is that I can't select minimalization filter for Texture2D
scaling. There is MinFilter
GraphicsDevice.SamplerS开发者_JS百科tates[0].MinFilter
But it's not working. When I try to assign some filter it just changes back to the Linear.
Is there a way to implement my own filter or how to select one of the available?
I read an article on Shawn Hargreaves' blog a while back that said, "SpriteBatch will automatically set what it needs for drawing in 2D...", which includes setting the MinFilter to Linear.
So, you could try what this article says to do and set your SpriteSortMode to Immediate. Then after your SpriteBatch.Begin call, you can set the MinFilter to whatever you want, and it should retain that setting when it draws the sprite.
I have one answer to my own question and i think it will be better to post a new answer for readability.
private Texture2D Scale(GraphicsDevice gd, Texture2D texture, float scale)
{
int sourceWidth = texture.Width;
int sourceHeight = texture.Height;
int destWidth = (int)(sourceWidth * scale);
int destHeight = (int)(sourceHeight * scale);
//convert texture into bitmap
byte[] textureData = new byte[4 * sourceWidth * sourceHeight];
texture.GetData<byte>(textureData);
System.Drawing.Bitmap bmp = new System.Drawing.Bitmap(sourceWidth, sourceHeight, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
System.Drawing.Imaging.BitmapData bmpData = bmp.LockBits(new System.Drawing.Rectangle(0, 0, sourceWidth, sourceHeight), System.Drawing.Imaging.ImageLockMode.WriteOnly,
System.Drawing.Imaging.PixelFormat.Format32bppArgb);
IntPtr safePtr = bmpData.Scan0;
System.Runtime.InteropServices.Marshal.Copy(textureData, 0, safePtr, textureData.Length);
bmp.UnlockBits(bmpData);
//output bitmap
System.Drawing.Image outputImage = new System.Drawing.Bitmap(destWidth, destHeight, System.Drawing.Imaging.PixelFormat.Format24bppRgb);
System.Drawing.Graphics grPhoto = System.Drawing.Graphics.FromImage(outputImage);
grPhoto.InterpolationMode = (System.Drawing.Drawing2D.InterpolationMode)(interpolationMode);
grPhoto.DrawImage((System.Drawing.Image)bmp, new System.Drawing.Rectangle(0, 0, destWidth, destHeight),
new System.Drawing.Rectangle(0, 0, sourceWidth, sourceHeight), System.Drawing.GraphicsUnit.Pixel);
grPhoto.Dispose();
textureData = new byte[4 * sourceWidth * sourceHeight];
MemoryStream ms = new MemoryStream();
((System.Drawing.Bitmap)outputImage).Save(ms, System.Drawing.Imaging.ImageFormat.Bmp);
ms.Seek(0, SeekOrigin.Begin);
Texture2D result = Texture2D.FromFile(gd, ms);
ms.Dispose();
return result;
}
This metod runs in about 20ms - 100ms depending on interpolation mode, maybe someone will find it usefull. Is there a way to optimize it? I dont need 32bit support but there seems to be no way to set it to 24. I found different sizing algorithms http://www.codeproject.com/KB/GDI-plus/imgresizoutperfgdiplus.aspx but they are slow.
Is there a way to implement these methods using speed of graphic card?
The best approach to minification is to create mipmaps for the textures as the hardware and the directx pipeline is optimized to use mipmaps in the best way possible depending on the final drawing size of the texture.
Here's a quote from MSDN on mipmaps
The most popular approach to minification is to create mipmaps for each texture. A mipmap is a pre-shrunk texture, normally half the size of the original. The mipmap itself then gets mipmapped, and this process continues until a 1x1 texture is created. This is the final mipmap for the texture. You can think of mipmaps as a chain, starting with the original texture and becoming smaller and smaller until the 1 texel texture is reached. When minification is needed, first the appropriate mipmapped texture is chosen, then that mipmap is applied to the object, with real-time texture filtering if needed. The default Texture processor for the Content Pipeline has an option to generate mipmaps automatically.
You can enable automatic mipmap generation using the content pipeline or Texture.GenerateMipMaps to generate mipmaps at runtime for a render target texture.
The best way I can see, when using spriteBatch (2D mode) is to use one of the longer spriteBatch.Begin() overloads, specifically the one here works for me:
spriteBatch.Begin(SpriteSortMode.Immediate, BlendState.AlphaBlend, SamplerState.PointClamp, DepthStencilState.Default,RasterizerState.CullNone);
the important part is the SamplerState.PointClamp, which tells all draw() calls until the next spriteBatch.end() to use point- sampling for both min and max. There are several other options in SamplerState, which I'm sure intelisense can describe better than I.
for reference: http://msdn.microsoft.com/en-us/library/ff433699.aspx
精彩评论