生成Perlin噪声时的问题

时间:2013-10-06 21:12:07

标签: java game-engine noise terrain perlin-noise

我创建了一个函数来生成Perlin Noise数据的二维数组,从0到1之间随机值的基本噪声数组开始。

基本白噪声数组如下所示:Random values 0-1 in 2d array

从那里开始,我使用smoothNoise()函数来插值,以创建漂亮的图像(我没有,因为它不起作用)

每个八度音程调用一次平滑噪声函数。平滑噪声函数返回的数据的图像如下(从最低到最高的八度)

Octave 0 Octave 1 Octave 2 Octave 3 Octave 4 Octave 5

完成所有平滑后,输出的图像变黑。我会上传一张图片,但它只是黑色,所以没有必要。

我的代码是:

    import java.util.Random;


public class Noise2D {

    int width;
    int height;
    public Noise2D(int width, int height){
        this.width = width;
        this.height = height;
    }

    public double[][] generateWhiteNoise(int width,int height){
        Random r = new Random(0);
        double[][] whiteNoise = new double[width][height];

        for(int i = 0; i<whiteNoise.length; i++){
            for(int j = 0; j<whiteNoise[0].length;j++){
                double rNum =   r.nextDouble()%1;
                whiteNoise[i][j] = (double)rNum;
            }
        }
        ImageWriter.writeImage(whiteNoise, "WhiteNoise");
        return whiteNoise;
    }

    public double interpolate(double x0, double x1, double alpha){
        return x0 * (1 - alpha) + alpha * x1;
    }

    public double[][] generateSmoothNoise(double[][] baseNoise, int octave){
        int width = baseNoise.length;
        int height = baseNoise[0].length;

        double[][] smoothNoise = new double[width][height];

        int period = 1<< octave; //2^i
        double frequency = 1.0/period;

        for(int x = 0; x<width; x++){
            int x0 = (x/period)*period; //7/3 = 2 *3 = 6
            int x1 = (x0+period)%width;

            double hBlend = (x-x0)*frequency;

            for(int y = 0; y<height; y++){

                int y0 = (y/period)*period;
                int y1 = (y0 + period)%height;

                double vBlend = (y - y0)*frequency;

                double top = interpolate(baseNoise[x0][y0],baseNoise[x1][y1],hBlend);
                double bottom = interpolate(baseNoise[x0][y1],baseNoise[x1][y0],hBlend);

                smoothNoise[x][y] = interpolate(top,bottom,vBlend);
            }
        }
        ImageWriter.writeImage(smoothNoise,"Smooth"+Integer.toString(octave));
        return smoothNoise;
    }

    public double[][] generatePerlinNoise(double baseNoise[][], int octaves){
        int width = baseNoise.length;
        int height = baseNoise[0].length;

        double persistence = 0.5;

        double[][][] smoothNoise = new double[octaves][][];

        for(int i = 0; i<octaves; i++){
            smoothNoise[i] = generateSmoothNoise(baseNoise,i);
        }

        double[][] perlinNoise = new double[width][height];
        double amplitude = 1;
        double totalAmplitude = 0;

        for(int octave = octaves-1; octave>=0; octave--){
            amplitude*=persistence;
            totalAmplitude+=amplitude;
            for(int x = 0; x<width;x++){
                for(int y = 0; y<height; y++){
                    perlinNoise[x][y] = smoothNoise[octave][x][y] * amplitude;
                }
            }
        }
        ImageWriter.writeImage(perlinNoise,"files");
        for(int i = 0; i<width; i++){
            for(int j = 0; j<height; j++){
                perlinNoise[i][j] /= totalAmplitude;
            }
        }
        return perlinNoise;
    }

}

定义类,并通过以下方式调用方法:

Perlin p = new Perlin(256,256);
writeImage(p.smoothNoise(p.makeNoise(256,256), 1, 16), "Perlin");

1是频率,16是倍频程 使用以下代码在函数writeImage(2d数组,“name”)中写入数据的位置(我不认为这部分有问题,但无论如何我都会发布):

public static void writeImage(double[][] data,String name){
        BufferedImage img = new BufferedImage(data.length,data[0].length,BufferedImage.TYPE_INT_RGB);

        for(int y = 0; y<data.length; y++){
            for(int x = 0; x<data[y].length; x++){
                if(data[y][x]>1){
                    data[y][x] = 1;
                }
                if(data[y][x]<0){
                    data[y][x] = 0;
                }

                Color c = new Color((float)data[y][x],(float)data[y][x],(float)data[y][x]);
                img.setRGB(x,y,c.getRGB());
            }
        }

        try{
            File file = new File(name+".png");
            file.createNewFile();

            ImageIO.write(img,"png",file);
        }catch(IOException e){
            e.printStackTrace();
        }
    }

    public static void writeExistingImage(BufferedImage img){
        try{
            File file = new File("noise2.png");
            file.createNewFile();

            ImageIO.write(img,"png",file);
        }catch(IOException e){
            e.printStackTrace();
        }
    }

总而言之,我认为问题在于smoothNoise方法,尽管我很可能错了,因为我对Perlin Noise的了解并不广泛。如果问题不在这里,我认为它位于generatePerlinNoise()方法中。任何帮助将不胜感激。我会对任何建议感到高兴,我一直试图解决这个问题很长一段时间。

澄清: 我的问题是generatePerlinNoise方法返回一组数据(2d)数组,它产生一个黑色图像(而不是一个很酷的噪声图像) 我还认为平滑的噪声图像不应该看起来像是分成正方形

0 个答案:

没有答案