Je cherche un moyen agréable et facile de générer un masque pour une carte d'île avec C #.
Fondamentalement, j'utilise avec une carte d'altitude aléatoire générée avec du bruit perlin, où le terrain n'est PAS entouré d'eau.
La prochaine étape serait de générer un masque, pour s'assurer que les coins et les bordures ne sont que de l'eau.
Ensuite, je peux simplement soustraire le masque de l'image de bruit perlin pour obtenir une île.
et jouer avec le contraste ..
et la courbe de gradient, je peux obtenir une carte de hauteur d'île comme je le veux ..
(ce ne sont bien sûr que des exemples)
comme vous pouvez le voir, les "bords" de l'île sont juste coupés, ce qui n'est pas un gros problème si la valeur de la couleur n'est pas trop blanche, car je vais juste diviser l'échelle de gris en 4 couches (eau, sable, herbe et Roche).
Ma question est, comment puis-je générer un beau masque comme dans la deuxième image?
MISE À JOUR
J'ai trouvé cette technique, elle semble être un bon point de départ pour moi, mais je ne sais pas exactement comment je peux l'implémenter pour obtenir la sortie souhaitée. http://mrl.nyu.edu/~perlin/experiments/puff/
MISE À JOUR 2
c'est ma dernière solution.
J'ai implémenté la makeMask()
fonction dans ma boucle de normalisation comme ceci:
//normalisation
for( int i = 0; i < width; i++ ) {
for( int j = 0; j < height; j++ ) {
perlinNoise[ i ][ j ] /= totalAmplitude;
perlinNoise[ i ][ j ] = makeMask( width, height, i, j, perlinNoise[ i ][ j ] );
}
}
et c'est la fonction finale:
public static float makeMask( int width, int height, int posX, int posY, float oldValue ) {
int minVal = ( ( ( height + width ) / 2 ) / 100 * 2 );
int maxVal = ( ( ( height + width ) / 2 ) / 100 * 10 );
if( getDistanceToEdge( posX, posY, width, height ) <= minVal ) {
return 0;
} else if( getDistanceToEdge( posX, posY, width, height ) >= maxVal ) {
return oldValue;
} else {
float factor = getFactor( getDistanceToEdge( posX, posY, width, height ), minVal, maxVal );
return oldValue * factor;
}
}
private static float getFactor( int val, int min, int max ) {
int full = max - min;
int part = val - min;
float factor = (float)part / (float)full;
return factor;
}
public static int getDistanceToEdge( int x, int y, int width, int height ) {
int[] distances = new int[]{ y, x, ( width - x ), ( height - y ) };
int min = distances[ 0 ];
foreach( var val in distances ) {
if( val < min ) {
min = val;
}
}
return min;
}
cela donnera une sortie comme dans l'image # 3.
avec un peu de changement dans le code, vous pouvez obtenir la sortie initialement souhaitée comme dans l'image # 2 ->
public static float makeMask( int width, int height, int posX, int posY, float oldValue ) {
int minVal = ( ( ( height + width ) / 2 ) / 100 * 2 );
int maxVal = ( ( ( height + width ) / 2 ) / 100 * 20 );
if( getDistanceToEdge( posX, posY, width, height ) <= minVal ) {
return 0;
} else if( getDistanceToEdge( posX, posY, width, height ) >= maxVal ) {
return 1;
} else {
float factor = getFactor( getDistanceToEdge( posX, posY, width, height ), minVal, maxVal );
return ( oldValue + oldValue ) * factor;
}
}