Precautions

This page describes the various precautions to keep in mind when using particles.

Precautions when Calling ParticleSet::UpdateParticle Multiple Times

UpdateParticle can be called multiple times within a single frame regardless of settings when there is only a single command buffer, but special settings are necessary when command buffers are doubled, because the implementation makes alternate use of the rendering buffers (doubled) maintained withing the particle set. The UpdateParticle function can be called multiple times within a single frame without settings.

    Ex: Calling UpdateParticle multiple times within a single frame when command buffers are doubled
    CPU: UpdateParticle(DrawBuff0) -> UpdateParticle(DrawBuff1)
    GPU: Draw(DrawBuff1)
    On the second call to UpdateParticle(DrawBuff1),
    UpdateParticle overwrites DrawBuff0 as the GPU is processes it.

Use one of the following approaches to allow calling UpdateParticle multiple times in a single frame. 

Adjusting the step frame is one method where the playback rate can be increased by gathering updates together and forming one big update. Although this is useful in terms of execution speed, the results differ slightly from per frame processing.

Making multiple updates using a single, internal buffer is another method. Although this requires a looping CPU process, results match the per frame processing.

For details, see ParticleDropFrameDemo.

Delete Shader Resources During Binary Output

During ordinary binary output with no arguments specified, the binary includes shader resources. Delete shader resources from the binary output to reduce the particle binary file size by up to 70%. However, when loading binaries without shader resources, you must attach the shader resources to load separately. See ResGraphicsFile Operations for details.

Deleting Unnecessary Animation Members

Delete any unnecessary animation members to reduce the binary file size by up to 15%. Deleting these from the binary files should be quite effective for particle data that does not use material animations. See Optimization Tips for details.

    Sample XML with all animation members deleted:
    
    <?xml version="1.0" encoding="utf-8"?>
    <OptimizeAnimationMemberSettings>
      <Filters Mode="positive">
      </Filters>
    </OptimizeAnimationMemberSettings>

Precautions when Using Doubled Command Buffers

When command buffers are doubled, the implementation makes alternate use of the rendering buffers (doubled) within the particles, so you cannot update or change the rendering order.

    Ex: Rendering after updating
    0th frame:
    CPU: UpdateParticle(DrawBuff0) → Draw(DrawBuff0)
    GPU:  -
    1st frame:
    CPU: UpdateParticle(DrawBuff1) → Draw(DrawBuff1)
    GPU: Draw(DrawBuff0)
    2nd frame:
    CPU: UpdateParticle(DrawBuff0) → Draw(DrawBuff0)
    GPU: Draw(DrawBuff1)
    Ex: Updating after rendering
    0th frame:
    CPU: Draw(DrawBuff0) → UpdateParticle(DrawBuff1)
    GPU:  -
    1st frame:
    CPU: Draw(DrawBuff1) → UpdateParticle(DrawBuff0)
    GPU: Draw(DrawBuff0)
    UpdateParticle overwrites DrawBuff0 as the GPU is processing it.

Precautions when Deleting Instances

Deleting an instance at the wrong time can cause the destruction of a particle's rendering buffer as it is in use by the GPU, possibly causing the GPU to hang.

    Ex: When there are only single command buffers
    CPU: UpdateParticle(DrawBuff0) → Draw(DrawBuff0)        
    GPU:                                   → Draw(DrawBuff0)
    It is dangerous to delete an instance after CPU rendering.
    To delete after CPU rendering, wait until the GPU is done processing.
    Ex: When command buffers are doubled
    CPU: UpdateParticle(DrawBuff0) → Draw(DrawBuff0)
    GPU: Draw(DrawBuff1)
    Because the render buffer from the previous frame is used by the GPU,
    you account for this fact when deleting instances. (Such as by halting the render and deleting one frame later)

Precautions Regarding Random Numbers

The ParticleContext, ParticleEmitter, and ParticleSet classes all have objects of the ParticleRandom class. You must configure an appropriate seed for each of these ParticleRandom objects. Use the ParticleUtil::SetupParticleObject function to properly configure the random number seed. Not using this function will result in the animation using the same fixed particle emission pattern each time, so you must properly configure the random number seed on the user side for the ParticleEmitter and ParticleSet objects.

About Reusing Instances

Particle creation and destruction are very expensive processes. Every time the effect occurs, an instance (node) is generated and then destroyed again after playback, causing considerable CPU processing load. Nintendo recommends deleting unnecessary instances beforehand and reusing instances where possible.

Ex: How to reuse an instance
Generates nodes.
nw::gfx::ParticleModel*   particleModel   = nw::gfx::SceneBuilder();
nw::gfx::ParticleEmitter* particleEmitter = nw::gfx::SceneBuilder();
// Attach node to scene.
sceneRoot->AttachChild(particleModel);
sceneRoot->AttachChild(particleEmitter);
   :
// Detach from scene once scene is done playing.
sceneRoot->DetachChild(particleModel);
sceneRoot->DetachChild(particleEmitter);
   :
// A reset process for ParticleModel and ParticleEmitter classes if re-used.
// These are then re-attached to the scene.
particleEmitter->Reset();
particleModel->ForeachParticleSet(nw::gfx::ParticleSetsClear());
particleModel->ParticleAnimFrameController().SetFrame(0.f);
sceneRoot->AttachChild(particleModel);
sceneRoot->AttachChild(particleEmitter);

When using doubled command buffers, take care when calling nw::gfx::ParticleSetsClear, as this can wind up clearing the buffer referenced by the GPU.

Precautions When Using ParticleSet::ClearParticleCollection

If doubling the command buffer, the buffer being accessed by the GPU may be cleared if ClearParticleCollection is called.

nw::gfx::ParticleSetClear calls ClearParticleSetCollection internally.

These functions are for initialization when re-using a ParticleSet currently not being used. They cannot be used during rendering.

If the ParticleSet currently in use is cleared, use ParticleCollection::KillParticles instead.

About Instances that Are Done Playing

Nintendo recommends immediately detaching nodes once they are done playing to reduce the processing load. Use code like the following to check if a node is done playing.
Ex: Code sample for checking if a node is done playing
bool IsDone()
{
    nw::gfx::ParticleModel*   particleModel;
    nw::gfx::ParticleEmitter* particleEmitter;
    // Are any particles playing?
    if  (particleModel->HasParticle())
    {
        return false;
    }
    // Is emitter done?
    if (particleEmitter->IsAlive())
    {
        return false;
    }
    return true;
}

CONFIDENTIAL