Я шукаю приємний та простий спосіб створити маску для карти острова за допомогою C #.
В основному я використовую довільну карту висоти, генеровану перлинським шумом, де місцевість НЕ оточена водою.
Наступним кроком буде створення маски, щоб кути та межі були лише водою.
Тоді я можу просто відняти маску від зображення шуму перлин, щоб отримати острів.
і граючи навколо з контрастом ..
і крива градієнта, я можу отримати мапу висоти острова так, як мені хочеться.
(це лише приклади, звичайно)
так що, як бачите, "краї" острова просто обрізані, що не є великою проблемою, якщо значення кольору не надто біле, тому що я просто розділю сірий масштаб на 4 шари (вода, пісок, трава і скеля).
Моє запитання: як я можу створити добре виглядає маску, як на другому зображенні?
ОНОВЛЕННЯ
Я знайшов цю техніку, це здається гарною відправною точкою для мене, але я не впевнений, наскільки точно я можу її реалізувати, щоб отримати бажаний результат. http://mrl.nyu.edu/~perlin/experiment/puff/
ОНОВЛЕННЯ 2
це моє остаточне рішення.
Я реалізував makeMask()
функцію всередині мого циклу нормалізації так:
//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 ] );
}
}
і це заключна функція:
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;
}
це дасть вихід, як на зображенні №3.
трохи змінивши код, ви можете отримати вихідно потрібний вихід, як на зображенні №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;
}
}