Luecx
Luecx

Reputation: 160

OpenGL render fonts instanced

I want to render font with OpenGL. I got a texture with all my chars and a file where every position of the digits on the texture are saved.

for example:

char id=40      x=167  y=0    width=21   height=74   xoffset=-3   yoffset=33   xadvance=59   page=0    chnl=0 
char id=41      x=188  y=0    width=21   height=74   xoffset=-3   yoffset=33   xadvance=59   page=0    chnl=0 

I want to render this onto a quad now. But how is this normally done? One render call for each of the digits? Or should I render the digits instanced? That would mean that I store the texture coordinates and offset etc. as instanced attributes in my VBO. This would be the hardest solution and It must be easier. One render call each would probably take too long to render.

I've seen a solution where a new VAO + VBO is created with quads next to each other fitting to the text. There he stored the textureCoords in the vertices. But isn't this very ineffective? I also want to change the content of my text.

Does anyone know a good solution for my problem?

Upvotes: 2

Views: 699

Answers (1)

Bartvbl
Bartvbl

Reputation: 2928

Since you mention quads, I'll assume you are working with pairs of triangles. Quads have long been deprecated from the OpenGL specification.

To set up the rendering, the idea is that you create a buffer containing a number of side-by-side rectangles, each with a single character projected on them. As you say this can be done using a VAO+VBO combo. It's the way I would personally do this.

Since vertices will likely have different texture coordinates as opposed to sharing the same, you really need to define each vertex with texture cordinate separately. That's not inefficient really; it's a necessity caused by the way the rendering process is implemented in OpenGL.

The way you render your text is by binding your font texture using glBindTexture(). Next, you bind your VAO using glBindVertexArray(), and finally draw it using a single glDrawElements() call. So you only issue a single drawcall for however muich text you need.

What's important here is that you minimise the number of draw calls you issue. Draw calls are relatively expensive, so properly minimising them is the way to go. This is the reason instanced rendering exists; to draw the exact same object multiple times without as much overhead of draw calls. However, in this case it's far better to just put everything in a single buffer and issue a single draw call to draw it.

Upvotes: 1

Related Questions