好的,所以我找到了这篇文章,我对其中的一些部分感到困惑。如果有人能更深入地向我解释这个过程,我将不胜感激,因为我已经尝试了两个月的代码,但仍然没有得到正确的版本。我对文章的Persistence部分感到特别困惑,因为我基本上不理解作者试图解释的内容,在文章的底部,他谈到了这方面的2D伪代码实现,但PerlinNoise_2D函数对我来说没有意义,因为在对随机值进行平滑和插值后,它是一个整数值,但函数采用浮点值?在持久性部分的下面是八度音阶部分。我不太明白,因为他把平滑的函数"加在一起"得到了Perlin函数。他所说的"加法"是什么意思,因为你显然没有把价值加在一起。所以,如果有人能向我解释这些部分,我会非常高兴。谢谢
这是我的代码:
import java.awt.Color;
import java.awt.Graphics;
import java.util.Random;
import javax.swing.JFrame;
import javax.swing.JPanel;
@SuppressWarnings("serial")
public class TerrainGen extends JPanel {
public static int layers = 3;
public static float[][][][] noise = new float[16][16][81][layers];
public static int[][][][] octaves = new int[16][16][81][layers];
public static int[][][][] perlin = new int[16][16][81][layers];
public static int[][][] perlinnoise = new int[16][16][81];
public static int SmoothAmount = 3;
public static int interpolate1 = 0;
public static int interpolate2 = 10;
public static double persistence = 0.25;
//generate noise
//smooth noise
//interpolate noise
//perlin equation
public TerrainGen() {
for(int t = 0; t < layers; t++) {
for(int z = 0; z < 81; z++) {
for(int y = 0; y < 16; y++) {
for(int x = 0; x < 16; x++) {
noise[x][y][z][t] = GenerateNoise();
}
}
}
}
for(int t = 0; t < layers; t++) {
SmoothNoise(t);
}
for(int t = 0; t < layers; t++) {
for(int z = 0; z < 81; z++) {
for(int y = 0; y < 16; y++) {
for(int x = 0; x < 16; x++) {
octaves[x][y][z][t] = InterpolateNoise(interpolate1, interpolate2, noise[x][y][z][t]);
}
}
}
}
for(int t = 0; t < layers; t++) {
PerlinNoise(t);
}
}
public static Random generation = new Random(5);
public float GenerateNoise() {
float i = generation.nextFloat();
return i;
}
public void SmoothNoise(int t) {
//Huge smoothing algorithm
}
//Cosine interpolation
public int InterpolateNoise(int base, int top, float input) {
return (int) ((1 - ((1 - Math.cos(input * 3.1415927)) * 0.5)) + top * ((1 - Math.cos(input * 3.1415927)) * 0.5));
}
public void PerlinNoise(int t) {
double f = Math.pow(2.0, new Double(t));
double a = Math.pow(persistence, new Double(t));
for(int z = 0; z < 81; z++) {
for(int y = 0; y < 16; y++) {
for(int x = 0; x < 16; x++) {
perlin[x][y][z][t] = (int) ((octaves[x][y][z][t] * f) * a);
}
}
}
}
public static void main(String [] args) {
JFrame frame = new JFrame();
frame.setSize(180, 180);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
TerrainGen test = new TerrainGen();
frame.add(test);
frame.setVisible(true);
}
public static int size = 5;
public void paintComponent(Graphics g) {
super.paintComponent(g);
int i = 0;
for(int t = 0; t < 9; t++) {
for(int z = 0; z < 9; z++) {
for(int y = 0; y < 16; y++) {
for(int x = 0; x < 16; x++) {
g.setColor(new Color(perlin[x][y][i][0] * 10, perlin[x][y][i][0] * 10, perlin[x][y][i][0] * 10));
g.fillRect((z * (16 * size)) + (x * size), (t * (16 * size)) + (y * size), size, size);
}
}
i++;
}
}
repaint();
}
}
我没有包括平滑部分,因为这大约需要400行代码来在块之间进行平滑。
本文所称的持久性是指当高频噪声组合在一起时,它们的振幅如何"下降"。
"八度音阶"正是本文所说的不同频率下的噪声函数。
你取1.0,然后重复乘以持续性,得到每个八度音阶要乘以的幅度列表——例如,持续性为0.8时,因子为1.0、0.8、0.64、0.512。
噪声不是整数,他的函数Noise1产生的噪声范围为0..1,即变量n是Int32位,它返回浮点值。
输入参数为整数,即Noise1函数仅在(1,0)或(2,2)处求值。在SmoothNoise_1中将噪波平滑/涂抹一点后,将对值进行插值,以在其间生成值。
希望有帮助!!
这个循环从2d噪声中产生八度音阶。同样的循环也适用于3d佩林。。。
function octaves( vtx: Vector3 ): float
{
var total = 0.0;
for (var i:int = 1; i < 7; i ++)//num octaves
{
total+= PerlinNoise(Vector3 (vtx.x*(i*i),0.0,vtx.z*(i*i)))/(i*i);
}
return total;//added multiple perlins into noise with 1/2/4/8 etc ratios
}
对于学习perlin,我看到的最好的东西是下面的代码。它使用了基于sin的半随机函数,而不是哈希表。使用2-3个八度音阶,它就成为高品质的perlin。。。令人惊讶的是,我在实时环境中运行了30个八度音阶,它没有变慢,而我曾经使用过1个voronoi,它正在变慢。所以…令人惊叹的代码值得学习。
#ifndef __noise_hlsl_
#define __noise_hlsl_
// hash based 3d value noise
// function taken from https://www.shadertoy.com/view/XslGRr
// Created by inigo quilez - iq/2013
// License Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License.
// ported from GLSL to HLSL
float hash( float n )
{
return frac(sin(n)*43758.5453);
}
float noise( float3 x )
{
// The noise function returns a value in the range -1.0f -> 1.0f
float3 p = floor(x);
float3 f = frac(x);
f = f*f*(3.0-2.0*f);
float n = p.x + p.y*57.0 + 113.0*p.z;
return lerp(lerp(lerp( hash(n+0.0), hash(n+1.0),f.x),
lerp( hash(n+57.0), hash(n+58.0),f.x),f.y),
lerp(lerp( hash(n+113.0), hash(n+114.0),f.x),
lerp( hash(n+170.0), hash(n+171.0),f.x),f.y),f.z);
}
请注意,sin在CPU上很昂贵,相反,您会使用:
function hash ( n: float ): float
{//random -1, 1
var e = ( n *73.9543)%1;
return (e*e*142.05432)%2-1;// fast cpu random by me :) uses e*e rather than sin
}