개발/Shader / / 2023. 3. 22. 16:34

GLSL - Gradient Noise 기울기 노이즈

반응형

https://thebookofshaders.com/11/

 

The Book of Shaders

Gentle step-by-step guide through the abstract and complex universe of Fragment Shaders.

thebookofshaders.com

※ 다음 페이지를 참고하여 공부한 게시물입니다.

https://www.opentutorials.org/module/3659/25298

https://eullee.tumblr.com/post/164705753760/gradient-noise-%EA%B8%B0%EC%A1%B4%EA%B9%8C%EC%A7%80-%EC%97%B0%EB%A7%88%ED%96%88%EB%8D%98-noise%EB%A5%BC-value-noise%EB%9D%BC%EA%B3%A0-%EB%B6%80%EB%A5%B8%EB%8B%A4%EB%8A%94

Gradient Noise

value noise는 정수값에 해당하는 각각의 방점들이 가진 랜덤 value가 있고, 각 4 방점으로부터 이루는 거리에 따라 점차 보간된다. 

gradient noise의 경우 정수 방점에 해당하는 vec2 data를 랜덤으로 가지고, 그림 화살표로 표현되는 것처럼 랜덤 벡터값이 있다.

gradient noise를 보면, 랜덤 벡터와 반대 방향에 위치한 좌표들은 어둡고, 같은 방향에 위치한 좌표들은 밝은데, 랜덤벡터(화살표)와 각 좌표와의 내적값이 색의 어두움을 결정하기 때문이다. 반대방향으로 -1에 근접하면 어둡고, 같은 방향으로 1에 근접하면 밝다.

 

#ifdef GL_ES
precision mediump float;
#endif

uniform vec2 u_resolution;
uniform vec2 u_mouse;
uniform float u_time;

vec2 random(vec2 v){
    float f1 = dot(v, vec2(56.37, 67.531));
    float f2 = dot(v, vec2(69.08641, 75.3739));
    
    float x = fract(sin(f1*6.7876)*156423.12312);
    float y = fract(cos(f2*1.34531)*163451.12512);
    
    return vec2(x, y) * 2. -1.; // range -1 ~ 1
}

float noise(vec2 v){
    vec2 i = floor(v);
    vec2 f = fract(v);
    
    vec2 i2 = i+vec2(1., 0.);
    vec2 i3 = i+vec2(0., 1.);
    vec2 i4 = i+vec2(1., 1.);
    
    vec2 r = random(i);
    vec2 r2 = random(i2);
    vec2 r3 = random(i3);
    vec2 r4 = random(i4);
    
    f = smoothstep(0., 1., f);
    // f = f*f*f*(f*(f*6.-15.)+10.);
    
    float d = dot(r, v-i);
    float d2 = dot(r2, v-i2);
    float d3 = dot(r3, v-i3);
    float d4 = dot(r4, v-i4);
    
    float bot = mix(d, d2, f.x);
    float top = mix(d3, d4, f.x);
    float ret = mix(bot, top, f.y);
    
    return ret; // range -1 ~ 1
    // return ret*0.5 + 0.5; // range 0 ~ 1
}

void main(){
    vec2 coord = gl_FragCoord.xy/u_resolution;
    coord *= 10.;
    coord.x *= u_resolution.x/u_resolution.y;
    
    // vec3 col = vec3(random(coord), 1.);
    vec3 col = vec3(noise(coord));
    
    gl_FragColor = vec4(col, 1.0);
}

 

gradient noise는 value noise와 다르게 vec2 형의 r_n을 가진다. 

value noise는 r_n을 이용하지만, gradient nosie는 랜덤값 r_n과 v-i_n 벡터를 통해 만든 내적 값 d_n을 이용한다.

 

return에 주석된 코드를 변경하면, 결과 ret의 범위는 -1 ~ 1이지만, 0~1 범위로 만들면 전체적인 밝기가 밝아진다.

 

// f = smoothstep(0., 1., f);
f = f*f*f*(f*(f*6.-15.)+10.);

주석 코드를 변경하여 f에 대한 smooth 식을 변경하면, noise가 조금 더 부드러워 진다. 

위 그림에서 왼쪽이 smoothstep이고 오른쪽이 수식을 이용한 결과이다. 미세하여 뿌연 느낌이 줄어들고 부드러워진 것 같다.

 

Improved Noise, Simplex Noise

value noise와 gradient noise 이외에도, improved noise와 simplex noise라는 것이 있다.

반응형
  • 네이버 블로그 공유
  • 네이버 밴드 공유
  • 페이스북 공유
  • 카카오스토리 공유