펄린 노이즈 이해


31

다이아몬드 스퀘어와 함께 일한 후 Perlin Noise와 함께 놀았습니다. 나는 Hugo Elias구현에 따라 기본적으로 x, y를 사용하여 각 좌표 값을 던지는 입력으로 일련의 함수를 만듭니다.

내 PHP 코드는 다음과 같습니다.

두 가지 질문이 있습니다.

알고리즘을 사용하여 배열에서 높이 맵을 생성하는 방법 나는 그것을 완전히 이해하지 못했고 단지 의사 코드를 PHP로 포팅했지만 알고리즘이 "매직 적으로"주어진 x, y 지점에 대한 전환 값을 제공하는 곳을 읽은 후 마지막 함수 (map_perlined) 인접 값), 임의의 함수로 사용할 때 이것을 얻습니다.mt_rand(-100,100)/100;

여기에 이미지 설명을 입력하십시오

그리고 이것은 암호화를 사용할 때 : 1.0-(($n*($n*$n*15731+789221)+1376312589)&0x7fffffff)/1073741824.0;(BTW는 PHP에서 "있는 그대로"구현 될 수 있습니까?) :

여기에 이미지 설명을 입력하십시오

요약하면 세 가지 질문이 있습니다.

  1. 내 코드가 맞습니까?
  2. 코드에 설명 된대로 임의 함수를 PHP로 이식 할 수 있습니까? 오류가 발생하지 않지만 결과는 없습니다.
  3. 실제로 알고리즘을 어떻게 사용합니까?

최신 정보

좋아, Gustavson 논문에 표시된 코드의 PHP 포트를 만들었고 다른 코더가 말했듯이 1 옥타브를 생성합니다. 노이즈 기능을 제어하기 위해 다중 옥타브, 진폭, 주파수 등의 개념으로 이것을 사용하는 방법에 대한 다른 유용한 사이트 / 페이퍼 / 가이드가 있습니까? Gustavson의 논문에서 알고리즘의 실제 구현이 아니라 결과를 보여줍니다. 아마 뭔가 빠졌습니까?

업데이트 2
@NATHAN

나는 다음과 같은 것을 만들었다 :

$persistence = 0.5;

for ($j = 0; $j < $size; $j++) {
    for ($i = 0; $i < $size; $i++) {

        for ($o = 0; $o < 8; $o++) {
            $frequency = pow(2,$o);
            $amplitude = pow($persistence, $o);
            $value += SimplexNoise($i*$frequency, $j * $frequency) * $amplitude;
            }

            //$value = SimplexNoise($i, $j) + 0.5 * SimplexNoise($i, $j) + 0.25 * SimplexNoise($i, $j);
            $this->mapArray[$i][$j] = new Cell($value);

그리고 값을 0..1로 정규화 한 후 다소 둔한 높이 맵을 얻습니다.

여기에 이미지 설명을 입력하십시오

지도를 어떻게 시딩합니까? 아마도 구현해야 할 것은 임의의 높이로 세 번째 값을 가진 3d 버전입니까? 그러나 그렇다면 인접 값을 고려해야한다는 것을 알아야합니다.이 값은 다이아몬드 사각형 알고리즘과 같은 것으로 끝나고 싶습니다. 정확히 내가 원하지 않는 것.

업데이트 3

더 많은 Perlin 작품. 소음을 내 결과에 안내하는 방법을 아직 찾지 못했습니다. 이 옥타브와 최종 결과를 확인하십시오.

옥타브 I에서 IV

옥타브 1옥타브 2옥타브 3옥타브 4

요약

옥타브 1-4 요약

각 옥타브는 거의 동일합니다. 코드를 확인하십시오 :

$persistence = 0.5;

    for ($j = 0; $j < $size; $j++) {
      for ($i = 0; $i < $size; $i++) {
        $value = 0;

        for ($o = 0; $o < 4; $o++) {
          $frequency = pow(2,$o);
          $amplitude = pow($persistence, $o);
          $value += improved_noise($i*$frequency, $j*$frequency, 0.5)*$amplitude;

        }
        $this->map[$i][$j] = new Cell($value);

결과는 정규화됩니다. 소음 발생에 어떤 영향을 미치겠습니까? 진폭을 변경하면 부드럽거나 거친 표면이 나오는 예를 볼 수 있지만 큰 진폭을 제공하더라도 차이가 거의 없습니다.


perlin (x) + 0.5 * perlin (2 * x) + 0.25 * perlin (4 * x) + ...와 같이 매번 여러 인스턴스를 추가하여 빈도를 높이고 진폭을 줄입니다. 당신이 원하는). 다른 모양을 갖도록 요소를 변경해 볼 수도 있습니다. 그들은 2의 거듭 제곱 일 필요는 없습니다.
Nathan Reed

1
업데이트 후, Y를 올바르게 확장하지 못하는 것 같습니다. PHP를 알기에는 너무 피곤합니다. 그러나 나는 펄린을 처음 구현할 때 모국어로 비슷한 문제를 겪었습니다. 또한 옥타브를 제거하고 한 단계의 펄린을 디버깅하십시오.
조나단 디킨슨

내 III 업데이트를위한 사람이 있습니까?
Gabriel A. Zorrilla

답변:


28

당신이 구현 한 것은 Perlin 소음이 아닙니다. 휴고 엘리아스가 왜 그렇게 말했는지 잘 모르겠지만 혼란스러워합니다. 다음 은 Ken Perlin의 참조 구현입니다. 실제로 외부 난수 생성기를 호출하지 않지만 내장 해시 함수를 사용하여 의사 난수 그라디언트 벡터를 생성합니다.

Perlin 노이즈는 한 옥타브로만 구성됩니다. Hugo Elias가 제안한 것처럼 여러 옥타브 (노이즈 기능의 스케일 된 인스턴스)를 합산하는 것은 유용한 기술이지만 Perlin 노이즈의 일부는 아닙니다. 이를 통해 얻는 것은 프랙탈 노이즈, 때로는 "프랙탈 브라운 노이즈"(브라운 모션과 유사하다고 가정)입니다.

알고리즘이 수행하는 작업을 기하학적으로 이해하려면 이 백서를 시도 하십시오 . "심플 렉스 노이즈"라는 다른 종류의 노이즈에 관한 것이지만 고전적인 Perlin 노이즈에 대한 설명도 포함되어 있습니다. 덧붙여서, 단순 노이즈는 Perlin에 의해 발명되었으며 그의 클래식 노이즈에 비해 개선되어야하므로 노이즈 기능을 사용하는 데 관심이 있다면이를 구현해 볼 수도 있습니다.


2
Gustavson의 논문 +1 그것은 지금까지 본 가장 분명한 방식으로 펄린과 심플 렉스 노이즈를 모두 설명합니다. 분명히 단순한 소음 규칙!
FxIII

나는 또한 얼마 전에 그 종이를 발견했지만 휴고는 더 단순 해 보였다. 읽고 읽어 볼게요! 감사!
Gabriel A. Zorrilla

2
단순 노이즈를 다운로드 할 때주의하십시오. 바이러스가있을 수 있습니다.)
bobobobo

나는 이것이 오래된 주제라는 것을 알고 있지만 참조 구현이 임의의 숫자를 사용하지 않는다고 말하는 것은 올바르지 않습니다. 라이브러리가 초기화되면 (또는 처음으로 노이즈 함수가 호출 될 때) 256 개의 임의 그라디언트가 생성됩니다. 언급 한 해싱은 무한한 정수 세트를 캐시 된 [0, 255] 범위로 강제 변환하는 것입니다. 본질적으로 이것은 조회 테이블 최적화 일뿐이며 예를 들어 그리드 좌표로 PRNG를 시드하고 그라디언트를 생성하는 데 사용하는 경우 알고리즘이 작동합니다.이 방법은 속도가 느립니다.
bcrist

@bcrist 나는 당신이 이전 버전의 Perlin 노이즈를 언급하고 있다고 생각합니다. 펄린의 "개선 된 잡음" I가 연결된 12 개 그래디언트 벡터가 아닌 임의의 것 (256)의 고정 된 세트를 사용한다. 그리드 테이블을 12 개의 그래디언트 벡터 중 하나에 매핑하기 위해 순열 테이블을 해시 함수로 사용합니다.
Nathan Reed

11

그것은 일반적인 오해입니다. 휴고 엘리아스가 "펄린"노이즈라고 부르는 것은 실제로 프랙탈 또는 핑크 노이즈입니다. Perlin 노이즈가 무엇인지 더 잘 이해하려면 Nathan Reed의 답변에 링크 된 Perlin의 기사 또는 libnoise 문서 (Perlin 노이즈는 Gradient noise라고 부르는 오류가 있음) 또는 CoherentNoise docs를 읽을 수 있습니다 .

이제 실제로 귀하의 질문에 대답하십시오 : 잡음 주파수가 너무 높아서 예상 한 결과를 얻지 못했습니다. 빈도는 1로 시작하여 증가합니다. 결과 맵의 모든 픽셀은 임의의 값을 갖습니다. 맵의 미세한 구조를 보려면 노이즈를 "확대"해야합니다. 나는 실제로 PHP를 말하지 않지만 코드는 다음과 같아야한다고 생각합니다.

$arrayMap[$i][$j] = PerlinNoise_2D($i/$width, $j/$height, $p, $octaves);

즉, 전체지도에서 한주기의 노이즈를 "스트레치"합니다. 물론, 다른 계수를 사용할 수 있습니다. 다른 계수를 시도하고 결과를 확인하십시오.


일관된 노이즈 문서에 감사드립니다! 나는 당신이 그것을 쓴 것을 보았습니다 :) libnoise 문서의 오류는 무엇입니까? 펄린 노이즈는 그라디언트 노이즈가 아닙니까?
legends2k
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.