the Fiddler's picture

Text: absolute vs relative coordinates

In an effort to finalize the text branch and get 0.9.2 out, I'd like some input on this matter.

Currently, text rendering takes place in ortho 2D with absolute coordinates (0, Width) - (0, Height). This allows for pixel-perfect rendering, but is invasive (it changes your projection matrix) and it is resolution dependent.

Would you prefer it, if the text renderer left your projection matrix alone (i.e. text is rendered in 3d space unless you specify otherwise)?


Comments

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.
objarni's picture
  1. Is the projection matrix destroyed, or push-poped?
  2. Highest priority use case for me: 2d display of text.
  3. I can imagine drawing text on signs and walls in 3d space. But this is quite possible with the current API, I guess? By storing the text in a texture..? Would require ability to measure an OpenTK text string, to allocate the appropriately sized texture (and store the exact dimensions of the text string)
JTalton's picture

Yes, I would like a way for the text renderer to leave the projection matrix alone.
I would also like to be able to manage the rendering state for the text rendering.

Here is just a quickly thought out interface allowing both simple usage and advanced usage of text rendering. It is just an example to demonstrate what I would find useful.

Basic Usage - The Render() function sets and restores the projection, state, and position.

void        TextRenderer.Render(TextObject textObject);
void        TextRenderer.Render(string text, Font font);
void        TextRenderer.Render(int x, int y, TextObject textObject);
void        TextRenderer.Render(int x, int y, string text, Font font);

Basic Example

TextRenderer.Render(myText, myFont);

Advanced Usage - Each step has it's own functions

TextObject  TextRenderer.Prepare(string text, Font font);
TextObject  TextRenderer.Prepare(uint x, uint y, string text, Font font); // Allows offsetting the text in the internal VBO
void        TextRenderer.Release(TextObject textObject);
 
void        TextRenderer.PushProjection(); // Sets the projection matrix saving the current projection matrix
void        TextRenderer.PopProjection(); // Restores the projection matrix
void        TextRenderer.SetProjection(); // Sets the projection matrix without saving the previous projection martix
IDisposable TextRenderer.UseProjection(); // Sets the projection matrix, returning an IDisposable so it can be used in a "using" statement, properly restoring the previous matrix
bool        TextRenderer.ValidateProjection(); // Validates the projection matrix to verify it is correct for pixel perfect rendering.
 
void        TextRenderer.PushState();
void        TextRenderer.PopState();
void        TextRenderer.SetState();
IDisposable TextRenderer.UseState();
bool        TextRenderer.ValidateState();
 
void        TextRenderer.PushPosition(int x, int y);
void        TextRenderer.PopPosition();
void        TextRenderer.SetPosition(int x, int y);
IDisposable TextRenderer.UsePosition(int x, int y);
 
void        TextRenderer.Draw(TextObject textObject); // Draws the text without modifying projection or state
 
void        TextRenderer.Reset(); // Clears all texture pages and regenerates unreleased text objects

Advanced Example - Using the IDisposable methods

using( TextObject textObject = TextRenderer.Prepare(myText, myFont) )
{
	using(TextRenderer.UseProjection())
	{
		Debug.Assert(TextRenderer.ValidateProjection());
 
		using(TextRenderer.UseState())
		{
			Debug.Assert(TextRenderer.ValidateState());
 
			using(TextRenderer.UsePosition(x,y))
			{
				TextRenderer.Draw(textObject);
			}
		}
	}
}

In my GUI I am hoping to only setup the projection matrix at the beginning of the GUI rendering. I would like to manage the state to reduce state changes. I will be caching the VBO and GL state calls in cascading Display Lists. From frame to frame if nothing changes, the top display list will be called which calls child display lists which set state, call VBOs, etc... When something does change only the display list containing that item will need to be updated. All of this requires good state management. I am eagerly awaiting the new text rendering code.

kanato's picture

My preference would be that the text renderer does its rendering in ortho 2D by default, and have the option to specify other behaviors, ie. using the current projection matrix. How easy is it to achieve pixel-perfect resolution independent text rendering? Could this be done by telling TextPrinter the orthogonal matrix to use?

Personally, I can't see a whole lot of use of rendering text in a general 3D space. For something like the computer screens in doom 3 I would think the way to go would be to use a framebuffer object to do the 2D rendering of the screen.

JTalton's picture

I've been pondering this more. I believe I can work with either relative or absolute. As for optimizing the rendering by controlling the state, well there's usually not too much text on the screen that it would make a difference with today's hardware acceleration.

objarni's picture

Some uses cases I think all of us would like to see:

- Frames-per-second display
- Debug/console text (HalfLife)
- RPG-style storylines/conversations (Chronotrigger)
- Game menus (Doom)
- GUI widget captions (Golem3d)
- Playlists in media players (3d Winamp anyone?)

If the text rendering APIs handles these, I'm fine.