SLOW performance drawing multiple polygons per frame with stencil buffer

Nibbie
Posts: 4
Joined: 2013.04
Post: #1
ok so i am drawing separate polygons each frame. some polygons are concave.

for each poly in each frame, i am using glMapBuffer and orphaning the previously mapped buffer per apple's specifications and then calling draw functions

performance is 30fps when I do not use the stencil buffer to draw concave polygons. As soon as I include the code to draw polygons with the stencil buffer my frame rate drops to 15fps

so for each frame, for each polygon on stage i am doing the following.

Code:
glBufferData(GL_ARRAY_BUFFER, sizeof(Vertex) * 1024, NULL, GL_STREAM_DRAW);
    _vertices = glMapBufferOES(GL_ARRAY_BUFFER, GL_WRITE_ONLY_OES);

    glEnableVertexAttribArray(attribPosition);
    glEnableVertexAttribArray(attribColor);
    
    glVertexAttribPointer(attribPosition, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex),
                          (void *)(offsetof(Vertex, position)));
    
    glVertexAttribPointer(attribColor, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(Vertex),
                          (void *)(offsetof(Vertex, color)));

    //Compute vertices and put into _vertices

    glUnmapBufferOES(GL_ARRAY_BUFFER);

    //if a whole in it OR concave
    if (concave) {
        //NSLog(@"Concave");
        
        //set the value when stencil is cleared
        glClearStencil(0);
        
        //clear the stencil
        glClear(GL_STENCIL_BUFFER_BIT);
        
        //disable writing to color buffer
        glColorMask( GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE );
    
        //enable writing to stencil buffer
        glEnable(GL_STENCIL_TEST);
        
        //always place a 1 in the stencil buffer
        glStencilFunc(GL_ALWAYS, 1, 1);
        
        //replace where rendered
        glStencilOp(GL_INVERT, GL_INVERT, GL_INVERT);
        
        //write to the stencil buffer
        glDrawArrays(GL_TRIANGLE_FAN, 0, _vertexCount);

        //re-enable color buffer
        glColorMask( GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE );
        
        //where a 1 was rendered
        glStencilFunc(GL_EQUAL, 1, 1);
        
        //keep the pixels in the stencil buffer
        glStencilOp( GL_KEEP, GL_KEEP, GL_KEEP );
    }
    
    glDrawArrays(GL_TRIANGLE_FAN, 0, _vertexCount);
        
    if (concave) {
        //finished using stencil
        glDisable( GL_STENCIL_TEST );
        
    }

any help is appreciated. thanks
Quote this message in a reply
Moderator
Posts: 3,572
Joined: 2003.06
Post: #2
You're only supposed to call glBufferData() once, when you initially create the buffer, not each frame.
Quote this message in a reply
Sage
Posts: 1,232
Joined: 2002.10
Post: #3
So when a polygon is concave, you clear the stencil buffer and you draw twice as much. And you don't expect this to go any slower? Generally, doing work will always be slower than not doing work.


Since you are only using one stencil bit, you might try amortizing the cost of clearing the stencil buffer: keep a running stencil ref value and increment it for each polygon, and REPLACE instead of INVERT. Then you only need to clear the stencil buffer every 256 polygons.

But, you should probably describe at a higher level what you're really trying to do, perhaps there is a better, completely different algorithm.
Quote this message in a reply
Nibbie
Posts: 4
Joined: 2013.04
Post: #4
(Apr 25, 2013 10:42 AM)AnotherJake Wrote:  You're only supposed to call glBufferData() once, when you initially create the buffer, not each frame.

This is a technique called orphaning. I just learned about it myself:
http://www.opengl.org/wiki/Buffer_Object...cification

Quote:So when a polygon is concave, you clear the stencil buffer and you draw twice as much. And you don't expect this to go any slower? Generally, doing work will always be slower than not doing work.

yes i expected slower. but i was not sure if slowing to this degree is expected. if i had a major flaw i wanted someone to expose it before trying a completely different algorithm.

Quote:REPLACE instead of INVERT

i need invert because i am using this method of drawing concave polygons

http://www.glprogramming.com/red/chapter14.html#name13


the way i see it i have two options

1. Reduce the #of draw calls. Right now I am using one draw call per poly.

2. Use polygon triangulation on concave polygons ad avoid the stencil buffer altogether. The problem here is that realtime triangulation might not be fast enough. Triangulating BEFORE might lead to files (I load frame data from files on disk into memory) that are too large.
Quote this message in a reply
Moderator
Posts: 3,572
Joined: 2003.06
Post: #5
(Apr 25, 2013 02:33 PM)clam61 Wrote:  
(Apr 25, 2013 10:42 AM)AnotherJake Wrote:  You're only supposed to call glBufferData() once, when you initially create the buffer, not each frame.

This is a technique called orphaning. I just learned about it myself:
http://www.opengl.org/wiki/Buffer_Object...cification

Well I'll be darned; learn something new every day. I'll have to give it a try!
Quote this message in a reply
Nibbie
Posts: 4
Joined: 2013.04
Post: #6
haha. yeah definitely.

any other options anyone can see?
Quote this message in a reply
Sage
Posts: 1,232
Joined: 2002.10
Post: #7
(Apr 25, 2013 02:33 PM)clam61 Wrote:  2. Use polygon triangulation on concave polygons ad avoid the stencil buffer altogether.

The trade-off is CPU triangulation vs draw-time stencil buffer masking. Only you can decide which is better, based on what you are trying to draw.

If your mesh is animated so the triangulation constantly changes, then you should carefully measure the cost of CPU triangulation; for some number of vertices it is likely better to triangulate on the CPU.

If your mesh is static, it's probably always better to triangulate as a pre-processing step (fix the data, and keep the algorithm simple.)
Quote this message in a reply
Nibbie
Posts: 4
Joined: 2013.04
Post: #8
the polygons i am drawing are definitely dynamic, but i dont think it would be a "mesh". i am not doing anything 3d.

just drawing 2d polygons onto stage.

i guess there is no way to reduce the # of draw calls if I am drawing separate polygons? one draw call per polygon is typical?
Quote this message in a reply
Post Reply 

Possibly Related Threads...
Thread: Author Replies: Views: Last Post
  Masking without a stencil buffer? Bachus 12 13,212 Sep 2, 2010 02:42 PM
Last Post: Skorche
  Making 2D Stencil Shadows Soft metacollin 16 14,786 Jul 22, 2009 01:59 PM
Last Post: NelsonMandella
  Frame buffer objects seem to be messing with my computer Jar445 2 3,315 Feb 24, 2009 08:59 AM
Last Post: Jar445
  Saving Frame Buffer nicromonicon 2 3,084 Apr 9, 2008 08:23 AM
Last Post: stevejohnson
  Stencil shadows meant to look like this? ia3n_g 2 3,653 Nov 23, 2006 06:57 PM
Last Post: akb825