Quick question about textures

Started by
6 comments, last by TomNZ 16 years, 6 months ago
I am currently working on a pet project partially as a learning exercise and partially because I think it would be a pretty nifty thing to have :D In short, it involves wrapping a C# app around a console to display the output in a creative way (ie. as Direct3D objects, offering some interesting possibilities for visualising things such as multiple consoles open simultaneously etc). The issue I'm currently having is this: I am displaying each line output from the console as a rendered texture on a simple mesh primitive (four vertices making a rectangle). As you can see from the pictures below, when zoomed in close these textures have a nice anti-aliased appearance. HOWEVER when zoomed out to the level I wish to be zoomed at, this anti aliased look is all but gone and the text becomes barely discernible. Is there something I can do to easily fix this or do I need to look into things such as mip mapping and texture filtering? Zoomed out Zoomed in Also to actually generate these textures (using Graphics.DrawString currently) can be considerably slow. Is there a more efficient way?
Advertisement
You'll have to generate mipmaps every frame if you want to reduce the minification artifacts.
What minification, magnification and mip filters are you using? In general LINEAR filtering breaks down beyond a scale of 2 so you may need to be careful what size you render your text with.

Also, the text rendering should be handed over to Win32 (although not 100% sure with MDX) so you're limited in the AA effect you can achieve - any flag suggesting this to DrawString() will use Windows-provided methods rather than Direct3D-provided ones...

As for text rendering performance - yes, it is slow. Always has been, always will be [smile] You can mitigate it using clever algorithms though. I had great success with temporal caching based on the simple observation that if the text doesn't change every frame why am I re-rendering it every frame?

hth
Jack

<hr align="left" width="25%" />
Jack Hoxley <small>[</small><small> Forum FAQ | Revised FAQ | MVP Profile | Developer Journal ]</small>

Quote:Original post by jollyjeffers
What minification, magnification and mip filters are you using? In general LINEAR filtering breaks down beyond a scale of 2 so you may need to be careful what size you render your text with.

As far as I'm aware I'm not using any. That's part of the problem, I'm not sure how to go about doing it. Like if it's as simple as

device.RenderState.TextureFiltering = TextureFiltering.Bilinear; // Ya I just made this up >_>


then feel free to fill me in. Otherwise I'll go away and do some research on how to properly do mip mapping etc.

Quote:Original post by jollyjeffers
Also, the text rendering should be handed over to Win32 (although not 100% sure with MDX) so you're limited in the AA effect you can achieve - any flag suggesting this to DrawString() will use Windows-provided methods rather than Direct3D-provided ones...

As for text rendering performance - yes, it is slow. Always has been, always will be [smile] You can mitigate it using clever algorithms though. I had great success with temporal caching based on the simple observation that if the text doesn't change every frame why am I re-rendering it every frame?



Not entirely sure what you mean by handing rendering over to Win32. I currently use a setup/teardown system where the textures I use are generated only on instantiation of a new line and on a device reset. It still takes a good 250-500ms to generate a single line though. The code used to generate the texture is as follows:

// Set up the line textureBitmap b = new Bitmap(1, 1);Graphics g = Graphics.FromImage(b);// Calculate the text metricsSizeF stringSize = g.MeasureString(_line, new System.Drawing.Font(_fontFace, _fontSize));_lineWidth = Size.Truncate(stringSize).Width;_lineHeight = Size.Truncate(stringSize).Height;b = new Bitmap(_lineWidth, _lineHeight);g = Graphics.FromImage(b);// Antialiasingg.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;g.TextRenderingHint = System.Drawing.Text.TextRenderingHint.AntiAliasGridFit;g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;// Fill a black background then draw the text over topg.FillRectangle(new SolidBrush(Color.Black), new Rectangle(0, 0, b.Width, b.Height));g.DrawString(_line, new System.Drawing.Font(_fontFace, _fontSize), new SolidBrush(Color.White), new PointF(0, 0));_lineTexture = Texture.FromBitmap(device, b, Usage.Dynamic, Pool.Default);
Uploaded a vid so you can see what I mean about how slow it is to generate lines. I just did "cd \" then "dir" to get it to spew a few lines. Interestingly it doesn't block rendering or anything while it is creating the textures. You can also see where my animation is at currently when I hit page up/down a few times near the end.

">
When optimizing you need to find out exactly where the bottleneck is. I'd recommend timing each of the calls in that texture generation code first of all to get an idea where the slowness is coming from.

I'd also investigate the performance effect of those antialiasing settings. Maybe you don't really need bicubic.

My guess is that it's probably related to this problem. Have you tried running without the debugger attached?

Also why are you using default pool dynamic textures, when I presume they won't actually ever change, or at least only change rarely? I'd recommend managed pool and non dynamic.
Ahh yes it appears you are correct. Runs fine without the debugger attached, and the line

_lineTexture = Texture.FromBitmap(device, b, Usage.Dynamic, Pool.Default);


takes in the region of 500ms with the debugger attached. Very frustrating. Not too keen on writing unsafe code and using Texture.FromStream instead seemed to have no effect at all. At least I know what is causing it though, I'm sure I can work around it :)
Probably not best practice, but this seems to solve the problem for the lacking minification:

if (device.DeviceCaps.TextureFilterCaps.SupportsMinifyAnisotropic)    device.SamplerState[0].MinFilter = TextureFilter.Anisotropic;

This topic is closed to new replies.

Advertisement