Contrôler des milliers de poissons en utilisant les Particles

Le problème avec les MeshInstances est qu'il est coûteux de mettre à jour leurs tableaux de transforms. Ils sont idéaux pour placer de nombreux objets statiques partout dans la scène, mais ça reste difficile de déplacer ces objets.

Pour faire bouger de manière intéressante chaque instance, nous allons utiliser un nœud de Particles. Les particules profitent de l'accélération GPU en calculant et en définissant les informations par instance dans un Shader.

Note

Les particules ne sont pas disponibles dans GLES2, utilisez plutôt CPUParticles, qui font la même chose que les particules, mais ne bénéficient pas de l'accélération GPU.

Créez d'abord un nœud Particles. Ensuite, sous "Draw Passes" définissez le "Draw Pass 1" de la particule sur votre Mesh. Puis sous "Process Material" créez un nouveau ShaderMaterial.

Définissez le shader_type sur particles.

shader_type particles

Ajoutez ensuite les deux fonctions suivantes :

float rand_from_seed(in uint seed) {
  int k;
  int s = int(seed);
  if (s == 0)
    s = 305420679;
  k = s / 127773;
  s = 16807 * (s - k * 127773) - 2836 * k;
  if (s < 0)
    s += 2147483647;
  seed = uint(s);
  return float(seed % uint(65536)) / 65535.0;
}

uint hash(uint x) {
  x = ((x >> uint(16)) ^ x) * uint(73244475);
  x = ((x >> uint(16)) ^ x) * uint(73244475);
  x = (x >> uint(16)) ^ x;
  return x;
}

Ces fonctions proviennent du ParticlesMaterial par défaut. Elles sont utilisées pour générer un nombre aléatoire à partir du RANDOM_SEED de chaque particule.

Ce qui est unique avec les shaders de particules, c'est que certaines des variables intégrées sont sauvegardées d'une frame à l'autre. TRANSFORM, COLOR et CUSTOM sont tous accessibles dans le shader spatial du maillage, ainsi que dans le shader de particules lors de sa prochaine exécution.

Ensuite, configurez votre fonction vertex. Les shaders de particules ne contiennent qu'une fonction vertex et aucune autre.

Nous allons d’abord faire la distinction entre le code devant être exécuté uniquement au démarrage du système de particules et le code devant toujours être exécuté. Nous voulons attribuer à chaque poisson une position aléatoire et un décalage d'animation aléatoire lors de la première exécution du système. Pour ce faire, nous encapsulons donc ce code dans une instruction if vérifiant la variable intégrée RESTART qui devient true pour une image(frame) lorsque le système de particules est redémarré.

D'un niveau supérieur, cela ressemble à :

void vertex() {
  if (RESTART) {
    //Initialization code goes here
  } else {
    //per-frame code goes here
  }
}

Ensuite, nous devons générer 4 nombres aléatoires : 3 pour créer une position aléatoire et un autre pour le décalage aléatoire du cycle de nage.

Tout d'abord, générez 4 graines à l'intérieur du bloc RESTART à l'aide de la fonction hash fournie ci-dessus :

uint alt_seed1 = hash(NUMBER + uint(1) + RANDOM_SEED);
uint alt_seed2 = hash(NUMBER + uint(27) + RANDOM_SEED);
uint alt_seed3 = hash(NUMBER + uint(43) + RANDOM_SEED);
uint alt_seed4 = hash(NUMBER + uint(111) + RANDOM_SEED);

Ensuite, utilisez ces graines pour générer des nombres aléatoires à l'aide de rand_from_seed :

CUSTOM.x = rand_from_seed(alt_seed1);
vec3 position = vec3(rand_from_seed(alt_seed2) * 2.0 - 1.0,
                     rand_from_seed(alt_seed3) * 2.0 - 1.0,
                     rand_from_seed(alt_seed4) * 2.0 - 1.0);

Enfin, affectez position à TRANSFORM[3].xyz, qui est la partie du transform qui contient l'information de position.

TRANSFORM[3].xyz = position * 20.0;

Rappelez-vous, tout ce code jusqu'à présent va à l'intérieur du bloc RESTART.

Le vertex shader de votre maillage peut rester exactement le même que dans le tutoriel précédent.

Vous pouvez maintenant déplacer chaque poisson individuellement à chaque image, soit en ajoutant directement à son TRANSFORM, soit en réécrivant sa VELOCITY.

Faisons avancer les poissons en définissant leurs VELOCITY.

VELOCITY.z = 10.0;

C'est la façon la plus simple de régler VELOCITY : chaque particule (ou poisson) aura la même vitesse.

Juste en définissant VELOCITY vous pouvez faire nager les poissons comme vous voulez. Par exemple, essayez le code ci-dessous.

VELOCITY.z = cos(TIME + CUSTOM.x * 6.28) * 4.0 + 6.0;

Cela donnera à chaque poisson une vitesse unique entre 2 et 10.

Si vous avez utilisé CUSTOM.y dans le dernier tutoriel, vous pouvez également définir la vitesse de l'animation de nage en fonction de la VELOCITY. Utilisez simplement CUSTOM.y.

CUSTOM.y = VELOCITY.z * 0.1;

Ce code vous donne le comportement suivant :

../../../_images/scene.gif

En utilisant un ParticlesMaterial (matériau de particules), vous pouvez rendre le comportement du poisson aussi simple ou complexe que vous le souhaitez. Dans ce tutoriel, nous ne réglons que Velocity, mais dans vos propres Shaders vous pouvez aussi régler COLOR, la rotation, l'échelle (via TRANSFORM). Pour plus d'informations sur les shaders de particules, reportez-vous à la page Particles Shader Reference.