2

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

基本白噪声数组如下所示:二维数组中的随机值 0-1

从那里,我使用 smoothNoise() 函数插入值以创建好看的图像(我没有,因为它不起作用)

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

八度音阶 0 八度音阶 1 八度音阶 2 八度音阶 3 八度 4 八度 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 array, "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)数组,该数组生成黑色图像(而不是酷噪声图像)我还认为平滑噪声图像不应该看起来像它们被分割成正方形

4

0 回答 0