Particles and birth position

Started by
3 comments, last by noodleBowl 9 years, 4 months ago

I was wondering if anyone had some ideas on how I could solve this

I have a stateless particle system, where on creation of my particle emitter a buffer is filled with all the initial particle values. This includes a start position for each particle based on the position of the emitter.

Now I'm wondering how could I change the birth position of a particle, after the particle emitter is created.

I want to be able to move my particle emitter and still have any live particles stay their course, when they die/restart they then just use the newest emitter position.

I currently have a vec2 uniform ( emitterPosition ) that represents my emitters position but I definitely don't think this is enough for what I want to do.

My particles position is based on the following GLSL


vec2 position;
position.x = emitterPosition.x + (velocity.x * elapsedTime) + (0.5 * acceleration.x * pow(elapsedTime, 2.0));
position.y = emitterPosition.y + (velocity.y * elapsedTime) + (0.5 * acceleration.y * pow(elapsedTime, 2.0));
	

Any ideas on how I can do this that is not too crazy?

Advertisement

Out of curiosity, why do you feel changing the emitter position isn't enough (unless you want to simply change some particles and not all of them)? A cursory glance seems like it should. I think my general setup for particles looks similar, and if I need them to start in a different position, I just change the code that calculates the starting position.

If for whatever reason that doesn't work, couldn't you just pass in another value and subtract it from the emitter position? So, if you wanted random starting points, you'd calculate and pass in random values and subtract them from the emitter position (You'd need to calculate them on creation and keep them as a value of your particle struct, otherwise they'd be random every iteration).

Feel free to clarify, it's possible I'm misunderstanding your problem tongue.png

Beginner here <- please take any opinions with grain of salt

Out of curiosity, why do you feel changing the emitter position isn't enough (unless you want to simply change some particles and not all of them)? A cursory glance seems like it should. I think my general setup for particles looks similar, and if I need them to start in a different position, I just change the code that calculates the starting position.

If for whatever reason that doesn't work, couldn't you just pass in another value and subtract it from the emitter position? So, if you wanted random starting points, you'd calculate and pass in random values and subtract them from the emitter position (You'd need to calculate them on creation and keep them as a value of your particle struct, otherwise they'd be random every iteration).

Feel free to clarify, it's possible I'm misunderstanding your problem tongue.png


I thought this too! I thought I could just do some simple math and everything would be ok, so I'm not sure if I'm just doing it wrong or over thinking something

What I want to be able to do is: lets say I let my particle emit X particles for 20 seconds and then my emitter jumps to a secondary location and continues emitting particles.
Whatever amount of particles that were emitted at the first location, I want them t stay there and run their course. Then the particles at the second location do there own thing
I really just want my particles to be disconnected from the emitter

When my constructor for my particle emitter runs, it fills a buffer with individual particle data which includes the start position for a particle.
That is the only time I give particles data, after that all calculations are based on elapsed time and are done in the vertex shader.

I thought if I did something like this I would be ok


vec2 position;
position.x = (emitterPosition.x + startPosition.x) + (velocity.x * elapsedTime) + (0.5 * acceleration.x * pow(elapsedTime, 2.0));
position.y = (emitterPosition.y + startPosition.y) + (velocity.y * elapsedTime) + (0.5 * acceleration.y * pow(elapsedTime, 2.0));

But I think I need to preserve a value per particle or do something on the CPU side?

Oh, certainly. If you only have a single emitter, and you're passing that value, then when you change it, it's going to change for all your particles. Rather than using an emitter, you could just add a second variable to your particle struct and set it when you create your particle, like "startingPos" or something along those lines. Without seeing your particle creation function, I couldn't be more specific than that.

What sort of container are you using for your particles? I imagine in addition to position, you're assigning color, speed, life(time existed) etc for them, correct? You can even leave in your emitter for simplicity, but just set your startingPos value based on that, then pass that value into the shader instead of the emitter. Feel free to post a bit more code if you need help with the specifics.

Beginner here <- please take any opinions with grain of salt

All my particles are created up front when the emitters constructor is called. I pass in a value for the max amount of particles the emitter is able to have.
And then in my particle emitter constructor I create all of the values for each of my particles and store it into a static VBO like:


//Particle creation
GLfloat *vertices = new GLfloat[size];

for (int i = 0; i < size;)
{
	for (int j = 0; j < VERTEX_COUNT_PER_QUAD; j++)
	{
		vertices[i++] = initEmitterPosition.x;
		vertices[i++] = initEmitterPosition.y;
		
		vertices[i++] = velocityX;
		vertices[i++] = velocityY;

		vertices[i++] = accelerationX;
		vertices[i++] = accelerationY;

		vertices[i++] = particleLifetime;
	}
}

//VBO setup
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBufferData(GL_ARRAY_BUFFER, size * sizeof(GLfloat), vertices, GL_STATIC_DRAW);


So my container is just my VBO and then everything is handled by the GPU in the shader after the initial creation.
My emit function is super simple:
if (active == false)
	return;

elapsedTime += deltaTime;
glUseProgram(shaderProgram.programID);
glUniformMatrix4fv(shaderProgram.uniforms["MVP"].location, 1, GL_FALSE, viewMatrix->matrix);
glUniform2f(shaderProgram.uniforms["emitterPosition"].location, x, y);
glUniform1f(shaderProgram.uniforms["elapsedTime"].location, elapsedTime);
glUniform1f(shaderProgram.uniforms["particleSpawnDelay"].location, particleSpawnDelay);
glUniform1f(shaderProgram.uniforms["respawnParticles"].location, respawnParticles);

glBindVertexArray(vao);
glDrawElements(GL_TRIANGLES, particleLimit * INDICES_COUNT_PER_QUAD, GL_UNSIGNED_SHORT, (void*)NULL);
glBindVertexArray(NULL);
So really I am never "creating" any particles after the initial the emitter creation

This topic is closed to new replies.

Advertisement