Features Used to Render Particles

Enlarging and reducing particles during rendering

Sometims you want to change only the size of particles without changing their render position. To apply a different scale to each individual particle, you can either add an animation or change stream content within the program. Here, we introduce a feature for changing the size of all particles at once.
An offset can be applied to the particle scale during rendering by setting a multiplication factor using ParticleSet::SetScaleOffset. Similarly, you can add an offset to the rotation of a particle during rendering by using ParticleSet::SetRotateOffset.

Using VRAM

Higher speeds can be expected when rendering particles by placing textures in VRAM.
VBO is allocated in FCRAM. FCRAM is required because calculations are performed by the CPU each frame. Because the cost of transferring this data to VRAM is high, it's faster to use the data while in FCRAM.

Textures can be placed in VRAM at time of setup using code such as the following

resource.ForeachTexture(
    nw::gfx::TextureLocationFlagSetter(
        NN_GX_MEM_VRAMA  | GL_NO_COPY_FCRAM_DMP)); 

to set flags for resources. With 3D models, even IndexStream and VertexStream can be placed in VRAM using code like the following.

resource.ForeachIndexStream(
    nw::gfx::IndexStreamLocationFlagSetter(
        NN_GX_MEM_VRAMB  | GL_NO_COPY_FCRAM_DMP));
resource.ForeachVertexStream(
    nw::gfx::VertexStreamLocationFlagSetter(
        NN_GX_MEM_VRAMB  | GL_NO_COPY_FCRAM_DMP));

However, even if the code given above is applied to particle resources, they will not be placed in VRAM.
Since particles are not resources, ParticleShape directly creates, owns and destroys VBO. A resource flag is not used at time of creation.

Explicitely Flushing VBO

Because the VBO is not explicitly flushed when using particles, problems sometimes arise in rendering depending on the situation. One common problem that occurs is particle motion does not appear smooth when renderign status two frames previously.

You can accurately determine if there is a problem with flushing the VBO by setting the IsBufferFlushEnabled flag of ResParticleSet to true.
Below is sample code for writing true in all loaded resource flags.

resource.ForeachModel(nw::gfx::ParticleSetIsBufferFlushEnabledSetter(true));

When flags are set, the VBO is flushed using SDK features.

However, this technique has a significant impact on performance. We therefore recomend that you handle this by placing a CPU flush instruction between Update and Draw or between other calculations and rendering processes.

Below is sample code for flushing the cache. 32KB of device memory is accessed. Since reconciliation between CPU cores is not taken into account, this does not represent a general-purpose method of flushing the cache.

Sample code for flushing the cache

class FlushCache
{
public:
   //! This is the @brief constructor. 
   FlushCache(nw::demo::DemoDeviceMemoryAllocator* deviceAllocator)
   {
       m_DeviceAllocator = deviceAllocator;
       m_Buffer =  NULL;
       if (m_DeviceAllocator != NULL)
       {
           m_Buffer = (u8*)m_DeviceAllocator->Alloc(BufferSize);
           NW_ASSERT(nw::os::IsDeviceMemory(m_Buffer));
       }
   }
    //! This is the @brief destructor. 
   ~FlushCache()
   {
       if (m_Buffer != NULL)
       {
           m_DeviceAllocator->Free(m_Buffer);
       }
   }
    //! Flushes the @brief cache. 
   void
   Execute()
   {
       if (m_Buffer != NULL)
       {
           ::std::memcpy(m_Buffer + BufferSize / 2, m_Buffer, BufferSize / 2);
       }
   }
private:
   static const int BufferSize = 16 * 1024 * 2;
   u8* m_Buffer;
   nw::demo::DemoDeviceMemoryAllocator* m_DeviceAllocator;
};

Using ParticleMaterialActivator

You can expect faster execution times using the material class ParticleMaterialActivator especially intended for particles, rather than the usual material class. With the ParticleMaterialActivator class, material settings unrelated to particle rendering is omitted.
Materials settings that are skipped by using the ParticleMaterialActivator class are listed below.

ParticleMaterialActivator can be used by setting a flag inside the resource using the followign code.

resource.ForeachModelMaterial(nw::gfx::ParticleMaterialFlagSetter());

To use the ParticleMaterialActivator class, the rendering layers for models and particles must be separated. You can specify separation of the rendering layers for models and particles using arguments to SceneUpdater::SubmitView().


CONFIDENTIAL