如何在JPanel上制作和绘制Perlin噪音

时间:2016-09-29 21:14:52

标签: java swing awt

我想创建一个在Java中为JPanel提取噪音的应用程序。我想出了一个非常随机的噪音,但我想画一个Perlin或Simplex Noise 这是代码:

import java.awt.*;
import java.util.*;
import javax.swing.*;

public class Paint extends JPanel {

private static boolean running = false;
private static Paint paint = new Paint();
private static Random random = new Random();

public static void main(String args[]) {
    running = true;
    JFrame f = new JFrame();
    f.setSize(800, 800);
    f.setResizable(running);
    f.setUndecorated(running);
    f.setLocationRelativeTo(null);
    f.add(paint);
    f.setVisible(running);

    while(running) {
        paint.repaint();
    }
}

public void paint(Graphics g) {
    noise(g);
}

private void noise(Graphics g) {
    for(int i = 0; i < 800; i=i+10) {
        for(int j = 0; j < 800; j=j+10) {
            g.setColor(new Color(random.nextInt(255),random.nextInt(255),random.nextInt(255)));
            g.fillRect(j, i, 10, 10);
        }
    }
    running = false;
}

}

那么我如何将Perlin Noise算法植入此代码,而不必安装外部库 编辑:我不是懒惰,或者其他什么。我通过所有可能的噪声生成阅读我的方式,我只是不完全理解如何将噪声方法移植到课堂中。

1 个答案:

答案 0 :(得分:1)

你很幸运,我最近做到了这一点,继承我的代码:

BufferedImage tex;
float[] interpol;
int size;
float[] noise;
float[] workSet;
float r1,g1,b1,r2,g2,b2;
int octaves=4;
int octaveOffset=2;
public void init(int size)
{
    this.size=size;
    tex=new BufferedImage(size,size,BufferedImage.TYPE_INT_ARGB);
    interpol=new float[size];
    workSet=new float[size*size];
    noise=new float[size*size];
    float smult=(float) (Math.PI/size);
    for(int i=0;i<size;i++)
    {
        interpol[i]=(1+(float) Math.cos(i*smult))/2;
    }
    r1=255;
    g1=255;
    b1=255;
    r2=0;
    g2=0;
    b2=0;
}

public void generate()
{
    Random r=new Random();
    int[] pix=((DataBufferInt)(tex.getRaster().getDataBuffer())).getData();
    int totalSize=size*size;
    for(int i=0;i<totalSize;i++)
    {
        noise[i]=0.5f;
    }
    float[] randoms=new float[(size+1)*(size+1)];
    int scale=size>>octaveOffset;
    float max=0.50f;
    for(int oct=0;oct<octaves;oct++)
    {
        int randsPerLine=size/scale+1;
        int rands=randsPerLine*randsPerLine;
        for(int i=0;i<rands;i++)
        {
            randoms[i]=max*(r.nextFloat()-0.5f);
        }
        for(int i=0;i<totalSize;i++)
        {
            int y=(i/size)/scale;
            int suby=(i/size)%scale;
            int x=(i%size)/scale;
            int subx=(i%size)%scale;
            float intp=interpol[subx*(size/scale)];
            float colorA=randoms[y*randsPerLine+x]*intp+(1-intp)*randoms[y*randsPerLine+x+1];
            float colorB=randoms[(1+y)*randsPerLine+x]*intp+(1-intp)*randoms[(1+y)*randsPerLine+x+1];
            intp=interpol[suby*(size/scale)];
            workSet[i]=colorA*intp+(1-intp)*colorB;
        }

        for(int i=0;i<totalSize;i++)
        {
            noise[i]+=workSet[i];
        }
        max/=2;
        scale/=2;
    }
    for(int i=0;i<totalSize;i++)
    {
        int red=(int) (r1*noise[i]+r2*(1-noise[i]));
        int g=(int) (g1*noise[i]+g2*(1-noise[i]));
        int b=(int) (b1*noise[i]+b2*(1-noise[i]));
        pix[i]=(255<<24)+(red<<16)+(g<<8)+b;
    }
}

要绘制它,请使用g.drawImage(tex,[your coordinates],null)。 我的代码会生成一个方形图像size x size,两种颜色之间存在噪音混合,目前是黑色和白色,可以通过修改r1, g1, b1, r2, g2, b2来更改。使用octavesoctaveOffset值来调整噪音以满足您的需求。 我只测试了此代码,size是2的强大功能,在与代码合并时,我发现仅当paint.init(1024)paint.generate()在{{{}处开始调用时才有效1}}。