CPP로 RayTracing 구현하기 - 5. 빛 반사 (Matte무광 재질)
여기에서 감마보정에 대해 설명했음
다시 짧고 간결하게 설명하면

이 사진을 봐보자
아래줄은 실질적인 밝기의 변화임
윗줄은 사람이 올바르다고 느끼는 밝기의 변화임
그럼 문제가 뭐냐?
게임에서는 실질적인 밝기로 표현을 하는데, 사람이 보기에는 어색하다는거임
그래서 감마 보정을 통해 밝기를 어둡게 바꿈
그 값이 2.2승 정도임
따라서 모니터에 출력을 할때, 인간이 어색하지 않기 위해 더 어둡게 보정을 함
밝기가 0.5인 색이 있다고 가정, 감마보정을 통해 이라는 밝기가 됨
그럼 밝기가 1.0인 색이 있다고 해보자. 위의 예시인 0.5의 2배임.
따라서 0.436 approx가 되어야하지 않나?
임
따라서 2배 밝기 조절을 했음에도 불구하고 감마 보정을 한 후에는 약 4.5배의 차이가 생기게 되는거임
따라서 감마 보정을 할때 감마 인코딩, 감마 디코딩이라는 과정을 거침
를 해서 이미지를 출력하면 됨
기본적으로 색상계산이 끝난 후 픽셀이 그대로 모니터를 통해 출력되면
우리 눈에는 너무 어둡거나 우리가 원하는 방향으로 쉐이더가 적용된것처럼 보이지 않음
따라서 밝기를 약간 올려줘서 모니터에 출력될때
모니터 감마특성이 적용되어 우리눈에 안정감 있는 밝기로 출력하는거임
몇몇 이미지들은 이미 감마 인코딩이 되어있음
이러한 색상을 sRGB라고 함
이러한 이미지들을 이용해 텍스쳐 더하기, 뭐 섞기를 하면
이미 감마 인코딩이 되어있는 이미지라,
결과가 왜곡되게 됨
따라서 sRGB이미지는 디코딩을 통해 인코딩된걸 해제해줘야함
간단하긴한데
가 끝임ㅋㅋㅋ
가장 중요한건 최종 출력 직전에 감마 보정을 해줘야함
감마 디코딩 같은 특수한 경우가 아니고서야 미리 감마 보정을 하면 왜곡됨
쉐이더에서 직접 할수도 있고
opengl한테 제어권 넘길수도 잇음
opengl한테 제어권 넘기는건
glEnable(GL_FRAMEBUFFER_SRGB);
으로 끝임ㅋㅋㅋ
쉐이더에서 하는것도 마지막 출력 직전에
void main()
{
//스게-나 빛 계산로직...
[...]
// 감마 보정 적용
float gamma = 2.2;
FragColor.rgb = pow(fragColor.rgb, vec3(1.0/gamma));
}
이것또한 쉐이더에서 직접 할수도 있고
opengl을 통해 할수도 있음
opengl을 통해 하는건
glTexImage2D(GL_TEXTURE_2D, 0, GL_SRGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, data);
이렇게 특정 텍스쳐/이미지의 색상타입이 sRGB로 되어있다고 알려서 감마 디코딩을 하도록 하면 됨
쉐이더에서는
float gamma = 2.2;
vec3 diffuseColor = pow(texture(diffuse, texCoords).rgb, vec3(gamma));
이렇게 텍스쳐/이미지 로드 후에 2.2제곱을 해주면 됨ㅇㅇ
감마 디코딩할때 주의해야할 점
ㅤ
보통 사용하게 될 이미지는 텍스쳐파일임
normal, metalic, diffuse, ao등등
ㅤ
이중에서 디코딩을 해줘야하는 텍스쳐는 주로 diffuse뿐임
ㅤ
픽셀의 색상을 결정짓는 이미지는 디코딩하고
그외에는 디코딩 하지 않는다고 보면 됨
일반적으로 빛의 감쇠는 거리의 제곱만큼 밝기가 감쇠한다고 함
따라서
float attenuation = 1.0 / (distance * distance);
이게 감쇠값이 되어서 밝기에 더해져 해당 거리에서 어느정도의 빛이 오냐...가 되는거징ㅇㅇ
근데 모니터에 출력될때 감마가 조정되지?
저상태로 밝기를 조절해서 모니터에 출력하면 겁나 어두워짐ㅇㅇ
따라서 감쇠도 그에 따라 값을 변화시켜야함
float attenuation = pow((1.0 / distance), 2.2);
가 되는거임
ㅇㅇㅇ