벡터 내부의 데이터에 C언어의 구조체처럼 접근한다.
vec3 red = vec3(1.0,0.0,0.0);
red.x = 1.0;
red.y = 0.0;
red.z = 0.0;
색상을 x, y, z 표기법으로 정의하면 혼란스러울 수 있다.
그래서 다른 접근법도 있다.
s,t,p는 일반적으로 텍스처의 공간 좌표에 사용된다.
vector[0] = vector.r = vector.x = vector.s;
vector[1] = vector.g = vector.y = vector.t;
vector[2] = vector.b = vector.z = vector.p;
vector[3] = vector.a = vector.w = vector.q;
GLSL 벡터의 또 다른 특징은 프로퍼티를 원하는 순서대로 결합할 수 있다.
값을 쉽게 캐스팅하고 혼합한다.
이 기능을 스위즐이라고 한다.
vec3 yellow, magenta, green;
// Making Yellow
yellow.rg = vec2(1.0); // Assigning 1. to red and green channels
yellow[2] = 0.0; // Assigning 0. to blue channel
// Making Magenta
magenta = yellow.rbg; // Assign the channels with green and blue swapped
// Making Green
green.rgb = yellow.bgb; // Assign the blue channel of Yellow (0) to red and blue channels
Mixing color
두 값을 백분율로 혼합할 수 있는 함수 mix()가 있다.
백분율 범위는 0.0에서 1.0 사이의 값이다.
// ... 생략
vec3 colorA = vec3(0.149,0.141,0.912);
vec3 colorB = vec3(1.000,0.833,0.224);
void main() {
vec3 color = vec3(0.0);
float pct = abs(sin(u_time));
color = mix(colorA, colorB, pct);
gl_FragColor = vec4(color,1.0);
}
Playing with gradients
벡터값을 이용해 mix할 수도 있다.
// ... 생략
vec3 colorA = vec3(0.149,0.141,0.912);
vec3 colorB = vec3(1.000,0.833,0.224);
float plot (vec2 st, float pct){
return smoothstep( pct-0.01, pct, st.y) -
smoothstep( pct, pct+0.01, st.y);
}
void main() {
vec2 st = gl_FragCoord.xy/u_resolution.xy;
vec3 color = vec3(0.0);
vec3 pct;
pct.r = smoothstep(0.0,1.0, st.x);
pct.g = sin(st.x*PI);
pct.b = pow(st.x,0.5);
color = mix(colorA, colorB, pct);
// Plot transition lines for each channel
color = mix(color,vec3(1.0,0.0,0.0),plot(st,pct.r));
color = mix(color,vec3(0.0,1.0,0.0),plot(st,pct.g));
color = mix(color,vec3(0.0,0.0,1.0),plot(st,pct.b));
gl_FragColor = vec4(color,1.0);
}
HSB
RGB가 아닌 다른 색공간도 있다.
HSB는 Hue, Saturation, Brightness(또는 Value)의 약자이다.
직관적인 색공간이다.
// ... 생략
vec3 rgb2hsb( in vec3 c ){
vec4 K = vec4(0.0, -1.0 / 3.0, 2.0 / 3.0, -1.0);
vec4 p = mix(vec4(c.bg, K.wz),
vec4(c.gb, K.xy),
step(c.b, c.g));
vec4 q = mix(vec4(p.xyw, c.r),
vec4(c.r, p.yzx),
step(p.x, c.r));
float d = q.x - min(q.w, q.y);
float e = 1.0e-10;
return vec3(abs(q.z + (q.w - q.y) / (6.0 * d + e)),
d / (q.x + e),
q.x);
}
vec3 hsb2rgb( in vec3 c ){
vec3 rgb = clamp(abs(mod(c.x*6.0+vec3(0.0,4.0,2.0),
6.0)-3.0)-1.0,
0.0,
1.0 );
rgb = rgb*rgb*(3.0-2.0*rgb);
return c.z * mix(vec3(1.0), rgb, c.y);
}
void main(){
vec2 st = gl_FragCoord.xy/u_resolution;
vec3 color = vec3(0.0);
color = hsb2rgb(vec3(st.x,1.0,st.y));
gl_FragColor = vec4(color,1.0);
}
HSB in polar coordinates (극좌표계)
// 극좌표계란?
극좌표계는 평면 위의 위치를 각도와 거리를 써서 나타내는 2차원 좌표계이다
두 점 사이의 관계가 각이나 거리로 쉽게 표현되는 경우 유용하다
https://ko.wikipedia.org/wiki/%EA%B7%B9%EC%A2%8C%ED%91%9C%EA%B3%84
// 코드 설명
HSB는 원래 극좌표로 표현하도록 설계되었다.
HSB 함수를 극좌표로 매핑하려면 중심점에서 픽셀 좌표까지의 각도와 거리를 구해야한다.
각도와 길이를 구한 후, 해당 값을 0.0에서 1.0 사이의 범위로 정규화한다.
27번째 줄에서 atan(y,x)는 -PI와 PI(-3.14~3.14) 사이의 라디안 단위 각도를 반환한다.
이 값을 TWO_PI로 나누어 -0.5에서 0.5 사이의 값을 구한다.
간단한 덧셈을 통해 원하는 범위인 0.0에서 1.0으로 변경한다.
반경은 최대 0.5를 반환하므로, (뷰포트의 중심으로부터의 거리를 계산하기 때문에)
최대 1.0을 얻으려면 이 범위를 두 배(2를 곱하여)로 늘려야 한다.
요약하자면 ㅇ범위를 0.0에서 1.0으로 변환하고 매핑하는 것이 전부이다.
// ... 생략
#define TWO_PI 6.28318530718
void main(){
vec2 st = gl_FragCoord.xy/u_resolution;
vec3 color = vec3(0.0);
vec2 toCenter = vec2(0.5)-st;
float angle = atan(toCenter.y,toCenter.x);
float radius = length(toCenter)*2.0;
color = hsb2rgb(vec3((angle/TWO_PI)+0.5,radius,1.0));
gl_FragColor = vec4(color,1.0);
}
Note about functions and arguments
매개변수 전에 위치한 in이라는 키워드를 보자.
이는 읽기 전용인지를 지정하는 qualifier(수식어)이다.
out이나 inout도 있다.
inout은 전달된 변수를 수정할 수 있는 방식인 레퍼런스로 전달하는 것과 유사한 개념이다.
'셰이더 (Shader) > The Book of Shaders (완)' 카테고리의 다른 글
[GLSL] 8 - 2D Matrices (1) | 2023.04.20 |
---|---|
[GLSL] 7 - Shapes (0) | 2023.04.19 |
[GLSL] 5 - Shaping functions (0) | 2023.04.17 |
[GLSL] 4 - Running your shader (세부내용 생략) (0) | 2023.04.17 |
[GLSL] 3 - Uniforms, gl_FragCoord (0) | 2023.04.14 |
댓글