vec3 ComputeDirectionalLight(Light L, Material mat, vec3 normal, vec3 toEye) {
// 계산에 사용하는 lightVector는 directional light가 향하는 방향의 반대
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);
}
픽셀마다 ComputeDirectionalLight로 색을 결정한다. 먼저 빛이 들어오는 방향의 반대방향과 법선벡터를 내적한 것을
lightStrength 벡터와 곱한다. 그것을 BlinnPhong 함수로 전달한다. BlinnPhong은 기존의 Phong 쉐이더에서 계산을
줄이기 위해 최적화한 모델이다.

specular을 계산할 때 기존 phong 모델은 빛이 반사되는 reflection vector을 구해야 하는데 식이 꽤나 복잡해서 연산이 오래 걸린다. 그것을 최적화 하기 위해 식을 줄인 것이 Blinn Phong 모델이다. Blinn Phong 모델은 식을 최소화하기 위해서
reflection vector를 구하지 않고 half way vector을 구한다. half way vector은 v(충돌지점부터 시점까지 벡터)와 l (빛이 들어오는 방향 반대 벡터)를 더한걸 2로 나눈 것이다. h(halfway 벡터)와 n(노말 벡터)를 내적하는 것으로 v(충돌지점->시점 벡터)와 r(reflection 벡터)의 내적을 대신할 수 있다.
vec3 BlinnPhong(vec3 lightStrength, vec3 lightVec, vec3 normal, vec3 toEye,
Material mat) {
// Halfway vector 계산
vec3 halfway = normalize((lightVec + toEye) / 2.f);
// Halyway vector를 이용해서 specular albedo 계산
vec3 specular = mat.specular*pow(glm::max(dot(normal, halfway),0.f),mat.shininess);
// ambient, diffuse, specular 합쳐서 계산
return mat.ambient + (mat.diffuse + specular)*lightStrength;
}
halfway 벡터를 먼저 구한다. normalize하기 때문에 사실 2로 나누지 않아도 상관 없다. (크기가 중요하지 않기 때문에)
그리고 halfway를 이용해 specular을 구한다. normal 벡터와 halfway를 내적한 값을 shininess만큼 제곱해준걸 specular에 곱해주면 된다. 그 후 diffuse와 specular에만 적용되는 lightStrength를 곱해준다. specular만 추가적으로 반짝임을 표현하기 위해 추가로 계산을 해준다고 생각하면 된다.
'그래픽스' 카테고리의 다른 글
| [그래픽스] non-uniform scaling에서 normal vector 변환 (0) | 2023.06.04 |
|---|---|
| [그래픽스] Row-Major vs Column-Major (0) | 2023.05.30 |
| [그래픽스] Perspective Projection 비율 문제 해결 (0) | 2023.05.28 |
| [그래픽스] 쉐이더(Shader) 개념 (0) | 2023.05.28 |
| [그래픽스] 래스터화(Rasterization)가 빠른 이유 (0) | 2023.05.23 |