Search

[TIL] shader glsl from scratch

subtitle
Tags
webGL
threejs
Created
2025/03/24
2 more properties

Z-buffering

Z-buffer는 화면의 각 점(pixel)이 얼마나 카메라에서 멀리 있는지를 저장하는 표
이걸 이용해서 더 가까운 물체만 보이게 하고, 뒤에 있는 건 가림
컴퓨터가 물체를 화면에 그리려고 할 때, 그 물체의 픽셀이 화면의 어디에 위치할지를 계산하고, 그 픽셀의 Z값(깊이)을 확인 → 만약 그 픽셀이 더 앞에 있다면, 기존 것을 덮어쓰고 Z-buffer도 업데이트. 만약 뒤에 있다면, 무시하고 원래 있던 걸 그대로 둔다.

semicolon

glsl 개발할 때 반드시 세미콜론을 잊지 말 것.

vec: ivec, bvec

ivec: int vector
bvec: bool vector

vertext shader, fragment shader

void를 return하는 main function이 반드시 존재해야 함
vertex shader는 gl_Position에 값을, fragment shader는 gl_FragColor, gl_FragCoord에 값을 할당할 수 있다.

uniforms

uniforms를 통해 javascript에서 만든 값을 shader에 전달할 수 있다.
const uniforms = { u_time: { value: 0.0 }, u_mouse: { value: { x: 0.0, y: 0.0 } }, u_resolution: { value: { x: 0.0, y: 0.0 } }, u_color: { value: new THREE.Color(0, 1, 1) }, }; const material = new THREE.ShaderMaterial({ uniforms, vertexShader: vshader, fragmentShader: fshader, });
JavaScript
복사

sin, cos

-1 ~ 1 사이의 값 반환
(sin(u_time) + 1.0)/2: 시간의 흐름에 따라 sin(u_time)은 -1 ~ 1 사이의 값을 반환. -1이 color의 rgba 값으로 들어가면 안되므로 이 경우에는 + 1을 해준다. 반대로 sin(u_time)이 1일 때는 1을 초과하게 되므로 2로 나눠준다.

mix

선형 보간 함수
float x, y, a: 3개의 파라미터를 받는다.
(x, y, 0) = x
(x, y, 1) = y
x * (1-a) + y * a

varying

varying: vertex shader → fragment shader로 넘길 수 있는 값에 키워드로 선언
vec2 uv: (0~1, 0~1):varying vec2 v_uv
vec3 position: (-1~1, -1~1, -1~1)

clamp

n, min, max 3개의 파라미터: clamp(n, min, max)
x 값이 minVal보다 작으면 → minVal을 반환
x 값이 maxVal보다 크면 → maxVal을 반환
그 사이면 → x 그대로 반환
clamp(n, 1, 5) - n=0) 1 - n=6) 5 - n=3) 3
JavaScript
복사
어떤 값을 "최소~최대 범위 안"으로 맞춰주는 함수
언제 쓰는가
색상 값을 0~1 사이로 제한할 때 → clamp(color, 0.0, 1.0)
물체가 화면 밖으로 안 나가게 할 때
밝기, 음영, 거리 등을 정해진 범위 내로 조정할 때

step

step(edge, n) : 0 또는 1 반환
nedge보다 크면 1.0, 작으면 0.0을 반환하는 계단 함수
놀이공원 입장할 때 키 140cm 이상이면 입장 가능
step(140.0, 130.0) // 결과: 0.0 (입장 불가) step(140.0, 150.0) // 결과: 1.0 (입장 가능)
GLSL
복사
언제쓰는가
어떤 기준보다 크냐 작냐에 따라 색, 투명도 등을 딱 나눌 때
마스크 효과 만들 때

smoothstep

smoothstep(edge0, edge1, n)
부드럽게 0에서 1로 넘어가게 해주는 함수
해가 천천히 지면서 하늘이 어두워지는 것처럼, 부드럽게 밝기(0→1)가 바뀌는 느낌
smoothstep(0.0, 1.0, 0.0) // 결과: 0.0 smoothstep(0.0, 1.0, 0.5) // 결과: 0.5 (중간) smoothstep(0.0, 1.0, 1.0) // 결과: 1.0
GLSL
복사
nedge0보다 작으면: 0
nedge1보다 크면: 1
그 사이면: 부드럽게 0 → 1로 변화
언제 쓰는가
그라데이션 효과
부드러운 테두리
자연스러운 전환

length

벡터(화살표)의 길이(거리)를 구하는 함수: length(vec2(x,y))=sqrt(x2+y2)length(vec2(x, y)) = sqrt(x^2 + y^2)
(0, 0)에서 (3, 4)까지 걸어가면, 걸은 거리 = 5 (피타고라스)
length(vec2(3.0, 4.0)) // 결과: 5.0
언제 쓰는가
어떤 점이 중심에서 얼마나 멀리 떨어져 있는지 계산할 때
원형 그라데이션 만들기
마우스 거리 기반 반응 만들기
챌린지! length로 노란색 원 만들어보기!

쉐이더에서 If 문이 느린 이유: 분기 발산

rect(custom function)

float rect(vec2 pt, vec2 size, vec2 center) { vec2 p = pt - center; vec2 halfsize = size * 0.5; float horz = step(-halfsize.x, p.x) - step(halfsize.x, p.x); float vert = step(-halfsize.y, p.y) - step(halfsize.y, p.y); return horz * vert; }
GLSL
복사
yellow square
void main (void) { vec3 color = vec3(1.0,1.0, 0.0) * rect(v_position.xy, vec2(1.0), vec2(0.0)); gl_FragColor = vec4(color, 1.0); }
GLSL
복사

(cos, sin)

원으로 움직이게 만들 때 사용

mat2

2*2 행렬 데이터

fract

1.5 → 0.5, 6.5 → 0.5
정수를 버림

dot

dot(d, p)는 픽셀이 바늘(p) 방향으로 얼마나 가까이 있는지 측정
두 벡터 d, p를 넣으면 "얼마나 같은 방향을 보고 있는지" 알려주는 함수
dot(a, b) = a.x * b.x + a.y * b.y (+ a.z * b.z ... 3D인 경우)
GLSL
복사
같은 방향일 수록 값이 커지고, 반대방향일 수록 값은 작아진다.
dot(a, b)1 → 완전 같은 방향
0 → 90도 (수직)
1 → 완전 반대 방향