Sign in to follow this  
gekko

DX9: Rendering 2D text above 3D objects

Recommended Posts

Hey, I'm looking to implement 2D text in a 3D world, much like when a FPS displays the players name above their character. Currently I'm using ID3DXFont to render text, but so far I've only been rendering to screen coordinates for HUDs and menus. I noticed ID3DXFont::DrawText takes a ID3DXSprite* as the first parameter. I'm unfamiliar with the ID3DXSprite class and the documentation of how the font and sprites works together is lacking. Would it be possible to render text to a sprite and use it as a billboard positioned above my objects? If not, does anyone have any suggestions? Preferably, I'd like to continue to use ID3DXFont, if that's possible. Thanks.

Share this post


Link to post
Share on other sites
Sample funcion to get 2d screen coords from a 3d position with ability to offset the 3d position. some of the identifiers have to be set by you; WORLD_POSITION, SCREEN_WIDTH and SCREEN_HEIGHT. I put it like this to be able to use the function in classes then you want position offsets. If you are going to use it as a global function then the PositionOffset could be the world position directly.

returns true if object is in front of camera and false if object is behind camera


bool GetScreenPosition(D3DXVECTOR2& ScreenPosition, float& Distance, D3DXVECTOR3 PositionOffset = D3DXVECTOR3(0,0,0))
{
D3DXMATRIX m;
D3DXVECTOR4 s;
D3DXVECTOR3 w;

w = WORLD_POSITION + PositionOffset;

//VIEW * PROJECTION
m = mCamView * mCamProjection;

//get vectors from view * proj
s.x = w.x * m._11 + w.y * m._21 + w.z * m._31 + m._41;
s.y = w.x * m._12 + w.y * m._22 + w.z * m._32 + m._42;
s.z = w.x * m._13 + w.y * m._23 + w.z * m._33 + m._43;
s.w = w.x * m._14 + w.y * m._24 + w.z * m._34 + m._44;

//get inverse of w
float w_inv = 1.0f / s.w;
//get center of screen
float fWidth2 = SCREEN_WIDTH * 0.5f;
float fHeight2 = SCREEN_HEIGHT * 0.5f;

//get screen coordinates
ScreenPosition.x = (1.0f + (s.x * w_inv)) * fWidth2;
ScreenPosition.y = SCREEN_HEIGHT - ((1.0f + (s.y * w_inv)) * fHeight2);
//get distance to object from camera position
Distance = s.z;

return (s.z > 0.0f);
}


Share this post


Link to post
Share on other sites
Thanks, but I'm looking more for the opposite. Drawing text with DirectX is always putting it in screen coordinates, which works fine for menus and other things. I'm trying to see if there's a way I can have some control over the quad it's drawing the texture to, so I can move it around in the 3D world and not be locked to screen coordinates.

I should be more clear. I am having trouble understanding the ID3DXFont documentation on MSDN to know if it is possible to do this. I've looked at tutorials and books and they all stop at drawing the text as a 2D quad in screen coordinates. I was hoping someone was more familiar with the DirectX interfaces than I was, and hopefully knows how to make it work, or knows if it's simply not possible.

Share this post


Link to post
Share on other sites
I don't have a lot of experience with ID3DXFont, but I think you will find that with time you will want a more general purpose way of drawing text, hud elements, billboards, particle effects, etc. both in front of the camera and in the world. Best to bite the bullet now and write your own rendering path. Point sprites are a short-cut, but eventually you will likely want even greater control. For instance I have rain drop splat particles that are always up-facing, so point sprites don't work for that.

ID3DXFont is there as a helper to get quads drawing in screen coordinates quick and dirty. Sounds like you are at the point where quick and dirty is not enough.

Hope that helps...

Share this post


Link to post
Share on other sites
I understand, I just have other priorities right now than figuring out how to rasterize fonts, so I'm actively looking for a way to utilize what's already in place and working just fine.

I did some trial and error, and if I use the object space flag on a D3DXSprite, I can transform it around in world space and it gets the job done. It's a bit weird to me, since it's the only place I would be using D3DXSprite.

I also just tried changing rendering to a texture, at which point the regular DrawText function will draw to a texture of my choosing, which I can then map to any quad I want. I think I may explore this solution more, since it gives me more freedom than I have with D3DXSprite.

Thanks for the suggestions though, and if anyone has gone with either of these methods, please let me know if it worked out.

Share this post


Link to post
Share on other sites
As an alternative you could render to a texture and then place a rectangle with this texture in your world.
If your text does not change often this would be an acceptable solution, but if you've got a lot of text that changes much, you should definitely go with the advices already given and roll your own.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this