Specular Showdown in the Wild West

반응형

원문 : https://blog.selfshadow.com/2011/07/22/specular-showdown/

개인 공부를 위해 번역하였으며 원문을 읽길 적극 추천합니다.


요즘 엘리어싱 문제로 고민이 많다.

기존 사용하던 fxaa 대신  smaa로 바꿔서 사용하고 있긴 한데 그럼에도 불구하고 specular에 의한 반짝임은

도저히 고칠수가 없었다.

몇가지 아이디어를 테스트 해보기도 했다.

specular의 power, intensity를 거리 또는 pixel의 depth를 기반으로 한 감쇠정도가 그나마 괜찮았다.

그리고 구글링중 괜찮은 내용이 있어 번역했다.

번역은 적당히 했으니 원문을 추천.!!


// 이 색상은 개인적으로 추가한 내용.


말에 안장을 얹자!

이 글에서는 잘 동작하는 specular lighting을 위해 기존 방법들을 검토할 거다.

그리고 추가적으로, 현재 게임 라이팅 접근과 콘솔 메모리 제약의

간단한 변형에 대해서도 다룰 것이다.


잘 동작한다는 건 어떤 의미일까?

울퉁불퉁한 표면에 반짝이는 specular 하이라이트를 피하는 것 뿐만 아니라

먼 거리에서 올바른 외관을 얻는것에 대해 이야기 한다.

개별적인 주름과 불규칙성들은 너무 작아서 이러한 울퉁불퉁한 효과를 나타내기 어렵다.

주어진 예산으로 이러한 모든 것들을 처리 할 수 있을까?

이것들을 알아내기 위해 여행을 떠나보자!


좋음, 나쁨, 그리고 이상함.

어떤 날은 비디오게임 렌더링에 속해있는 우리들이 카우보이 무리처럼 느껴질 때가 있다.

우리는 화면에 제시간에 맞게 물체들을 올리기 위해 법칙에 맞게 빠르고 느리게 플레이 하며

우리와 아티스트가 원하는 모양을 만들기 위해 픽셀과 다툰다.


최근에 우리는 선형 라이팅(linear lighting)과 물리 기반음영모델(physically basedshading models)을 채택하여 

몇가지 잘못된 것들을 바로잡고 있었다.

이 부분은 더 발달해 있는 영화계에서조차 최근에서야 전환하고 있는 추세이다.

이러한 것들이 다 좋기는 하지만, 앞서나가거나 거친 서부시대가 끝났다고 믿기 전에, 

잘 대처해야 하는 중요한 영역이 있다 : 엘리어싱


Dan Baker가 당당히 주장했던 것 처럼, 엘리어싱은 실시간을 다루는 사람들과 오프라인을 다루는 사람들을

사이를 구별하는 중요한 요소다.

문제부분에 좀 더 많은 샘플을 할 여유는 있겠지만, 무거운 슈퍼샘플링은 우리한테는 너무 느리다.

(실제로 나는 링크4의 내용을 구현해 보지는 않았지만, 현재 콘솔에서 잘 동작하지 않을 것이라 생각한다)

MSAA 또한 외곽 엘리어싱만 처리하니 효과적이지 않고, 음영의 샘플링 내부에서 아티펙트가  생긴다.

specular 반짝임이 대표적인 예다.

후처리 AA(현재 많은 잠재적인 옵션이 있음, 링크5 참고)는 카메라나 물체가 움직일 때 

생기거나 사라지는 선명한 하이라이트를 해결하지 못하기 때문에 실제로 도움이 되지 않는다.

마지막으로, temporal AA가 해결책이 될지도 모른다고 생각하겠지만, 이는 시간적 일관성에 대한

의존도가 높아짐에 따라 프레임 전반에 걸친 저렴한 수퍼 샘플링일 뿐이다.


요약하자면, 우리가 게임에서 사용하는 기본적인 AA기술은 반짝이는 것을 막는것에, 

특히 높은 specular power일 경우에서는 그다지 쓸모있지 못하며 우리가 원하는 

거리를 기반으로 우리가 원하는 결과를 만들어 내지 못한다.

성능부분은 제외하고, 커스텀 텍스쳐 필터링과 함께 난해한 수의 샘플을 사용하지 않는다면 

수퍼샘플링조차도 부족하다고 의심되며, 그렇지 않다면 bump정보는 평균화되어 사라진다.

(전체적으로는 아니지만 나중에 자세히 설명)


다른 선택지가 있을까?

예전 컨퍼런스에서, Dan은 일반적으로 개발자들이 사용하는 두가지 해결방법에 대해 다루었는데,

거리에 따라 울퉁불퉁함(bumpiness)이나 광택(glossiness)를 줄이는 것이다.

첫번째 방법인 bump를 줄이는건 우리가 원하는 것과 반대의 개념이기 때문에 실제로 잘못되었고,

카메라에서 멀어질 때 울퉁불퉁한 표면이 흐릿해 보이게 하는 것 보다는

법선맵을 평평하게 하는 것이 보다 더 광택이 생긴다.

대신에, specular power를 (첫번째 근사치) 줄이는 것은 옳은 방법이다.

비록 경우에 따라 조정(tweak)해야 하고 울퉁불퉁지역과 평평한 지역 모두에서 normal map이

정확하게 동작하지는 않지만, 단순한 엘리어싱을 사용하거나 높은 power를 피하는 것 보다는 낮다.

텍스쳐 공간 라이팅에 대해서 이야기 하고 싶지만, 이는 자체적으로 문제가 있는 

또 다른 중대한 대안이므로 여기서는 더이상 논의하지 않겠다.


모두들, 제대로 동작하지 않는 스펙큘러와 못생긴 반짝임을 그냥 체념해 버려야 할까?

만약 마을에 보안관이 새로 온다면 아닐지도 모르지....


거리 청소

LEAN Mapping은 각계각층의(확대율에 예외가 있을수 있는데 이 부분에 대해선 나중에 좀 더 이야기 함)

specular 하이라이트를 강력하게 필터링 하기 위한 최신 접근 방식이다.


이 기술은 거리에 따라 표면의 거친정도의 거시적 효과를 잘 나타낼 뿐 아니라, 

-심지어 능선이 있는 법선맵 (ridged normal map)으로부터 이방성 하이라이트를 생성-

런타임에 동적 범프 레이어 결합을 지원한다. (부하는 좀 더 들지만 더 자연스러워진다.)


실제로 어떻게 동작하는지 자세히 알아볼 여유는 없지만, -자세히 보고자 한다면 아래 링크를 참조-

수많은 이전 기술들에 비교해 글의 말미에 있는 해결책이 좀 더 현실적이라는건 명확하다.

어쨌든 Civilization V(문명 5)에 적용되었고, 내가 경험해 보기로는 어느정도 인상적인 결과였다.


그렇긴 하지만, 바로 광범위하게 적용하기에 몇가지 문제점이있다.

- 많은 저장공간이 필요.

- 이방성, 접선공간 Beckmann 공식


우선 저장공간에 대한 요구사항은 지금당장 많은 개발자에게 제한요소가 될 것이다.

Lean매핑은 표준 normal map대신 두개의 텍스처가 더 필요하며(그리고 아마 레이어를 결합하기 위해 더 필요할지도..),

Variance Shadow Maps과 비슷한 이유인 성가신 정밀도 조건에 의해 오버헤드가 발생한다.

Firaxis는 경우에 따라 채널당 8비트 저장공간으로 압축 작업을 수행했지만, 논문에서는 아래와 같이 조언했다.

"일반적으로, 8비트 텍스쳐는 속도나 공간에 절대적으로 필요한 경우에만 의미가 있다."


당연하게도, 이 기술은 현재 콘솔에서 normal map을 위한 가장 일반적인 크로스 플랫폼 형식 중 하나 인

DXT1 또는 DXT5에서 사용할 수 없다.

이에 비해, 저장공간 비용은 최소 8배가 될 수 있다.( 핵심 LEAN 조건에서 normal이 복구되고 

다른 데이터가 그 자리에 포함 된 경우)


지연(deffered) 렌더링을 쓸 경우 더욱 거칠어지는데,

G버퍼의 공간은 일반적으로 부족하며 설상가상으로 조명 공식은 더욱 복잡해 진다

모든것을 공통 공간(예를 들자면 월드 공간같은)으로 옮길 수 있다고 가정하더라도,

여전히 추가 접선 벡터를 저장해야 한다.

또한 LEAN 매핑과 관련된 수학적인 내용이 더 있으며 이는 환경에 라이트를 드리우기 위해 

어떤 선택을 할지와 별개로 고려해야할 또 다른 중요한 사항이다.


그래서 전반적으로 보자면, 대체품이 처음 나타나는 것은 아니다.

다행스럽게도 보안관은, 더 빠른 draw가 가능한 대리자가 있다.

올해 GDC에서 Dan은 저렴한 버전인 Clean(저렴한 LEAN) Mapping을 발표했다.

낮은 저장 공간(대략 절반정도)과 약간 더 높은 퍼포먼스를 위해 이방성을 희생한다.

이는 중요한 개선이며 이방성을 잃으면 효율적으로 두번째 문제를 해결하지만,

DXT에 대한 영역은 여전히 내 취향에 맞지 않는다.


내가 정말 좋아하는 것은 예술품들을 심각하게 "재평가"할 필요 없이 자유롭게 적용하는 것이다.

(그리고 물론, 다른 부분에서 삭감하는 것을 의미한다.)

내 말을 오해하지 마라, LEAN 매핑은 실제로 흥미로운 진보라고 생각한다.

나느 현 세대의 콘솔에서 와일드 한 것을 포기하는 현 상태로 사용하는 것을 기대하지는 않는다.

그러나 문명5의 물의 경우 처럼 특정한 상황에서 적절히 사용하면 훌륭한 옵션이다.


더 저렴한 방법이 필요하다.

투자대비 더 높은 효율을 얻을 방법이 있을까?

실제로 2004년에 Michael Toksvig가 LEAN 매핑과 비슷하게 밉매핑의 이점과 하드웨어 텍스쳐 필터링을 활용하지만

이미 존재하는 normal map에서 저장되어 있는 normal 벡터의 평균 길이로부터 직접 범프 편차를 측정하는

매우 간단한 기법을 제시했다.

일반적으로 명명된 이름이 아직 없기에 그냥 Toksvig AA라고 부르겠다.


문서에서, 기존 블린 퐁 공식은 아래와 같다.



Na는 텍스쳐에서 읽은 평균법선값이며, 이로부터 Toksvig Factor라고 부를 ft값을 얻는다.

그리고나서 스펙큘러 지수(specular exponent)인 s를 조절하는데 사용하고, 이 값(s)은 분산에 따른

전체강도를 조절한다.(거친정도)


여기 위 식을 간단하게 트윅한 코드버전이 있다.

float len = length(Na);

float ft = len/lerp(s, 1, len);  // 텍스쳐의 평균값(Na)이 1에 가깝다는 말은 각 텍셀에 저장된 벡터의 방향이 비슷하다는 뜻.

float scale = (1 + ft * s) / (1 + s);

float spec = scale * pow(saturate(dot(Na,H))/len, ft*s);

// 결국 스펙큘러 지수를 평균법선값을 기반으로 조절하겠다는 뜻.


원래 버전에서는 이 모든것들이 dot(Na, H)와 dot(Na, Na)로 인덱스화된 2D LUT에 저장되는데,

이 경우 Clamp 텍스쳐 주소 모드는 saturate()를 처리해 준다.

LUT는 픽셀 셰이더 2.0 이하 버전을 쓰던 옛날에는 의미가 있었지만, 현재 우리는 셰이더에서

그냥 바로 판별 할 수 있기 때문에 스펙큘러 지수당 LUT는 필요 없고, 그럼 으로 인해 

잠재적인 캐시 와 정밀도 문제를 피할 수 있다.


방정식의 첫번째 부분인  또한 한 방향으로만 에너지 보존을 처리하기 때문에 

약간 가짜의 느낌이 나며, 1은 실제로 2가 되어야 한다고 확신한다.

내가 정말 원하는건 블린 퐁을 정규분포함수(NDF)로 취급하는 것이다.



이미 에너지 보존 블린 퐁을 사용하는 사람이라면 이 공식은 익숙하고 우아하게 보일 것이다.

스펙큘러 지수를 조정하면 모든것이 잘 동작할 것이다.


이는 명확해 보이긴 하지만 디퍼드 렌더링의 경우 초기 화면 패스에서 이 작업을 수행해야 한다.

그러므로 모든 라이팅 대신에  G버퍼에 지수를 팩킹하기 전에 한번만 스케일링 해야 한다.

이는 또한 뷰 공간에서 BFN(best fit texture인듯) 또는 두개의 구성요소 같이

법선의 영리한 G버퍼 인코딩을 자유롭게 사용할 수 있다는 것을 의미한다.


불행히도, 이는 Toksvig AA의 중대 문제점을 발생한다.

3Dc 및 (일반적으로)DXT5와 같은 두개의 입력성분을 사용하는 법선에서는 사용할 수 없다.

이 기술의 전체 기조는 지역 거칠기(분기하는 법선)는 필터링된 법선의 길이에 의해 대략적으로 포착되므로 

단위벡터를 재 구성하는 인코딩으로는 이를 수행하는 것이 좋지 않다.

또한 DXT1을 노멀맵에만 독점적으로 사용하더라도, 압축은 여전히 벡터 길이와 혼동된다.

(DXT의 압축방식이 벡터길이에 영향을 끼쳐 Toksvig AA의 결과에 영향을 끼친다는 말이듯..)

재 정규화 후 조명에 대해 허용되는 결과가 종종 나오기 때문에 이 사실을

잊어버리기는 쉽지만 실제로 Toksvig AA에서는 혼란스러울 수 있다.

(어차피 ~1로 정규화 하고 그 결과는 결국 라이팅에서 허용하는 결과값이기때문에 이상함을 못느낄수 있다는 말인듯..)

이 모든것을 감안해 보면 개발자가 이 기술을 채택하지 않은게 놀라운 사실은 아니다.


이는 또 다른 막다른 골목이었을까?

실제적으로 전혀 아니다. 해결책에 좀 더 가까워졌다.


야생적 직감

사실 간단한 아이디어가 하나 있다.

Toksvig과 LEAN 매핑은 텍스쳐 필터링을 사용하니까 이를 오프라인으로 만드는 것이다.

그림1의 법선맵에서 각 밉 레벨의 가우시안 필터링된 버전으로부터 Toksvig Factor을 

미리 계산해서 가져올 수 있다면 어떨까?

그림 1 : 법선 맵


결과는 그림 2에 나와있으며 무처 직관적이다.

원본 법선맵에서 평평한 부분은 흰색(광택), 지글거리고 울퉁불퉁할 수록 어두워진다.

그림 2 : Toksvig map


올바른 커널 사이즈를 가진 이 Toksvig map은 실시간 Toksvig 메소드와 실제로 잘 어울리며

이를 구현한 실제 데모는 글의 마지막에서 볼 수 있다.


그림 3a : Toksvig AA 확대 관찰

그림 3b : Toksvig map 확대 관찰


우리가 실제로 가지고 있는 것은 자동 생성된 안티 엘리어싱 gloss 맵이며 LEAN 용어와 달리 실제로 잘 압축된다.

또한 이 맵이 아트 임포트 파이프라인의 일부로 생성되면 선택한 압축 방법을 사용하기 전에

고 정밀도 3성분 법선을 무료로 사용할 수 있다.


이 맵을 사용하는 것은 다른 gloss map을 사용하는 것과 마찬가지로 어렵지 않다.


1
2
3
4
float ft = tex2D(gloss_map, uv).x;
float p = ft*s;
float scale = (p + 2)/8;
float spec = scale*pow(saturate(dot(N, H)), p);


하지만 이 글을 주의깊게 읽은 독자라면 Toksvig Map이 특별한 스펙큘러 파워를 염두에 두고 생성되었음을 알 수 있다. 

다행히도 100정도의 값으로 잘 동작하는 것처럼 보이는 적당한 콘트라스트를 제공하는 고정된 power로 

텍스쳐를 만들 수 있고, 유연성이 필요한 경우 나중에 다시 변환 할 수 있다.(예를 들자면 텍스쳐 재사용이나 재질 속성 변경)


ft /= lerp(s/fixed_s, 1, ft);

다른 방법은 적절한 power인  를 Naty Hoffman에 의해 제안된 최대 스펙큘러 지수(범위 0~1)로서 저장하는 것이다.

이 로그 공간 광택 용어는 아티스트가 보다 직관적으로 작업할 수 있으며,

지수에 대한 별도의 머티리얼 속성이 필요하지 않고, 게다가 또한 직접 G버퍼 저장을 위한 편리한 포멧이다.

세번째 방법은 분산 또는 법선의 길이를 대신 저장하고 나머지 계산은 실시간으로 수행하는 것이다.


데이터 자체는 스펙큘러 마스크와 함께 팩 되거나 기존 gloss맵을 조정하는데 사용된다.

심지어 아티스트가 그림을 그리는 시작점으로 직접 사용가능한지도 생각해 봤지만, 이럴경우

엘리어싱이 다시 나타나는 것을 방지하기 위해 주의가 필요하다.


물리 기반 셰이딩 측면에서 gloss 맵이 스펙큘러 마스크보다 더 중요하지만, 아티스트들은

일반적으로 후자에 더 편하다.

게다가, 에너지 보존 스펙큘러로 가능한 높은 강도의 범위에서 안티 엘리어싱은 보다 더 치명적이다.


이러한 이유로 인해 자동 생성되는 텍스쳐에 대한 아이디어는 아직 결과물에 대해 모두 

테스트 해보지는 않았지만 실제로 매력적인 아이디어라고 생각한다.


나는 작업의 80~90프로를 자동으로 해주는 아트 툴을 무척이나 좋아하지만,

여전히 직접 들어가서 결과물을 트윅(조정)할 수 있는 방법을 제공한다.

결과적으로 머리카락을 덜 당기고 폴리싱에 더 시간을 할애 할 수 있다.

이것이 내가 원하는 방식이다.


OK목장의 결투

Toksvig Mapping은 Lean Mapping과 무었이 다른가?

글쎄, 이방성(anisotropy) 부분이 부족한 만큼 확실히 좋지는 않으며,

어떤 경우에는 스펙큘러 하이라이트가 과도하게 넓어지고, 또 어떤 경우에는 엘리어싱 얼룩들을 남긴다.

하지만 Clean Mapping을 대신 미리 저장하는 것이 가능하며, 보수적으로 감쇠하는 경향이 있기 때문에

약간의 하이라이트 블룸이 발생하는 비용으로 나머지 반짝이는 것들을 줄인다.


우리가 이것을 할 수 있는 이유는 Toksvig와 Clean을 행하는 데 있어 서로를 분리해 주는

가장 중요한 것이 분산의 측정이기 때문이다.


Toksvig Maps과 관련해서 앞서 언급한 모든것(베이킹, 평가, power 간 변환 등)도 마찬가지로 여기에 적용된다.

LEAN을 베이킹하는데 성공했지만 다른 이야기를 하겠다.


LEAN 매핑은 기본 사실에 더 가깝지만 미리 구운 Toksvig/CLEAN 매핑은 여전히 바로 지금 

대부분의 사람들이 하는것 처럼 아무것도 하지 않는 것보다는 훨씬 낫다.


어서 가요, 카우보이!

여기에 표준 블린 퐁(기본)과 Toksvig AA및 Toksvig Map 를 전환할 수 있는 간단한 WebGL 데모가 있다.

셰이더 코드도 바로 편집할 수 있다.


데모 업데이트 : Toksvig Map 옵션과 NVIDIA GPU와 관련된 시각적 문제에 대한 보고가 있었다.

Mip맵이 없는 것처럼 보이면 최신 드라이브로 업데이트 하면 문제가 해결된다.


블린 퐁으로 반짝거리는 것 외에도 마우스 휠로 줌 아웃 할 때 울퉁불퉁한게 사라지는 것 처럼 주전자가

어떻게 반짝이는지 확인해라.

대조적으로, 머티리얼은 Toksvig의 외관을 유지한다.


필터링 프로세스를 보여주는 또 다른 작은 예제도 만들었다.







아래 내용은 렌더몽키로 테스트 해 본 내용.

기존 블린 퐁 방법


Tobsk 방법


Tobsk.rfx


nvidia거 : 

ToksvigFactorComparison.zip


Reference Link

중요한 링크들은 원문에 대부분 다 포함되어 있고 아래 링크들은 추가로 달아둔 링크.

원문의 링크도 꼭 한번 다 읽어보길 추천.

1. energy conserving Blinn-Phong

2. best fit normal map generator + source code

3. Selective supersampling

'Study > Graphics ' 카테고리의 다른 글

Chromatic Aberration 1 (색수차)  (0) 2020.12.28
밉맵 텍스쳐링  (0) 2020.01.05
Clipmaps  (0) 2019.06.15
early z  (0) 2018.08.29
hlod  (0) 2018.07.20
TAGS.

Comments