GLSL Suitable for fluid physics?


I’m new to these forums, and relatively new to GLSL, although I’ve implemented a couple of basic shaders.

I’m working on a 2D game which focuses mostly around fluid physics (specifically a variation of Smoothed Particle Hydrodynamics, as described in this paper). For the purposes of this discussion, the specific details of the fluid simulation isn’t important, but these points might be:

  • The simulation involves particles, which could potentially be modelled as vertex information.
  • Each particle needs to know about the particles which are close to it in order to work out what to do next.
  • I need to have some representation of the particle positions available on the CPU in order to resolve the interactions between the fluid particles and the solid objects in my physics engine.

So, what I want to do is to have a bunch of information about each particle stored somewhere accessible from my main program (be that in RAM or as a Vertex Buffer Object or something similar on the GPU), but have the ability to hand off the actual fluid physics calculations off to some processor other than the CPU. In other words, I want to handle some of my physics and other game logic in my main program, but get the graphics card to handle most of the fluid physics. So something like (pseudocode):

for(each particle) DoInteractionsWithWorld(); // This updates particle positions if they intersect with solid objects in the physics engine

RenderParticles(); // Before rendering the particles, this invokes a GLSL shader which updates their positions according to the fluid sim.

GetNewParticlePositions(); // This retrieves the results of RenderParticles, so I have the new particle positions to interact with the world in the next timestep.

Is this sort of thing possible with GLSL? Is it sensible? Or is it folly to try to write a vertex shader which has an awareness of other vertices, and which can return the results of its processing t0 the CPU?

See Nvidia’s fluid sample circa 2004.

I guess I need more information, or for someone to take me through this more slowly. The fluid sample demo doesn’t seem to run properly on my machine (not that I especially need it to, I’m aware of Jos Stam’s method), but the accompanying white paper goes some way towards explaining the different paradigms and terminology of working on the CPU and the GPU, and it’s something I’ll be referring back to.

I don’t want to get too bogged down in the specifics of different approaches to simulating fluid, but it’s worth re-iterating that Stam’s method works on an Eulerian grid (values at specific points on a fixed grid changing, with the obvious analogies to a texture being utilised by the NVidia sample), whereas the approach that I’m using is based on Smoothed Particle Hydrodynamics, which is a Langragian approach (i.e. particles moving freely in a space, where the behaviour of each particle is influenced by other particles which are close to it). It seems like more of a job for a vertex shader rather than a fragment shader, since the things involved are not neatly aligned to a grid.

Consider it this way, if it helps to think of things more as particle systems than as fluids: I want to make a 2D top-down snooker game, and I want to have the GPU control the physics to move the balls around and to deal with balls colliding with each other, but I want the get the results of those physics back so that I can perform other actions (such as balls bouncing off cushions or going into pockets) on the CPU. I’m aware that that’s a silly thing to want to do in the snooker analogy, but for my fluid physics it’s less silly - let the GPU handle the interactions between the particles, but have the CPU handle the interactions between the particles and the world.

What’s an efficient way to go about this? How can I feed the positions and velocities of the balls to the GPU to calculate their movement, and then get those results back so that I can make other calculations about cushions and pockets on the CPU? I have two things I don’t understand:

1 - If a ball is consired as a particle (with a position and a velocity and a number of other attributes), how can I pass that to a vertex shader in such a way that it’s able to be aware of the other balls which might be near it so it can interact with them appropriately?

2 - If, once I’ve used a shader to calculate movements and collisions between balls, how do I get the new positions and velocities back so that I can monkey with them some more on the CPU, ready to pass the monkeyed-with positions and velocities back to the shader on the next frame?

IMHO yes. You could take a look at CUDA, perhaps it is better suited as it is not a graphics API designed to get input data and to output images.

The CUDA nBody demo is something to behold.

Chapter 33 of GPU Gems 3 outlines an algorithm for LCP-based collision detection using CUDA.

CUDA is not something I was previously aware of, although after doing some reading it seems closer to what I’m trying to achieve than trying to force GLSL to do such things. The main problem with it seems to be that it’s an Nvidia only thing, which isn’t ideal for me since I want my game to be as compatible with as many graphics cards as possible. I see that AMD has similar stuff (FireStream, is it?), and that there appears to be the beginnings of a more open standard for this sort of thing in the form of OpenCL, but it all seems a bit new and untested from what I’ve read.

If GLSL isn’t suitable for this job, is there any other widely-established non-vendor-specific way to perform arbitrary calculations on a GPU? Should I do CUDA for Nvidia GPUs and find other ways to code things for other GPUs, or is there a broader solution? My game is heavy on the fluid particle physics, so I can’t have the CPU do all of the work, but I want to make it as accessible as possible to people with a wide variety of hardware configurations, because that has a direct impact on how many people will buy the game.

It looks like it’s going to be a pretty short walk (a hop and half a skip) from CUDA to OpenCL, which is shaping up to be the compute standard in the very near future. NVIDIA just released CL drivers to developers this week so maybe now’s a good time to give it a spin. Otherwise I imagine many of the lessons learned from CUDA will be applicable to CL when it makes its public debut (in very short order we hope).

It sounds like my options are to start prototyping with CUDA, then, and probably to add AMD support as well (FireStream?), and hope that OpenCL might become established enough before the game ships that I could consider switching over to that (and/or supporting it as well as CUDA & FireStream)… Sounds like a bit of a maintenance headache. Perhaps I’ve chosen the wrong time to get into doing physics on the GPU :slight_smile:

I’ve read up on CUDA and OpenCL some more, and CL certainly looks promising. I suppose my main question is that if it becomes widely adopted by NVidia, AMD, and others, what are the chances of them updating the drivers for cards already in existence which might be suitable for running CL? Is it reasonable to expect NVidia to add CL support to cards going back to (say) the G8X series, and AMD to add support for the Radean 580 onwards? Or would CL only be available for new cards?