본문 바로가기
Shader CG

2.4 Noise 함수 사용해보기

by SimonLee 2023. 8. 12.

http://editor.thebookofshaders.com/

 

** The Book of Shaders Editor **

 

editor.thebookofshaders.com

 

유니티에서 쉐이더를 수정하고 빌드 타임이 약간 소모가 되기도 하고, 애니메이션이 editor에서는 확인이 어려운데,

Noise와 같은 effect들은 바로바로 이전 프레임과 비교하는 일이 많습니다.

 

그래서 shaderbook에서 지원하는 반응형 웹에서 아래 코드를 실행해 보겠습니다.

이후 예제에서도 unity 대신 사용할 생각인데, 헷갈릴수 있으니 코드 윗 부분에 적어 놓겠습니다.

 

 

editor.thebookofShader.com 에서 사용하는 Uniform 변수 들입니다.

자주 해당 변수들을 사용을 하니, 상단에 선언만 하면 사용할 수 있도록 자동으로 값이 넘어 옵니다.

#ifdef GL_ES
precision mediump float;
#endif

uniform vec2 u_resolution; // Canvas size (width,height)
uniform vec2 u_mouse;      // mouse position in screen pixels
uniform float u_time;     // Time in seconds since load

---------------------------------------------------------------------

 

이번에는 Noise 함수를 사용해보겠습니다.

똑똑한 사람들이 구현한 많은 Noise 효과가 있습니다.

코드를 이해하기 어려운 것들이 많기에, 코드를 이해하려고 머리를 싸매는 것보다,

최대한 많이 사용해보고, 변형해보면서 효과를 만들어 내보는 공부 방법이 좋을 것 같습니다..

 

먼저 mix 함수를 알아보고 갑시다.

mix 함수는 a, b값을 p의 비율로 보간 합니다.

- mix(a, b, p) = a * ( 1 - p ) + b * p

즉 p가 0이면 a, p가 1면 b 입니다.

 

다음은 noise 함수의 원리를 이해하기 위한 예제를 site(thebookshaders.com)에서 가져왔습니다.

line을 그려주는 코드는 숨겨져 있습니다.

 

random 함수를 통해 특정 영역에 고정된 y 값을 그래프 렌더링 합니다.

 

mix 함수를 통해 rand(i) ~ rand(i + 1.0) 값을 f에 따라 보간합니다.

f는 0 ~ 1 사이의 값입니다.

mix의 마지막 인자 값에 smoothstep(0, 1, f)를 통해 그래프가 꺽이는 부분을 좀 더 부드럽게 만들어 줍니다.

 

noise 함수를 보면 봅시다.

float noise (in vec2 st) 
{
	vec2 i = floor(st);
    vec2 f = fract(st);
    
    // Four cornders in 2D of a tile
    float a = random(i);
    float b = random(i + vec2(1., 0.));
    float c = random(i + vec2(0., 1.));
    float d = random(i + vec2(1., 1));
    
    vec2 u = f * f * (3.0 - 2.0 * f);
    
    return mix(a, b, u.x) + 
        (c - a) * u.y * (1.0 - u.x) +
        (d - b) * u.x * u.y;
}

1> fract, floor 함수를 사용해서 소숫점과 정수부분 가져 오는 이유는 영역관련 처리 때문입니다.

2> random 함수의 input으로 tile의 각 꼭지점에 해당하는 좌표를 넣어 a, b, c, d 값을 가져 옵니다.

- 사각 형태의 4 꼭지점에 해당하는 좌표 입니다.

3> u값을 계산하는 부분은 "vec2 u = smoothstep(0, 1, f);" 코드와 동일합니다.

- vec2 u = f * f * (3.0 - 2.0 * f); 

4> noise를 만드는 공식입니다.

mix(a, b, u.x) + (c - a) * u.y * (1.0 - u.x) + (d - b) * u.x * u.y 

 

 

// main funciton
vec3 color = vec3(0.);
vec2 pos = vec2(st * 5.);
color = vec3(noise(pos));

gl_FragColor = vec4(color, 1.0);

좌표를 5배 확장을 시키고 noise 함수에 확장시킨 좌표를 넣어줍니다.

 

결과는 아래와 같습니다.

Noise 함수 결과

흐리멍텅한 저런걸 어디다 쓸까 라고 생각이 드실텐데,

애니메이션 효과를 섞어서 불이나 물결과 같은 것들을 만들수도 있습니다.

그리고 예술쪽으로는 다양한 형태의 작품에도 사용이 된다고 하네요.

 

 

아래 예제는 웹에디터에서 작성되었습니다.

// Author: SimonLee
// Title: Noise

#ifdef GL_ES
precision mediump float;
#endif

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

#define PI 3.141592

float random(vec2 st) 
{
    return fract(sin(dot(st.xy, vec2(12.9898, 78.2333))) * 43758.5453123);
}

float line(vec2 st, float thickness, float blur, bool reverse) 
{
    if (reverse) {
    	st.x = st.x * -1. + 1.;    
    }
    
	return smoothstep(st.x-thickness-blur, st.x-thickness+blur, st.y) -
        smoothstep(st.x+thickness-blur, st.x+thickness+blur, st.y);
}

float noise (in vec2 st) 
{
	vec2 i = floor(st);
    vec2 f = fract(st);
    
    float a = random(i);
    float b = random(i + vec2(1., 0.));
    float c = random(i + vec2(0., 1.));
    float d = random(i + vec2(1., 1));
    
    vec2 u = f * f * (3.0 - 2.0 * f);
    return mix(a, b, u.x) + 
        (c - a) * u.y * (1.0 - u.x) +
        (d - b) * u.x * u.y;
}

void main() {
    vec2 st = gl_FragCoord.xy/u_resolution.xy;
    st.x *= u_resolution.x/u_resolution.y;	
    
    vec3 color = vec3(0.);
    vec2 pos = vec2(st * 5.);
    
    vec2 i = floor(st);
    vec2 f = fract(st);

    color = vec3(noise(pos));
    gl_FragColor = vec4(color, 1.0);
}

 

 

아래 사이트에서 여러가지 noise 효과를 검색해서 활용해보세요

https://www.shadertoy.com/

 

Shadertoy BETA

 

www.shadertoy.com

https://www.shadertoy.com/view/4dS3Wd

 

Shadertoy

 

www.shadertoy.com

 

'Shader CG' 카테고리의 다른 글

2.6 나이테 Noise  (0) 2023.08.19
2.5 Gradient Noise  (0) 2023.08.17
2.3 Noise 미로 만들기  (0) 2023.08.11
2.2 Noise 모자이크 효과  (0) 2023.08.09
2.1 Noise TV 화면 만들어보기  (0) 2023.08.06