C # ile bir ada haritası için maske oluşturmak için güzel ve kolay bir yol arıyorum.
Temel olarak, arazinin su ile çevrili OLMADIĞINDA, perlin gürültüsü ile oluşturulan rastgele bir yükseklik haritası kullanıyorum.
Bir sonraki adım, köşelerin ve sınırların sadece su olmasını sağlamak için bir maske oluşturmak olacaktır.
O zaman bir ada almak için maskeyi perlin gürültüsü görüntüsünden çıkarabilirim.
ve kontrast ile uğraşırken ..
ve gradyan eğrisi, istediğim gibi bir ada yükseklik haritası alabilirim ..
(bunlar sadece elbette örneklerdir)
Görebildiğiniz gibi, adanın "kenarları" kesildi, renk değeri çok beyaz değilse büyük bir sorun değil çünkü gri tonlamayı sadece 4 katmana (su, kum, çim ve Kaya).
Sorum şu, ikinci resimde olduğu gibi nasıl iyi görünümlü bir maske oluşturabilirim?
GÜNCELLEŞTİRME
Bu tekniği buldum, benim için iyi bir başlangıç noktası gibi görünüyor, ancak istenen çıktıyı elde etmek için ne kadar doğru uygulayabileceğimden emin değilim. http://mrl.nyu.edu/~perlin/experiments/puff/
GÜNCELLEME 2
bu benim son çözümüm.
Bu makeMask()
işlevi normalleştirme döngümün içine şu şekilde uyguladım :
//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 ] );
}
}
ve bu son işlevdir:
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;
}
bu, resim # 3'teki gibi bir çıktı verecektir.
kodda biraz değişiklik yapılması durumunda, başlangıçtaki resimden # 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;
}
}