Batched text rendering with an offset and depth

Hey Embers,

I’m in the process of updating my GUI rendering pipeline from horrible, ugly, slug-speed, (yet simple) immediate mode, to sleek, suave, and a little intimidating batch rendering.

I’ll most likely be posting a question regarding that topic this upcoming week, but for now, I’ll settle with what’s currently plaguing my conscience. Namely, as the topic implies, batched text rendering with both an offset and a depth - which would essentially just be a vec3 offset in more refined circles.

Looking into cinder’s gosh darn awesome TextureFont implementation, which I love so much I’d marry (if it were legal), I found a lovely pair of functions called getGlyphPlacements() and drawGlyphs().

Although I couldn’t find a single sample making use of these functions, they seem fairly straight forward.

getGlyphPlacements() returns a std::vector<std::pair<uint16_t,vec2> >, and drawGlyphs() accepts that type of vector, effectively drawing several glyphs as a batch. However, using these functions, all I’ve managed to do is draw an impressive amount of glyphs on top of eachother. Rendering most of them unreadable.

Ideally, I’d like to offset each string of text with its own individual offset vector. drawGlyphs() accepts an offset vector, but that seems to apply equally to all glyphs. Beyond that, the only idea I’ve been able to think of (but have yet to try) is manually modifying the vec2's that getGlyphPlacements() returns. That’ll do in a pinch if it works as expected, but then I’m still left a bit out in the cold in regards to providing a depth. It’s of course possible to call a translation operation in-between rendering glyphs, but that also defeats the whole purpose of batching all these glyphs…

So perhaps someone else has figured out a good way of batching glyphs and giving them an offset including a depth?

Regards,
Gazoo

Perhaps my tendency for being wordy has bit me in the behind as I was hoping for more than a tumbleweed to pass through this thread.

The TL;DR version is that I’ve been searching for a variant of TextureFont::drawGlyphs( const vector<pair<uint16_t,vec2> > &glyphMeasures, const vec2 &baselineIn, const DrawOptions &options, const std::vector<ColorA8u> &colors ), that support multiple offsets.

Why? Well the TextureFont::drawGlyphs looks to go through a whole lot of setup, binding all kinds of stuff, so it’d seem ideal to make a batch version that could handle more than just a multitude of glyphs with one base offset.

I’ve not been able to find anything still, so currently I’ve resorted to just calling the function sort of like this:

// Glyphs
ci::gl::color( ci::Color::white() );
for ( auto const& pairGlyphsAndOffset : mGridLabelGlyphs )
{
	if ( !pairGlyphsAndOffset.first.empty() )
	{
		mLabelTextureFont->drawGlyphs( pairGlyphsAndOffset.first, pairGlyphsAndOffset.second );
	}
}

Regards,

Gazoo

You can directly manipulate the vec2 in the glyph placements vector as you want.

To do 3d positioning, you will need to do some work in a custom shader. The TextureFont will provide you with a properly bound texture, the 2d position from the glyph placements, and texture coordinates. You could sample another texture in the shader to do that.

It might also be easier to modify the TextureFont class to add the 3d positioning support you want.