J'ai un terrain généré, avec une géométrie hexagonale, selon la capture d'écran ci-dessous:
Je génère ensuite des biomes, mais comme vous pouvez le voir, les frontières entre eux sont vraiment laides et droites. Pour cacher cette origine hexagonale, il me faudrait lisser les frontières entre les biomes. Voici à quoi cela ressemble maintenant en filaire avec de vraies faces tringulaires:
Ce que je vise, c'est quelque chose de plus comme ceci:
Chaque sommet a un attribut qui contient le type de biome, je peux également ajouter des attributs spéciaux aux sommets sur le bord entre deux biomes, mais je ne semble pas être en mesure de comprendre comment retirer cela dans le code du shader, évidemment du bruit est impliqué ici, mais comment puis-je le rendre continu sur plusieurs faces et sur toute la frontière de plusieurs biomes?
Je rend avec WebGL en utilisant THREE.js
Réponses:
D'autres réponses suggèrent ici l'utilisation d'une texture. Voici une technique qui n'utilise pas de textures.
Vous voulez que les frontières entre les hexagones soient intéressantes. Il est plus facile de créer des limites intéressantes lorsque vous les déplacez au centre de ce que vous dessinez. Au lieu de dessiner les tuiles directement, vous dessinez le "double" de la tuile. Cette technique est appelée «tuiles d'angle» ( ici et ici et ici ). Le dual d'un hexagone est un triangle, donc nous dessinerions ces triangles au lieu des hexagones:
Les frontières entre les hexagones sont maintenant au milieu des triangles rendus, ce qui nous permettra de faire des choses plus intéressantes avec eux. Bonus: il vous suffit de dessiner deux triangles par hexagone, au lieu de six (ou vingt-quatre comme vous le faites actuellement).
À l'intérieur de chacun de ces triangles, nous voulons que le fragment shader dessine les hexagones. Nous pouvons le faire avec des coordonnées barycentriques . Mettez (1,0,0), (0,1,0) et (0,0,1) à chaque sommet du triangle. À l'intérieur du triangle, ces coordonnées seront interpolées. Le fragment shader recevra (a, b, c) et peut regarder pour voir quelle valeur est la plus grande - cela nous indiquera lequel des trois hexagones devrait être dessiné à ce point.
float max_n = max(barycentric.r, max(barycentric.g, barycentric.b)); if (max_n == barycentric.r) { color = v_color0; } else if (max_n == barycentric.g) { color = v_color1; } else if (max_n == barycentric.b) { color = v_color2; }
C'est pour les lignes droites.
Si vous voulez des bords bruyants, vous pouvez ajouter du bruit aux coordonnées barycentriques:
En jouant avec la longueur d'onde / fréquence d'amplitude du bruit, vous pouvez obtenir des effets sympas:
Vous devez être prudent avec le bruit, en vous assurant qu'il est cohérent à travers les limites du triangle. Une façon de le faire est de passer un identifiant hexadécimal et de l'utiliser comme valeur de départ pour chacune des trois valeurs de bruit ajoutées aux coordonnées barycentriques.
J'ai fait une démo interactive ici . (Pour la démo, je n'ai pas implémenté l'identifiant hexadécimal ou certaines des autres choses dont vous pourriez avoir besoin si vous faisiez ce travail dans un vrai projet - c'est juste une démo rapide et sale)
la source
Je suis sûr que "pourrait" être résolu avec un algorithme d'image mais si c'était moi, je le résoudrais probablement avec des textures. Je ferais des textures hexagonales, les mettrais toutes dans un atlas de texture, puis pour chaque hexagone, je regarderais ses voisins et déciderais quelle texture appliquer.
Les textures devraient avoir des versions pour chaque type de terrain et des versions pour chaque type de transition.
Ceci est similaire au nombre de systèmes basés sur des tuiles qui font du terrain. Voici un exemple de jeux 2D .
Une autre possibilité serait d'avoir juste vos textures pour vos différents types de terrain (eau, neige, terre, herbe) et d'ajouter des quantités de mélange à chaque sommet d'hexagone pour décider comment les mélanger.
Cet article montre l'idée de mélanger des textures de terrain. Je ne suggère pas de suivre leur mise en œuvre mais cela montre l'idée.
la source
Tout d'abord, donnez à vos biomes une texture. Mappez les triangles aux texcoords. Vous pouvez le faire en utilisant une projection de mercator ou, mieux, une carte de cube . Maintenant, dans le shader de fragment, faites quelque chose comme ceci:
où se
noise
trouve une fonction pseudo-aléatoire (utilisant, disons, des sinusoïdes) sur la position 3D du sommet dans l'espace objet qui renvoie un décalage bruyant à la coordonnée de la texture. Échantillonnez la texture en utilisantGL_NEAREST
pour garder des bordures nettes.la source