I. Introduction▲
Cette série explique comment générer de manière procédurale des continents dans Unity.
Vous pouvez retrouver les autres épisodes de cette série dans le sommaire dédié.
II. Vidéo▲
Unity - Génération procédurale de terrain - Rendu plat
III. Résumé▲
Dans ce chapitre, vous apprendrez à modifier le rendu de votre terrain, afin qu'il ait un aspect plus polygonal. Pour cela, vous allez modifier le mode de calcul de l'éclairage.
III-A. Lumière sur un polygone▲
La lumière reçue par un polygone est calculée grâce aux normales de celui-ci. Habituellement, pour avoir un rendu réaliste et cohérent, la normale d'un sommet partagé par plusieurs faces prendra la valeur équivalente à la moyenne des normales de chaque face utilisant ce sommet.
Vous pouvez modifier le rendu afin de donner une couleur unie pour chaque face en faisant en sorte qu'au lieu d'avoir une normale par sommet vous ayez une normale par face utilisant ce sommet.
Normalement, les sommets qui sont partagés par plusieurs faces ne sont dans la mémoire du logiciel qu'une unique fois (tout en étant utilisé plusieurs fois). Ici, pour spécifier différentes normales pour un sommet partagé, vous devez avoir autant de sommets que nécessaire afin de spécifier une normale différente par utilisation du sommet.
Pour ce faire, vous devez modifier la génération du modèle.
III-B. Implémentation▲
La duplication des sommets est réalisée dans une nouvelle fonction FlatShading(). Celle-ci lit les sommets générés et les duplique lorsqu'ils sont utilisés par les indices du modèle. De la même façon, les coordonnées de texture générées sont dupliquées :
void
FlatShading
(
) {
Vector3[]
flatShadedVertices =
new
Vector3[
triangles.
Length];
Vector2[]
flatShadedUvs =
new
Vector2[
triangles.
Length];
for
(
int
i =
0
;
i <
triangles.
Length;
i++
) {
flatShadedVertices [
i]
=
vertices [
triangles [
i]];
flatShadedUvs [
i]
=
uvs [
triangles [
i]];
triangles [
i]
=
i;
}
vertices =
flatShadedVertices;
uvs =
flatShadedUvs;
}
Ensuite, un booléen est ajouté au constructeur de la classe MeshData(), ainsi qu'un membre de la classe afin de pouvoir contrôler si le rendu plat est à utiliser ou non. La fonction GenerateTerrainMesh() est modifiée pour passer ce booléen au constructeur de MeshData().
Le booléen est utilisé dans une nouvelle fonction ProcessMesh() déterminant quelle fonction doit être appelée :
public
void
ProcessMesh
(
) {
if
(
useFlatShading) {
FlatShading (
);
}
else
{
BakeNormals (
);
}
}
Les normales n'ont pas besoin d'être calculées pour le rendu plat, car le processus par défaut utilisé par Unity convient à notre besoin : prendre en compte les bordures est inutile.
L'appel à BakeNormals() est remplacé par ProcessMesh() dans la fonction GenerateTerrainMesh().
Un code similaire est ajouté à la fonction CreateMesh() pour générer les données adéquates :
public
Mesh CreateMesh
(
) {
Mesh mesh =
new
Mesh (
);
mesh.
vertices =
vertices;
mesh.
triangles =
triangles;
mesh.
uv =
uvs;
if
(
useFlatShading) {
mesh.
RecalculateNormals (
);
}
else
{
mesh.
normals =
bakedNormals;
}
return
mesh;
}
Finalement, le booléen pour contrôler le rendu est aussi ajouté dans le fichier MapGenerator.cs. De plus, sachant que les sommets sont dupliqués, il faut veiller à ne pas dépasser la limite du nombre de sommets dans un modèle, imposée par Unity. Par conséquent, la valeur de mapChunkSize est passée à 95. Cette valeur peut être conditionnée suivant la valeur du booléen pour le rendu plat de la manière suivante :
public
static
int
mapChunkSize {
get
{
if
(
instance ==
null
) {
instance =
FindObjectOfType<
MapGenerator>
(
);
}
if
(
instance.
useFlatShading) {
return
95
;
}
else
{
return
239
;
}
}
}
IV. Commenter▲
Vous pouvez commenter et donner vos avis dans la discussion associée sur le forum.