유튜브 kishimisu의 An introduction to Shader Art Coding 영상을 정리한 내용입니다.
중간에 등장하는 자료들은 영상을 캡처한 것입니다.
이번 포스팅의 예제는 Shadertoy 에서 GLSL로 진행했습니다.
🐥 UV 좌표계 수정
origin resolution |
downsampled resolution |
|
|
void main(out vec4 fragColor, in vec2 fragCoord)
{
vec2 uv = fragCoord / iResolution.xy; // 0 ~ 1
uv = uv - 0.5; // align center
uv = uv * 2.0; // -1 ~ 1
fragColor = vec4(uv, 0.0, 1.0);
}
- 스크린의 중앙을 기준으로 작업을 하기 때문에 uv 좌표계를 center 중심으로 바꿔주기
🐥 Fix Aspect Ratio
Before Fix |
After Fix |
|
|
void main(out vec4 fragColor, in vec2 fragCoord)
{
vec2 uv = fragCoord / iResolution.xy; // 0 ~ 1
uv = uv - 0.5; // align center
uv = uv * 2.0; // -1 ~ 1
fragColor = vec4(uv, 0.0, 1.0);
}
- 일반적으로 모니터의 가로x세로 해상도가 다르기 때문에 정사각형 모양의 스크린을 원한다면 aspect ratio를 보정해야 한다.
🐥 2D Signed Distance Function
void main(out vec4 fragColor, in vec2 fragCoord)
{
vec2 uv = (fragCoord * 2.0 - iResolution.xy) / iResolution.y;
float d = length(uv);
d -= 0.5;
d = abs(d);
fragColor = vec4(d, d, d, 1.0);
}
- 물체의 표면을 표현하고 싶을 때 사용하는 SDF
- Signed Distance Function : 물체의 형태를 유지하는 level set
- negative : 물체 내부
- zero : 물체 표면
- positive : 물체 외부
- absolute value, abs()를 이용하여 내부, 외부 모두 흰색으로 만들어주기
- Q ) 경계면 좀 더 깔끔하게 만들 수는 없나..??
Step Function
Graph |
Result |
|
|
- step function을 이용하면 칼 같은 경계 표현 가능
Smoothstep Function
Graph |
Result |
|
|
- smoothstep으로는 원하는 두께로 부드럽게 표현 가능
🐥 Sine 함수로 주기 만들기
void main(out vec4 fragColor, in vec2 fragCoord)
{
vec2 uv = (fragCoord * 2.0 - iResolution.xy) / iResolution.y;
float d = length(uv);
d = sin(d * 8.0 + iTime) / (8.0);
d = abs(d);
d = smoothstep(0.0, 0.1, d);
fragColor = vec4(d, d, d, 1.0);
}
- sine function을 이용하여 주기를 주고
- iTime을 더해주며 움직임 표현
🐥 1/x 함수로 색 반전시키기
Graph |
Result |
|
|
void main(out vec4 fragColor, in vec2 fragCoord)
{
vec2 uv = (fragCoord * 2.0 - iResolution.xy) / iResolution.y;
float d = length(uv);
d = sin(d * 8.0 + iTime) / (8.0);
d = abs(d);
d = 0.01 / d;
fragColor = vec4(d, d, d, 1.0);
}
- 색을 반전시키기 위해서는 0 -> 1, 1 -> 0 으로 부드럽게 변경해야 함
- 1/x 함수를 이용하면 원하는 강도로 부드럽게 반전시킬 수 있다.
- color 곱해주면 알록달록 표현 가능
Example1 |
Example2 |
|
|
🐥 Palette 만들기
vec3 palette(float t)
{
vec3 a = vec3(0.5, 0.5, 0.5);
vec3 a = vec3(0.5, 0.5, 0.5);
vec3 a = vec3(1.0, 1.0, 1.0);
vec3 a = vec3(0.263, 0.416, 0.557);
vec3 a + b*cos(6.28318 * (c*t + d));
}
void main(out vec4 fragColor, in vec2 fragCoord)
{
vec2 uv = (fragCoord * 2.0 - iResolution.xy) / iResolution.y;
float d = length(uv);
vec3 col = palette(d + iTime);
d = sin(d * 8.0 + iTime) / (8.0);
d = abs(d);
d = 0.02 / d;
col *= d;
fragColor = vec4(col, 1.0);
}
Inigo Quilez website
- 위 사이트에 들어가면 원하는 팔레트의 변수 값들을 찾을 수 있음
- 연속적으로 색이 변하는 팔레트이기 때문에 시간에 따른 주기함수에 쓰기 좋다.
- palette 변수로 time을 더해주면 같은 원 내에서도 알록달록 변함
Example1 |
Example2 |
|
|
🐥 Fraction 함수로 스크린 분할
Graph |
Result |
|
|
void main(out vec4 fragColor, in vec2 fragCoord)
{
vec2 uv = (fragCoord * 2.0 - iResolution.xy) / iResolution.y; // -1 ~ 1
uv = fract(uv * 2.0) - 0.5; // -2 ~ 2 : 가로세로 4등분 & center 보정
float d = length(uv);
vec3 col = palette(d + iTime);
d = sin(d * 8.0 + iTime) / (8.0);
d = abs(d);
d = 0.02 / d;
col *= d;
fragColor = vec4(col, 1.0);
}
- fraction : 정수 부분을 뺀 소수 부분
- uv의 범위를 늘려주고 fraction을 이용하면 스크린을 반복할 수 있음
Global Effect 추가하기
void main(out vec4 fragColor, in vec2 fragCoord)
{
vec2 uv = (fragCoord * 2.0 - iResolution.xy) / iResolution.y; // -1 ~ 1
vec2 uv0 = uv; // glbal coordinate
uv = fract(uv * 2.0) - 0.5; // -2 ~ 2 : 가로세로 4등분 & center 보정
float d = length(uv);
vec3 col = palette(length(uv0) + iTime); // global effect
d = sin(d * 8.0 + iTime) / (8.0);
d = abs(d);
d = 0.02 / d;
col *= d;
fragColor = vec4(col, 1.0);
}
- fraction 적용 전 global coordinate(?)을 저장해두고, 이를 이용하여 global effect를 만들어 줄 수 있다.
🐥 Iteration으로 Fractal 구조 만들기
void main( out vec4 fragColor, in vec2 fragCoord )
{
vec2 uv = (fragCoord * 2.0 - iResolution.xy) / iResolution.y;
vec2 uv0 = uv;
vec3 finalColor = vec3(0.0);
for(float i=0.0; i<2.0; i++)
{
uv = fract(uv * 2.0) - 0.5;
float d = length(uv);
vec3 col = palette(length(uv0) + iTime);
d = sin(d*8. + iTime) / 8. ;
d = abs(d);
d = 0.02 / d;
finalColor += col * d;
}
fragColor = vec4(finalColor, 1.0);
}
- fraction으로 쪼갠 영역 안에서 또 fraction으로 쪼개버리기
- i를 늘려주면서 fractal 구조 만들 수 있음
🐥 Final Results
void main( out vec4 fragColor, in vec2 fragCoord )
{
vec2 uv = (fragCoord * 2.0 - iResolution.xy) / iResolution.y;
vec2 uv0 = uv;
vec3 finalColor = vec3(0.0);
for(float i=0.0; i<4.0; i++)
{
uv = fract(uv * 1.5) - 0.5;
float d = length(uv) * exp(-length(uv0));
vec3 col = palette(length(uv0) + i*0.4 + iTime*0.4);
d = sin(d*8. + iTime) / 8. ;
d = abs(d);
d = pow(0.01 / d, 1.2);
finalColor += col * d;
}
fragColor = vec4(finalColor, 1.0);
}
- 규칙성을 흩트려 뜰이기 위해 몇 가지 작업 수행
- for문 안에서 2.0이 아닌 1.5배로 애매하게 쪼개기
- d = x * exp(-x), 부드러운 형태로 변형
- 0~1 사이에 pow 함수를 적용해 어두운 부분은 더 어둡게 표현
맨 위로 이동하기
Mini_Project 카테고리 내 다른 글 보러가기
댓글 남기기