4
\$\begingroup\$

I have a method for drawing strings in 3D that does the following:

  • Set a render target
  • Draw each character as a quadrangle using a orthographic projection to the render target
  • Unset the render target
  • Draw the render target texture using a perspective projection and a world transform

My problem is how to deal with strings whose characters length exceeds that of the render target dimensions? For example if I have string "This is a reallllllllllly long string" and the render target can't accommodate it, it will only capture "This is a realllll".

The render target (and its size) could be set each frame but wouldn't that be far too costly?

\$\endgroup\$
2
  • \$\begingroup\$ Might I suggest that it would be better - rather than drawing via a render target - simply drawing your strings directly in 3D space? You can do this, for example, with SpriteBatch by passing in the effect you are using for 3D rendering (usually BasicEffect) to the version of SpriteBatch.Begin that takes an effect as an argument. (See this blog post blogs.msdn.com/b/shawnhar/archive/2010/04/05/…) \$\endgroup\$ Commented Jul 7, 2012 at 13:26
  • \$\begingroup\$ Unfortunately I have my own TextureAtlas and do not use SpriteFont. SpriteBatch doesn't play nicely with Deferred Rendering either. \$\endgroup\$ Commented Jul 7, 2012 at 16:38

3 Answers 3

3
\$\begingroup\$

Before rendering the text, compute its bounds. If the text would be too long horizontally, split the string you render into substrings. This can be done as an implementation detail of the text rendering API, so users don't have to know their string was too long to fit. If you employ a bin-packing technique to place each text substring in your render target (this one, for example, is simple and effective and this page describes some improves to it) you can fit quite a lot of text onto a single render target sheet, especially if you start getting fancy and trying to rotate some of the strings.

If you ever fill a render target sheet, create another one. You can't really resize render target textures -- you destroy them and recreate them, so simply creating a new one alongside your existing one is generally easier on computing resources.

Plus, it allows you to build a caching mechanism into your text rendering -- exploiting the fact that if a piece of text was rendered this frame it will probably be rendered again next frame, which can save you from having to re-rasterize a lot of text into your sheets.

\$\endgroup\$
1
  • \$\begingroup\$ This sounds good, thank you. I have a TextureAtlas implementation but how can I stitch together multiple source rectangles into one quadrangle? I am drawing the text as a Spherical Billboard so multiple quadrangles would need to be attached in some manner. \$\endgroup\$ Commented Jul 6, 2012 at 20:43
1
\$\begingroup\$

Just resize the RenderTarget when you are sure the text won't fit, and keep the new size. Then calculate the text string rectangle bounds and draw only that portion of the RenderTarget.

\$\endgroup\$
1
  • \$\begingroup\$ In order to resize the RenderTarget in XNA you have to create a new instance. If it is not too costly then I can resize it to fit the current text each frame. I'm uncertain about this though. \$\endgroup\$ Commented Jul 6, 2012 at 13:25
1
\$\begingroup\$

I would suggest to make yourself a small function that calculates the length the text will take depending on the font and the size. Then make the render target big enough. That's how we deal with any type of text where I work. If the render target cannot be bigger, we scale down the font. And beyond let say a scale of 70% of the original size, we simply flag the text as too long (like put it in a bright red) to be able to quickly see when some text need to be reviewed.

Hope that helps.

\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .