그래픽스에서 제일 재미있는 라이팅! 물체를 더욱 사실적으로 느껴지게 만들어주는 역할을 하는 라이팅은 광원, 물체(재질), 위치를 고려하여 이들 간의 관계를 해석하게 된다.
가장 단순한 모델인 "Phong lighting model"에 대해 살펴보면서 어떻게 빛을 표현해낼지 생각해보도록 하자.
퐁 모델은 세 가지 요소를 통해 빛을 표현한다.
주변광이라고 하는 ambient light은 물체가 기본적으로 받게되는 최소한의 빛이라고 생각하면 된다. 직접적인 광원이 없더라도 아예 검은색이 아니라, 주변에 물체들이 반사하게되는 빛이 퍼지면서 은은하게 보여지는데 그것을 주변광을 통해 표현한다.
퐁 모델은 굉장히 단순화된 모델이기때문에 복잡한 계산을 최소화하고 단순화했다. 주변광도 단순히 상수항으로 처리하여 물체의 위치나 다른 요소에 영향을 받지 않게 처리된다.
물체에 빛이 닿아 분산되는 빛을 나타낸다. 일반적으로 물체를 볼 때 보게되는 기본적인 색상값을 diffuse light으로 처리하게 되는데 빛이 어느 위치에 있냐에 따라 색상 처리가 달라진다. 비스듬하게 빛을 받게되면 그만큼 음영이 진 물체여야하므로 어두운 색상이 되고, 직접적으로 빛을 받는 물체라면 환하게 물체의 색상으로 비추어지게 된다.
빛이 물체에 들어오는 각도가 내적을 통해 조절되다보니, 빛의 위치와 물체의 위치가 중요하고, 내적 계산을 위한 법선벡터가 필요하다. 흔히 light_dir vector와 normal vector의 내적을 diffuse_light 값으로 세팅한다.
만약 물체가 반짝이는 금속 재질의 물질로 되어있다면, 빛이 표면에서 반사되는 일이 생길 것이고, 그 부분을 직접 눈으로 보면 빛나는 것을 강하게 느낄 것이다. 이를 반사광이라 불리는 specular light로 처리한다. 당연히 빛의 위치, 방향이 물체에 어떻게 입사하는지가 중요하고, 물체의 법선벡터와 카메라의 위치 또한 반사광을 결정짓는데 필요하다.
퐁 라이팅 모델을 통해 빛의 표현이 가능하다.
광원과 물체의 재질 간의 관계가 값을 결정하다보니, 아예 아래와 같은 구조로 정리해서 사용하면 다양한 빛 표현이 가능할 것 같다.
// light parameter
struct Light {
glm::vec3 position { glm::vec3(3.0f, 3.0f, 3.0f) };
glm::vec3 ambient { glm::vec3(0.1f, 0.1f, 0.1f) };
glm::vec3 diffuse { glm::vec3(0.5f, 0.5f, 0.5f) };
glm::vec3 specular { glm::vec3(1.0f, 1.0f, 1.0f) };
};
Light m_light;
// material parameter
struct Material {
glm::vec3 ambient { glm::vec3(1.0f, 0.5f, 0.3f) };
glm::vec3 diffuse { glm::vec3(1.0f, 0.5f, 0.3f) };
glm::vec3 specular { glm::vec3(0.5f, 0.5f, 0.5f) };
float shininess { 32.0f };
};
Material m_material;
각 물체별로 어떤 재질이냐에 따라, 어떤 색상이냐에 따라 material의 값이 달라지기 때문에 구조체로 만들어서 넘긴다면 좀 더 코드를 깔끔히 구성할 수 있을 것 같다.
빛도 마찬가지로 다양한 색상과 위치로 구분할 수 있어서 좋을 듯.
하지만 이런 material이라는 특성은 "Lighting map" 이라는 일종의 텍스쳐를 통해 표현할 수 있다. 텍스처 하나를 받아와서 물체의 해당 위치에는 어떻게 빛처리를 할지 결정해놓는 것이다.