Jump to content
  • Advertisement
Sign in to follow this  
biohaz

Bitmap text rendering problems

This topic is 4417 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I am having a problem with my text, created with BM Font generator, which I suspect it is a DX filter problem but I dont know. When the texture gets smaller, it seems to get bolder and harder to read, imo bluring the texture in the distance. When I try to make the font larger it gets crisper and ugly. Is there a filter/method to blur it when it gets big and lessen the bluring as it gets smaller without having to use diffrent font textures for the small and the large fonts. I am not trying to blow them up huge or make them tiny, just in an acceptable range for customization. Thanks Oh the texture is saved as a .dds in DXT3 format

Share this post


Link to post
Share on other sites
Advertisement
In my experience, there isn't an aweful lot you can do here that is a standard solution. I can only suggest that you create bitmap font textures for varying text sizes. You might also be able to blend between the textures to make smoother interpolated text.

Hope that helps,

Dave

Share this post


Link to post
Share on other sites
Thats what I thought, so I kept making my font on the texture smaller, but Then it shows another problem. hard to tell with words, so here is some pictures.
Image Hosted by ImageShack.us
When I make the font smaller on the texture, it still blurs, and seems to turn more invisible. I was/am using ID3DXFont right now - which is what I want to match with a bitmap font if possible.
This size was the best I have seen yet for smaller (~12-10pt text). If I go a little higher, going above ~20-25pt fonts, this is what I get:
Image Hosted by ImageShack.us
(the blurry one is the bitmapped font) font texture shown also - I have used the .tga, and have converted it to .dds still no luck.

Here is some of my code I have for rendering it - most is just a patch job till it works good then I can fix it:

create texture
D3DXCreateTextureFromFileEx(_pDevice, L"MainFont_00.tga", 512, 512, D3DX_DEFAULT, 0, D3DFMT_DXT3, D3DPOOL_MANAGED, D3DX_DEFAULT, D3DX_DEFAULT, NULL, NULL, NULL, &_pTexture);

//just a little snippit of making a vertex for a letter triangle:
vertices[count].x = cursorXposition + OffsetX;
vertices[count].y = cursorYposition - OffsetY;
vertices[count].u = CharX / texturesize;
vertices[count].v = CharY / texturesize;
vertices[count].color = D3DXCOLOR(1.0f,1.0f,1.0f,1.0f);
count++;

--- Rendering: ---
Min, Max and Mip filters are all on Linear filtering

Perspective set to: D3DXMatrixOrthoOffCenterLH(&mtxProj, -1280, 1280, -1024, 1024, -1, 1); //screen size hard coded and projection is set before text drawn

Camera and world matrixes are set to an identity matrix
_pDevice->SetTransform(D3DTS_WORLD, &Identity);
_pDevice->SetTransform(D3DTS_VIEW, &Identity);

_pDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, true);
_pDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
_pDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);

_pDevice->SetVertexDeclaration(_pVertexDecl);
_pDevice->SetStreamSource(0, _pVB, 0, sizeof(TextVertex));

_pDevice->SetTexture(0, _pTexture);// not feeding to a shader just yet..
_pDevice->DrawPrimitive(D3DPT_TRIANGLELIST, 0, num_triangles);

_pDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, false);




It must be something with a filter or something, perhaps maybe because I am running AA 4x??

Perhaps I am just used to the crisp font received from ID3DXFont and I am getting correct results right now. Im out of Ideas, I have been stumped on this all afternoon/night.

note: the pt sizes I mention are just estimates, to common word processing font sizes.

[Edited by - biohaz on April 20, 2006 5:23:20 PM]

Share this post


Link to post
Share on other sites
2 quick notes.

First, DXT3 is a lossy compression format. There's a chance the blur is caused by the compression. Try an uncompressed format, if you can.

Second, have a look at Directly Mapping Texels to Pixels. This is a prime cause for blurring in these types of uses. If you can't understand how this applies to your situation, feel free to ask for more assistance :).

[EDIT]

Gonna add a third issue, you say you're using Linear filtering for both the Min, Mag, and MIP filters. I'd recommend at least trying NONE for MIP (or using 1 for the number of MIP maps in the D3DXCreateTextureFromFileEx call), and if that doesn't help, trying to use POINT for the other two.

Hope this helps.

Share this post


Link to post
Share on other sites
I had exactly the same problem with my font-renderer and it was to do with the way that DX texels/pixels are centered. You need to add an offset as specified in the link provided by sirob.

If you need further help I will dig out the code...

Share this post


Link to post
Share on other sites
Thanks for the link, I tried it by subtracting 0.5 from the vertex point and no dice. Will I have to find the position, and say the vertex is 0.2, subtract 0.7 to get it aligned - with characters being different sizes this couldn't be correct, could it? or do I just subtract 0.5 from all of the verticies? Also will this have to happen in a shader, because my ortho projection is not in screen coordinates, does it have to be?

Quote:
Original post by XiotexStudios
If you need further help I will dig out the code...

That would be great if you could


I was using DXT3 because of This thread
Quote:
Original post by Promit
I strongly suggest you use DXT/S3TC on the texture in video memory. However, it is critically important to use DXT3. DXT1 will mangle your fonts, as it does not cope well with sharp changes in alpha.


[Edited by - biohaz on April 20, 2006 12:50:37 PM]

Share this post


Link to post
Share on other sites
Here is where I build the vertex information:


pVertices->m_fX = fCursorX + pDesc->m_fXOffset;
pVertices->m_fY = fCursorY + pDesc->m_fYOffset;
pVertices->m_fZ = 0.0f;
pVertices->m_fU = pDesc->m_fX + CSystemInfo::GetHalfTexelX();
pVertices->m_fV = pDesc->m_fY + CSystemInfo::GetHalfTexelY();
pVertices->m_dwDiffuse = 0xFFFFFFFF;
pVertices++;

pVertices->m_fX = fCursorX + pDesc->m_fWidth + pDesc->m_fXOffset;;
pVertices->m_fY = fCursorY + pDesc->m_fYOffset;
pVertices->m_fZ = 0.0f;
pVertices->m_fU = pDesc->m_fX + (pDesc->m_fWidth/256.0f) + CSystemInfo::GetHalfTexelX();
pVertices->m_fV = pDesc->m_fY + CSystemInfo::GetHalfTexelY();
pVertices->m_dwDiffuse = 0xFFFFFFFF;
pVertices++;


pVertices->m_fX = fCursorX + pDesc->m_fXOffset;;
pVertices->m_fY = fCursorY + pDesc->m_fHeight + pDesc->m_fYOffset;;
pVertices->m_fZ = 0.0f;
pVertices->m_fU = pDesc->m_fX + CSystemInfo::GetHalfTexelX();
pVertices->m_fV = pDesc->m_fY + (pDesc->m_fHeight/256.0f) + CSystemInfo::GetHalfTexelY();
pVertices->m_dwDiffuse = 0xFFFFFFFF;
pVertices++;

// Second Tri
pVertices->m_fX = fCursorX + pDesc->m_fWidth + pDesc->m_fXOffset;;
pVertices->m_fY = fCursorY + pDesc->m_fYOffset;;
pVertices->m_fZ = 0.0f;
pVertices->m_fU = pDesc->m_fX + (pDesc->m_fWidth/256.0f) + CSystemInfo::GetHalfTexelX();
pVertices->m_fV = pDesc->m_fY + CSystemInfo::GetHalfTexelY();
pVertices->m_dwDiffuse = 0xFFFFFFFF;
pVertices++;

pVertices->m_fX = fCursorX + pDesc->m_fWidth + pDesc->m_fXOffset;;
pVertices->m_fY = fCursorY + pDesc->m_fHeight + pDesc->m_fYOffset;;
pVertices->m_fZ = 0.0f;
pVertices->m_fU = pDesc->m_fX + (pDesc->m_fWidth/256.0f) + CSystemInfo::GetHalfTexelX();
pVertices->m_fV = pDesc->m_fY + (pDesc->m_fHeight/256.0f) + CSystemInfo::GetHalfTexelY();
pVertices->m_dwDiffuse = 0xFFFFFFFF;
pVertices++;

pVertices->m_fX = fCursorX + pDesc->m_fXOffset;;
pVertices->m_fY = fCursorY + pDesc->m_fHeight + pDesc->m_fYOffset;;
pVertices->m_fZ = 0.0f;
pVertices->m_fU = pDesc->m_fX + CSystemInfo::GetHalfTexelX();
pVertices->m_fV = pDesc->m_fY + (pDesc->m_fHeight/256.0f) + CSystemInfo::GetHalfTexelY();
pVertices->m_dwDiffuse = 0xFFFFFFFF;

pVertices->m_fX = fCursorX + pDesc->m_fXOffset;
pVertices->m_fY = fCursorY + pDesc->m_fYOffset;
pVertices->m_fZ = 0.0f;
pVertices->m_fU = pDesc->m_fX + CSystemInfo::GetHalfTexelX();
pVertices->m_fV = pDesc->m_fY + CSystemInfo::GetHalfTexelY();
pVertices->m_dwDiffuse = 0xFFFFFFFF;
pVertices++;

pVertices->m_fX = fCursorX + pDesc->m_fWidth + pDesc->m_fXOffset;;
pVertices->m_fY = fCursorY + pDesc->m_fYOffset;
pVertices->m_fZ = 0.0f;
pVertices->m_fU = pDesc->m_fX + (pDesc->m_fWidth/256.0f) + CSystemInfo::GetHalfTexelX();
pVertices->m_fV = pDesc->m_fY + CSystemInfo::GetHalfTexelY();
pVertices->m_dwDiffuse = 0xFFFFFFFF;
pVertices++;


pVertices->m_fX = fCursorX + pDesc->m_fXOffset;;
pVertices->m_fY = fCursorY + pDesc->m_fHeight + pDesc->m_fYOffset;;
pVertices->m_fZ = 0.0f;
pVertices->m_fU = pDesc->m_fX + CSystemInfo::GetHalfTexelX();
pVertices->m_fV = pDesc->m_fY + (pDesc->m_fHeight/256.0f) + CSystemInfo::GetHalfTexelY();
pVertices->m_dwDiffuse = 0xFFFFFFFF;
pVertices++;

// Second Tri
pVertices->m_fX = fCursorX + pDesc->m_fWidth + pDesc->m_fXOffset;;
pVertices->m_fY = fCursorY + pDesc->m_fYOffset;;
pVertices->m_fZ = 0.0f;
pVertices->m_fU = pDesc->m_fX + (pDesc->m_fWidth/256.0f) + CSystemInfo::GetHalfTexelX();
pVertices->m_fV = pDesc->m_fY + CSystemInfo::GetHalfTexelY();
pVertices->m_dwDiffuse = 0xFFFFFFFF;
pVertices++;

pVertices->m_fX = fCursorX + pDesc->m_fWidth + pDesc->m_fXOffset;;
pVertices->m_fY = fCursorY + pDesc->m_fHeight + pDesc->m_fYOffset;;
pVertices->m_fZ = 0.0f;
pVertices->m_fU = pDesc->m_fX + (pDesc->m_fWidth/256.0f) + CSystemInfo::GetHalfTexelX();
pVertices->m_fV = pDesc->m_fY + (pDesc->m_fHeight/256.0f) + CSystemInfo::GetHalfTexelY();
pVertices->m_dwDiffuse = 0xFFFFFFFF;
pVertices++;

pVertices->m_fX = fCursorX + pDesc->m_fXOffset;;
pVertices->m_fY = fCursorY + pDesc->m_fHeight + pDesc->m_fYOffset;;
pVertices->m_fZ = 0.0f;
pVertices->m_fU = pDesc->m_fX + CSystemInfo::GetHalfTexelX();
pVertices->m_fV = pDesc->m_fY + (pDesc->m_fHeight/256.0f) + CSystemInfo::GetHalfTexelY();
pVertices->m_dwDiffuse = 0xFFFFFFFF;

pVertices->m_fX = fCursorX + pDesc->m_fXOffset;
pVertices->m_fY = fCursorY + pDesc->m_fYOffset;
pVertices->m_fZ = 0.0f;
pVertices->m_fU = pDesc->m_fX + CSystemInfo::GetHalfTexelX();
pVertices->m_fV = pDesc->m_fY + CSystemInfo::GetHalfTexelY();
pVertices->m_dwDiffuse = 0xFFFFFFFF;
pVertices++;

pVertices->m_fX = fCursorX + pDesc->m_fWidth + pDesc->m_fXOffset;;
pVertices->m_fY = fCursorY + pDesc->m_fYOffset;
pVertices->m_fZ = 0.0f;
pVertices->m_fU = pDesc->m_fX + (pDesc->m_fWidth/256.0f) + CSystemInfo::GetHalfTexelX();
pVertices->m_fV = pDesc->m_fY + CSystemInfo::GetHalfTexelY();
pVertices->m_dwDiffuse = 0xFFFFFFFF;
pVertices++;


pVertices->m_fX = fCursorX + pDesc->m_fXOffset;;
pVertices->m_fY = fCursorY + pDesc->m_fHeight + pDesc->m_fYOffset;;
pVertices->m_fZ = 0.0f;
pVertices->m_fU = pDesc->m_fX + CSystemInfo::GetHalfTexelX();
pVertices->m_fV = pDesc->m_fY + (pDesc->m_fHeight/256.0f) + CSystemInfo::GetHalfTexelY();
pVertices->m_dwDiffuse = 0xFFFFFFFF;
pVertices++;

// Second Tri
pVertices->m_fX = fCursorX + pDesc->m_fWidth + pDesc->m_fXOffset;;
pVertices->m_fY = fCursorY + pDesc->m_fYOffset;;
pVertices->m_fZ = 0.0f;
pVertices->m_fU = pDesc->m_fX + (pDesc->m_fWidth/256.0f) + CSystemInfo::GetHalfTexelX();
pVertices->m_fV = pDesc->m_fY + CSystemInfo::GetHalfTexelY();
pVertices->m_dwDiffuse = 0xFFFFFFFF;
pVertices++;

pVertices->m_fX = fCursorX + pDesc->m_fWidth + pDesc->m_fXOffset;;
pVertices->m_fY = fCursorY + pDesc->m_fHeight + pDesc->m_fYOffset;;
pVertices->m_fZ = 0.0f;
pVertices->m_fU = pDesc->m_fX + (pDesc->m_fWidth/256.0f) + CSystemInfo::GetHalfTexelX();
pVertices->m_fV = pDesc->m_fY + (pDesc->m_fHeight/256.0f) + CSystemInfo::GetHalfTexelY();
pVertices->m_dwDiffuse = 0xFFFFFFFF;
pVertices++;

pVertices->m_fX = fCursorX + pDesc->m_fXOffset;;
pVertices->m_fY = fCursorY + pDesc->m_fHeight + pDesc->m_fYOffset;;
pVertices->m_fZ = 0.0f;
pVertices->m_fU = pDesc->m_fX + CSystemInfo::GetHalfTexelX();
pVertices->m_fV = pDesc->m_fY + (pDesc->m_fHeight/256.0f) + CSystemInfo::GetHalfTexelY();
pVertices->m_dwDiffuse = 0xFFFFFFFF;



and here is the function that builds the halftexel info...



void CSystemInfo::BuildHalfTexel()
{
m_fHalfTexelX = -1.0f/m_fWidth;
m_fHalfTexelY = 1.0f/m_fHeight;
}



Now, in the code above the assumption is that the font is contained in a 256x256 image. I can't remember where I got the information to do the above or even that it's 100% correct - it appears to work for me (note - not tested on any other cards)

Share this post


Link to post
Share on other sites
wow! thanks for the code post.

So it is a texture UV shift, and not an vertex XY?

Can you get small fonts to look good in your system. I am not having problems with the large ones? If it continues, I may just have to change fonts (Using Tahoma now)

EDIT:
actually just read an article on neXe on this
Quote:
neXe
You need to extend the texture coordinates out by half a texel to directly map texels to pixels. For a 256x256 texture, the top left coordinate would be (-.5f /256.0f, -.5f/256 .0f) and the bottom right coordinate would be (255.5f/256.0f, 255.5f/256.0f).


[Edited by - biohaz on April 20, 2006 5:55:36 PM]

Share this post


Link to post
Share on other sites
Something that is easier than shifting your texture coordinates or your vertices is just applying the -0.5f shift to your orthographic projection matrix. For example, set it to go from -0.5f to -1023.5f rather than 0.0f to 1024.0f. This is how the ID3DXSprite interface does it.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

Participate in the game development conversation and more when you create an account on GameDev.net!

Sign me up!