조명은 크게 3가지로 나뉜다.

Directional : 한 쪽 방향으로 쏘는 조명.
Point Light : 한 점에서 사방으로 나아가는 조명.
Spotlight : 특정 부분만을 비추는 조명.
예전에는 컴퓨터가 좋지 않았기 때문에 리얼타임 그래픽스에서는 정확하게 조명을 나타내는 연산이 중요하지 않았다. 그럴듯하게 표현 할 수 있는 최적화 되어 있는 연산, 상황을 구현하는 것이 중요했다.
따라서 falloff Start, End 를 사용했다.
Start 거리를 시작으로 이 이상으로 멀어지면 강도 1~0으로 줄어들며 해당 픽셀을 어둡게 만들었다. 따라서 멀리 있는 조명은 애초에 강도 0이니 연산에서 빼버리기 때문에 최적화 할 수 있었다.

3가지 조명의 기초 연산 식
Directional : 기초 블린 퐁을 위한 계산
Point Light : 조명의 위치와 정점의 위치, 거리(d 강도) 를 기반으로 빛의 방향과 세기를 결정 후 퐁 쉐이딩
Spot Light : 포인트 조명에서 Spot 조명은 방향이 결정되어 있기 때문에 구하려는 정점의 위치와 조명 방향의 내적을 추가하여 바로 구할 수 있다.
vec3 ComputeDirectionalLight(Light L, Material mat, vec3 normal, vec3 toEye) {
vec3 lightVec = -L.direction;
float ndotl = glm::max(dot(lightVec, normal), 0.0f);
vec3 lightStrength = L.strength * ndotl;
// Luna DX12 책에서는 Specular 계산에도
// Lambert's law가 적용된 lightStrength를 사용합니다.
return BlinnPhong(lightStrength, lightVec, normal, toEye, mat);
}
// 쉐이더에서 많이 사용되는 함수입니다. HLSL에는 내장되어 있습니다.
// https://learn.microsoft.com/en-us/windows/win32/direct3dhlsl/dx-graphics-hlsl-saturate
float Saturate(float x) { return glm::max(0.0f, glm::min(1.0f, x)); }
float CalcAttenuation(float d, float falloffStart, float falloffEnd) {
// Linear falloff
return Saturate((falloffEnd - d) / (falloffEnd - falloffStart));
}
vec3 ComputePointLight(Light L, Material mat, vec3 pos, vec3 normal,
vec3 toEye) {
vec3 lightVec = L.position - pos;
// 쉐이딩할 지점부터 조명까지의 거리 계산
float d = length(lightVec);
// 너무 멀면 조명이 적용되지 않음
if (d > L.fallOffEnd)
return vec3(0.0f);
lightVec /= d;
float ndotl = glm::max(dot(lightVec, normal), 0.0f);
vec3 lightStrength = L.strength * ndotl;
float att = CalcAttenuation(d, L.fallOffStart, L.fallOffEnd);
lightStrength *= att;
return BlinnPhong(lightStrength, lightVec, normal, toEye, mat);
}
vec3 ComputeSpotLight(Light L, Material mat, vec3 pos, vec3 normal,
vec3 toEye) {
vec3 lightVec = L.position - pos;
// 쉐이딩할 지점부터 조명까지의 거리 계산
float d = length(lightVec);
// 너무 멀면 조명이 적용되지 않음
if (d > L.fallOffEnd)
return vec3(0.0f);
lightVec /= d;
float ndotl = glm::max(dot(lightVec, normal), 0.0f);
vec3 lightStrength = L.strength * ndotl;
float att = CalcAttenuation(d, L.fallOffStart, L.fallOffEnd);
lightStrength *= att;
/// 추가!!!!
float spotFactor =
glm::pow(glm::max(dot(-lightVec, L.direction), 0.0f), L.spotPower);
lightStrength *= spotFactor;
return BlinnPhong(lightStrength, lightVec, normal, toEye, mat);
}
스포트라이트는 방향이 있고 실제 구할 위치점과 얼마나 각이 졌는지에 따라 빛의 세기가 달라지도록 만든다.

Point Light

Spot Light

'DX' 카테고리의 다른 글
| 역행렬과 컴퓨터 그래픽스 (짧) (0) | 2025.05.11 |
|---|---|
| Orthogonal (0) | 2025.05.11 |
| 쉐이딩 (0) | 2025.05.01 |
| 원근 투영 실습 (0) | 2025.04.30 |
| 뒷면 제거 (0) | 2025.04.30 |