Which function is faster to draw a circle odCircle, ofDrawEllipse or ofDrawCircle?

I’m doing a particle system and I have to draw around 300 particles, right now I’m using ofcircle but I don’t know if ofDrawCircle is better, any suggestion? :slight_smile:

here the particle systme:

if you look at method ofCircle inside, it calls ofDrawCircle method so it’s the same.

Your circles look square a little bit.
Try to set ofSetCircleResolution(200); or maybe do you use an ofFbo to draw the particles?

1 Like

yes I do , I use ofFbo to draw the particles because I use ofShader to create a “mandala”

@SebastianSobotka

I had some issues with circles and fbo in the past. Setting numSamples parameter helped.

//numSamples max = 16
fbo.allocate(width, height, GL_RGB, 8);
1 Like

thanks for your advice, I gonna search information about ‘numSamples’ and the functionality of this parameter

the numSamples is for antialiasing. It might help on having hard edges correctly antialised.
Although, if you are drawing a lot of circles or whatever geometry, a better approach is using instanced rendering. there are some examples in the gl folder. It is a lot faster and more efficient than calling ofDrawCircle.

@roymacdonald 's method is probably the fastest, but if you want to avoid shaders, you can put all of the circles into a single mesh. That reduces the draw calls to one vs. the number of circles.
You can store the normalized vertices at your desired resolution so that you don’t have to call sin and cos for each circle.
In your setup function do something like:

int res = 32;
ofVec3f tvert;
for( int i = 0; i < res; i++ ) {
    float angle = (float)i * (TWO_PI / (float)res);
    tvert.x = cos( angle );
    tvert.y = sin( angle ); 
    mCircleVerts.push_back( tvert );
}

And then use the following function to add circles to your mesh.
If you call if every frame, don’t forget to call mesh.clear();

void _addCircleToMesh( ofMesh& amesh, ofVec2f& acentroid, float aradius, ofFloatColor& acolor ) {
    int voffset = amesh.getNumVertices(); 
    ofVec3f tvert;  
    for( int i = 0; i < res; i++ ) {
        tvert.x = mCircleVerts[i].x * aradius + acentroid.x;
        tvert.y = mCircleVerts[i].y * aradius + acentroid.y;
        amesh.addVertex( tvert );
        amesh.addColor( acolor );
    }
    
    amesh.addVertex( acentroid );
    
    for( int i = 0; i < res; i++ ) {
        if( i == res -1 ) {
            amesh.addIndex( i + voffset );
            amesh.addIndex( 0 + voffset );
            amesh.addIndex( res + voffset );
        } else {
            amesh.addIndex( i+0 + voffset );
            amesh.addIndex( i+1 + voffset );
            amesh.addIndex( res + voffset );
        }
    }
}
1 Like

Hi @NickHardeman.

Did you actually check that your method is faster? I’m doing now some tests and I get similar frame rates, compared with a loop of ofDrawCircle

By the way, there is a amesh.addColor( acolor ) missing after amesh.addVertex( acentroid );

Ah right, thanks for that addColor.

I just did a quick test drawing 40,000 circles with a resolution of 22 ( the default circle resolution for OF).
ofDrawCircle: 15 fps
Single Mesh: 22 fps.

So a 7fps increase for the Single Mesh.
But if you’re only drawing 300 circles, it might be insignificant.

@NickHardeman, @jagracar, @roymacdonald

I increase the number of particle an the fps using gl methods but I would like to increase the fps using mesh but I’m not if I will be able to have the same result, here is code if anyone can help and thanks so much for your advice :slight_smile:

I have just implemented mesh and this is the result, Any idea to increase the fps? here if the new code :slight_smile:

Actually, if the color for all the circles is the same, you can get a considerable improvement removing the addColor calls and calling ofSetColor(acolor) before you draw the mesh.

And you can get some extra fps if you resize the vectors first:

ofMesh mesh = ofMesh();
vector<ofVec3f>& meshVertices = mesh.getVertices();
vector<ofIndexType>& meshIndices = mesh.getIndices();
meshVertices.resize((1 + circleResolution) * nPoints);
meshIndices.resize(3 * circleResolution * nPoints);

and then simply set the values avoiding creating new objects:

meshVertices[verticesCounter].set(x, y,0);
meshVertices[indicesCounter] = i;

I get 37fps for 100,000 points (res=22) using this method, compared to 13fps using drawCircle.

I implemented it in ofxGrafica here:

Cheers!

1 Like

@GinesMendoza, you can also get some fps if you use a mesh for your lines:

ofMesh mesh = ofMesh();
mesh.setMode(OF_PRIMITIVE_LINES);
vector<ofVec3f>& meshVertices = mesh.getVertices();

meshVertices.emplace_back(x1, y1, 0);
meshVertices.emplace_back(x2, y2, 0);
1 Like

eyy @jangracar, thanks for your answer, I’m just drawing line and I’m doing this:

ParticleSystem.cpp

void ParticleSystem::addForce(float targetX, float targetY, float radius, float scale, ofMesh& mesh, Particle& cur) {
	float minX = targetX - radius;
	float minY = targetY - radius;
	float maxX = targetX + radius;
	float maxY = targetY + radius;
	if(minX < 0)
		minX = 0;
	if(minY < 0)
		minY = 0;
	unsigned minXBin = ((unsigned) minX) >> k;
	unsigned minYBin = ((unsigned) minY) >> k;
	unsigned maxXBin = ((unsigned) maxX) >> k;
	unsigned maxYBin = ((unsigned) maxY) >> k;
	maxXBin++;
	maxYBin++;
	if(maxXBin > xBins)
		maxXBin = xBins;
	if(maxYBin > yBins)
		maxYBin = yBins;
	float xd, yd, length, maxrsq;
	float xhalf;
	int lengthi;
	maxrsq = radius * radius;
	int x,y;
	for(y = minYBin; y < maxYBin; y++) {
		for(x = minXBin; x < maxXBin; x++) {
			vector<Particle*>& curBin = bins[y * xBins + x];
			int n = curBin.size();
			for(int i = 0; i < n; i++) {
				Particle& curParticle = *(curBin[i]);
					xd = curParticle.pos.x - targetX;
					yd = curParticle.pos.y - targetY;
					length = xd * xd + yd * yd;
					if(length > 0 && length < maxrsq) {

						mesh.addVertex(cur.pos);
						mesh.addColor(ofFloatColor(cur.color.r / 255.f, cur.color.g / 255.f, cur.color.b / 255.f, 0.12f));
						mesh.addVertex(curParticle.pos);
						mesh.addColor(ofFloatColor(curParticle.color.r / 255.f, curParticle.color.g / 255.f, curParticle.color.b / 255.f, 0.12f));
						int voffset = mesh.getNumVertices();
						mesh.addIndex(voffset - 2);
						mesh.addIndex(voffset - 1);

						xhalf = 0.5f * length;
						lengthi = *(int*) &length;
						lengthi = 0x5f3759df - (lengthi >> 1);
						length = *(float*) &lengthi;
						length *= 1.5f - xhalf * length * length;
						xd *= length;
						yd *= length;
						length *= radius;
						length = 1 / length;
						length = (1 - length);
						length *= scale;
						xd *= length;
						yd *= length;
						curParticle.force.x += xd;
						curParticle.force.y += yd;
					}
			}
		}
	}
}

mesh.addVertex(cur.pos);
mesh.addColor(ofFloatColor(cur.color.r / 255.f, cur.color.g / 255.f, cur.color.b / 255.f, 0.12f));
mesh.addVertex(curParticle.pos);
mesh.addColor(ofFloatColor(curParticle.color.r / 255.f, curParticle.color.g / 255.f, curParticle.color.b / 255.f, 0.12f));
int voffset = mesh.getNumVertices();
mesh.addIndex(voffset - 2);
mesh.addIndex(voffset - 1);

ofApp.h
ofMesh mesh;

Why are you getting the vertices to draw the lines?
all particles have their own color :slight_smile:

I have just changed

mesh.addVertex(cur.pos);
mesh.addColor(ofFloatColor(cur.color.r / 255.f, cur.color.g / 255.f, cur.color.b / 255.f, 0.12f));
mesh.addVertex(curParticle.pos);
mesh.addColor(ofFloatColor(curParticle.color.r / 255.f, curParticle.color.g / 255.f, curParticle.color.b / 255.f, 0.12f));
int voffset = mesh.getNumVertices();
mesh.addIndex(voffset - 2);
mesh.addIndex(voffset - 1);

to

vector<ofVec3f>& meshVertices = mesh.getVertices();
						meshVertices.emplace_back(cur.pos);
						mesh.addColor(ofFloatColor(cur.color.r / 255.f, cur.color.g / 255.f, cur.color.b / 255.f, 0.12f));
						meshVertices.emplace_back(curParticle.pos);
						mesh.addColor(ofFloatColor(curParticle.color.r / 255.f, curParticle.color.g / 255.f, curParticle.color.b / 255.f, 0.12f));

and it seems to be running faster, thanks @jagracar

In my case it saves me one object creation, because I can use emplace_back, instead of push_back.

In your case, you already have the ofVec3f object, so you don’t win anything.

Note that if you use mesh.setMode(OF_PRIMITIVE_LINES), you don’t have to add the indices information, which will save you some time.

Cheers!