Categories: MSDN / DotNet / Java / Scripts / Linux / PHP Ask - La ask - La Answer

ID3DXFont poor quality

Hello,

I am drawing some text with ID3DXFont, and the quality is very poor. Antialias is present, but the font still has jagged edges.

The font is drawn on a rendertarget texture that is then rendered to screen with ID3DXSprite. Some minor scaling (+/- 1 pixel) does seem to occur on anything that gets drawn to the texture and I don't know why, but that wouldn't be enough to affect the font quality as much as it seems to be affected.

Here's an example:

D3DXCreateFont(pDevice,

-18, // height
0, // width
FW_NORMAL, // weight
1, // mip levels
FALSE, // italic
DEFAULT_CHARSET, // charset
OUT_DEFAULT_PRECIS, PROOF_QUALITY, DEFAULT_PITCH | FF_DONTCARE,
_T("arial"), // facename
&pFont);

And here's how that example looks in game:
http://img256.imageshack.us/img256/1447/testingame2ef.jpg

Here's what the arial font of just about the same size looks like in my Notepad:
http://img397.imageshack.us/img397/9039/textnotepad4tw.jpg
[1215 byte] By [val] at [2007-11-11 8:49:43]
# 1 Re: ID3DXFont poor quality
Actually it does look like poor scaling to me -- its amazing how much a couple of pixels can mess things up.

What you might try is pop this same font parameters into a rich edit box and play with it until it looks "right" and then pop it back to graphics mode and see if its any better. Notepad wont help, you need all the parameters to match up, and notepad will use "good" defaults.
jonnin at 2007-11-11 21:01:03 >
# 2 Re: ID3DXFont poor quality
Can you suggest something as per unwanted scaling then?

I noticed that when I draw the same text on the default rendertarget (in another part of my program, with another font object created the same way) the text appears ok.

I am not doing anything special as far as I can tell...

Creating the buffer:

CreateTexture((UINT)nWidth, (UINT)nHeight, 1, D3DUSAGE_RENDERTARGET, nBufferFormat, D3DPOOL_DEFAULT, &pBuffer, NULL)
// let's say width=1024 and height=1024, nBufferFormat = X8R8G8B8

Then retrieve the current render target, save it, set the created texture as a new render target, render stuff to it (calling BeginSprite before starting and EndSprite after all is done), then restore the old target. Then render the created texture with a source rect = {0, 0, nWidth, nHeight} by using ID3DXSprite on the default target.

Just the usual stuff, right? I even made a dummy program to test this, and the test looked just as wrong.

http://img352.imageshack.us/img352/50/dummytest3pw.jpg

And really, this doesn't even look like a scaling error anymore... Looks like some kind of alpha blending/testing error :confused:

Thanks, I hope somebody can help.
val at 2007-11-11 21:01:57 >
# 3 Re: ID3DXFont poor quality
Im stumped too now, you are right its not scaling or not *just* scaling. The first image looked like it was pushing say 100 pixels into 95 sort of squishing (as textures can do sometimes) but this one just looks wrong, like the wrong filters (alias, blending, lighting? something) are applied. I will dig around, but I really do not know what it could be.
jonnin at 2007-11-11 21:02:56 >
# 4 Re: ID3DXFont poor quality
When the text is drawn on a dark background with a light color, it looks fine. But when it is drawn on a light background with a dark color, it still looks horrible.

Here's a link to the dummy project code:
http://www.freewebs.com/valsoftfl/BadText.zip
val at 2007-11-11 21:04:07 >
# 5 Re: ID3DXFont poor quality
Hello val,

Recently I came across the same problem you have. I want to prerender a text drawn through ID3DXFont on a render target texture for performance considerations. But when I scaled the texture to a size smaller than the size of original text then the text looked awfull. I did a lot of tests and finally came to the conclusion that ID3DXFont does something "extra" to the text when it draws it on a "normal" surface directly, because even if I scale the text using ID3DXFont on the render target and then draw the render target as is the text still looks very good. So I realized that it was mipmaping that ID3DXFont actaully adds to the text. The only solution in this case that worked for me was to turn on the automatic generation of mipmap levels for the render target texture too. So you should modify the texture creation as follows:

CreateTexture((UINT)nWidth, (UINT)nHeight, 0, D3DUSAGE_RENDERTARGET | D3DUSAGE_AUTOGENMIPMAP, nBufferFormat, D3DPOOL_DEFAULT, &pBuffer, NULL)

This way you tell the device to automatically generate all neccessary mipmap levels down to 1x1 pixel for the render target texture. This solution was the only one that made my text rendered via render target to look the same quallity the standard ID3DXFont Draw would render it. I hope that this will work for you too and I'm sorry if the answer comes maybe too late.

Regards,
Ivo
X3m at 2007-11-11 21:05:06 >
# 6 Re: ID3DXFont poor quality
It's never too late, X3m! I labeled this problem as "deferred" and went to work on other stuff. Two days ago, I hit this problem again and put it on my active list, planning to work on in within the next week.

I will try this as soon as I get home. Note that I tried drawing black text on white background without any sort of render target texture (on the default backbuffer) and the result is still the same, so I doubt this can be a target scaling problem, which is likely to rule out mipmapping solution.

[EDIT]

Bad news, the font renders just as bad on a default backbuffer when font color is dark and the background is light. Obviously, it's impossible to create a default backbuffer manually with mipmapping flags on. I don't want to use GDI's fonts because then I would need to create a rendertarget for each string of text - but GDI fonts render 100% fine on any rendertarget, and D3DX fonts do not.
val at 2007-11-11 21:06:09 >
# 7 Re: ID3DXFont poor quality
Here's a link to the updated dummy project (VC++6 workspace):
http://www.freewebs.com/valsoftfl/badtext.zip
val at 2007-11-11 21:07:07 >
# 8 Re: ID3DXFont poor quality
Why don't you try to use an ID3DXSprite when drawing with:
g_pTextFont->DrawText(NULL, "WHAT'S WRONG WITH ANTIALIAS?!", -1, (RECT*)&RC_DRAW, DT_SINGLELINE | DT_NOCLIP, D3DCOLOR_ARGB(255, 0, 0, 0));

Instead of NULL set an initialized ID3DXSprite for the first param. Don't forget the Sprite's begin end pair of methods. You can also set a new texture min, mag and mip filters immediatelly after sprite begin, using:
SetSamplerState etc
You can use anisotropic filter for instance. Dont forget to set the MaxAnisotropy in that case too.

Looking forward to hear from you if this could be of any help.
X3m at 2007-11-11 21:08:11 >
# 9 Re: ID3DXFont poor quality
You can also try to do the following:
Initialize the ID3DXFont with a really big Font size.
Then use the SetTRansform of ID3DXSprite to scale the font to smaller size.
X3m at 2007-11-11 21:09:03 >
# 10 Re: ID3DXFont poor quality
I tried all of your suggestions, nothing worked. Note that I've never used anisotropic filters before so I may have made a mistake setting them up... but I doubt.

BTW, I remember that a long time ago, I rendered black text on an ARGB texture surface and then it looked fine... But I failed to reproduce this behavior ever again.

[EDIT]

Download link for updated dummy test:
http://www.freewebs.com/valsoftfl/badtext.zip
val at 2007-11-11 21:10:04 >
# 11 Re: ID3DXFont poor quality
BTW, I remember that a long time ago, I rendered black text on an ARGB texture surface and then it looked fine... But I failed to reproduce this behavior ever again.
Actually I use A8R8G8B8 as a render target and it works fine. All you need is to fill the background with ARGB = 0,255,255,255 then you render the text with fully white color (255,255,255,255) in your A8R8G8B8 render target. Then in your ID3DXSprite Draw function you set the last param to the color you want the text to be displayed with (in your case black).
This is how it works for me and I'm happy with the quallity.
X3m at 2007-11-11 21:11:08 >