APEX Particle Integration Guide
Introduction
This document gives some tips and guidelines for how to integrate APEX particles into a game that uses PhysX 3.x, to get the best performance without sacrificing visual quality.
CUDA Context Manager
- Do not share a single CudaContextManager between multiple scenes. Although the API does allow you to do this, if you share the CudaContextManager there will be dependencies created between scenes on CUDA work. Most of the time this is not what you want.
- Do not use a CudaContextManager on scenes that don’t use GPU features. For example, if you have a primary scene for handling standard rigid body interactions in your game, and an effects scene for handling APEX particles, you would only need to give a CudaContextManager to the effects scene.
Second Effects Scene
If your game already uses PhysX 3.x for gameplay-affecting rigid body simulation, it may make sense to simulate APEX particles in a separate scene so your game logic won’t be blocked waiting for the APEX simulation to complete. We recommend keeping your primary PxScene as-is, and creating a second effects PxScene paired with an Scene for APEX particle effects. The effects scene can be stepped whenever convenient. Any rigid bodies or shapes you want to interact with APEX particles must be mirrored into the effects scene.
Stepping the effects scene
Even if you use multiple simulation steps per frame in your primary scene, we recommend using a single variable-length timestep in the effects scene. In other words, just pass the elapsed time to the effects scene’s simulate() once each frame. If necessary, you could set a minimum and maximum timestep size.
The effects scene does not have to be stepped at the same time as the primary scene. You could call effectsScene->simulate() earlier and effectsScene->fetchResults() later than the primary scene to allow it to simulate in parallel with other game work.
Mirroring shapes to the effects scene
Any rigid bodies or shapes you want to interact with APEX particles must be mirrored into the effects scene from the primary scene. Keep in mind that you should only add objects to the effects scene when the effects scene is not being simulated. You may be able to get away with much simpler primitives in your effects scene. For example, even if you have a very detailed collision model for your character controller (to detect head shots for example) you could probably just mirror it into the effects scene as a single capsule that approximates the size of the character.
You may want to mirror static geometry into the effects scene so that APEX particles interact with the static environment. Static geometry typically doesn’t get updated once it’s created so this could be done once as the geometry is loaded. Dynamic rigid bodies should be mirrored into the effects scene as kinematics. The PhysX 3.x Extensions include PxCloneDynamic and PxCloneStatic helpers to get you started. See the PhysX documentation for more details.
Fully asynchronous effects scene
If you want to be able to add APEX particle effects with minimal impact on the game’s frame rate, you can take it a step further and create a fully asynchronous effects scene. In this model you step the effects scene in a separate thread at whatever rate you can simulate it at. You buffer the render data and in your game’s normal render loop you render the most recently completed APEX particle render data. If the effects scene simulation time falls behind the game’s frame time, you will see a visual artifact of the particles stuttering, but without any large impact on overall frame rate.
The benefit is the minimal impact the particle effects have on frame rate. The downside is that it becomes more complex to manage the effects scene. Here are some of the things you’ll want to check that you’re handling properly:
- You will need to handle safe communication between your main game thread and the thread managing the effects scene.
- You will have to handle the case where a shape that gets mirrored is added to the primary scene, queued up to be added to the effects scene, then deleted from the primary before it has been added to the effects scene.
- You will have to mirror updates to the mirrored objects like pose or collision group changes.
- You will need to double-buffer the particle rendering data received from APEX in the effects thread and pass it safely to the rendering thread. You will most likely be calling simulate, fetchResults, dispatchRenderResources, and updateRenderResources all from the effects thread.
- There’s no point in simulating the effects more than once a frame, so you’ll also want to limit how often simulate gets called on the effects scene when simulation time is low.