개발/Shader / / 2023. 2. 15. 23:29

GLSL - Uniform, gl_FragCoord, step, smoothstep

반응형

GLSL 공부를 시작하려고 한다. 여지껏 한다고 생각하고 계속해서 미뤘는데 이번에야말로 한 번 끝내보자.

shader 코드를 짤 때 일일히 그래픽 API를 사용해서 그리지 않고 바로 보여주는 editor사이트가 있다.

아래 사이트가 그 사이트이다.

https://thebookofshaders.com/edit.php

 

GLSL Shader Editor

The Book of Shaders Editor

thebookofshaders.com

GLSL Uniform

// Author:
// Title:

#ifdef GL_ES
precision mediump float;
#endif

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

void main() {
    vec2 st = gl_FragCoord.xy/u_resolution.xy;
    st.x *= u_resolution.x/u_resolution.y;

    vec3 color = vec3(0.);
    color = vec3(st.x,st.y,abs(sin(u_time)));

    gl_FragColor = vec4(color,1.0);
}

위 코드는 GLSL editor 사이트를 처음 열었을 때 볼 수 있는 코드인데, uniform이라는 키워드가 있다. 

uniform은 응용 프로그램에서 GPU의 데이터를 shader로 전달하는 방법이라고 한다.

 

 

#ifdef GL_ES
precision mediump float;
#endif

uniform float u_time;

void main() {
	gl_FragColor = vec4(abs(sin(u_time)),0.0,0.0,1.0);
}

위 코드는 기초적인 color 조정 예제이다. sin함수를 이용해서 R 색깔을 0~1로 왔다 갔다하는 효과를 낸다.

 

gl_FragCoord

#ifdef GL_ES
precision mediump float;
#endif

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

void main() {
	vec2 st = gl_FragCoord.xy/u_resolution;
	gl_FragColor = vec4(st.x,st.y,0.0,1.0);
}

gl_FragColor가 색을 지정한다면, gl_FragCoord는 색상을 띄울 픽셀을 지정하는 변수이다.

화면의 모든 픽셀에 동일한 로직이 적용되기 때문에 gl_FragCoord를 통해 픽셀 좌표값에 따라 다르게 값이 적용될 수 있도록 처리한다.

위 예제 코드의 경우, gl_FragCoord로 x,y 좌표를 가져와서 해상도로 나누면 0~1사이의 float 값으로 나온다. 각 위치에 해당하는 0~1 사이의 값을 색으로 넣은 것이다. shader를 조금이라도 해보았다면, 각 좌표값에 대응하는 0~1 사이 값으로 색을 넣는 이 과정은 이미 보았을 것이다.

 

Shaping functions

#ifdef GL_ES
precision mediump float;
#endif

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

// Plot a line on Y using a value between 0.0-1.0
float plot(vec2 st) {    
    return smoothstep(0.02, 0.0, abs(st.y - st.x));
}

void main() {
	vec2 st = gl_FragCoord.xy/u_resolution;

    float y = st.x;

    vec3 color = vec3(y);

    // Plot a line
    float pct = plot(st);
    color = (1.0-pct)*color+pct*vec3(0.0,1.0,0.0);

	gl_FragColor = vec4(color,1.0);
}

대각선을 그리는 코드인데 이 코드 안에 smoothstep이라는 함수가 있다. 이것이 뭘까?

 

https://thebookofshaders.com/glossary/?search=smoothstep 

 

The Book of Shaders

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

thebookofshaders.com

위 사이트에 smoothstep에 대한 설명이 있다. step과 smoothstep이라는 두 함수가 있는 모양인데.

 

step

https://thebookofshaders.com/glossary/?search=step 

 

The Book of Shaders

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

thebookofshaders.com

설명이 이렇게 써있다.

 

float step(float edge, float x)  
vec2 step(vec2 edge, vec2 x)  
vec3 step(vec3 edge, vec3 x)  
vec4 step(vec4 edge, vec4 x)

vec2 step(float edge, vec2 x)  
vec3 step(float edge, vec3 x)  
vec4 step(float edge, vec4 x)
step() generates a step function by comparing x to edge.
For element i of the return value, 0.0 is returned if x[i] < edge[i], and 1.0 is returned otherwise.

step의 경우 x의 값이  edge보다 작은 경우 0을, 큰 경우 1을 반환하는 함수이다. 

 

smoothstep

https://thebookofshaders.com/glossary/?search=smoothstep 

 

The Book of Shaders

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

thebookofshaders.com

 

float smoothstep(float edge0, float edge1, float x)  
vec2 smoothstep(vec2 edge0, vec2 edge1, vec2 x)  
vec3 smoothstep(vec3 edge0, vec3 edge1, vec3 x)  
vec4 smoothstep(vec4 edge0, vec4 edge1, vec4 x)

vec2 smoothstep(float edge0, float edge1, vec2 x)  
vec3 smoothstep(float edge0, float edge1, vec3 x)  
vec4 smoothstep(float edge0, float edge1, vec4 x)
smoothstep()
 performs smooth Hermite interpolation between 0 and 1 when edge0 < x < edge1. This is useful in cases where a threshold function with a smooth transition is desired. smoothstep() is equivalent to:
    genType t;  /* Or genDType t; */
    t = clamp((x - edge0) / (edge1 - edge0), 0.0, 1.0);
    return t * t * (3.0 - 2.0 * t);

smoothstep은 step과 달리 그 사이의 값에 대해서 clamp 처리 즉 0~1 사이의 값으로 보간한다.

 

example

#ifdef GL_ES
precision mediump float;
#endif
​
#define PI 3.14159265359
​
uniform vec2 u_resolution;
uniform vec2 u_mouse;
uniform float u_time;

float plot(vec2 st, float pct){
  return  smoothstep( pct-0.02, pct, st.y) -
          smoothstep( pct, pct+0.02, st.y);
}
​
void main() {
    vec2 st = gl_FragCoord.xy/u_resolution;
​
    float y = st.x;
​
    vec3 color = vec3(y);
​
    // 선분 그리기
    float pct = plot(st,y);
    color = (1.0-pct)*color+pct*vec3(0.0,1.0,0.0);
​
    gl_FragColor = vec4(color,1.0);
}

다시 예제로 돌아와서 main함수를 보면, st라는 변수에는 해상도의 각 좌표 위치를 nomalize한 값이 들어간다. 이 값의 x좌표를 RGB 값으로 지정하게 되어 왼쪽은 0으로 검은색, 오른쪽은 1로 흰색으로 점점 색이 배정된다. 

 

float plot(vec2 st, float pct){
  return  smoothstep( pct-0.02, pct, st.y) -
          smoothstep( pct, pct+0.02, st.y);
}

smoothstep의 차이를 return하는 plot코드를 보면 pct는 st.x 값을 가진다. 첫 번째 smoothstep의 경우 pct 즉 st.x위치 에서 0.02를 뺀 위치보다 작으면 0으로 st.x의 위치까지는 0~1사이의 값만이, 그 이상으로는 1로 처리된다. 

두 번째 smoothstep의 경우 반대로 st.x의 위치로부터 +0.02까지의 범위가 1~0으로 제한되는 범위, 그 미만은 0, 이상은 1로 처리되는 구간이다. 

첫 번째에서 두 번째 smoothstep을 빼므로, 첫 번째 두 번째 smoothstep 구간에 해당하는 가운데 부분만이 값이 나오는 부분이고, 나머지 범위는 0으로 상쇄된다.

그러므로 그림과 같이 선분인 부분만이 칠해질 수 있는 것이다. 코드에서 0.02에 해당하는 것이 색을 칠하는 범위의 두께를 결정한다.

 

// Title: Expo

#ifdef GL_ES
precision mediump float;
#endif

#define PI 3.14159265359

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

float plot(vec2 st, float pct){
    float bound = 0.244;
  return  smoothstep( pct-bound, pct, st.y) -
          smoothstep( pct, pct+bound, st.y);
}

void main() {
    vec2 st = gl_FragCoord.xy/u_resolution;

    //float y = pow(st.x,5.0);
    float y = st.x;

    vec3 color = vec3(y);

    float pct = plot(st,y);
    color = (1.0-pct)*color+pct*vec3(0.0,1.0,0.0);

    gl_FragColor = vec4(color,1.0);
}

해당 부분을 이렇게 0.244로 수정하면

 

이렇게 색이 칠해지는 부분의 두께가 바뀐다.

 

    float pct = plot(st,y);
    color = (1.0-pct)*color+pct*vec3(0.0,1.0,0.0);

결과적으로 pct가 0인 부분에서는 배경색 color가 적용되고, pct가 1인 부분 즉 y=x에 해당하는 좌표에서는 배경색이 0으로 제거되고, 지정된 색이 표시된다. 그 사이 pct가 0~1사이인 부분에서는 배경색과 지정색이 적절히 혼합된 상태로 나올 것이다.

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