Perlin Noise Assistance - PullRequest
       70

Perlin Noise Assistance

0 голосов
/ 03 марта 2012

Хорошо, поэтому я нашел эту статью, и некоторые ее части меня смущают.Если кто-нибудь сможет объяснить мне этот процесс более подробно, я был бы очень признателен, потому что я пытался закодировать это уже 2 месяца и до сих пор не получил правильную версию.Меня особенно смущает часть статьи, посвященная персистентности, потому что я в основном не понимаю, что автор пытается объяснить по этому поводу, и в нижней части статьи он говорит о реализации этого в псевдокоде 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 строк кода для сглаживания между кусками.

Ответы [ 2 ]

1 голос
/ 03 марта 2012

То, что статья называет постоянством, - это то, как амплитуда шумов более высокой частоты «падает», когда они объединяются.

«октавы» - это то, что статья называет шумовыми функциями на разных частотах.

Вы берете 1,0 и многократно умножаетесь на постоянство, чтобы получить список амплитуд, на которые умножается каждая октава - например, постоянство 0,8 дает коэффициенты 1,0, 0,8, 0,64, 0,512.

Шум нецелое число, его функция Noise1 производит шум в диапазоне 0..1 - т.е. переменная n является битом Int32, который возвращает число с плавающей запятой.

Входные параметры являются целыми числами, т.е. функция Noise1 только оценивается при (1, 0) или (2, 2).После сглаживания / размытия шума в SmoothNoise_1 значения интерполируются для получения промежуточных значений.

Надеюсь, это помогло !!

0 голосов
/ 09 февраля 2014

эта петля создает октаву из 2d шума. тот же цикл будет работать для 3d Perlin ...

   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, это следующий код. вместо хеш-таблиц используется полуслучайная функция на основе греха. используя 2-3 октавы, это становится высококачественным перлином ... удивительно то, что я пробежал 30 октав на ландшафте в реальном времени, и он не замедлился, тогда как я использовал 1 вороной один раз, и он замедлялся. так что ... удивительный код для изучения.

#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);
}

обратите внимание, что грех стоит на процессоре, вместо этого вы бы использовали:

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
}
...