The difference with the other particle properties (positon, rotation, etc) is that setParticles() doesn’t compute the materials at all.
Indeed setParticles() is designed to be called each frame in the render loop and to make sure to keep the garbage collector activity to its minimum by allocating nothing.
Applying the changes of materialIndex values requires to sort again all the particles, to recompute the whole SPS geometry and moreover to recreate new SubMesh objects from the SPS mesh.
Therefore a dedicated method is provided sps.computeSubMeshes() . This method is to be called manually after each change of particle materialIndex values for them to be taken in account at once.
Like setMultiMaterials() , it’s probably not a good idea to call it each frame in the render loop.