   Bitmap Font Rendering
  I am generating a bitmap, however, I am not sure on how to render the UV's and placement. I had a thread like this once before, but it was too loosely worded as to what I was looking to do.What I am doing right now is creating a large 1024x1024 image with characters evenly placed every 64 pixels. Here is an example of what I mean. I then save the bitmap X/Y information to a file (which is all multiples of 64).However, I am not sure how to properly use this information and bitmap to render. This falls into two different categories, UV generation and kerning. Now I believe I know how to do both of these, however, when I attempt to couple them together I will get horrendous results.For example, I am trying to render two different text arrays, "123" and "njfb". While ignoring the texture quality (I will be increasing the texture to provide more detail once I fix this issue), here is what it looks like when I try to render them.Now for the algorithm. I am doing my letter placement with both GetABCWidth and GetKerningPairs. I am using GetABCWidth for the width of the characters, then I am getting the kerning information for adjust the characters. Does anyone have any suggestions on how I can implement my own bitmap font renderer? I am trying to do this without using external libraries such as angel bitmap tool or freetype. I also want to stick to the way the bitmap font sheet is generated so I can do extra effects in the future.Rendering Algorithmfor(U32 c = 0, vertexID = 0, i = 0; c < numberOfCharacters; ++c, vertexID += 4, i += 6){ObtainCharInformation(fontName, m_Text[c]);letterWidth = (charInfo.A + charInfo.B + charInfo.C) * scale;if(c != 0){DWORD BytesReq = GetGlyphOutlineW(dc, m_Text[c], GGO_GRAY8_BITMAP, &gm, 0, 0, &mat);U8 * glyphImg= new U8[BytesReq];DWORD r = GetGlyphOutlineW(dc, m_Text[c], GGO_GRAY8_BITMAP, &gm, BytesReq, glyphImg, &mat);for (int k=0; k<nKerningPairs; k++) {if ((kerningpairs[k].wFirst == previousCharIndex) && (kerningpairs[k].wSecond == m_Text[c])) {letterBottomLeftX += (kerningpairs[k].iKernAmount * scale);break;}}letterBottomLeftX -= (gm.gmCellIncX * scale);}SetVertex(letterBottomLeftX, 0.0f, zFight, vertexID);SetVertex(letterBottomLeftX, letterHeight, zFight, vertexID + 1);SetVertex(letterBottomLeftX + letterWidth, letterHeight, zFight, vertexID + 2);SetVertex(letterBottomLeftX + letterWidth, 0.0f, zFight, vertexID + 3);zFight -= 0.001f;float BottomLeftX = (F32)(charInfo.bitmapXOrigin) / (float)m_BitmapWidth;float BottomLeftY = (F32)(charInfo.bitmapYOrigin + charInfo.charBitmapHeight) / (float)m_BitmapWidth;float TopLeftX = BottomLeftX;float TopLeftY = (F32)(charInfo.bitmapYOrigin) / (float)m_BitmapWidth;float TopRightX = (F32)(charInfo.bitmapXOrigin + charInfo.B - charInfo.C) / (float)m_BitmapWidth;float TopRightY = TopLeftY;float BottomRightX = TopRightX;float BottomRightY = BottomLeftY;SetTextureCoordinate(TopLeftX, TopLeftY, vertexID + 1);SetTextureCoordinate(BottomLeftX, BottomLeftY, vertexID + 0);SetTextureCoordinate(BottomRightX, BottomRightY, vertexID + 3);SetTextureCoordinate(TopRightX, TopRightY, vertexID + 2);/// index settingletterBottomLeftX += letterWidth;previousCharIndex = m_Text[c];}EDIT: Since the tags are broken, here is a link to the code http://codepad.org/AVHrDxiF[They're broken? They seem to work fine for me and everyone else. -Zahlman]   
  I was just doing more or less the same thing using a custom font texture in OpenGL.  I don't know if you're using OpenGL or not, but if you are, be warned:  if you are using glBegin() and glEnd() for each letter, you could take a serious speed penalty.  On the computer I was working on, I went down to like 5 fps printing a sentence of around 800 characters.Now to answer your question:  it's apparent that the screen spacing isn't large enough, but as far as the poor-looking texture drawing, it would be hard to say what is going on without knowing what API you are using.   ;Quote:Original post by synth_catI was just doing more or less the same thing using a custom font texture in OpenGL.  I don't know if you're using OpenGL or not, but if you are, be warned:  if you are using glBegin() and glEnd() for each letter, you could take a serious speed penalty.  On the computer I was working on, I went down to like 5 fps printing a sentence of around 800 characters.Now to answer your question:  it's apparent that the screen spacing isn't large enough, but as far as the poor-looking texture drawing, it would be hard to say what is going on without knowing what API you are using.I am currently using DirectX. The big issue for me seems to be appropriate letter placing, although it could be that the letter placing is correct and that the uv's are wrong.I am creating multiple rectangles, then assigning them into the same vertex buffer to optimize the rendering.;  Without seeing all the tasteless global variables and getCharacterInformation() commenting is hard, however there are some issuesletterBottomLeftX -= (gm.gmCellIncX * scale);...letterBottomLeftX += letterWidth;It seems you are subtracting and then adding the width of your character, possibly in incoherent units, rather than only adding it once.float BottomLeftY = (F32)(charInfo.bitmapYOrigin + charInfo.charBitmapHeight) / (float)m_BitmapWidth;Wrong (it should be m_BitmapHeight), but the problem happens in the horizontal direction.float TopRightX = (F32)(charInfo.bitmapXOrigin + charInfo.B - charInfo.C) / (float)m_BitmapWidth;Subtracting the C width to draw from 0 to B-C makes no sense. Sensible ranges are from 0 or from A to A+B or A+B+C, including or not whitespace (and protruding glyph portions) on each side.Why don't you consolidate the 8 coordinates into 4, LeftX and RightX and BottomY and TopY? for (int k=0; k<nKerningPairs; k++) {   if ((kerningpairs[k].wFirst == previousCharIndex) && (kerningpairs[k].wSecond == m_Text[c]))   {    ... break;   }}What about std::map<std::pair<wchar_t,wchar_t>,float>? One other possible cause of error, not present in this code, is the agreement between the position of your glyphs  in the bitmap and their metrics in the font. You should compute and store all metrics and kerning data beforehand as you build your bitmap, never calling GetGlyphOutlineW() and GetCharABCWidths() in the text drawing routine.   ;Quote:Original post by LorenzoGattiWithout seeing all the tasteless global variables and getCharacterInformation() commenting is hard, however there are some issuesAll this is doing is querying a table generated from GetABCWidth's, nothing fancy. The table is created earlier so it does not have to happen during runtime.Quote:Original post by LorenzoGattiletterBottomLeftX -= (gm.gmCellIncX * scale);...letterBottomLeftX += letterWidth;It seems you are subtracting and then adding the width of your character, possibly in incoherent units, rather than only adding it once.How can I check the units? When I create the Font for Kerning, I do "SetMapMode(dc,MM_TEXT)".Quote:Original post by LorenzoGattifloat BottomLeftY = (F32)(charInfo.bitmapYOrigin + charInfo.charBitmapHeight) / (float)m_BitmapWidth;Wrong (it should be m_BitmapHeight), but the problem happens in the horizontal direction.Oh, that was a typo that I never noticed due to the fact they are the same. Thank you for pointing that outQuote:Original post by LorenzoGattifloat TopRightX = (F32)(charInfo.bitmapXOrigin + charInfo.B - charInfo.C) / (float)m_BitmapWidth;Subtracting the C width to draw from 0 to B-C makes no sense. Sensible ranges are from 0 or from A to A+B or A+B+C, including or not whitespace (and protruding glyph portions) on each side.I am not 100% sure what you mean, do you mean something likefloat TopRightX = (F32)(charInfo.bitmapXOrigin + charInfo.A + charInfo.B) / (float)m_BitmapWidth;Quote:Original post by LorenzoGattiWhy don't you consolidate the 8 coordinates into 4, LeftX and RightX and BottomY and TopY? I am going to, I just have them all seperated right now for testing.Quote:Original post by LorenzoGatti*** Source Snippet Removed ***What about std::map<std::pair<wchar_t,wchar_t>,float>? To which does this pertain to? For storing the values out of runtime? If so, I plan on doing that optimization once all of this is functional.Quote:Original post by LorenzoGattiOne other possible cause of error, not present in this code, is the agreement between the position of your glyphs  in the bitmap and their metrics in the font. This is all computed with a size 48 "Times New Roman" font, with no italics or anything else.;  There are couple issues you need to take care of when you handle font texture yourself:1. Half-Texel offset - http://msdn.microsoft.com/en-us/library/bb219690(VS.85).aspx2. Make sure your letter quad has exactly the same width/height in texels as the letter. That is not as easy as it sounds and can take a couple of long debugging sessions. Otherwise, you`ll always have artifacts due to interpolation - so make sure every pixel in texture corresponds to exactly one pixel on screen. 3. Texture Filtering - a hell breaks loose when you render fonts with bilinear filtering. That`s not to say you can`t have bilinear filtering on. You can, but you have to be aware of how it works so you aren`t surprised with results (e.g. on borders).4. Sanity Check - Always have a reference word rendered (with full size of the letter - i.e. a lot of empty space) so you can always compare the difference and rule out couple of rasterization artifacts.5. Have a font texture opened up in background (in PSP/Photoshop) with grid on, so you can always check if your offsets (start/end col/row) within 32x32 are correct.Not sure how many of those are you handling yourself, but this is a good start.A Half-Texel off is all you need to get a trash result.   ;Quote:Original post by VladRThere are couple issues you need to take care of when you handle font texture yourself:1. Half-Texel offset - http://msdn.microsoft.com/en-us/library/bb219690(VS.85).aspxI am using DirectX11, so this should not be an issue.Quote:Original post by VladR2. Make sure your letter quad has exactly the same width/height in texels as the letter. That is not as easy as it sounds and can take a couple of long debugging sessions. Otherwise, you`ll always have artifacts due to interpolation - so make sure every pixel in texture corresponds to exactly one pixel on screen. How can I do this? I have been debugging this for nearly two weeks.;  I just read your other thread and it was mostly about kerning, so I`m slightly confused.It seems to me you`re trying to do way too much at first shot.So, aside from kerning, do you already have your fonts displayed correctly - i.e. without any artifacts from stretching / filtering / blending ? Because I`d definitely recommend concentrating on this first, and leave kerning when your fonts are artifact-free.Regarding your last question - it helps debugging and checking visual output a lot if you overlay a grid over the font (e.g. into the texture) (say, at every 4th col/row). Otherwise it`s hard to tell, if the letter is one texel too long/short or not (especially at this size - 64x64).What I`m trying to say, is that to get a perfect output, each texel of your font texture should correspond to one pixel at screen. I`m assuming your using pretransformed vertices (e.g. RHW), right ? So, each letter quad should have only as many texels as you want it to be.You probably figured that out by now, but you have to be very cautious about off-by-one error here. A Half texel is usually enough to wreak havoc on the output (though, you mention that DX11 rasterizes differently than DX8/9 - i.e. without that half-texel offset).Isn`t it funny, that such a seemingly trivial thing (font rasterizing) can easily take couple of weeks to get it right ? I also did it over a weekend at first and then spent two weeks hunting the artifacts :-)   ;Quote:Original post by VladRI just read your other thread and it was mostly about kerning, so I`m slightly confused.It seems to me you`re trying to do way too much at first shot.So, aside from kerning, do you already have your fonts displayed correctly - i.e. without any artifacts from stretching / filtering / blending ? Because I`d definitely recommend concentrating on this first, and leave kerning when your fonts are artifact-free.I am not concerned with the stretching, filtering or blending. I have that working seperately, I am only concerned with getting the UV's and kerning information correct.Quote:Original post by VladRRegarding your last question - it helps debugging and checking visual output a lot if you overlay a grid over the font (e.g. into the texture) (say, at every 4th col/row). Otherwise it`s hard to tell, if the letter is one texel too long/short or not (especially at this size - 64x64).The kerning and ABC's will not be perfectly aligned with the grid though, as they can be different.Quote:Original post by VladRWhat I`m trying to say, is that to get a perfect output, each texel of your font texture should correspond to one pixel at screen. I`m assuming your using pretransformed vertices (e.g. RHW), right ? So, each letter quad should have only as many texels as you want it to be.I know, however, the problem is that I do not know the correct algorithm for using the kerning and generation UV's.   ;  Does anyone have any recommendations? I am still trying to solve this   