Sign in to follow this  

Simple particle system completely in HLSL?

This topic is 3192 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I just got my first particle system working in software (C++, D3D9, Point Sprites). The features I've got are: Variable point size per particle Velocity + Position per particle global gravity global force vector (wind, secondary gravity, etc) I think it wouldn't be terribly hard to make this all calculated in a shader, but I'm new-ish to HLSL so I have a few questions and want to run my general theory by the more experienced here. Textures for: Position Velocity Birth Time + Size Position2 Velocity2 1) Render pass 1 would render out Position + Velocity * dt to Position2 render target. 2) Pass 2 would render Velocity + Gravity * dt + Force * dt to Velocity2 render target. 3) I would then read Position2 into a vertex array and do a pointlist render through my normal point-sprite shader, using the Birth Time + Size texture. 4) Effectively swap Position and Position2, and Velocity and Velocity2 by swapping pointers 5) Do it all again. Does this seem reasonable? Is it possible to render to the same target that I'm sampling (i.e. pass 1 would source Position texture AND render back to it at the same time)? Is there any way I can skip render #2 and calculate the present velocity just using currTime - birthTime? I'm planning on storing the current beginning of the free particles position as a texcoord so I know where to go to start allocating new ones when old ones die. Is there any better way to do this? Right now (in my mostly-software implementation) each particle's psize is sent as part of the FVF... is there any way to get around this and use values from my Birth Time + Size texture? I guess if it's not possible I could do another pass to render to that... or else just forget about variable particle sizes. Thanks very much! [edit] I guess it probably would have been better to put this in the DirectX forum. Sorry about that. Mods feel free to move this there. [/edit] [Edited by - c0uchm0nster on March 15, 2009 3:53:12 PM]

Share this post


Link to post
Share on other sites
This doesn't really relate only to DirectX as its applicable in OpenGL and even on the current-gen consoles - no need for it to be moved.

Quote:

Textures for:
Position
Velocity
Birth Time + Size
Position2
Velocity2


Ideally you would want to minimize the amount of textures used. With renderable textures, you can have 4 channels of data - so try to tightly pack textures where possible.

For example:
Texture 0: Pos X, Pos Y, Pos Z, Birth Time
Texture 1: Vel X, Vel Y, Vel Z, Radius


Quote:

1) Render pass 1 would render out Position + Velocity * dt to Position2 render target.
2) Pass 2 would render Velocity + Gravity * dt + Force * dt to Velocity2 render target.
3) I would then read Position2 into a vertex array and do a pointlist render through my normal point-sprite shader, using the Birth Time + Size texture.
4) Effectively swap Position and Position2, and Velocity and Velocity2 by swapping pointers
5) Do it all again.
Does this seem reasonable?


Yeah it can be done that way, although the reading of a texture into a vertex array may be prohibitive on many videocards. Its possible on some hardware to treat texture memory as a vertex buffer directly avoiding this. On other hardware, its possible to sample a texture in the vertex shader, also avoiding the need to 'read' texture memory.

Quote:

Is it possible to render to the same target that I'm sampling (i.e. pass 1 would source Position texture AND render back to it at the same time)?

Not likely on most PC hardware. Some console hardware can do this. If you can set up your code so that it can optionally do this, that would be your best bet :)

Quote:

Is there any way I can skip render #2 and calculate the present velocity just using currTime - birthTime?

Yes, if the velocity & gravity never changes per particle then you can just use standard physics formulae. Instead of current pos & current vel, you just have spawn position and spawn velocity. Google "linear motion equations"

Quote:

I'm planning on storing the current beginning of the free particles position as a texcoord so I know where to go to start allocating new ones when old ones die. Is there any better way to do this?

There are all different ways of handling this, and not any one is particularly perfect. You may want to experiment with different solutions and come back here if you find some awesome way to handle this and let everyone else know ;)

Quote:

Right now (in my mostly-software implementation) each particle's psize is sent as part of the FVF... is there any way to get around this and use values from my Birth Time + Size texture? I guess if it's not possible I could do another pass to render to that... or else just forget about variable particle sizes.

Most if not all shader languages allow for point sprite size as an output of a vertex shader. The semantic is PSIZE i believe. If you have your size and time data in the vertex shader, you can make PSIZE a function of that.

Share this post


Link to post
Share on other sites
Thanks very much for the answers!

I actually ended up figuring out a lot of this today with the help of some very smart friends.

Still not quite there yet (I'm having some problems with the render targets) but I'm sure it's just something stupid I'm doing or overlooking. On the bright side I've learned a ton of new things in the debugging process.

I'll try and update this thread as best as I can once I have something noteworthy so any passers-by can read what worked out for me.

Share this post


Link to post
Share on other sites
If particles do not interact with environment and each other (which would be hard to do with hlsl), you can simply calculate position at specific time right in the shader without having to do any simulation or render targets.

Using the formula
p=p0+v0*t+a*t*t;
where p0 is initial position, v0 is initial velocity, and a is acceleration (vector).

The velocity at time t is a*t , by the way.
You can also calculate the time when particle would hit the floor, and use it as particle lifetime.

Share this post


Link to post
Share on other sites

This topic is 3192 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this