paris master class 2011 - 06 gpu particle system

27
GPU Particle System Wolfgang Engel Confetti Special Effects Inc., Carlsbad Paris Master Class

Upload: wolfgang-engel

Post on 28-Jul-2015

163 views

Category:

Engineering


5 download

TRANSCRIPT

GPU Particle System

Wolfgang EngelConfetti Special Effects Inc., Carlsbad

Paris Master Class

Agenda

• Why GPU Particle System (PS)?• Difference between a Stateless / State-

preserving PS• Implementation of a State-preserving PS

Particle System

Particle System

Particle System

Particle System

Why GPU Particles?

• CPU Particles: – transfer bandwidth of particle data CPU -> GPU ==

bottleneck– CPU not fast enough

• GPU Particles [Latta]: – Data is generated on the GPU and kept on the

GPUminimize CPU <-> GPU interaction

– Challenges: how to play sound ….

Stateless / State-Preserving PS

• Stateless: data computed from birth to death by closed-form function

p is the computed particle positionp0 is the initial position

v0 is the initial velocity

t is the current time

• Does not store current position or other attributes-> can hardly react to a change of the environment

• First-gen programmable GPU -> 99% of all particle systems used in games

• Ideal for small and simple effects without environment interaction e.g. weapon, splash, sparks of a collision

Stateless / State-Preserving PS

• State-preserving: numerical, iterative integration method – Compute particle data every frame by comparing

with the data from the previous frame• Integral of acceleration over time gives you velocity• Integral of velocity over time gives you position

– Based on environmental changes or other changes

• More flexible -> Next-Gen

State-Preserving PS

• Agenda– Particle Data Storage– Process birth and death– Update Velocities– Update Positions– (Optional) Sort for alpha blending or other

reasons

State-Preserving PS

• Particle Data Storage• Most important data is position and velocity• There is also orientation, size, color, opacity• Stored each in render targets (several values packed up in

16-bit or 32-bit fp render target channels)-> each texture is conceptually treated as a 1D array; texture coordinates representing array indices-> textures are 2D

• Blit into render target• Data need to be double-buffered because a texture can’t

be read and write to at the same time

State-Preserving PS

• Process birth and death– Birth and death are handled on the GPU -> no CPU

interaction– A time variable decides on the death and re-birth of

the particle– In case of a GPU Particle system there is re-birth

happening -> the particles just can’t remember their previous life

– In other words the slot in the texture is re-used over and over again

State-Preserving PS

• Process birth and deathpos.w += frameTime;

// if the particle exists since more than 4 seconds let it die and re-birth at the same time with some starting valuesif (pos.w >= 4.0){

// Restart animationdir.xyz = sprinkleDir;pos.xyz = float3(0, -235, 0);pos.w -= 4.0;

} else {

// run a cool physics simulation here}

State-Preserving PS

• Update Velocities– Several velocity operations possible– Global forces: gravity, wind– Local forces (all are based on a fall off with

distance): • Attraction • Repulsion• Velocity dampening / un-dampening• Collision response

State-Preserving PS

• Update Velocities• Complex local forces can be mapped with a 2D or 3D

texture containing vector data -> called flow field texture• Sampled flow vector vfl can be used with Stoke’s law of a

drag force Fflow on a sphere

• Where η is the flow viscosity, r the radius of the sphere (in our case the particle) and v the velocity vector

State-Preserving PS

• Update Velocities• All global and local forces are then accumulated into a single force vector• Convert force to acceleration -> Newton physics

where

a is the acceleration vector

F the accumulated force

m the particle’s mass

• Velocity is then updated from acceleration with simple Euler integration

where

v is the current velocity,

v is the previous velocity

∆t the time step

• Update Velocitiespos.w += frameTime;

if (pos.w >= 4.0)

{

// initialization

} else {

// Gravity

// rough approx. of Newton physics

// a = F / m

// here m is 1.0

// Update position ~ Euler integration

// v = vprev + a * deltaTime

dir.y -= 500.0 * frameTime;

// Update position

// collision handling comes here

}

State-Preserving PS

• Update Velocities– Dampening

• special case of Stoke’s law of drag force on a sphere

– With vflow == 1.0

• Or just

r – distancee – small epsilon to prevent divide by 0

• Or just

// dampening simplified

dir.xyz -= (dir.xyz * frameTime2 * 0.4f);

– Un-dampening: imitate self-propelled objects like a bee swarm

State-Preserving PS

• Update Velocities– Collision [Sims]– Split velocity (relative to collider) into normal vn ad

tagential vt component

vn = (v.n)n

vt = v - vnn is the normal of the collider == plane normal/normal map

v is the velocity computed so far

vn is the normal component of velocity

vt is the tangential vector

State-Preserving PS

• Update Velocities– Collision [Sims]

New velocity is then

dynamic friction μ reduces the tangential component

resilience Є scales the reflected normal component

vn = collisionPlane.xyz * dot(collisionPlane.xyz, velocity.xyz);

vt = velocity.xyz – vn;

velocity.xyz = (1 – u) * vt – e*vn;

State-Preserving PS

• Update Velocities– Collision [Sims]– Challenges• dynamic friction μ might approach zero

-> don’t apply friction slow-down if velocity is smaller than threshold

State-Preserving PS

• Update Velocities– Particles caught in the collider• Calculate distance twice for previous and current frame• Create line segment• Figure out the contact point• Set the new position to the contact point

float4 collisionPlane = collisionPlanes[collisionPlaneIdx];

float startDist = dot(lastPosition.xyz, collisionPlane.xyz) - collisionPlane.w;

float endDist = dot(position.xyz, collisionPlane.xyz) - collisionPlane.w;

//

float3 lineSegment = (position - lastPosition);

float frontbackRatio = abs(startDist) / (abs(startDist) + abs(endDist));

float3 contactPoint = lastPosition + (frontbackRatio * lineSegment);

State-Preserving PS

• Update Velocities– Other collision

• Terrain: height map -> generate normal from height map• Complex collisions -> cube collision map store depth and normals

in a cube map

State-Preserving PS

• Update Position– Integral of velocity over time gives you position

-> Euler Integration again for position

if (pos.w >= 4.0){

// Restart animation

dir.xyz = sprinkleDir;

pos.xyz = float3(0, -235, 0);

pos.w -= 4.0;

} else {

// Gravity

dir.y -= 500.0 * frameTime;

// Update position

// p = p + v * deltaTime

pos.xyz += frameTime * dir;

}

State-Preserving PS

• Sorting – Sort per-particle

• For alpha blending– Ignore if possible– Use Order-Independent Transparency– Sort on the GPU -> expensive see [Latta]

• Any other reason to sort per-particle -> probably not

– Sort per-emitter • Sort emitters with certain properties like lights, lights and

shadows and render them together• Sort on the CPU -> send down new index points into the

render targets -> next to free on the GPU

State-Preserving PS

• Alternatives to Euler Integration– Verlet Integration see [Latta] -> save the velocity

buffer – Runge Kutta RK4 [Fiedler]

State-Preserving PS

References

• [Latta] Lutz Latta, http://www.2ld.de/• [Fiedler] Glenn Fiedler

http://gafferongames.com/game-physics/integration-basics/

• [Sims] Sims, Karl; Particle Animation and Rendering Using Data Parallel Computation, in SIGGRAPH Proceedings 1990