如何在 JPanel 上制作和绘制柏林噪声
How to make and draw a Perlin Noise on a JPanel
我想制作一个应用程序,在 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 噪声算法植入此代码,同时不必安装外部库。
编辑:我并不懒惰,或者什么的。我阅读了所有可能的噪音世代,我只是不完全理解如何将噪音方法迁移到 class。
你真幸运,我最近就是这样做的,这是我的代码:
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
来改变。尝试使用 octaves
和 octaveOffset
值来使噪音满足您的需要。
我只测试了这段代码 size
是 2 的幂并且在与你的代码合并时我发现它只有在 paint.init(1024)
和 paint.generate()
在 [= 的开头被调用时才有效20=].
我想制作一个应用程序,在 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 噪声算法植入此代码,同时不必安装外部库。
编辑:我并不懒惰,或者什么的。我阅读了所有可能的噪音世代,我只是不完全理解如何将噪音方法迁移到 class。
你真幸运,我最近就是这样做的,这是我的代码:
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
来改变。尝试使用 octaves
和 octaveOffset
值来使噪音满足您的需要。
我只测试了这段代码 size
是 2 的幂并且在与你的代码合并时我发现它只有在 paint.init(1024)
和 paint.generate()
在 [= 的开头被调用时才有效20=].