Jump to content

  • Log In with Google      Sign In   
  • Create Account


gpu particle system problems


Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.

  • You cannot reply to this topic
5 replies to this topic

#1 ic0de   Members   -  Reputation: 808

Like
0Likes
Like

Posted 22 October 2012 - 09:56 PM

So I tried simulating my particles in the vertex shader. I wrote a simple shader that moves point sprite particles based on a velocity vector passed via the colour buffer. Also passed through the alpha component of the colour buffer is the time of the particle's creation. I passed a simple gravity vector as velocity (0, -1.0, 0) and I ran into a problem. The particles fall alright but they start off far lower than they are supposed to. I'm thinking this might have to do with the fact that I'm passing data through the color buffer.

Vertex Shader:
uniform float Time;
uniform float scr_h;


void main()
{
	 vec4 newpos = gl_Vertex;

	 newpos.xyz += gl_Color.xyz*(Time - gl_Color.w); // move the sprite based on velocity

	 vec3 particle = vec3(gl_ModelViewMatrix * newpos); // scale point sprite for perspective
	 gl_PointSize = scr_h / sqrt(dot(particle, particle));
	
	 gl_Position = gl_ModelViewProjectionMatrix * newpos;
}

C++ part:
glUniform1f(ptime, float(SDL_GetTicks()/1000.0));
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_COLOR_ARRAY);
glUniform1f(pr_scrh, float(screen->h));
glBindBuffer(GL_ARRAY_BUFFER, Vbuffer);
glBufferData(GL_ARRAY_BUFFER, particle::getNumParticles() * 3 * sizeof(float), particle::get(), GL_STATIC_DRAW);
glVertexPointer(3, GL_FLOAT, 0, 0);
glBindBuffer(GL_ARRAY_BUFFER, Tbuffer);
glBufferData(GL_ARRAY_BUFFER, particle::getNumParticles() * 4 * sizeof(float), particle::getVelocityTime(), GL_STATIC_DRAW);
glColorPointer(3, GL_FLOAT, 0, 0);
glDrawArrays(GL_POINTS, 0,  particle::getNumParticles() * 3);
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_COLOR_ARRAY);

Anything obvious wrong with my code or even my approach?

P.S. don't bother telling me if anything I'm using is deprecated because this is targeted for OpenGL 2.1

Edited by ic0de, 22 October 2012 - 09:57 PM.

you know you program too much when you start ending sentences with semicolons;


Sponsor:

#2 mhagain   Crossbones+   -  Reputation: 7328

Like
1Likes
Like

Posted 23 October 2012 - 05:49 AM

On older hardware the color array may be interpolated - or just generally stored - with lower precision, as these values generally only need a 0-255 range. You're targetting GL2.1 so you can and should junk glVertexPointer/glColorPointer and use generic attrib arrays instead (glEnableVertexAttribArray/glVertexAttribPointer) - these are guaranteed available with GL2.0 and may even be available on lower versions that have the GL_ARB_vertex_program extension (beware of attrib index 3 on this older hardware as GL_ARB_vertex_program maps that to the color array - I saw the same happen once when storing texcoords at that index; won't be a problem with GL2.0 though).

It appears that the gentleman thought C++ was extremely difficult and he was overjoyed that the machine was absorbing it; he understood that good C++ is difficult but the best C++ is well-nigh unintelligible.


#3 Koehler   Members   -  Reputation: 228

Like
0Likes
Like

Posted 23 October 2012 - 09:25 AM

Your problem could be related to calling glBufferData every frame. Is there a reason you're doing this? The spawn time and original position of your particles does not ever change, and your vertex shader appears to assume that the velocity remains constant as well. If nothing else, calling the function only once when you first create the particle system should help your program in terms of efficiency.

Since you're simulating your particle's position using a single velocity value and its' point of origin. I think you'll find that particle effects will be rather boring when simulated that way. Allow me to suggest some alternative options:

Plain old CPU simulation! You can do something similar to what you're doing now (although I recommend glBufferSubData) to pass a 4 component (position.xyz, time) vector for each particle to your shader, along with uniforms for initial and final (or multiple over time) values for color and scale, and use your time value to interpolate between those in the shader. This will let you handle more complex particle physics such as acceleration while not changing your implementation too much.

If you really want to simulate particles using the vertex shader, I'd suggest using GL_ARB_TRANSFORM_FEEDBACK2 (or GL_EXT_TRANSFORM_FEEDBACK if the ARB version isn't available to you). This will allow you to write the output of a vertex shader back into a buffer, which means you can account for accelerations, changing velocity, and any other properties you may wish to update over time. Note that Transform Feedback probably won't let you write to more than one buffer at a time on GL 2, so you'd probably need to do multiple draw calls to update a system with changing velocity and position.

Another option for GL 2 is to use a pixel shader to do your particle physics, and store properties that change over time in floating-point textures. You can then use vertex texture fetch to read position, age, etc. from said textures in your vertex shader. This will require GL_ARB_texture_float, while you can look up textures in your vertex shader using texture2DLod.

Edited by Koehler, 23 October 2012 - 09:26 AM.


#4 mhagain   Crossbones+   -  Reputation: 7328

Like
1Likes
Like

Posted 23 October 2012 - 10:20 AM

Transform feedback isn't available at all on GL2.

A simple time/gravity/velocity equation on the vertex shader is a good option; something like this:
vec3 NewPosition = StartPosition + (Velocity + (DeltaVee * Time) + Gravity) * Time;

It appears that the gentleman thought C++ was extremely difficult and he was overjoyed that the machine was absorbing it; he understood that good C++ is difficult but the best C++ is well-nigh unintelligible.


#5 Geometrian   Crossbones+   -  Reputation: 1411

Like
0Likes
Like

Posted 23 October 2012 - 10:53 AM

For particle systems, my strong recommendation is to use OpenCL. It's easier to write, more robust, and faster. And, IIRC, requires only a similar level of support as TF.
And a Unix user said rm -rf *.* and all was null and void...|There's no place like 127.0.0.1|The Application "Programmer" has unexpectedly quit. An error of type A.M. has occurred.

#6 ic0de   Members   -  Reputation: 808

Like
0Likes
Like

Posted 23 October 2012 - 09:58 PM

Problem solved it was a stupid mistake.

This:

glColorPointer(3, GL_FLOAT, 0, 0);

Should be This:

glColorPointer(4, GL_FLOAT, 0, 0);

I'll probably switch to attribute arrays later just cause some hardware may not like me re-purposing the colour buffer.

also the reason I'm calling glBufferData every frame is cause this is just test code to try to make it work. For performance reasons it won't appear in the final code.

Edited by ic0de, 23 October 2012 - 10:00 PM.

you know you program too much when you start ending sentences with semicolons;





Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.



PARTNERS