[CG] Premultiplied Alpha & Straight Alpha


(1) Straight Alpha

  • RGB와 Alpha는 독립된 채널
  • 색상을 합성할 때, 매번 RGB * Alpha의 계산이 필요하다
// src는 합성 대상, dst는 배경색
Result = (src.rgb * A) + (dst.rgb * (1-A))

(2) Premultiplied Alpha

  • Alpha 값을 RGB에 미리 반영한다. 즉 RGB에 미리 Alpha를 곱해둔다. (pre-multiplied)
  • 이미 Alpha가 곱해져있는 상태이므로 합성시 Alpha 곱 연산을 할 필요가 없다
// src는 합성 대상, dst는 배경색
Result = src.rgb + (dst.rgb * (1-A))

Distinguishing Straight vs Premultiplied Alpha

추가적인 메타데이터를 저장하는 자체 포맷이 아닌 일반 이미지(PNG, PPM, JPG 등)라면, 파일의 포맷만 보고 premultiplied alpha인지 straight alpha인지 구분할 수 없다. 사용자가 graphic processor에게 따로 알려주어야 한다.

edge artifact (경계 현상)

일반적인 이미지 뷰어는 이미지가 straight alpha로 표현되어있다고 가정하고 이미지를 렌더한다. 이 때문에 premultiplied alpha로 표현된 이미지를 일반적인 이미지 뷰어가 렌더할 때, 영역의 경계가 어둡게 보이는 현상이 생긴다.

아래는 게임 에셋 이미지를 만들고 있는 한 유저의 사례로, 에셋 생성을 위해 사용하고 있는 프로그램에서 ‘premultiply alpha’ 옵션을 체크했을 때 의문의 테두리가 생겨 포럼에 이런 글을 올렸다.

Not using premultiply alpha:

Using premultiply alpha:

(옵션의 체크 유무와 관계 없이 프로그램은 이미지를 straight alpha로 해석하여 렌더하고 있다)

대부분의 래스터(비트맵) 이미지에서 영역의 경계 부근은 반투명한 픽셀들로 이루어져 있다.
어떤 반투명 픽셀의 RGB 값이 (255, 0, 0) 그리고 Alpha=0.5라고 했을 때, 이 픽셀을 premultiplied alpha로 표현 하면 (127.5, 0, 0)이 된다.
그런데 이미 Alpha가 곱해져 이렇게 어두워진 픽셀을 straight alpha로 해석하여 또 Alpha를 곱해버리면, 원래 색상보다 더 어두워져 버리는 것이다. 이것이 edge artifact의 원인이다.

현상의 근본적인 원인과 결과는 Alpha를 두 번 곱해 합성 대상의 원 색상이 배로 죽어버리는 것이나, 배경 색에 따라서 다른 느낌을 주게 되는데 이는 각 배경 색에 따라 앞선 계산식으로 결과 픽셀을 얻어보면 확인할 수 있다. (대표적으로 흰색과 투명한 배경을 비교할 것). 참고: 투명한 배경의 RGBA 값은 (0, 0, 0, 0)으로, 이는 사실상 검은색을 의미한다.

References

comments