해당 글을 읽기 전, Gaussian blur에 대해 알고 있어야 원활한 진행이 가능합니다.
이 링크에 해당 내용을 읽어보실 수 있습니다.
Bloom은 이미지가 더 밝아보이게 만드는 효과입니다.
하단 이미지처럼 Bloom 효과를 적용하면 이미지가 밝아집니다.
Bloom 효과는 세가지 과정을 통해 구현할 수 있습니다.
1. 밝은 pixel은 두고 어두운 pixel은 검은색으로 처리한다.
2. 이 결과물에 Gaussian blur를 적용한다.
3. 원본에 blur 이미지를 더하면 bloom 효과가 완성된다.
어두운 pixel만 처리하기 위해서는 해당 pixel이 밝은지 어두운지 판별할 수 있어야 합니다.
이를 판별하기 위해 Relative Luminance를 사용합니다.
아래 식을 이용해 밝기를 계산할 수 있다.
해당 식을 보면 R G B에 곱해지는 가중치가 다름을 볼 수 있다. 사람의 눈은 녹색 빛이 많을수록 더 밝다고 느낀다. 그래서 G에 곱해지는 가중치가 가장 큰 것이다.
위 원본 이미지의 각 pixel들의 relative luminance를 계산해 적용하면 아래처럼 나온다.
그리고 threshold 값을 지정해 밝기가 threshold 아래라면 해당 pixel을 검게 만든다.
for (int j = 0; j < height; j ++)
for (int i = 0; i < width; i++)
{
Vec4& pixel = GetPixel(i, j);
const float y = 0.2126f * pixel.x + 0.7152f * pixel.y + 0.0722f * pixel.z;
if (y < threshold)
{
pixel.x = 0.0f;
pixel.y = 0.0f;
pixel.z = 0.0f;
}
}
이렇게 하면 첫번째 단계가 끝난다.
이제 첫번째 단계 결과물에 Gaussian blur를 적용한다.
for (int i = 0; i < repeatCnt; i++)
{
this->GaussianBlur();
}
해당 결과물은 Blur를 1000번 돌린 결과물이다.
원본 이미지와 Blur 이미지를 더한다. weight 값을 통해 bloom의 강도를 조절할 수 있다.
for (int i = 0; i < pixelsBackup.size(); i++)
{
pixels[i].x = std::clamp(pixels[i].x * weight + pixelsBackup[i].x, 0.0f, 1.0f);
pixels[i].y = std::clamp(pixels[i].y * weight + pixelsBackup[i].y, 0.0f, 1.0f);
pixels[i].z = std::clamp(pixels[i].z * weight + pixelsBackup[i].z, 0.0f, 1.0f);
}
코드에서는 결과값이 0~1 사이가 되도록 clamp시켰다.
해당 글은 홍정모 그래픽스 새싹코스를 수강하며 학습한 내용을 정리한 것입니다. 혹시라도 잘못된 내용이 있다면 말씀해주시면 감사하겠습니다.