Jump to content

  • Log In with Google      Sign In   
  • Create Account


#Actualharshman_chris

Posted 18 January 2013 - 08:20 PM

I need some some advice on my particle system.

 

Right now I have a particle emitter which holds a list of particles and each particle has a VBO for its vertices and uvs.

 

Which is bad I know this, it with drawing only 150 particles, I go from just over 100 draw calls, to 3000 draw calls using gDEBugger.

 

Each particle keeps track of its own local and world matrix.

 

I know the general idea is that I need to create a single VBO for each piece of data in the particle emitter, but then how to I pass the mvp for each particle, my particles are not always going to start at the same size.

 

Do I do something like this:

 

int i = 0;

// Pass in new mvp here and any other data that may have changed like colour

glDrawArrays(GL_TRIANGLE_STRIP, i, 4);

i+= 4;

 

 

My code is below:

// Particle Initialization

uvs.push_back(Vector2(1,1)); 
	vertices.push_back(Vector3(
		0+(particleInfo.sizeX/2),
			0+(particleInfo.sizeY/2),
			0));

	uvs.push_back(Vector2(0,1)); 
	vertices.push_back(Vector3(
			0-(particleInfo.sizeX/2),
			0+(particleInfo.sizeY/2),
			0));

	uvs.push_back(Vector2(1,0)); 
	vertices.push_back(Vector3(
			0+(particleInfo.sizeX/2),
			0-(particleInfo.sizeY/2),
			0));

	uvs.push_back(Vector2(0,0)); 
	vertices.push_back(Vector3(
			0-(particleInfo.sizeX/2),
			0-(particleInfo.sizeY/2),
			0));

// This is just a bind function.

// Binding the Data

void Particle::bind()
{
	glGenBuffers(1, &vertexbuffer);
	glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);
	glBufferData(GL_ARRAY_BUFFER, vertices.size() * sizeof(Vector3), &vertices[0], GL_STATIC_DRAW);

	glGenBuffers(1, &uvbuffer);
	glBindBuffer(GL_ARRAY_BUFFER, uvbuffer);
	glBufferData(GL_ARRAY_BUFFER, uvs.size() * sizeof(Vector2), &uvs[0], GL_STATIC_DRAW);
}

 

 

Here is where I update the particle based on the properties.

 

// Updating the Matrix

/* removed for space */

localMatrix = Matrix4::toMatrix4(rotation,position,scale);

 

 

 

Drawing the Particles

 

void Particle::draw()
{
	if(alive)
	{
		glEnable(GL_BLEND);
		glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);

		glEnable(GL_DEPTH_TEST);
		glDepthFunc(GL_ALWAYS);

		Camera *cam = this->particleInfo.scene->getActivePerspectiveCamera();

		worldMatrix = cam->getObjectToWorld().inverse() * localMatrix;

		Matrix4 mvp = cam->getProjectionMatrix() * worldMatrix;

		glUniformMatrix4fv((*particleInfo.shader)["mvp"], 1, GL_FALSE, mvp.transpose().getArray());

		glUniform4f((*particleInfo.shader)["colour"],
			particleInfo.colour.R,
			particleInfo.colour.G,
			particleInfo.colour.B,
			particleInfo.colour.A);

		glEnableVertexAttribArray(0);
		glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);
		glVertexAttribPointer(
			(*particleInfo.shader)["modelVertex"],	// attribute
			3,							// size
			GL_FLOAT,					// type
			GL_FALSE,					// normalized?
			0,							// stride
			(void*)0					// array buffer offset
		);

		// 2nd attribute buffer : UVs
		glEnableVertexAttribArray(1);
		glBindBuffer(GL_ARRAY_BUFFER, uvbuffer);
		glVertexAttribPointer(
			(*particleInfo.shader)["uv"],			// attribute
			2,							// size
			GL_FLOAT,					// type
			GL_FALSE,					// normalized?
			0,							// stride
			(void*)0					// array buffer offset
		);

		// Draw the triangle !
		glDrawArrays(GL_TRIANGLE_STRIP, 0, vertices.size());

		glDisableVertexAttribArray(0);
		glDisableVertexAttribArray(1);

		glDepthFunc(GL_LESS);

		glDisable(GL_BLEND);

	}
}

 

 

Particle Emitter Draw

 

void ParticleEmitter::draw()
{
	Component::draw();

	if(running)
	{
		iter = particles.begin();

		this->getShader()->begin();

		textureDiffuse->bindTexture((*this->getShader())["diffuseTextureSampler"],0);
	
		while (iter != particles.end())
		{
			(*iter)->draw();
			++iter;
		}

		glBindTexture(GL_TEXTURE_2D, 0);

		this->getShader()->end();	
	}
}

#1harshman_chris

Posted 18 January 2013 - 08:15 PM

I need some some advice on my particle system.

 

Right now I have a particle emitter which holds a list of particles and each particle has a VBO for its vertices and uvs.

 

Which is bad I know this, it with drawing only 150 particles, I go from just over 100 draw calls, to 3000 draw calls using gDEBugger.

 

Each particle keeps track of its own local and world matrix.

 

I know the general idea is that I need to create a single VBO for each piece of data in the particle emitter, but then how to I pass the mvp for each particle, or do I loop through the particles and just pass the mvp for each particle and only store 1 vertex and 1 uv coords since they are always the same and any changes happen in the mvp.

// Particle Initialization

uvs.push_back(Vector2(1,1)); 
	vertices.push_back(Vector3(
		0+(particleInfo.sizeX/2),
			0+(particleInfo.sizeY/2),
			0));

	uvs.push_back(Vector2(0,1)); 
	vertices.push_back(Vector3(
			0-(particleInfo.sizeX/2),
			0+(particleInfo.sizeY/2),
			0));

	uvs.push_back(Vector2(1,0)); 
	vertices.push_back(Vector3(
			0+(particleInfo.sizeX/2),
			0-(particleInfo.sizeY/2),
			0));

	uvs.push_back(Vector2(0,0)); 
	vertices.push_back(Vector3(
			0-(particleInfo.sizeX/2),
			0-(particleInfo.sizeY/2),
			0));

// This is just a bind function.

// Binding the Data

void Particle::bind()
{
	glGenBuffers(1, &vertexbuffer);
	glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);
	glBufferData(GL_ARRAY_BUFFER, vertices.size() * sizeof(Vector3), &vertices[0], GL_STATIC_DRAW);

	glGenBuffers(1, &uvbuffer);
	glBindBuffer(GL_ARRAY_BUFFER, uvbuffer);
	glBufferData(GL_ARRAY_BUFFER, uvs.size() * sizeof(Vector2), &uvs[0], GL_STATIC_DRAW);
}

 

 

Here is where I update the particle based on the properties.


// Updating the Matrix

/* removed for space */

localMatrix = Matrix4::toMatrix4(rotation,position,scale);

 

 

 

Drawing the Particles


void Particle::draw()
{
	if(alive)
	{
		glEnable(GL_BLEND);
		glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);

		glEnable(GL_DEPTH_TEST);
		glDepthFunc(GL_ALWAYS);

		Camera *cam = this->particleInfo.scene->getActivePerspectiveCamera();

		worldMatrix = cam->getObjectToWorld().inverse() * localMatrix;

		Matrix4 mvp = cam->getProjectionMatrix() * worldMatrix;

		glUniformMatrix4fv((*particleInfo.shader)["mvp"], 1, GL_FALSE, mvp.transpose().getArray());

		glUniform4f((*particleInfo.shader)["colour"],
			particleInfo.colour.R,
			particleInfo.colour.G,
			particleInfo.colour.B,
			particleInfo.colour.A);

		glEnableVertexAttribArray(0);
		glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);
		glVertexAttribPointer(
			(*particleInfo.shader)["modelVertex"],	// attribute
			3,							// size
			GL_FLOAT,					// type
			GL_FALSE,					// normalized?
			0,							// stride
			(void*)0					// array buffer offset
		);

		// 2nd attribute buffer : UVs
		glEnableVertexAttribArray(1);
		glBindBuffer(GL_ARRAY_BUFFER, uvbuffer);
		glVertexAttribPointer(
			(*particleInfo.shader)["uv"],			// attribute
			2,							// size
			GL_FLOAT,					// type
			GL_FALSE,					// normalized?
			0,							// stride
			(void*)0					// array buffer offset
		);

		// Draw the triangle !
		glDrawArrays(GL_TRIANGLE_STRIP, 0, vertices.size());

		glDisableVertexAttribArray(0);
		glDisableVertexAttribArray(1);

		glDepthFunc(GL_LESS);

		glDisable(GL_BLEND);

	}
}

 

 

Particle Emitter Draw

 

void ParticleEmitter::draw()
{
	Component::draw();

	if(running)
	{
		iter = particles.begin();

		this->getShader()->begin();

		textureDiffuse->bindTexture((*this->getShader())["diffuseTextureSampler"],0);
	
		while (iter != particles.end())
		{
			(*iter)->draw();
			++iter;
		}

		glBindTexture(GL_TEXTURE_2D, 0);

		this->getShader()->end();	
	}
}

 

 


PARTNERS