DirectX 9 Customs Fonts
Hi,
I have to draw text using a lookup table from a bitmap. I do not want to use D3DXFont since I have to apply an outline to each caracters after drawing it on the bitmap with TextOut API. I will use GDI+ for the Outline.
I have use the following code : http://www.gamedev.net/community/forums/viewreply.asp?ID=1098396
The problem is that the contour of the letter is not very precise. In conclusion it is not pretty. I have save the bitmap generated on hard disk and then opened it with MSPaint and the letter a perfectly smooth, I mean this is not the same result as what I have on the screen with Direct3D...
Here is a screenshot : http://i175.photobucket.com/albums/w155/Feltar/TextOutD3D.png
What can I do to improve the quality ? Or what do I have to do to improve the rendering quality ?
Best regards
PS : Cross posting : http://forums.xna.com/forums/p/48445/290551.aspx#290551
[Edited by - Erakis on February 25, 2010 11:35:32 AM]
Hi,
Here is how I'm rendering text to the Direct3D surface. First of all I'm pre-rendering all the font characters into a 32bpp bitmap.
Here is the result : http://i175.photobucket.com/albums/w155/Feltar/Direct3DLookUpFont.png
To add an outline to each caracters I'm using GDIPlus :
Now from this Bitmap, I create a Direct3D texture and I copy transfert all the pixels. But during the transfert I need to simulate the alpha. I other words, I need to set an alpha = 0 for each pixel of the background and set an alpha of 255 to all other. Here is how I do it :
And then from the texture I create a SPRITE. The result without the Outline is fair but not perfect as if I was writing text over a bitmap using MSPaint. But as you can see in the preceding image "Direct3DLookUpFont.png" some pixels of the background left mixed with those of the outline.
How can I get a better transparency ?
I feel the way I simulate the alpha value is not good... Else is someone here have an idea on how to better proceed, I am really desperate. This is 1 week as I try to display text with outline on a Direct3D surface.
Best regards
Here is how I'm rendering text to the Direct3D surface. First of all I'm pre-rendering all the font characters into a 32bpp bitmap.
Here is the result : http://i175.photobucket.com/albums/w155/Feltar/Direct3DLookUpFont.png
To add an outline to each caracters I'm using GDIPlus :
Graphics graphics(hdc); graphics.SetSmoothingMode(SmoothingModeAntiAlias); graphics.SetInterpolationMode(InterpolationModeHighQualityBicubic); GraphicsPath path; FontFamily fontFamily(m_szFontName); StringFormat strformat; // For each caracters loop ... path.Reset(); s = path.AddString(szTempString, 1, &fontFamily, FontstyleRegular, 32, PointF(unTextOutX, unTextOutY), &strformat); Color cOutlineColor; cOutlineColor.SetFromCOLORREF( outlineColor ); Pen pen(cOutlineColor, 2); pen.SetLineJoin(LineJoinRound); s = graphics.DrawPath(&pen, &path); Color cTextColor; cTextColor.SetFromCOLORREF(color); SolidBrush brush(cTextColor); graphics.FillPath(&brush, &path);
Now from this Bitmap, I create a Direct3D texture and I copy transfert all the pixels. But during the transfert I need to simulate the alpha. I other words, I need to set an alpha = 0 for each pixel of the background and set an alpha of 255 to all other. Here is how I do it :
DWORD* pDestData = (DWORD*)d3dLockedRect.pBits; DWORD dwTransparentColor = ((backgroundColor >> 16) & 0x000000ff) | ((backgroundColor << 16) & 0x00ff0000) | (backgroundColor & 0x0000ff00); pBitmapBits += m_unTextureWidth * (m_unTextureHeight - 1); for (UINT y = 0; y < m_unTextureHeight; ++y ) { DWORD* pRow = pBitmapBits; for (UINT k = 0; k < m_unTextureWidth; ++k, ++pRow ) { if (*pRow == dwTransparentColor) { *pRow = 0x00000000; } else { *pRow |= 0xff000000; } } memcpy(pDestData, pBitmapBits, m_unTextureWidth * sizeof(DWORD)); pDestData += ( d3dLockedRect.Pitch / 4 ); pBitmapBits -= m_unTextureWidth; } m_CharactersTexture->UnlockRect( 0 );
And then from the texture I create a SPRITE. The result without the Outline is fair but not perfect as if I was writing text over a bitmap using MSPaint. But as you can see in the preceding image "Direct3DLookUpFont.png" some pixels of the background left mixed with those of the outline.
How can I get a better transparency ?
I feel the way I simulate the alpha value is not good... Else is someone here have an idea on how to better proceed, I am really desperate. This is 1 week as I try to display text with outline on a Direct3D surface.
Best regards
Your current technique is formally called "color keying". It is not widely used in modern text rendering because - as you can see - the edges of the opacity are aliased.
GDI+ supports real alpha channels. If you create the temp bitmap with alpha, you can just copy the values to your D3D texture. Before drawing your text, be sure to clear the alpha channel to 0 so you actually get a transparent background.
GDI+ supports real alpha channels. If you create the temp bitmap with alpha, you can just copy the values to your D3D texture. Before drawing your text, be sure to clear the alpha channel to 0 so you actually get a transparent background.
Also, I note that you create the Graphics object against a HDC. The HDC is a classical Win32 device context which has poor native alpha channel support (though it can support some simple alpha ops on XP and later).
For the temp bitmap (to which you initially draw the text), consider using the GDI+ Bitmap class instead. It is very robust and you can create your Graphics object directly against it.
For the temp bitmap (to which you initially draw the text), consider using the GDI+ Bitmap class instead. It is very robust and you can create your Graphics object directly against it.
Sorry for my ignorance, but how to realize a bitmap with real alpha channels ?
Also if I'm using bitmap that support real alpha channels, will I get better result ? I mean sharpness edges without jagged pixels ?
So If I well understand I proceeed the same way but I use a GDI+ Bitmap class instead. And just before creating the texture I set the alpha value of each pixel having the same color as my background to 0 ?
If I use the GDI+ Bitmap class, I presume that I create the graphic object from the GDI+ Bitmap (PixelFormat32bppARGB ) ?
Thank you very much, it's very appreciated that you help me
Best regards
Also if I'm using bitmap that support real alpha channels, will I get better result ? I mean sharpness edges without jagged pixels ?
So If I well understand I proceeed the same way but I use a GDI+ Bitmap class instead. And just before creating the texture I set the alpha value of each pixel having the same color as my background to 0 ?
If I use the GDI+ Bitmap class, I presume that I create the graphic object from the GDI+ Bitmap (PixelFormat32bppARGB ) ?
Thank you very much, it's very appreciated that you help me
Best regards
To create a Bitmap with an alpha channel, just specify a pixel format that includes an alpha component when using the Bitmap ctor.
If you use a proper alpha channel, the antialiasing of the text carries through your pipeline. While it doesn't magically make the text sharper (increasing resolution will), it is more legible.
The Graphics object (which you can use to draw to a Bitmap, since Bitmap derives from Image) has a Clear method that you can use to init the pixels to a given value. This applies to the alpha channel too.
First, you should clear the Bitmap. Then, you draw your antialiased text into it. Finally, copy all the data (including the alpha as is) from the Bitmap to the D3D texture. You don't need any manual per-pixel processing here.
If you use a proper alpha channel, the antialiasing of the text carries through your pipeline. While it doesn't magically make the text sharper (increasing resolution will), it is more legible.
The Graphics object (which you can use to draw to a Bitmap, since Bitmap derives from Image) has a Clear method that you can use to init the pixels to a given value. This applies to the alpha channel too.
First, you should clear the Bitmap. Then, you draw your antialiased text into it. Finally, copy all the data (including the alpha as is) from the Bitmap to the D3D texture. You don't need any manual per-pixel processing here.
Forgot to mention that you can control the text rendering method by using Graphics::SetTextRenderingHint. I think that antialiasing is off by default.
Hi,
Nik02 let me tell you a thousand thanks you've made my day :)
The result is from far better quality than the traditionnal GDI.
And I no longer need to manually set the alpha component as I did before. A simple "memcpy" call do the trick and all the alpha values are maintained from the bitmap to the texture to allow transparancy. Exactly as you said. You're a pro !
Best regards
Nik02 let me tell you a thousand thanks you've made my day :)
The result is from far better quality than the traditionnal GDI.
And I no longer need to manually set the alpha component as I did before. A simple "memcpy" call do the trick and all the alpha values are maintained from the bitmap to the texture to allow transparancy. Exactly as you said. You're a pro !
Best regards
This topic is closed to new replies.
Advertisement
Popular Topics
Advertisement