Direct3D 12 graphics Pipeline
지난 포스팅에서는 pixel shader가 하는 일 중 texturing과 관련해서 texel과 pixel의 해상도 차이로 인한 확대,축소 문제를 어떻게 해결하는지 살펴봤다. 오늘 다룰 내용은 Lighting이다. 전통적인 phong 모델부터 per-pixel lighting, blinn-phong model까지 살펴볼 예정이다.

Phong Lighting Model
◇ Diffuse / Specular / Ambiend / Emissive 4가지를 섞어 그럴듯하게 빛을 표현하자
- 가장 유명하고 전통적인 방식이다.
- approximation을 어떻게 잘 하는지가 중요하다.
Light Sources
◇ Point light
- 하나의 point로부터 전방향으로 빛을 뿜어낸다.
- point로부터 거리에 따라 intensity가 결정된다
◇ Directional light
- scene으로부터 멀리 떨어진 곳에서 보내는 빛 ex) 태양
- scene 전체에서 one direction이다.
- 내가 어디에 존재하든 일정한 direction과 크기를 가진다
◇ Spotlight
- cone shaped light
- 거리와 각도에 따라 intensity가 달라진다.
- ex) 형광등, 백열등
◇ Ambient
- 은은하게 밝혀주는 간접광
- 반사되어 떠도는 빛을 계산하기 어렵기 때문에 constant value로 뭉개서 계산한다.
Diffuse (난반사광)
◇ 물체 표면에 빛이 반사되었을 때 전방향으로 uniform하게 퍼지는 것을 modeling한다.
- Lambert's law를 따른다 = 입사각이 작을 수록 밝게 보인다.
- Diffuse 조명은 표면의 밝기가 빛의 입사각 cos(θ)에 비례한다.
- θ: 빛의 방향과 표면 법선 벡터(normal) 사이의 각도
- 관찰자의 위치와 밝기는 무관하다.

- Diffuse computation

- n : surface normal (표면 법선 벡터)
- l : light direction (빛 방향 벡터)
- n · l : 두 벡터의 내적
- max(n·l, 0) : 음수 제거
- s_d : light color (빛 색)
- m_d : material diffuse color (물체 색)

Specular (정반사광)
◇ 물체 표면에 빛이 닿을 때, 특정 방향으로 강하게 반사되는 조명 효과
- 표면 특정 부분에 highlight 효과를 줄 수 있다.
- 관찰자의 방향에 따라 밝기가 달라진다.
- : view vector
- : reflection vector
- : shininess (클수록 날카롭고 작은 하이라이트)
- : light source의 gray-scale value
- : highlight on the surface


Ambient (간접광)
◇ 주변에 퍼져있는 일관된 빛
- 씬 내의 다양한 물체에 반사된 빛
- 표면에 도달한 주변 조명은 모든 방향에서 동일한 강도로 산란된다.
Emissive
◇ 표면 자체에서 방출되는 빛

Phong Lighting Model
◇ Diffuse / Specular / Ambiend / Emissive 4가지 term을 합쳐서 표현한다.

Per-pixel Lighting
◇ 각 픽셀 단위에서 조명을 계산하는 방식
- per-vertex 방식에 비해 high quality
- per-vertex 방식은 정점만 밝기 계산을 하고, 그 사이 픽셀은 선형 보간해서 부드럽지 않은 부분이 생긴다.

◇ pixel shader에서 per-pixel 조명 계산을 위해 필요한 벡터
- l : light vector
- n : normal
- v : view vector
- r : reflection vector ( r = 2n(n·l) - l )
- (이때 l은 directional light로 모든 surface에서 동일 / n,r,v는 픽셀마다 다름)
- 중요한 점은 l이 world space 기준이기 때문에 n,v도 world space 기준 좌표가 필요하다!
- n과 v는 vertex shader에서 pixel shader로 넘겨주는 값이고, r은 직접 계산이 가능하기 때문에 파라메터를 하나 줄일 수 있다.

◇ Normal이 pixel마다 생기는 과정
- vertex shader : vertex normal을 world space로 변환
- rasterizer : vertex normal을 보간

◇ View vector가 pixel마다 생기는 과정
- vertex shader : v = cameraPos - vertexPos (world space 좌표임)
- rasterizer : vector 보간

◇ 최종 pixel 별 Phong lighting 계산
- n,v,l이 준비되었기 때문에 r은 계산을 통해서 구할 수 있다.
- 다음 최종적으로 pixel마다 phong lighting을 계산하면 per-pixel을 구현할 수 있게 된다.

Blinn-Phong Reflection Model
◇ Phong model의 modified(수정된) version
- Phong은 lighting approximation에 효율적이다.
- 그러나 specular term에서 가끔 unrealistic한 결과를 낸다.


- dot project는 cos 계산이기 때문에 90도를 넘기면 음수를 반환하고, 그대로 max()를 통과하면 0이 된다.
- 이런 급격한 cut off 때문에 경계(boundray)가 생긴다.

◇ Blinn-Phong reflection model - specular term
- reflection vector(r) 대신에 halfway vector(h)를 이용한다.
- h : (view vector) 와 (light vector)을 이등분(bisects)하는 벡터
- blinn phong의 장점
- r과 v의 차이가 90도가 넘더라도, h와 n 사이 각도는 90도가 넘지 않기 때문에 이전의 문제점이 해결된다!
- 추가로 r을 구하기 위해서 내부적으로 내적을 했었는데, 이 과정이 없어지고 단순한 덧셈 연산으로 중간 벡터를 구하기 때문에 처리도 빨라진다.



- 적용 결과
- specular term을 개선한 것이기 때문에, 바다에 반사되는 햇빛이나 젖은 땅에 멀리 떨어진 가로등이 반사되는 등 평면에 대한 반사를 표현할 때 훨씬 현실적인 표현이 가능해진다고 한다.

Reference KHU 강형엽 교수님 강의를 수강하며 정리한 내용입니다.
'그래픽스' 카테고리의 다른 글
| [DirectX12] 5. Output Merger (1) | 2026.04.10 |
|---|---|
| [DirectX12] 3. Pixel Shader - Texturing (0) | 2026.03.13 |
| [DirectX12] 2. Rasterizer (1) | 2026.03.13 |
| [DirectX12] 1. Input Assembler, Vertex Shader (0) | 2026.03.12 |