Tôi đang tìm kiếm một cách hay và dễ dàng để tạo mặt nạ cho bản đồ đảo với C #.
Về cơ bản tôi đang sử dụng với một sơ đồ chiều cao ngẫu nhiên được tạo ra với nhiễu perlin, trong đó địa hình KHÔNG được bao quanh bởi nước.
Bước tiếp theo sẽ là tạo mặt nạ, để đảm bảo các góc và đường viền chỉ là nước.
Sau đó, tôi chỉ có thể trừ mặt nạ từ hình ảnh nhiễu perlin để có được một hòn đảo.
và chơi xung quanh với sự tương phản ..
và đường cong gradient, tôi có thể có được một sơ đồ chiều cao đảo giống như tôi muốn ..
(đây chỉ là ví dụ của khóa học)
Vì vậy, như bạn có thể thấy, các "cạnh" của hòn đảo chỉ bị cắt đi, đó không phải là vấn đề lớn nếu giá trị màu không quá trắng, vì tôi sẽ chỉ chia màu xám thành 4 lớp (nước, cát, cỏ và đá).
Câu hỏi của tôi là, làm thế nào tôi có thể tạo ra một mặt nạ đẹp như trong hình ảnh thứ hai?
CẬP NHẬT
Tôi đã tìm thấy kỹ thuật này, nó có vẻ là một điểm khởi đầu tốt đẹp đối với tôi, nhưng tôi không chắc chắn làm thế nào tôi có thể thực hiện nó một cách xuất sắc để có được đầu ra mong muốn. http://mrl.nyu.edu/~perlin/experiment/puff/
CẬP NHẬT 2
đây là giải pháp cuối cùng của tôi
Tôi đã thực hiện makeMask()
chức năng bên trong vòng lặp chuẩn hóa của mình như thế này:
//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 ] );
}
}
và đây là chức năng cuối cùng:
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;
}
điều này sẽ cho một đầu ra như trong hình ảnh # 3.
với một chút thay đổi trong mã, bạn có thể nhận được đầu ra mong muốn ban đầu như trong hình ảnh # 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;
}
}