• Create Account

### #Actualfastcall22

Posted 17 January 2012 - 09:24 AM

EDIT:
Since then I tested it with part.SetPosition(x,y); and App.Draw(part); commented out, so they are not drawn, and still Particle::show takes up 61% of the resources (was 74 previously)... with that commented out, the SDL and SFML Particle::show() are identical, except in SDL they actually get drawn.

This would suggest that the API is the bottleneck (as indicated earlier in the thread). If I recall correctly, SFML uses OpenGL 1.1 immediate-mode calls, which would mean for every particle rendered, there's a call to glBindTexture, glPushMatrix/glPopMatrix, and glBegin/glEnd. For something like a particle system, the overhead in each of these calls, while not significant on their own, can snowball. To reduce the overhead from texture switching, place all of your particle textures on one sheet. Since SFML doesn't seem to have any feature that will allow us to assign a part of an Image to a Sprite, you'll need to do the rendering yourself through raw OpenGL calls. By doing so, you can optimize out some OpenGL calls and will allow you to do batching, among other things:

glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA ); // sf::BlendMode::Alpha
Particle::particleSheet.Bind(); // sf::Image::Bind, essentially calls glBind( GL_TEXTURE_2D, particleSheet.handle )
for ( Partice& p : v_particles ) {
cnost Rect2f& texRect = getTextureRect( p.getTextureIdx() );

Vector2f coord[2] = {
p.getPosition() + Vector2f( -1, -1 ) * (p.getScale() / 2.f );
p.getPosition() + Vector2f(  1,  1 ) * (p.getScale() / 2.f );
};

glColor4ub( p.color().r, p.color().g, p.color().b, p.color().a );
glTexCoord2f( texRect.left,  texRect.bottom ); glVertex2f( coord[0].x, coord[0].y );
glTexCoord2f( texRect.right, texRect.bottom ); glVertex2f( coord[1].x, coord[0].y );
glTexCoord2f( texRect.right, texRect.top    ); glVertex2f( coord[1].x, coord[1].y );
glTexCoord2f( texRect.left,  texRect.top    ); glVertex2f( coord[0].x, coord[1].y );
}
} glEnd();


For further optimizations, you can use VBOs, use the CPU to update all the vertices of all the particles, then send the entire buffer to the GPU in one call.

### #1fastcall22

Posted 17 January 2012 - 09:22 AM

EDIT:
Since then I tested it with part.SetPosition(x,y); and App.Draw(part); commented out, so they are not drawn, and still Particle::show takes up 61% of the resources (was 74 previously)... with that commented out, the SDL and SFML Particle::show() are identical, except in SDL they actually get drawn.

This would suggest that the API is the bottleneck (as indicated earlier in the thread). If I recall correctly, SFML uses OpenGL 1.1 immediate-mode calls, which would mean for every particle, there's a call to glBindTexture, glPushMatrix/glPopMatrix, and glBegin/glEnd. For something like a particle system, the overhead in each of these calls, while not significant on their own, can snowball. To reduce the overhead from texture switching, place all of your particle textures on one sheet. Since SFML doesn't seem to have any feature that will allow us to assign a part of an Image to a Sprite, you'll need to do the rendering yourself through raw OpenGL calls. By doing so, you can optimize out some OpenGL calls and will allow you to do batching, among other things:

glBlendFunc( ..., ... );
Particle::particleSheet.Bind(); // sf::Image::Bind, essentially calls glBind( GL_TEXTURE_2D, particleSheet.handle )
for ( Partice& p : v_particles ) {
cnost Rect2f& texRect = getTextureRect( p.getTextureIdx() );

Vector2f coord[2] = {
p.getPosition() + Vector2f( -1, -1 ) * (p.getScale() / 2.f );
p.getPosition() + Vector2f(  1,  1 ) * (p.getScale() / 2.f );
};

glColor4ub( p.color().r, p.color().g, p.color().b, p.color().a );
glTexCoord2f( texRect.left,  texRect.bottom ); glVertex2f( coord[0].x, coord[0].y );
glTexCoord2f( texRect.right, texRect.bottom ); glVertex2f( coord[1].x, coord[0].y );
glTexCoord2f( texRect.right, texRect.top    ); glVertex2f( coord[1].x, coord[1].y );
glTexCoord2f( texRect.left,  texRect.top    ); glVertex2f( coord[0].x, coord[1].y );
}
} glEnd();


For further optimizations, you can use VBOs, use the CPU to update all the vertices of all the particles, then send the entire buffer to the GPU in one call.

PARTNERS