Close (Re: Optimisation trick: use GL_TRIANGLE_STRIP instead of GL_TRIANGLES)

23 views
Skip to first unread message

sduclos

unread,
Mar 22, 2014, 11:36:39 AM3/22/14
to freet...@googlegroups.com, Nicolas Rougier
Sorry folk for spamming. To close this thread I tested demo-benchmark.c with
GL_TRIANGLE_STRIP and it make no difference in timing.

In my code, I use to render one glyph at the time using FAN. Then I realize that
I could render a whole string in a single glDraw using STRIP. It make a huge
difference specially when rendering text shadow.

I thought I share my (now non) finding :|


Thanks to Behdad,

Sylvain.

On 3/21/14, Behdad Esfahbod <beh...@behdad.org> wrote:
> On 14-03-21 05:05 PM, sduclos wrote:
>> -- I couldn't find any way to get lower than six entries per glyph.
>>
>> Use GL_TRIANGLE_FAN and 4 vertexes ..
>> The layout of 'vertices' is the same.
>
> Then you need two extra entries for the degenerate triangles, adds up to
> six.
> Right?
>
>> On 3/21/14, Behdad Esfahbod <beh...@behdad.org> wrote:
>>> On 14-03-21 04:37 PM, sduclos wrote:
>>>> Hi,
>>>>
>>>> One can you fill a whole screen full of text in a single glDraw..
>>>> using GL_TRIANGLES!
>>>>
>>>> Sorry I miss that, perhaps I should try to make a demo for rendering a
>>>> bunch of
>>>> glyphs with triangles. Right now the demo illustrate that one glyph is
>>>> produce per
>>>> glDraw.. call. And that is expensive compare to a single glDraw for
>>>> rendering a whole page of text
>>>
>>> Ah I thought freetype-gl already does all in one GL_TRIANGLES. That's
>>> what
>>> GLyphy does, and I couldn't find any way to get lower than six entries
>>> per
>>> glyph.
>>>
>>>> rgds,
>>>>
>>>> Sylvain..
>>>>
>>>> On 3/21/14, Behdad Esfahbod <beh...@behdad.org> wrote:
>>>>> On 14-03-21 03:54 PM, sduclos wrote:
>>>>>> Bonjours M. Rougier,
>>>>>>
>>>>>> The trick is to render all text with a single call to
>>>>>> glDrawArrays(GL_TRIANGLE_STRIP, ..),
>>>>>
>>>>> How is this an improvement over GL_TRIANGLES? Both take six vertex
>>>>> entries
>>>>> per glyph.
>>>>>
>>>>> behdad
>>>>>
>>>>>> The simplified code bellow show how to make that happen for a string:
>>>>>>
>>>>>> ---------------------------------->8--------------------------------------------------
>>>>>> static GArray *_fill_ftglBuf(GArray *ftglBuf, const char *str)
>>>>>> {
>>>>>> int pen_x = 0;
>>>>>> int pen_y = 0;
>>>>>>
>>>>>> if (NULL == ftglBuf) {
>>>>>> ftglBuf = g_array_new(FALSE, FALSE,
>>>>>> sizeof(_freetype_gl_vertex_t));
>>>>>> } else {
>>>>>> g_array_set_size(ftglBuf, 0);
>>>>>> }
>>>>>>
>>>>>> int len = strlen(str);
>>>>>> for (int i=0; i<len; ++i) {
>>>>>> GLfloat x0 = pen_x + glyph->offset_x;
>>>>>> GLfloat y0 = pen_y + glyph->offset_y;
>>>>>> GLfloat x1 = x0 + glyph->width;
>>>>>> GLfloat y1 = y0 - (glyph->height);
>>>>>>
>>>>>> GLfloat s0 = glyph->s0;
>>>>>> GLfloat t0 = glyph->t0;
>>>>>> GLfloat s1 = glyph->s1;
>>>>>> GLfloat t1 = glyph->t1;
>>>>>>
>>>>>> // GL_TRIANGLE_STRIP
>>>>>> GLfloat z0 = 0.0;
>>>>>> _freetype_gl_vertex_t vertices[4] = {
>>>>>> {x0,y0,z0, s0,t0},
>>>>>> {x0,y1,z0, s0,t1},
>>>>>> {x1,y0,z0, s1,t0},
>>>>>> {x1,y1,z0, s1,t1}
>>>>>> };
>>>>>>
>>>>>> // connect glyphs with degenerated triangle (GPU skip those)
>>>>>> if (0 < ftglBuf->len) {
>>>>>> // dup last vertex
>>>>>> ftglBuf = g_array_append_vals(ftglBuf, &vertices[0], 1);
>>>>>> }
>>>>>>
>>>>>> // glyph strip
>>>>>> ftglBuf = g_array_append_vals(ftglBuf, &vertices[0], 4);
>>>>>> // dup 3rd vertex
>>>>>> ftglBuf = g_array_append_vals(ftglBuf, &vertices[2], 1);
>>>>>>
>>>>>> pen_x += glyph->advance_x;
>>>>>> pen_y += glyph->advance_y;
>>>>>> }
>>>>>>
>>>>>> return ftglBuf;
>>>>>> }
>>>>>> ---------------------------------->8--------------------------------------------------
>>>>>>
>>>>>> The GPU discard degenerated triangle. So the trick is to link glyph
>>>>>> strip
>>>>>> using
>>>>>> degenerated strip.
>>>>>>
>>>>>> Note how vertex in vertices are organize to form a strip.
>>>>>>
>>>>>> Also note how degenerated strip are appended to glyph.
>>>>>>
>>>>>> Finally there is no core code to change in freetype_gl
>>>>>> (texture-atlas,
>>>>>> texture-font
>>>>>> vector, vec123.h)
>>>>>>
>>>>>>
>>>>>> I use glib GArray to store stuff but anything could do.
>>>>>>
>>>>>>
>>>>>>
>>>>>> Salutation,
>>>>>>
>>>>>> Sylvain.
>>>>>>
>>>>>
>>>>> --
>>>>> behdad
>>>>> http://behdad.org/
>>>>>
>>>>> --
>>>>> You received this message because you are subscribed to the Google
>>>>> Groups
>>>>> "freetype-gl" group.
>>>>> To unsubscribe from this group and stop receiving emails from it, send
>>>>> an
>>>>> email to freetype-gl...@googlegroups.com.
>>>>> For more options, visit https://groups.google.com/d/optout.
>>>>>
>>>>
>>>
>>> --
>>> behdad
>>> http://behdad.org/
>>>
>>> --
>>> You received this message because you are subscribed to the Google
>>> Groups
>>> "freetype-gl" group.
>>> To unsubscribe from this group and stop receiving emails from it, send
>>> an
>>> email to freetype-gl...@googlegroups.com.
>>> For more options, visit https://groups.google.com/d/optout.
>>>
>>
>
> --
> behdad
> http://behdad.org/
>
> --
> You received this message because you are subscribed to the Google Groups
> "freetype-gl" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to freetype-gl...@googlegroups.com.
> For more options, visit https://groups.google.com/d/optout.
>

Nicolas Rougier

unread,
Mar 23, 2014, 12:10:08 PM3/23/14
to freet...@googlegroups.com

Hi Sylvain,

I just read the whole thread at once and in the end I'm not sure of your results.
Why do you triangle fan for rendering one glyph (versus triangle strip) ?

And thanks for trying to speed things up.



Nicolas

sduclos

unread,
Mar 25, 2014, 1:46:46 PM3/25/14
to freet...@googlegroups.com
Hi Nicolas,

I used FAN in the past because it seem simpler to send 4 vertex per glyph.
Where one vertex is X,Y,Z, u,v. (position + texture).

Then I realize that I could send a whole string in one shot by joining
glyph STRIP.

I missed the fact that you already do send a whole string. I work with the core
file of freetype_gl so that is why I missed that!

But my test using your demo-benchmark.c show that it make no
difference in timing using TRIANGLES or FAN.

Basically I just reinvent the wheel (ou, défoncer une porte ouverte:)



Next speed up is by using VBO for static text .. so the vertex stay on the GPU

#define BUFFER_OFFSET(i) ((char *)NULL + (i))
glEnableVertexAttribArray(_aPosition);
glVertexAttribPointer (_aPosition, 3, GL_FLOAT, GL_FALSE,
sizeof(_freetype_gl_vertex_t), BUFFER_OFFSET(0));

glEnableVertexAttribArray(_aUV);
glVertexAttribPointer (_aUV, 2, GL_FLOAT, GL_FALSE,
sizeof(_freetype_gl_vertex_t), BUFFER_OFFSET(sizeof(float)*3));

So this mean that you send only one "lazy fox.." string to the GPU.
Then you can call repeatedly the VBO.

Not timed yet, maybe I should try it on your benchmark!


rgds,

Sylvain.
Reply all
Reply to author
Forward
0 new messages