왜 Perlin Noise가“차단”처럼 보입니까?


21

나는 펄린 노이즈 구현하려고 혼자 (flafla2.github.io/2014/08/09/perlinnoise.html 다음) 단지 이론을 사용합니다. 불행히도 "원래"Perlin Noise의 모양을 얻을 수 없었습니다.

아래 코드가 Perlin Noise의 블록 버전을 렌더링하는 이유는 무엇입니까?

아티팩트없이 Perlin Noise를 렌더링하려면 코드를 어떻게 개선 / 변경해야합니까?

보간 또는 grads벡터에 문제가있을 수 있습니다 . 이 grads벡터에는 근처의 격자 점 4 개에 대한 (격자 점의 랜덤 벡터)와 (크기 벡터)의 내적 이 들어 있습니다. (랜덤 및 크기 벡터는 첫 번째 링크에 설명되어 있습니다.)

GLSL 샌드 박스 : http://glslsandbox.com/e#32663.0

소음의 유물

float fade(float t) { return t * t * t * (t * (t * 6. - 15.) + 10.); }
vec2 smooth(vec2 x) { return vec2(fade(x.x), fade(x.y)); }

vec2 hash(vec2 co) {
    return fract (vec2(.5654654, -.65465) * dot (vec2(.654, 57.4), co));
}

float perlinNoise(vec2 uv) {
    vec2 PT  = floor(uv);
    vec2 pt  = fract(uv);
    vec2 mmpt= smooth(pt);

    vec4 grads = vec4(
        dot(hash(PT + vec2(.0, 1.)), pt-vec2(.0, 1.)),   dot(hash(PT + vec2(1., 1.)), pt-vec2(1., 1.)),
        dot(hash(PT + vec2(.0, .0)), pt-vec2(.0, .0)),   dot(hash(PT + vec2(1., .0)), pt-vec2(1., 0.))
    );

    return 5.*mix (mix (grads.z, grads.w, mmpt.x), mix (grads.x, grads.y, mmpt.x), mmpt.y);
}

float fbm(vec2 uv) {
    float finalNoise = 0.;
    finalNoise += .50000*perlinNoise(2.*uv);
    finalNoise += .25000*perlinNoise(4.*uv);
    finalNoise += .12500*perlinNoise(8.*uv);
    finalNoise += .06250*perlinNoise(16.*uv);
    finalNoise += .03125*perlinNoise(32.*uv);

    return finalNoise;
}

void main() {
    vec2 position = gl_FragCoord.xy / resolution.y;
    gl_FragColor = vec4( vec3( fbm(3.*position) ), 1.0 );
}

답변:


24

보간이 잘 보입니다. 여기서 주요 문제는 사용중인 해시 함수가 좋지 않다는 것입니다. 한 옥타브를보고 출력하여 해시 결과를 시각화하면 hash(PT).x다음과 같은 결과가 나타납니다.

나쁜 해시 함수

이것은 그리드 정사각형마다 완전히 무작위로 가정되지만, 대각선에 많은 대각선 패턴이 있음을 알 수 있습니다 (거의 바둑판처럼 보입니다). 매우 임의의 해시가 아니며 해당 패턴이 그것에 의해 생성 된 소음.

다른 문제는 해시가 [0, 1]로만 그라디언트 벡터 만 반환하고 모든 방향으로 그라디언트를 얻으려면 [-1, 1]에 있어야한다는 것입니다. 해당 부분은 다시 매핑하여 쉽게 수정할 수 있습니다.

이러한 문제를 해결하기 위해이 해시 함수 (Mikkel Gjoel에서 배웠으며 WJJ Rey의 논문 때문일 수 있음) 를 사용하도록 코드를 전환했습니다 .

vec2 hash(vec2 co) {
    float m = dot(co, vec2(12.9898, 78.233));
    return fract(vec2(sin(m),cos(m))* 43758.5453) * 2. - 1.;
}

삼각 함수로 인해 버전보다 약간 비쌉니다. 그러나 결과 노이즈의 모양이 크게 향상됩니다.

더 나은 해시 기능으로 fbm 노이즈


주셔서 감사합니다 매우 당신의 설명을 많이. 이것은 아마도 주제가 아닐 수도 있지만 어쨌든 물어볼 것입니다. 잡음을 계산하는 일부 소스 코드에서 사람들은 벡터 vec3 (1, 57, 113)을 사용하여 현재 좌표로 내적을 계산합니다 (목표는 해시를 얻는 것으로 가정합니다). 이 상수를 선택하는 이유는 무엇입니까 (57은 약 1 라디안, 133 = 약 2 * 라디안) 삼각 함수의 주기성 때문입니까? 나는 이것을 구글 할 수 없다.
sarasvati

3
@sarasvati 확실하지 않지만 57과 113은 소수이기 때문에 선택됩니다. (113은 소수이지만 57은 그렇지 않지만 3 * 19이므로 여전히 소수입니다 ... 소수에 곱하거나 모딩하는 것은 비트를 뒤섞는 경향이 있으므로 드문 일이 아닙니다. 해시 성분.
Nathan Reed

1
@cat GLSL 프로그램이 결정 론적이라는 점에서 GLSL에 PRNG가 있다고 생각합니다.
user253751

1
이 댓글 스레드에 몇 가지 잠재적 인 새로운 질문이있는 것 같습니다 ...
trichoplax

1
나는 그 인공물을 가지고 있었고이 rand () 함수는 그것을 고쳤다. 문제는 지형에서 2km를 걷다가 OP와 같은 유물이 다시 나타나기 시작한 것입니다. 해시 함수를 사용하고 있습니다 : amindforeverprogramming.blogspot.com/2013/07/… 아티팩트가 사라졌습니다 (100km의 거리, bc의 부정확도 제외).하지만 덩어리로 나눠서 얻었습니다. 펄린 노이즈가 거의 무한정 실행되도록 두 값을 해싱하여 작동합니다. 그래서 나는 같은 문제를 가진 사람을 돕기 위해 여기에 남겨 둘 것입니다.
니콜라스 피피 톤
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.