✨ Shader Patterns with GLSL
GLSL을 사용하여 정해진 텍스처 없이 수학적으로 패턴을 생성하고, 다양한 형태의 그림, 변형, 왜곡, 그리고 애니메이션 가능한 모양을 만들어내는 기법들을 소개합니다.
🎯 목표
- GLSL(Fragment Shader)에서 다양한 패턴을 그리는 수학적 기법 학습
- vUv 좌표를 중심으로 값을 계산하고 시각화
- 텍스처 없이도 정확한 제어가 가능한 셰이더 패턴 구현
- mod, step, length, distance, mix, abs, sin, atan, cnoise, clamp 등의 함수 활용법 숙지
📦 기본 셋업
- ShaderMaterial을 사용한 PlaneGeometry 기반 장면 구성
- vUv 변수를 통해 vertex shader로부터 UV 좌표 전달
// vertex.glsl
varying vec2 vUv;
void main() {
// ...
vUv = uv;
}
// fragment.glsl
varying vec2 vUv;
void main() {
// vUv 접근 가능
}
🎨 패턴
1) Geometry의 attributes에서 uv 값을 이용하여 색상 패턴 만들기

// vertex.glsl
varying vec2 vUv;
void main()
{
gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
vUv = uv; // 보통 texture를 vertex에 맞게 mapping하기 위해 사용
}
// fragment.glsl
varying vec2 vUv;
void main()
{
gl_FragColor = vec4(vUv.r, vUv.g, 1.0, 1.0);
}
2) blue 값만 변경

// fragment.glsl
varying vec2 vUv;
void main()
{
gl_FragColor = vec4(vUv, 0.0, 1.0);
}
3) (x 축으로 이동할 수록 전체 색상이 1에 가까워지므로) 흑백 패턴 형성

// fragment.glsl
varying vec2 vUv;
void main()
{
gl_FragColor = vec4(vUv.x, vUv.x, vUv.x, 1.0);
}
또는
varying vec2 vUv;
void main()
{
float strength = vUv.x;
gl_FragColor = vec4(strength, strength, strength, 1.0);
}
4) y축으로

// fragment.glsl
varying vec2 vUv;
void main()
{
float strength = vUv.y;
gl_FragColor = vec4(strength, strength, strength, 1.0);
}
5)

// fragment.glsl
varying vec2 vUv;
void main()
{
float strength = 1.0 - vUv.y;
gl_FragColor = vec4(strength, strength, strength, 1.0);
}
6)

// fragment.glsl
varying vec2 vUv;
void main()
{
float strength = vUv.y * 10.0;
gl_FragColor = vec4(strength, strength, strength, 1.0);
}
7) mod(a, b)는 a를 b로 나눈 나머지 === a % b

// fragment.glsl
varying vec2 vUv;
void main()
{
float strength = mod(vUv.y * 10.0, 1.0);
gl_FragColor = vec4(strength, strength, strength, 1.0);
}
8) float step(float edge, float x) edge 기준값, x 비교값
// step 함수
if (x < edge)
return 0.0;
else
return 1.0;

// fragment.glsl
varying vec2 vUv;
void main()
{
float strength = mod(vUv.y * 10.0, 1.0);
// {} 중괄호 없어도 동작함.
if(strength < 0.5) {
strength = 0.0;
} else {
strength = 1.0;
}
// or
strength = strength <= 0.5 ? 0.0 : 1.0;
// or
strength = step(0.5, strength);
gl_FragColor = vec4(strength, strength, strength, 1.0);
}
9) step 기준값 조정

// Pattern 9
float strength = mod(vUv.y * 10.0, 1.0);
strength = step(0.8, strength);
10) vUv x 값으로 변경

// Pattern 10
float strength = mod(vUv.x * 10.0, 1.0);
strength = step(0.8, strength);
11)

// Pattern 11
float strength = step(0.8, mod(vUv.x * 10.0, 1.0));
strength += step(0.8, mod(vUv.y * 10.0, 1.0));
12) *= 으로 교차하는 곳(step이 0.8이므로 나머지 20%)만 값이 1.0이 되도록

// Pattern 12
float strength = step(0.8, mod(vUv.x * 10.0, 1.0));
strength *= step(0.8, mod(vUv.y * 10.0, 1.0));
13) x축 step 조절

// Pattern 13
float strength = step(0.4, mod(vUv.x * 10.0, 1.0));
strength *= step(0.8, mod(vUv.y * 10.0, 1.0));
14) 각각 생성 후 합치기

// Pattern 14
float barX = step(0.4, mod(vUv.x * 10.0, 1.0));
barX *= step(0.8, mod(vUv.y * 10.0, 1.0));
float barY = step(0.8, mod(vUv.x * 10.0, 1.0));
barY *= step(0.4, mod(vUv.y * 10.0, 1.0));
float strength = barX + barY;
gl_FragColor = vec4(strength, strength, strength, 1.0);
15) 위치 조정

// Pattern 15
float barX = step(0.4, mod(vUv.x * 10.0 , 1.0));
barX *= step(0.8, mod(vUv.y * 10.0 + 0.2, 1.0));
float barY = step(0.8, mod(vUv.x * 10.0 + 0.2, 1.0));
barY *= step(0.4, mod(vUv.y * 10.0, 1.0));
float strength = barX + barY;
gl_FragColor = vec4(strength, strength, strength, 1.0);
16)

// Pattern 16
float strength = abs(vUv.x - 0.5);
gl_FragColor = vec4(strength, strength, strength, 1.0);
17) min (abs로 x, y축 모두 대칭 구조로 만들고, min으로 두 값 중 작은 값을 출력한다.)

// Pattern 17
float strength = min(abs(vUv.x - 0.5), abs(vUv.y - 0.5));
gl_FragColor = vec4(strength, strength, strength, 1.0);
18) max

// Pattern 18
float strength = max(abs(vUv.x - 0.5), abs(vUv.y - 0.5));
gl_FragColor = vec4(strength, strength, strength, 1.0);
19)

// Pattern 19
float strength = step(0.2 ,max(abs(vUv.x - 0.5), abs(vUv.y - 0.5)));
gl_FragColor = vec4(strength, strength, strength, 1.0);
20)

// Pattern 20
float square1 = step(0.2 ,max(abs(vUv.x - 0.5), abs(vUv.y - 0.5)));
float square2 = 1.0 - step(0.25 ,max(abs(vUv.x - 0.5), abs(vUv.y - 0.5)));
float strength = square1 * square2;
gl_FragColor = vec4(strength, strength, strength, 1.0);
21)

// Pattern 21
float strength = round(vUv.x * 10.0) / 10.0;
// or
float strength = floor(vUv.x * 10.0) / 10.0;
gl_FragColor = vec4(strength, strength, strength, 1.0);
22)

// Pattern 22
float strength = floor(vUv.x * 10.0) / 10.0;
strength *= floor(vUv.y * 10.0) / 10.0;
gl_FragColor = vec4(strength, strength, strength, 1.0);
23) 난수 생성

// fragment.glsl
varying vec2 vUv;
// Pattern 23
float random(vec2 st){
return fract(sin(dot(st.xy, vec2(12.9898,78.233))) * 43758.5453123);
}
void main()
{
// Pattern 23
float strength = random(vUv);
gl_FragColor = vec4(strength, strength, strength, 1.0);
}
- dot(st.xy, vec2(12.9898, 78.233))
- dot product (내적) → st.x * 12.9898 + st.y * 78.233
- sin(...)
- 사인 함수 → 이걸 쓰면 출력값이 -1.0 ~ +1.0 사이의 복잡한 곡선형 값이 됩니다. → 주기적이면서 예측이 어려운 패턴
- * 43758.5453123
- 큰 수를 곱해 소수점 아래에 많은 변화를 유도 → 사인 결과는 -1 ~ 1 이므로, 곱셈을 통해 값 분산을 넓힘
- fract(...)
- 소수점 이하만 추출 (0.0 ~ 1.0 사이로 잘라냄)→ 결과는 항상 [0.0, 1.0) 범위의 float
- ex) fract(3.1415) == 0.1415, fract(-1.7) == 0.3
24)

// fragment.glsl
varying vec2 vUv;
// Pattern 23
float random(vec2 st){
return fract(sin(dot(st.xy, vec2(12.9898,78.233))) * 43758.5453123);
}
void main()
{
// Pattern 24
vec2 gridUv = vec2(
floor(vUv.x * 10.0) / 10.0, floor(vUv.y * 10.0) / 10.0
);
float strength = random(gridUv);
gl_FragColor = vec4(strength, strength, strength, 1.0);
}
정해진 난수이기 때문에 항상 동일한 패턴이 발생
25) vUv.y + vUv.x * 0.5, vUv.y * 10.0 + vUv.x * 5.0 부분이 기울기를 만듦.


// fragment.glsl
varying vec2 vUv;
// Pattern 23
float random(vec2 st){
return fract(sin(dot(st.xy, vec2(12.9898,78.233))) * 43758.5453123);
}
void main()
{
// Pattern 25
// vec2 gridUv = vec2(
// floor(vUv.x * 10.0) / 10.0, floor((vUv.y + vUv.x * 0.5) * 10.0) / 10.0
// );
vec2 gridUv = vec2(
floor(vUv.x * 10.0) / 10.0, floor(vUv.y * 10.0 + vUv.x * 5.0) / 10.0
);
float strength = random(gridUv);
gl_FragColor = vec4(strength, strength, strength, 1.0);
}
26) length: 길이 계산

// Pattern 26
float strength = length(vUv);
gl_FragColor = vec4(strength, strength, strength, 1.0);
27) distance(거리, 중앙): 거리 계산

// Pattern 27
float strength = distance(vUv, vec2(0.5, 0.5));
// or
float strength = length(vUv - 0.5);
gl_FragColor = vec4(strength, strength, strength, 1.0);
28)

// Pattern 28
float strength = 1.0 - distance(vUv, vec2(0.5));
gl_FragColor = vec4(strength, strength, strength, 1.0);
29)

// Pattern 29
float strength = 0.01 / distance(vUv, vec2(0.5));
gl_FragColor = vec4(strength, strength, strength, 1.0);
30)

// Pattern 30
vec2 lightUv = vec2(vUv.x * 0.1 + 0.45, vUv.y * 0.5 + 0.25);
float strength = 0.015 / distance(lightUv, vec2(0.5, 0.5));
gl_FragColor = vec4(strength, strength, strength, 1.0);
31)

// Pattern 31
vec2 lightUvX = vec2(vUv.x * 0.1 + 0.45, vUv.y * 0.5 + 0.25);
float lightX = 0.015 / distance(lightUvX, vec2(0.5, 0.5));
vec2 lightUvY = vec2(vUv.y * 0.1 + 0.45, vUv.x * 0.5 + 0.25);
float lightY = 0.015 / distance(lightUvY, vec2(0.5, 0.5));
float strength = lightX * lightY;
gl_FragColor = vec4(strength, strength, strength, 1.0);
32)

// fragment.glsl
#define PI 3.1415926535897932384626433832795
varying vec2 vUv;
// Pattern 32
vec2 rotate(vec2 uv, float rotation, vec2 mid)
{
return vec2(
cos(rotation) * (uv.x - mid.x) + sin(rotation) * (uv.y - mid.y) + mid.x,
cos(rotation) * (uv.y - mid.y) - sin(rotation) * (uv.x - mid.x) + mid.y
);
}
void main()
{
// Pattern 32
// vec2 rotatedUv = rotate(vUv, 0.5, vec2(0.5));
// or
vec2 rotatedUv = rotate(vUv, PI * 0.25, vec2(0.5));
vec2 lightUvX = vec2(rotatedUv.x * 0.1 + 0.45, rotatedUv.y * 0.5 + 0.25);
float lightX = 0.015 / distance(lightUvX, vec2(0.5, 0.5));
vec2 lightUvY = vec2(rotatedUv.y * 0.1 + 0.45, rotatedUv.x * 0.5 + 0.25);
float lightY = 0.015 / distance(lightUvY, vec2(0.5, 0.5));
float strength = lightX * lightY;
gl_FragColor = vec4(strength, strength, strength, 1.0);
}
33)

// Pattern 33
float strength = step(0.25, distance(vUv, vec2(0.5)));
gl_FragColor = vec4(strength, strength, strength, 1.0);
34)

// Pattern 34
float strength = abs(distance(vUv, vec2(0.5)) - 0.25);
gl_FragColor = vec4(strength, strength, strength, 1.0);
35)

// Pattern 35
float strength = step(0.01, abs(distance(vUv, vec2(0.5)) - 0.25));
gl_FragColor = vec4(strength, strength, strength, 1.0);
36)

// Pattern 36
float strength = 1.0 - step(0.01, abs(distance(vUv, vec2(0.5)) - 0.25));
gl_FragColor = vec4(strength, strength, strength, 1.0);
37)

// Pattern 37
vec2 wavedUv = vec2(vUv.x, vUv.y + sin(vUv.x * 30.0) * 0.1);
float strength = 1.0 - step(0.01, abs(distance(wavedUv, vec2(0.5)) - 0.25));
gl_FragColor = vec4(strength, strength, strength, 1.0);
38)

// Pattern 38
vec2 wavedUv = vec2(vUv.x + sin(vUv.y * 30.0) * 0.1, vUv.y + sin(vUv.x * 30.0) * 0.1);
float strength = 1.0 - step(0.01, abs(distance(wavedUv, vec2(0.5)) - 0.25));
gl_FragColor = vec4(strength, strength, strength, 1.0);
39)

// Pattern 39
vec2 wavedUv = vec2(vUv.x + sin(vUv.y * 100.0) * 0.1, vUv.y + sin(vUv.x * 100.0) * 0.1);
float strength = 1.0 - step(0.01, abs(distance(wavedUv, vec2(0.5)) - 0.25));
gl_FragColor = vec4(strength, strength, strength, 1.0);
40) atan 각도

// Pattern 40
float angle = atan(vUv.x, vUv.y);
float strength = angle;
gl_FragColor = vec4(strength, strength, strength, 1.0);
41) - 0.5 씩이므로 중앙을 기준으로 40과 같은 형태를 띈다.

// Pattern 41
float angle = atan(vUv.x - 0.5, vUv.y - 0.5);
float strength = angle;
gl_FragColor = vec4(strength, strength, strength, 1.0);
42)

// Pattern 42
float angle = atan(vUv.x - 0.5, vUv.y - 0.5) / (PI * 2.0) + 0.5;
float strength = angle;
gl_FragColor = vec4(strength, strength, strength, 1.0);
- vUv.x - 0.5, vUv.y - 0.5
- UV 좌표계를 (0,0) ~ (1,1) 범위에서 **중심 기준인 (-0.5, -0.5) ~ (+0.5, +0.5)**로 이동
- 즉, vec2(0.5, 0.5)를 원점(0,0)처럼 생각하고 회전 기준점으로 만듦
- atan(x, y) → 각도 계산
- atan(y, x)는 2D 좌표에서 (0,0)을 기준으로 한 벡터의 방향(각도)을 반환
- 출력 범위는 -π ~ +π 라디안
- 360도 회전하는 값을 -180° ~ +180° 식으로 표현한 셈
- angle / (PI * 2.0) + 0.5
- -π ~ +π를 0.0 ~ 1.0 범위로 정규화 (normalize)
- angle / (2π) → -0.5 ~ +0.5
- + 0.5 → 0.0 ~ 1.0
- 이렇게 하면 한 바퀴 회전하는 값을 UV 색상이나 강도로 표현 가능
43)

// Pattern 43
float angle = atan(vUv.x - 0.5, vUv.y - 0.5) / (PI * 2.0) + 0.5;
float strength = mod(angle * 20.0, 1.0);
gl_FragColor = vec4(strength, strength, strength, 1.0);
44)

// Pattern 44
float angle = atan(vUv.x - 0.5, vUv.y - 0.5) / (PI * 2.0) + 0.5;
float strength = sin(angle * 100.0);
gl_FragColor = vec4(strength, strength, strength, 1.0);
45)

// Pattern 45
float angle = atan(vUv.x - 0.5, vUv.y - 0.5) / (PI * 2.0) + 0.5;
float sinusoid = sin(angle * 100.0);
float radius = 0.25 + sinusoid * 0.02;
float strength = 1.0 - step(0.01, abs(distance(vUv, vec2(0.5)) - radius));
gl_FragColor = vec4(strength, strength, strength, 1.0);
46)

// fragment.glsl
#define PI 3.1415926535897932384626433832795
varying vec2 vUv;
// Pattern 46
// Classic Perlin 2D Noise
// by Stefan Gustavson (https://github.com/stegu/webgl-noise)
//
vec4 permute(vec4 x)
{
return mod(((x*34.0)+1.0)*x, 289.0);
}
vec2 fade(vec2 t) {return t*t*t*(t*(t*6.0-15.0)+10.0);}
float cnoise(vec2 P){
vec4 Pi = floor(P.xyxy) + vec4(0.0, 0.0, 1.0, 1.0);
vec4 Pf = fract(P.xyxy) - vec4(0.0, 0.0, 1.0, 1.0);
Pi = mod(Pi, 289.0); // To avoid truncation effects in permutation
vec4 ix = Pi.xzxz;
vec4 iy = Pi.yyww;
vec4 fx = Pf.xzxz;
vec4 fy = Pf.yyww;
vec4 i = permute(permute(ix) + iy);
vec4 gx = 2.0 * fract(i * 0.0243902439) - 1.0; // 1/41 = 0.024...
vec4 gy = abs(gx) - 0.5;
vec4 tx = floor(gx + 0.5);
gx = gx - tx;
vec2 g00 = vec2(gx.x,gy.x);
vec2 g10 = vec2(gx.y,gy.y);
vec2 g01 = vec2(gx.z,gy.z);
vec2 g11 = vec2(gx.w,gy.w);
vec4 norm = 1.79284291400159 - 0.85373472095314 *
vec4(dot(g00, g00), dot(g01, g01), dot(g10, g10), dot(g11, g11));
g00 *= norm.x;
g01 *= norm.y;
g10 *= norm.z;
g11 *= norm.w;
float n00 = dot(g00, vec2(fx.x, fy.x));
float n10 = dot(g10, vec2(fx.y, fy.y));
float n01 = dot(g01, vec2(fx.z, fy.z));
float n11 = dot(g11, vec2(fx.w, fy.w));
vec2 fade_xy = fade(Pf.xy);
vec2 n_x = mix(vec2(n00, n01), vec2(n10, n11), fade_xy.x);
float n_xy = mix(n_x.x, n_x.y, fade_xy.y);
return 2.3 * n_xy;
}
void main()
{
// Pattern 46
float strength = cnoise(vUv * 10.0);
gl_FragColor = vec4(strength, strength, strength, 1.0);
}
47)

// Pattern 47
float strength = step(0.0, cnoise(vUv * 10.0));
gl_FragColor = vec4(strength, strength, strength, 1.0);
48)

// Pattern 48
float strength = 1.0 - abs(cnoise(vUv * 10.0));
gl_FragColor = vec4(strength, strength, strength, 1.0);
49)

// Pattern 49
float strength = sin(cnoise(vUv * 10.0) * 20.0);
gl_FragColor = vec4(strength, strength, strength, 1.0);
50)

// Pattern 50
float strength = step(0.9, sin(cnoise(vUv * 10.0) * 20.0));
gl_FragColor = vec4(strength, strength, strength, 1.0);
번호 | 설명 | 핵심 | 개념
| 1 | RGB = (x, y, 1.0) | gl_FragColor = vec4(vUv, 1.0, 1.0) |
| 2 | RGB = (x, y, 0.0) | Blue 제거 |
| 3 | Grayscale X축 | strength = vUv.x |
| 4 | Grayscale Y축 | strength = vUv.y |
| 5 | Y축 반전 | strength = 1.0 - vUv.y |
| 6 | Gradient 확대 | strength = vUv.y * 10.0 |
| 7 | 반복되는 gradient | mod(...) 활용 |
| 8~9 | Step 함수를 이용한 흑백 스트라이프 | step(edge, value) |
| 10~15 | X, Y축 조합, offset 조절 | step, mod, +=, *=, clamp |
| 16~20 | 대칭, 중심 거리, 박스/라이트 | abs, length, distance |
| 21~25 | 격자화, tilt, 의사 랜덤 | floor, random, vec2(floor(...)) |
| 26~31 | 거리 기반 밝기, 중앙 집중 | distance, 0.15 / distance(...) |
| 32 | UV 회전 | 사용자 정의 rotate() 함수 |
| 33~36 | 원, 도넛, 링 만들기 | distance, abs, step 조합 |
| 37~39 | 웨이브 왜곡 | sin(...)으로 UV 조작 |
| 40~45 | 각도 기반 패턴 | atan, mod, sin |
| 46~50 | Perlin Noise 및 조합 | cnoise, sin(cnoise(...)), step(...) |
🎛️ 색상 혼합



단색 대신 색상 보간을 위해 mix(...) 함수 사용:
vec3 blackColor = vec3(0.0);
vec3 uvColor = vec3(vUv, 1.0);
vec3 mixedColor = mix(blackColor, uvColor, strength);
gl_FragColor = vec4(mixedColor, 1.0);
⚠️ 일부 패턴에서는 strength가 1.0을 초과할 수 있으므로 clamp(strength, 0.0, 1.0) 처리 필요
GLSL 함수 모음
| mod(a, b) | a를 b로 나눈 나머지 |
| step(edge, x) | x < edge: 0.0, x >= edge: 1.0 |
| length(vec) | 벡터의 길이 계산 |
| distance(a, b) | 두 벡터 사이 거리 |
| abs(x) | 절대값 |
| sin(x) | 사인 곡선 (웨이브 표현 등) |
| atan(y, x) | y/x의 아크탄젠트 (각도) |
| floor(x) | 내림 |
| mix(a, b, t) | 보간 (0: a, 1: b) |
| clamp(x, min, max) | 범위 제한 |
🌀 Perlin Noise
- Classic Perlin Noise 함수 정의 필요
- cnoise(vec2) 사용 전 permute, fade 함수 포함 필요
float strength = cnoise(vUv * 10.0);
활용 예시 효과
| step(0.0, cnoise(...)) | 젖소 무늬 스타일 패턴 |
| 1.0 - abs(...) | 밝은 중심, 어두운 테두리 |
| sin(cnoise(...) * 20.0) | 전기, 불꽃 같은 패턴 |
🔗 참고: Book of Shaders - Noise
🧪 연습 팁
- 각 패턴을 주석 처리하면서 실험할 것
- uTime 같은 uniform을 추가해 움직이는 패턴을 만들어 볼 것
- getCircle(), getSquare() 같은 재사용 함수로 추출하는 연습하기

// fragment.glsl
#define PI 3.1415926535897932384626433832795
varying vec2 vUv;
// Pattern 23
float random(vec2 st){
return fract(sin(dot(st.xy, vec2(12.9898,78.233))) * 43758.5453123);
}
// Pattern 32
vec2 rotate(vec2 uv, float rotation, vec2 mid)
{
return vec2(
cos(rotation) * (uv.x - mid.x) + sin(rotation) * (uv.y - mid.y) + mid.x,
cos(rotation) * (uv.y - mid.y) - sin(rotation) * (uv.x - mid.x) + mid.y
);
}
// Pattern 46
// Classic Perlin 2D Noise
// by Stefan Gustavson (https://github.com/stegu/webgl-noise)
//
vec4 permute(vec4 x)
{
return mod(((x*34.0)+1.0)*x, 289.0);
}
vec2 fade(vec2 t) {return t*t*t*(t*(t*6.0-15.0)+10.0);}
float cnoise(vec2 P){
vec4 Pi = floor(P.xyxy) + vec4(0.0, 0.0, 1.0, 1.0);
vec4 Pf = fract(P.xyxy) - vec4(0.0, 0.0, 1.0, 1.0);
Pi = mod(Pi, 289.0); // To avoid truncation effects in permutation
vec4 ix = Pi.xzxz;
vec4 iy = Pi.yyww;
vec4 fx = Pf.xzxz;
vec4 fy = Pf.yyww;
vec4 i = permute(permute(ix) + iy);
vec4 gx = 2.0 * fract(i * 0.0243902439) - 1.0; // 1/41 = 0.024...
vec4 gy = abs(gx) - 0.5;
vec4 tx = floor(gx + 0.5);
gx = gx - tx;
vec2 g00 = vec2(gx.x,gy.x);
vec2 g10 = vec2(gx.y,gy.y);
vec2 g01 = vec2(gx.z,gy.z);
vec2 g11 = vec2(gx.w,gy.w);
vec4 norm = 1.79284291400159 - 0.85373472095314 *
vec4(dot(g00, g00), dot(g01, g01), dot(g10, g10), dot(g11, g11));
g00 *= norm.x;
g01 *= norm.y;
g10 *= norm.z;
g11 *= norm.w;
float n00 = dot(g00, vec2(fx.x, fy.x));
float n10 = dot(g10, vec2(fx.y, fy.y));
float n01 = dot(g01, vec2(fx.z, fy.z));
float n11 = dot(g11, vec2(fx.w, fy.w));
vec2 fade_xy = fade(Pf.xy);
vec2 n_x = mix(vec2(n00, n01), vec2(n10, n11), fade_xy.x);
float n_xy = mix(n_x.x, n_x.y, fade_xy.y);
return 2.3 * n_xy;
}
void main()
{
// Pattern 3
// float strength = vUv.x;
// Pattern 4
// float strength = vUv.y;
// Pattern 5
// float strength = 1.0 - vUv.y;
// Pattern 6
// float strength = vUv.y * 10.0;
// Pattern 7
// float strength = mod(vUv.y * 10.0, 1.0);
// Pattern 8
// float strength = mod(vUv.y * 10.0, 1.0);
// strength = strength <= 0.5 ? 0.0 : 1.0;
// strength = step(0.5, strength);
// Pattern 9
// float strength = mod(vUv.y * 10.0, 1.0);
// strength = step(0.8, strength);
// Pattern 10
// float strength = mod(vUv.x * 10.0, 1.0);
// strength = step(0.8, strength);
// Pattern 11
// float strength = step(0.8, mod(vUv.x * 10.0, 1.0));
// strength += step(0.8, mod(vUv.y * 10.0, 1.0));
// Pattern 12
// float strength = step(0.8, mod(vUv.x * 10.0, 1.0));
// strength *= step(0.8, mod(vUv.y * 10.0, 1.0));
// Pattern 13
// float strength = step(0.4, mod(vUv.x * 10.0, 1.0));
// strength *= step(0.8, mod(vUv.y * 10.0, 1.0));
// Pattern 14
// float barX = step(0.4, mod(vUv.x * 10.0, 1.0));
// barX *= step(0.8, mod(vUv.y * 10.0, 1.0));
// float barY = step(0.8, mod(vUv.x * 10.0, 1.0));
// barY *= step(0.4, mod(vUv.y * 10.0, 1.0));
// float strength = barX + barY;
// Pattern 15
// float barX = step(0.4, mod(vUv.x * 10.0 , 1.0));
// barX *= step(0.8, mod(vUv.y * 10.0 + 0.2, 1.0));
// float barY = step(0.8, mod(vUv.x * 10.0 + 0.2, 1.0));
// barY *= step(0.4, mod(vUv.y * 10.0, 1.0));
// float strength = barX + barY;
// Pattern 16
// float strength = abs(vUv.x - 0.5);
// Pattern 17
// float strength = min(abs(vUv.x - 0.5), abs(vUv.y - 0.5));
// Pattern 18
// float strength = max(abs(vUv.x - 0.5), abs(vUv.y - 0.5));
// Pattern 19
// float strength = step(0.2 ,max(abs(vUv.x - 0.5), abs(vUv.y - 0.5)));
// Pattern 20
// float square1 = step(0.2 ,max(abs(vUv.x - 0.5), abs(vUv.y - 0.5)));
// float square2 = 1.0 - step(0.25 ,max(abs(vUv.x - 0.5), abs(vUv.y - 0.5)));
// float strength = square1 * square2;
// Pattern 21
// float strength = round(vUv.x * 10.0) / 10.0;
// Pattern 22
// float strength = floor(vUv.x * 10.0) / 10.0;
// strength *= floor(vUv.y * 10.0) / 10.0;
// Pattern 23
// float strength = random(vUv);
// Pattern 24
// vec2 gridUv = vec2(
// floor(vUv.x * 10.0) / 10.0, floor(vUv.y * 10.0) / 10.0
// );
// float strength = random(gridUv);
// Pattern 25
// vec2 gridUv = vec2(
// floor(vUv.x * 10.0) / 10.0, floor(vUv.y * 10.0 + vUv.x * 5.0) / 10.0
// );
// float strength = random(gridUv);
// Pattern 26
// float strength = length(vUv);
// Pattern 27
// float strength = distance(vUv, vec2(0.5, 0.5));
// float strength = length(vUv - 0.5);
// Pattern 28
// float strength = 1.0 - distance(vUv, vec2(0.5));
// Pattern 29
// float strength = 0.01 / distance(vUv, vec2(0.5));
// Pattern 30
// vec2 lightUv = vec2(vUv.x * 0.1 + 0.45, vUv.y * 0.5 + 0.25);
// float strength = 0.015 / distance(lightUv, vec2(0.5, 0.5));
// Pattern 31
// vec2 lightUvX = vec2(vUv.x * 0.1 + 0.45, vUv.y * 0.5 + 0.25);
// float lightX = 0.015 / distance(lightUvX, vec2(0.5, 0.5));
// vec2 lightUvY = vec2(vUv.y * 0.1 + 0.45, vUv.x * 0.5 + 0.25);
// float lightY = 0.015 / distance(lightUvY, vec2(0.5, 0.5));
// float strength = lightX * lightY;
// Pattern 32
// vec2 rotatedUv = rotate(vUv, PI * 0.25, vec2(0.5));
// vec2 lightUvX = vec2(rotatedUv.x * 0.1 + 0.45, rotatedUv.y * 0.5 + 0.25);
// float lightX = 0.015 / distance(lightUvX, vec2(0.5, 0.5));
// vec2 lightUvY = vec2(rotatedUv.y * 0.1 + 0.45, rotatedUv.x * 0.5 + 0.25);
// float lightY = 0.015 / distance(lightUvY, vec2(0.5, 0.5));
// float strength = lightX * lightY;
// Pattern 33
// float strength = step(0.25, distance(vUv, vec2(0.5)));
// Pattern 34
// float strength = abs(distance(vUv, vec2(0.5)) - 0.25);
// Pattern 35
// float strength = step(0.01, abs(distance(vUv, vec2(0.5)) - 0.25));
// Pattern 36
// float strength = 1.0 - step(0.01, abs(distance(vUv, vec2(0.5)) - 0.25));
// Pattern 37
// vec2 wavedUv = vec2(vUv.x, vUv.y + sin(vUv.x * 30.0) * 0.1);
// float strength = 1.0 - step(0.01, abs(distance(wavedUv, vec2(0.5)) - 0.25));
// Pattern 38
// vec2 wavedUv = vec2(vUv.x + sin(vUv.y * 30.0) * 0.1, vUv.y + sin(vUv.x * 30.0) * 0.1);
// float strength = 1.0 - step(0.01, abs(distance(wavedUv, vec2(0.5)) - 0.25));
// Pattern 39
// vec2 wavedUv = vec2(vUv.x + sin(vUv.y * 30.0) * 0.1, vUv.y + sin(vUv.x * 30.0) * 0.1);
// float strength = 1.0 - step(0.01, abs(distance(wavedUv, vec2(0.5)) - 0.25));
// Pattern 40
// float angle = atan(vUv.x, vUv.y);
// float strength = angle;
// Pattern 41
// float angle = atan(vUv.x - 0.5, vUv.y - 0.5);
// float strength = angle;
// Pattern 42
// float angle = atan(vUv.x - 0.5, vUv.y - 0.5) / (PI * 2.0) + 0.5;
// float strength = angle;
// Pattern 43
// float angle = atan(vUv.x - 0.5, vUv.y - 0.5) / (PI * 2.0) + 0.5;
// float strength = mod(angle * 20.0, 1.0);
// Pattern 44
// float angle = atan(vUv.x - 0.5, vUv.y - 0.5) / (PI * 2.0) + 0.5;
// float strength = sin(angle * 100.0);
// Pattern 45
// float angle = atan(vUv.x - 0.5, vUv.y - 0.5) / (PI * 2.0) + 0.5;
// float sinusoid = sin(angle * 100.0);
// float radius = 0.25 + sinusoid * 0.02;
// float strength = 1.0 - step(0.01, abs(distance(vUv, vec2(0.5)) - radius));
// Pattern 46
// float strength = cnoise(vUv * 10.0);
// Pattern 47
// float strength = step(0.0, cnoise(vUv * 10.0));
// Pattern 48
// float strength = 1.0 - abs(cnoise(vUv * 10.0));
// Pattern 49
// float strength = sin(cnoise(vUv * 10.0) * 20.0);
// Pattern 50
// float strength = step(0.9, sin(cnoise(vUv * 10.0) * 20.0));
// Black and white version
// gl_FragColor = vec4(strength, strength, strength, 1.0);
// Colored version
// Pattern 11
float strength = step(0.8, mod(vUv.x * 10.0, 1.0));
strength += step(0.8, mod(vUv.y * 10.0, 1.0));
strength = clamp(strength, 0.0, 1.0); // 범위 제한
vec3 blackColor = vec3(0.0);
vec3 uvColor = vec3(vUv, 1.0);
vec3 mixedColor = mix(blackColor, uvColor, strength);
gl_FragColor = vec4(mixedColor, 1.0);
}
// vertex.glsl
varying vec2 vUv;
void main()
{
gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
vUv = uv; // 보통 texture를 vertex에 맞게 mapping하기 위해 사용
}'Graphic > ThreeJS' 카테고리의 다른 글
| 30 Animated galaxy (5) | 2025.08.05 |
|---|---|
| 29 Animated Water Shader (2) | 2025.08.04 |
| 27 Shaders (5) | 2025.08.02 |
| 26. 프로젝트 구조화(Code structuring for bigger projects) (4) | 2025.08.02 |
| 25 Realistic render (2) | 2025.07.31 |