셰이딩 (Shading)
1. 개요
셰이딩(Shading)이란 3D 컴퓨터 그래픽스에서 빛과 물체 표면의 상호작용을 계산하여 각 픽셀의 색상과 밝기를 결정함으로써, 평면적인 폴리곤 모델에 입체감과 질감을 부여하는 렌더링 공정을 말한다. 렌더링 파이프라인의 후반 단계에서 수행되며, 광원의 위치, 표면의 각도, 재질의 특성 등을 수학적으로 계산하여 최종 화면에 출력될 색상을 산출하는 핵심적인 역할을 한다.
2. 셰이딩의 기본 원리
셰이딩의 핵심은 빛이 표면에 닿았을 때 어떻게 반사되는지를 시뮬레이션하는 것이다. 이를 위해 다음과 같은 벡터 정보가 사용된다.
- 광원 벡터(Light Vector): 표면의 한 점에서 광원을 향하는 방향 벡터.
- 법선 벡터(Normal Vector): 표면의 각 점에서 표면에 수직인 단위 벡터. 표면의 기울기를 결정하며, 특히 광원 벡터와 법선 벡터 사이의 각도를 계산하는 내적(Dot Product) 연산은 셰이딩의 밝기를 결정하는 핵심 요소가 된다.
- 시점 벡터(View Vector): 표면의 한 점에서 카메라(관찰자)를 향하는 방향 벡터.
빛의 반사 모델 (Phong Reflection Model 기초)
전통적인 셰이딩은 빛을 크게 세 가지 성분으로 나누어 계산한다.
| 성분 |
명칭 |
특징 |
시각적 효과 |
| Ambient |
환경광 |
모든 방향에서 균일하게 들어오는 간접광을 모사 |
그림자 영역이 완전히 검게 변하는 것을 방지 |
| Diffuse |
난반사광 |
표면의 거칠기로 인해 모든 방향으로 균일하게 산란되는 빛 |
물체의 기본적인 색상과 입체감(명암) 형성 |
| Specular |
정반사광 |
매끄러운 표면에서 특정 방향으로 강하게 반사되는 빛 |
금속이나 유리 표면의 '하이라이트' 광택 표현 |
3. 주요 셰이딩 기법
셰이딩 기법은 계산을 수행하는 단위(정점 vs 픽셀)와 보간 방식에 따라 발전해 왔다.
3.1 플랫 셰이딩 (Flat Shading)
폴리곤(삼각형/사각형) 하나당 하나의 법선 벡터만을 사용하여 단일 색상을 칠하는 방식이다. 계산량이 매우 적으나, 폴리곤의 경계가 뚜렷하게 보여 표면이 각져 보이는 단점이 있다.
* 그림 1: 플랫 셰이딩이 적용된 구체 (폴리곤 경계가 뚜렷함)
3.2 구로 셰이딩 (Gouraud Shading)
각 정점(Vertex)에서 조명 계산을 수행한 뒤, 폴리곤 내부의 픽셀들은 정점 간의 색상을 선형 보간(Linear Interpolation)하여 채우는 방식이다. 플랫 셰이딩보다 부드럽게 보이지만, 하이라이트(Specular) 부분이 뭉개지거나 사라지는 현상이 발생한다.
* 그림 2: 구로 셰이딩이 적용된 구체 (부드러운 표면이나 하이라이트 경계가 흐릿함)
3.3 퐁 셰이딩 (Phong Shading)
색상이 아닌 법선 벡터 자체를 픽셀 단위로 보간한 뒤, 모든 픽셀에서 개별적으로 조명 계산을 수행하는 방식이다. 계산량은 많지만, 매우 정교한 하이라이트 표현이 가능하여 매끄러운 표면 묘사에 적합하다.
수학적 계산식:
최종 색상 $I$는 다음과 같이 계산된다.
$$I = k_a I_a + k_d (L \cdot N) I_d + k_s (R \cdot V)^n I_s$$
(단, $k$는 계수, $I$는 빛의 강도, $L$은 광원 벡터, $N$은 법선 벡터, $R$은 반사 벡터, $V$는 시점 벡터, $n$은 광택 지수)
- 그림 3: 퐁 셰이딩이 적용된 구체 (매끄러운 광택과 뚜렷하고 정교한 하이라이트)
참고: 블린-퐁(Blinn-Phong) 셰이딩
실제 산업계에서는 퐁 셰이딩보다 계산 효율이 좋은 블린-퐁 방식이 더 널리 쓰인다. 이는 반사 벡터($R$)를 직접 계산하는 대신, 광원 벡터와 시점 벡터의 중간 방향인 하프웨이 벡터(Halfway Vector)를 사용하여 계산량을 줄이면서도 유사한 시각적 효과를 낸다.
4. 현대적 셰이딩 모델 (PBR)
물리 기반 렌더링(Physically Based Rendering, PBR)은 빛의 물리적 성질을 수학적으로 모델링하여 어떤 조명 환경에서도 일관된 사실감을 제공하는 현대적인 셰이딩 방식이다.
PBR의 핵심 원칙
- 에너지 보존 법칙: 표면에서 반사되는 빛의 총량은 입사된 빛의 총량을 초과할 수 없다. (Diffuse와 Specular의 합 $\le$ 입사광)
- 미세면 이론(Microfacet Theory): 모든 표면은 미세한 거울들로 이루어져 있다고 가정하며, 이 미세면들의 정렬 상태에 따라 거칠기를 표현한다.
- BRDF (Bidirectional Reflectance Distribution Function): '양방향 반사 분포 함수'로, 특정 방향에서 들어온 빛이 표면에서 어느 방향으로 얼마나 반사되는지를 정의하는 함수이다. PBR은 이 BRDF를 통해 재질의 물리적 특성을 수학적으로 정밀하게 묘사한다.
주요 맵(Map) 파라미터
- Metallic (금속성): 재질이 전도체(금속)인지 부도체(비금속)인지 결정한다. 금속은 반사광의 색상이 표면색의 영향을 강하게 받는다.
- Roughness (거칠기): 표면의 매끄러운 정도를 결정한다. 값이 낮을수록 거울처럼 선명하게 반사되고, 높을수록 빛이 넓게 퍼진다.
퐁 셰이딩 vs PBR 비교
| 구분 |
퐁 셰이딩 (Phong) |
PBR (Physically Based) |
| 접근 방식 |
경험적/시각적 근사치 (Empirical) |
물리 법칙 기반 (Physical) |
| 빛의 계산 |
단순 합산 (Ambient + Diffuse + Specular) |
에너지 보존 및 BRDF 사용 |
| 재질 표현 |
Specular Power 등 임의의 수치 조절 |
Metallic, Roughness 등 물리적 속성 정의 |
| 일관성 |
조명 환경이 바뀌면 재질 설정 수정 필요 |
다양한 환경(HDRI 등)에서 일관된 외형 유지 |
5. 셰이더 언어와 구현
셰이더(Shader)란 GPU(그래픽 처리 장치)에서 실행되는 작은 프로그램으로, 렌더링 파이프라인의 특정 단계에서 데이터를 처리한다.
셰이더 파이프라인 흐름
- Vertex Data: 모델의 정점 정보 입력
- Vertex Shader: 정점 좌표 변환 및 데이터 전달
- Primitive Assembly: 정점을 연결하여 폴리곤 생성
- Rasterizer: 폴리곤을 픽셀 단위로 분할
- Fragment/Pixel Shader: 각 픽셀의 최종 색상 계산 (조명, 텍스처링)
- Frame Buffer: 최종 결과물을 화면에 출력
주요 셰이더 종류 및 언어
- 정점 셰이더 (Vertex Shader): 3D 공간의 정점 좌표를 2D 화면 좌표로 변환하고, 법선 벡터 등을 전달한다.
- 픽셀/프래그먼트 셰이더 (Pixel/Fragment Shader): 래스터화된 각 픽셀의 최종 색상을 계산한다. 조명, 텍스처링, 그림자 처리가 여기서 이루어진다.
- 대표 언어:
- HLSL (High-Level Shading Language): DirectX 환경
- GLSL (OpenGL Shading Language): OpenGL, Vulkan 환경
- MSL (Metal Shading Language): Apple Metal 환경
GLSL 기본 조명 계산 예제 (Fragment Shader)
#version 330 core
out vec4 FragColor;
in vec3 FragPos; // 정점 셰이더에서 전달된 픽셀 위치
in vec3 Normal; // 정점 셰이더에서 전달된 법선 벡터
uniform vec3 lightPos; // 광원 위치
uniform vec3 viewPos; // 카메라 위치
uniform vec3 lightColor;
void main() {
// 1. Diffuse 계산 (Lambertian)
vec3 norm = normalize(Normal);
vec3 lightDir = normalize(lightPos - FragPos);
float diff = max(dot(norm, lightDir), 0.0);
vec3 diffuse = diff * lightColor;
// 2. Specular 계산 (Phong)
vec3 viewDir = normalize(viewPos - FragPos);
vec3 reflectDir = reflect(-lightDir, norm);
float spec = pow(max(dot(viewDir, reflectDir), 0.0), 32); // 32는 광택 강도
vec3 specular = spec * lightColor;
// 최종 색상 조합 (Ambient 0.1 가정)
vec3 result = (0.1 + diffuse + specular) * vec3(1.0, 0.5, 0.31); // 표면색 적용
FragColor = vec4(result, 1.0);
}
6. 응용 및 최적화
실시간 렌더링 최적화
모든 픽셀에서 복잡한 물리 계산을 수행하는 것은 비용이 매우 크다. 이를 위해 다음과 같은 기법이 사용된다.
* 라이트맵(Lightmap): 정적인 조명 정보를 텍스처에 미리 구워(Baking) 런타임 계산량을 줄인다.
* 지연 셰이딩(Deferred Shading): 기하 정보(법선, 색상, 깊이)를 G-버퍼에 먼저 저장한 뒤, 화면에 보이는 픽셀에 대해서만 조명 계산을 수행하여 광원 개수를 획기적으로 늘린다.
비실사 렌더링 (NPR, Non-Photorealistic Rendering)
물리적 정확성보다는 예술적 스타일을 강조하는 기법이다.
* 툰 셰이딩 (Cel Shading): 빛의 단계(Step)를 강제로 나누어 만화처럼 단순한 색면으로 표현하고, 외곽선을 추가하여 2D 애니메이션 느낌을 구현한다.
* 해칭(Hatching): 선의 밀도를 조절하여 명암을 표현하는 스케치 스타일의 셰이딩이다.
# 셰이딩 (Shading)
## 1. 개요
셰이딩(Shading)이란 3D 컴퓨터 그래픽스에서 빛과 물체 표면의 상호작용을 계산하여 각 픽셀의 색상과 밝기를 결정함으로써, 평면적인 폴리곤 모델에 입체감과 질감을 부여하는 렌더링 공정을 말한다. 렌더링 파이프라인의 후반 단계에서 수행되며, 광원의 위치, 표면의 각도, 재질의 특성 등을 수학적으로 계산하여 최종 화면에 출력될 색상을 산출하는 핵심적인 역할을 한다.
## 2. 셰이딩의 기본 원리
셰이딩의 핵심은 빛이 표면에 닿았을 때 어떻게 반사되는지를 시뮬레이션하는 것이다. 이를 위해 다음과 같은 벡터 정보가 사용된다.
* **광원 벡터(Light Vector):** 표면의 한 점에서 광원을 향하는 방향 벡터.
* **법선 벡터(Normal Vector):** 표면의 각 점에서 표면에 수직인 단위 벡터. 표면의 기울기를 결정하며, 특히 광원 벡터와 법선 벡터 사이의 각도를 계산하는 **내적(Dot Product)** 연산은 셰이딩의 밝기를 결정하는 핵심 요소가 된다.
* **시점 벡터(View Vector):** 표면의 한 점에서 카메라(관찰자)를 향하는 방향 벡터.
### 빛의 반사 모델 (Phong Reflection Model 기초)
전통적인 셰이딩은 빛을 크게 세 가지 성분으로 나누어 계산한다.
| 성분 | 명칭 | 특징 | 시각적 효과 |
| :--- | :--- | :--- | :--- |
| **Ambient** | 환경광 | 모든 방향에서 균일하게 들어오는 간접광을 모사 | 그림자 영역이 완전히 검게 변하는 것을 방지 |
| **Diffuse** | 난반사광 | 표면의 거칠기로 인해 모든 방향으로 균일하게 산란되는 빛 | 물체의 기본적인 색상과 입체감(명암) 형성 |
| **Specular** | 정반사광 | 매끄러운 표면에서 특정 방향으로 강하게 반사되는 빛 | 금속이나 유리 표면의 '하이라이트' 광택 표현 |
## 3. 주요 셰이딩 기법
셰이딩 기법은 계산을 수행하는 단위(정점 vs 픽셀)와 보간 방식에 따라 발전해 왔다.
### 3.1 플랫 셰이딩 (Flat Shading)
폴리곤(삼각형/사각형) 하나당 하나의 법선 벡터만을 사용하여 단일 색상을 칠하는 방식이다. 계산량이 매우 적으나, 폴리곤의 경계가 뚜렷하게 보여 표면이 각져 보이는 단점이 있다.
* **그림 1:** 플랫 셰이딩이 적용된 구체 (폴리곤 경계가 뚜렷함)
### 3.2 구로 셰이딩 (Gouraud Shading)
각 정점(Vertex)에서 조명 계산을 수행한 뒤, 폴리곤 내부의 픽셀들은 정점 간의 색상을 선형 보간(Linear Interpolation)하여 채우는 방식이다. 플랫 셰이딩보다 부드럽게 보이지만, 하이라이트(Specular) 부분이 뭉개지거나 사라지는 현상이 발생한다.
* **그림 2:** 구로 셰이딩이 적용된 구체 (부드러운 표면이나 하이라이트 경계가 흐릿함)
### 3.3 퐁 셰이딩 (Phong Shading)
색상이 아닌 법선 벡터 자체를 픽셀 단위로 보간한 뒤, 모든 픽셀에서 개별적으로 조명 계산을 수행하는 방식이다. 계산량은 많지만, 매우 정교한 하이라이트 표현이 가능하여 매끄러운 표면 묘사에 적합하다.
**수학적 계산식:**
최종 색상 $I$는 다음과 같이 계산된다.
$$I = k_a I_a + k_d (L \cdot N) I_d + k_s (R \cdot V)^n I_s$$
*(단, $k$는 계수, $I$는 빛의 강도, $L$은 광원 벡터, $N$은 법선 벡터, $R$은 반사 벡터, $V$는 시점 벡터, $n$은 광택 지수)*
* **그림 3:** 퐁 셰이딩이 적용된 구체 (매끄러운 광택과 뚜렷하고 정교한 하이라이트)
**참고: 블린-퐁(Blinn-Phong) 셰이딩**
실제 산업계에서는 퐁 셰이딩보다 계산 효율이 좋은 블린-퐁 방식이 더 널리 쓰인다. 이는 반사 벡터($R$)를 직접 계산하는 대신, 광원 벡터와 시점 벡터의 중간 방향인 **하프웨이 벡터(Halfway Vector)**를 사용하여 계산량을 줄이면서도 유사한 시각적 효과를 낸다.
## 4. 현대적 셰이딩 모델 (PBR)
**물리 기반 렌더링(Physically Based Rendering, PBR)**은 빛의 물리적 성질을 수학적으로 모델링하여 어떤 조명 환경에서도 일관된 사실감을 제공하는 현대적인 셰이딩 방식이다.
### PBR의 핵심 원칙
1. **에너지 보존 법칙:** 표면에서 반사되는 빛의 총량은 입사된 빛의 총량을 초과할 수 없다. (Diffuse와 Specular의 합 $\le$ 입사광)
2. **미세면 이론(Microfacet Theory):** 모든 표면은 미세한 거울들로 이루어져 있다고 가정하며, 이 미세면들의 정렬 상태에 따라 거칠기를 표현한다.
3. **BRDF (Bidirectional Reflectance Distribution Function):** '양방향 반사 분포 함수'로, 특정 방향에서 들어온 빛이 표면에서 어느 방향으로 얼마나 반사되는지를 정의하는 함수이다. PBR은 이 BRDF를 통해 재질의 물리적 특성을 수학적으로 정밀하게 묘사한다.
### 주요 맵(Map) 파라미터
* **Metallic (금속성):** 재질이 전도체(금속)인지 부도체(비금속)인지 결정한다. 금속은 반사광의 색상이 표면색의 영향을 강하게 받는다.
* **Roughness (거칠기):** 표면의 매끄러운 정도를 결정한다. 값이 낮을수록 거울처럼 선명하게 반사되고, 높을수록 빛이 넓게 퍼진다.
### 퐁 셰이딩 vs PBR 비교
| 구분 | 퐁 셰이딩 (Phong) | PBR (Physically Based) |
| :--- | :--- | :--- |
| **접근 방식** | 경험적/시각적 근사치 (Empirical) | 물리 법칙 기반 (Physical) |
| **빛의 계산** | 단순 합산 (Ambient + Diffuse + Specular) | 에너지 보존 및 BRDF 사용 |
| **재질 표현** | Specular Power 등 임의의 수치 조절 | Metallic, Roughness 등 물리적 속성 정의 |
| **일관성** | 조명 환경이 바뀌면 재질 설정 수정 필요 | 다양한 환경(HDRI 등)에서 일관된 외형 유지 |
## 5. 셰이더 언어와 구현
**셰이더(Shader)**란 GPU(그래픽 처리 장치)에서 실행되는 작은 프로그램으로, 렌더링 파이프라인의 특정 단계에서 데이터를 처리한다.
### 셰이더 파이프라인 흐름
1. **Vertex Data**: 모델의 정점 정보 입력
2. **Vertex Shader**: 정점 좌표 변환 및 데이터 전달
3. **Primitive Assembly**: 정점을 연결하여 폴리곤 생성
4. **Rasterizer**: 폴리곤을 픽셀 단위로 분할
5. **Fragment/Pixel Shader**: 각 픽셀의 최종 색상 계산 (조명, 텍스처링)
6. **Frame Buffer**: 최종 결과물을 화면에 출력
### 주요 셰이더 종류 및 언어
* **정점 셰이더 (Vertex Shader):** 3D 공간의 정점 좌표를 2D 화면 좌표로 변환하고, 법선 벡터 등을 전달한다.
* **픽셀/프래그먼트 셰이더 (Pixel/Fragment Shader):** 래스터화된 각 픽셀의 최종 색상을 계산한다. 조명, 텍스처링, 그림자 처리가 여기서 이루어진다.
* **대표 언어:**
* **HLSL** (High-Level Shading Language): DirectX 환경
* **GLSL** (OpenGL Shading Language): OpenGL, Vulkan 환경
* **MSL** (Metal Shading Language): Apple Metal 환경
### GLSL 기본 조명 계산 예제 (Fragment Shader)
```glsl
#version 330 core
out vec4 FragColor;
in vec3 FragPos; // 정점 셰이더에서 전달된 픽셀 위치
in vec3 Normal; // 정점 셰이더에서 전달된 법선 벡터
uniform vec3 lightPos; // 광원 위치
uniform vec3 viewPos; // 카메라 위치
uniform vec3 lightColor;
void main() {
// 1. Diffuse 계산 (Lambertian)
vec3 norm = normalize(Normal);
vec3 lightDir = normalize(lightPos - FragPos);
float diff = max(dot(norm, lightDir), 0.0);
vec3 diffuse = diff * lightColor;
// 2. Specular 계산 (Phong)
vec3 viewDir = normalize(viewPos - FragPos);
vec3 reflectDir = reflect(-lightDir, norm);
float spec = pow(max(dot(viewDir, reflectDir), 0.0), 32); // 32는 광택 강도
vec3 specular = spec * lightColor;
// 최종 색상 조합 (Ambient 0.1 가정)
vec3 result = (0.1 + diffuse + specular) * vec3(1.0, 0.5, 0.31); // 표면색 적용
FragColor = vec4(result, 1.0);
}
```
## 6. 응용 및 최적화
### 실시간 렌더링 최적화
모든 픽셀에서 복잡한 물리 계산을 수행하는 것은 비용이 매우 크다. 이를 위해 다음과 같은 기법이 사용된다.
* **라이트맵(Lightmap):** 정적인 조명 정보를 텍스처에 미리 구워(Baking) 런타임 계산량을 줄인다.
* **지연 셰이딩(Deferred Shading):** 기하 정보(법선, 색상, 깊이)를 G-버퍼에 먼저 저장한 뒤, 화면에 보이는 픽셀에 대해서만 조명 계산을 수행하여 광원 개수를 획기적으로 늘린다.
### 비실사 렌더링 (NPR, Non-Photorealistic Rendering)
물리적 정확성보다는 예술적 스타일을 강조하는 기법이다.
* **툰 셰이딩 (Cel Shading):** 빛의 단계(Step)를 강제로 나누어 만화처럼 단순한 색면으로 표현하고, 외곽선을 추가하여 2D 애니메이션 느낌을 구현한다.
* **해칭(Hatching):** 선의 밀도를 조절하여 명암을 표현하는 스케치 스타일의 셰이딩이다.