map : 데이터를 texture 형태로 인코딩한 것
High-frequency polygon mesh : 세부적인 디테일 정보가 담겨있지만, 실시간 렌더링이 거의 불가능할 정도로 계산 비용이 비싸지는 문제 발생
Low-resolution mesh : 렌더링은 빠르지만, 디테일이 사라지는 문제 발생

Normal Map : 표면의 각 픽셀이 향해야 할 가짜 법선 정보를 RGB 색상 값으로 저장한 텍스쳐
효율적으로 더 생생한 화면을 제공하기 위해 모델은 간단하지만 실제와 유사한 Normal 정보(Normal map)를 사용하여 사람의 눈이 이를 착각하도록 함

Height Map : 표면의 높낮이 정보를 gray-scale로 저장한 이미지
변환 과정

주변 픽셀과의 높이 차이를 이용해 표면의 기울기 벡터 두 개를 구하고, 두 벡터를 외적하여 각 픽셀의 Normal을 추정하는 방식
Normal의 각 요소들은 [-1, 1] 에 속하기에 이를 texture로 변환하기 위해서 [0, 1] 으로 변환 필요
이전 방식까지는 normal은 인접한 정점들의 interpolation으로 계산하였지만, 이제는 Normal Map을 이용하여 추정함.
// normal map filtering
vec3 normal = normalize(2.0 * texture(normalMap, v_texCoord).xyz - 1.0);
Normal Map으로 부터 특정한 좌표에 있는 값을 얻은 후 이를 실제 Normal 벡터로 변환
Tangent Space : 모델의 표면에 붙어있는 자신만의 로컬 좌표계

과 가 일치하는 평면에서는 tangent space와 world space 차이가 존재하지 않음.
일반적인 경우 tangent space와 world space에 차이가 존재함.
Normal Map을 기준으로 얻은 normal의 경우 tangent space를 기준으로 저장되며, light 의 경우 world space를 기준으로 저장되기에 Mapping 과정에서 부자연스러운 결과 발생
normal과 light의 space를 일치시켜야 하기에 light를 world space에서 tangent space로 변환 과정 필요
화면의 모든 픽셀을 변환하는 것보다 몇개의 광원 벡터만 변환하는 것이 효율적이므로 normal이 아닌 light를 변환하도록 함.
vec3 Nor = normalize(transpose(inverse(mat3(worldMat))) * normal);
vec3 Tan = normalize(mat3(worldMat) * tangent);
vec3 Bit = cross(Nor, Tan);
mat3 tbnMat = transpose(mat3(Tan, Bit, Nor));

Normal Map을 이용하면 간단한 모델에서 detail을 추가할 수 있음.
참고 영상 : ComputerGraphics Lecture 14. Normal Mapping - 김형기 교수님
참고 자료 : Introduction to Computer Graphics with OpenGL ES