다이아몬드 스퀘어와 함께 일한 후 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에서 “있는 그대로”구현 될 수 있습니까?) :
요약하면 세 가지 질문이 있습니다.
- 내 코드가 맞습니까?
- 코드에 설명 된대로 임의 함수를 PHP로 이식 할 수 있습니까? 오류가 발생하지 않지만 결과는 없습니다.
- 실제로 알고리즘을 어떻게 사용합니까?
최신 정보
좋아, 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
요약
각 옥타브는 거의 동일합니다. 코드를 확인하십시오 :
$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 소음이 아닙니다. 휴고 엘리아스가 왜 그렇게 말했는지 잘 모르겠지만 혼란스러워합니다. 다음 은 Ken Perlin의 참조 구현입니다. 실제로 외부 난수 생성기를 호출하지 않지만 내장 해시 함수를 사용하여 의사 난수 그라디언트 벡터를 생성합니다.
Perlin 노이즈는 한 옥타브로만 구성됩니다. Hugo Elias가 제안한 것처럼 여러 옥타브 (노이즈 기능의 스케일 된 인스턴스)를 합산하는 것은 유용한 기술이지만 Perlin 노이즈의 일부는 아닙니다. 이를 통해 얻는 것은 프랙탈 노이즈, 때로는 “프랙탈 브라운 노이즈”(브라운 모션과 유사하다고 가정)입니다.
알고리즘이 수행하는 작업을 기하학적으로 이해하려면 이 백서를 시도 하십시오 . “심플 렉스 노이즈”라는 다른 종류의 노이즈에 관한 것이지만 고전적인 Perlin 노이즈에 대한 설명도 포함되어 있습니다. 덧붙여서, 단순 노이즈는 Perlin에 의해 발명되었으며 그의 클래식 노이즈에 비해 개선되어야하므로 노이즈 기능을 사용하는 데 관심이 있다면이를 구현해 볼 수도 있습니다.
답변
그것은 일반적인 오해입니다. 휴고 엘리아스가 “펄린”노이즈라고 부르는 것은 실제로 프랙탈 또는 핑크 노이즈입니다. Perlin 노이즈가 무엇인지 더 잘 이해하려면 Nathan Reed의 답변에 링크 된 Perlin의 기사 또는 libnoise 문서 (Perlin 노이즈는 Gradient noise라고 부르는 오류가 있음) 또는 CoherentNoise docs를 읽을 수 있습니다 .
이제 실제로 귀하의 질문에 대답하십시오 : 잡음 주파수가 너무 높아서 예상 한 결과를 얻지 못했습니다. 빈도는 1로 시작하여 증가합니다. 결과 맵의 모든 픽셀은 임의의 값을 갖습니다. 맵의 미세한 구조를 보려면 노이즈를 “확대”해야합니다. 나는 실제로 PHP를 말하지 않지만 코드는 다음과 같아야한다고 생각합니다.
$arrayMap[$i][$j] = PerlinNoise_2D($i/$width, $j/$height, $p, $octaves);
즉, 전체지도에서 한주기의 노이즈를 “스트레치”합니다. 물론, 다른 계수를 사용할 수 있습니다. 다른 계수를 시도하고 결과를 확인하십시오.