원문 : http://bytewrangler.blogspot.kr/2011/10/signed-distance-fields.html

주의 : 허락받고 번역한 것이 아니므로 언제든 내려갈 수 있습니다.

주의 : 번역이 개판이므로 이상하면 원문을 참조하십시오.



Signed Distance Fields


필자는 Valve Software 의 Ghris Green 이 작성한 이 백서에서 처음으로 부호있는 디스턴스 필드( Signed Distance Fields )라는 것을 접했습니다. Valve 는 자신들의 이용가능한 그래픽스 기술들에 대한 기술 문서들을 만드는데, 정말 멋집니다. 이 경우에, 이 기법은 팀 포트리스 2 에서 사용되었는데, 특히 게임 내의 표지판이나 데칼들에 사용되었습니다.


부호있는 디스턴스 필드는 ( 일반적으로는 흑백인 ) 비트맵 데이터를 저장하는 다른 방식입니다. 비트맵의 각 픽셀이 그 점에서의 강도( intensity )를 표현하는 것이 아니라, 소스 이미지에서 검정색이 아닌 가장 가까운 픽셀에 대한 거리를 표현합니다. 그 모양 바깥쪽에 존재하는 픽셀들은 양수 거리 값을 가지게 됩니다. 반면에 그 모양 안쪽의 픽셀들은 음수 거리 값을 가지게 됩니다. 그러므로 "부호있는( signed )" 이라는 이름이 들어갑니다.


그림 1: 부호있는 디스턴스 필드가 픽셀 수준에서 보여지는 방식에 대한 예제.


디스턴스 필드는 사실 실수 데이터로 구성되어 있지만, 설명의 목적 때문에 정수로 보여 준다는 것에 주의하시기 바랍니다.


부호있는 디스턴스 필드를 생성하기 위해서, 여러분은 소스 이미지에 대한 디스턴스 트랜스폼( distance transform )을 적용합니다. 그리고 나서 원래 이미지를 렌더링하기 위해 다음과 같이 합니다.



부호있는 디스턴스 필드를 실제로 유용하게 만드는 것은 여러분이 이미지를 리사이징할 필요가 있을 때입니다. 이 거리값은 3D 하드웨어에 의해서 보간되는데, 그것은 전통적인 비트맵의 강도 값이 보간되는 방식과 동일합니다. 그러나 엣지가 테스트에 의해 생성되기 때문에, 그것은 crisp 하게 남아 있게 됩니다. 이는 여러분이 비트맵을 여러 번 확대할 수 있으며, 전통적인 비트맵이 필터링 아티팩트 때문에 뭉개지거나 두툼해지는 것과는 다르게 그런 현상을 겪지 않게 된다는 것을 의미합니다.


Creating the Distance Field


디스턴스 필드를 계산하기 위해서 사용할 수 있는 많은 트랜스폼들이 존재합니다. 가장 좋은 접근법은 고해상도 소스 이미지를 사용하고 여러분의 응용프로그램에 적절한 사이즈로 그것을 다운샘플링하는 것입니다. 그러면 디스턴스 필드의 속성이 많은 정보들을 보존하게 됩니다.


Brute force 기법( 비트맵에서 주어진 픽셀과 다른 픽셀들 간의 유클리디안( euclidean ) 거리를 계산하는 것을 의미합니다 )은 완벽한 디스턴스 필드를 생성하지만, 그것은 O(n^2) 복잡도를 가지기 때문에 큰 이미지에 대해서는 매우 느립니다. ( 정확하지는 않지만 ) 더 빠른 알고리즘이 존재하긴 합니다만 알고리즘을 선택하는 것은 별로 중요하지 않습니다. 왜냐하면 런타임에 실행할 필요가 없기 때문입니다. Valve 는 실제로 brute force 방식을 사용했으며 그들의 서버에서 밤 시간동안에 batch job 으로 처리합니다. 필자는 그냥 더 빠른 접근법을 선택했습니다. 왜냐하면 결과를 얻기 편하기 때문입니다.


그림 2: Bulldog 에서 최종 디스턴스 필드가 어떤 모양인지 보여주는 예제.


An application of Distance Fields


디스턴스 필드를 위한 소스 데이터는 일반적으로 흑백이기 때문에, 그것의 유용성은 제한되어 있습니다. 그러나 디스턴스 필드에 매우 적합한 응용프로그램은 텍스트를 그리는 것입니다.


예를 들어 TrueType 이나 OpenType 폰트( 혹은 정확한 개념을 사용하기 위해 "typeface" )는 벡터 형식으로 저장됩니다. 이것은 각 상형문자들( glyphs, typeface 내의 문자들 )이 코너( corner )와 제어점( control point )을 위해 x, y 좌표를 가진 도형으로서 표현됨을 의미합니다. 이는 스크린 상의 디스플레이를 위해서 비트맵으로 변환되거나 "래스터화( rasterised )"됩니다. 여러분이 원하는 텍스트의 크기에 의존해서 x, y 좌표들은 스케일링( scale )되며 문자 도형을 표현하는 커브들도 스케일링됩니다. 래스터화 과정은 현대 하드웨어에서도 느릴 수 있습니다. 그래서 게임에서 선호되는 방식은 여러분이 원하는 크기로 폰트를 미리 래스터화해서 비트맵에 저장하는 것입니다. 그리고 나서 비트맵으로부터 개별 문자들을 선택함으로써 요청된 텍스트를 구성합니다.


이 기법은 매우 빠르지만, 약간의 제약이 있습니다. 여러분은 모든 크기와 스타일의 조합에 대해서 개별적인 폰트 비트맵을 생성해야만 합니다. 왜냐하면 비트맵은 잘 스케일링되지 않기 때문입니다. Take for example a game that wants to have 2 different typefaces, say a normal looking sans serif typeface like Arial, and maybe a fancier caligraphy typeface for ye olde books and scrolls and the like. 문체상의( stylistic ) 이유로 여러분은 3 개의 다른 크기를 원할 것입니다. 타이틀/캡션 혹은 툴팁같은 것들 때문에 말이죠. 혹은 다양한 범위의 스크린 해상도를 지원하고자 할 수도 있고, 사람들이 UI 요소들을 읽는데 현미경을 필요로 하기를 원치 않을 수도 있습니다.  이미 우리는 2 * 3 = 6 개의 비트맵을 생성하고 관리해야 합니다. 만약 여러분이 이탤릭체나 볼드체를 원한다고 하면 더 심각해질 수 있습니다.


부호있는 디스턴스 필드 접근법은 taking the sizing out of the equation 을 통해 이러한 짐을 경감시켜주는데 도움을 줍니다. 왜냐하면 디스턴스 필드는 그래픽적 아티팩트가 거의 없이 스케일을 늘리거나 줄일 수 있기 때문입니다.


보너스로 디스턴스 필드 데이터를 사용해서 엣지를 안티 에일리어싱할 수 있습니다. 이는 거리 테스트에 부가적인 항을 추가함으로써 가능한데, 특정 범위 내의 디스턴스 값들에 대해서 페이딩( smoothly ramp from lit to unlit )을 수행합니다. Valve 기사에서는 drop shadows 와 outline 과 같은 몇 가지 다른 효과들에 대해 다룹니다.


Bulldog 에서 필자는 픽셀 쉐이더를 사용해서 부호있는 디스턴스 필드 폰트를 구현했는데, 그것은 디스턴스 필드 데이터를 가지고 노는 것을 꽤 쉽게 만들어 줍니다.


이 쉐이더 코드는 놀랄만큼 단순하며, 단순한 안티 에일리어싱 텍스트는 다음과 같습니다:



delta 는 상수인데, 이것은 문자의 엣지로부터 안티 에일리어싱이 확장되는 거리를 결정합니다. Bulldog 에서 필자가 사용하는 실제 쉐이더 코드는 약간 더 복잡합니다. 왜냐하면 그것은 테두리( border )와 ( 텍스트 박스에서 텍스트를 선택한 경우같이 ) ( 역주 : 색상이 )반전된 문자를 다뤄야 하기 때문입니다. 또한 다양한 폰트 크기에 대해 안티 에일리어싱을 조정해야 하기 때문입니다. 필자는 나중에 부호있는 디스턴스 필드를 사용해서 만들어진 새로운 폰트 시스템에 대한 포스트를 작성할 것입니다. 현재로서는, 여기에서는 다양한 크기로 렌더링된 같은 폰트들에 대한 예제를 보여드리겠습니다:


그림 3: 12, 24, 64 픽셀에서의 폰트 출력 예제.


마지막으로, Bulldog 의 다른 부분에서 보통과는 다른 방식으로 부호있는 디스턴스 필드를 사용해 봤다고 말씀드리고 싶습니다. 하지만 그것은 다음 포스트에서 언급하겠습니다...

+ Recent posts