작성자 : 오석주 테크니컬 디렉터( TD, Technical Director ).

모바일에서 사용할 수 있는 SSS 에 대해서 소개한 글입니다. 저는 오탈자 교정 및 비문 수정만 했습니다.


Surbsurface Scattering( 이하 'SSS' ) 은 주로 빛이 표면의 안쪽으로 투과되어 들어 갔다가 다른 곳으로 튀어 나가는 표면에서 일어나는 현상이다. 주로 피부, 대리석, 우유, 양초 등이 이해 해당하는 물질들이다. 

우리가 주로 사용하는 BRDF( Bidirectional Reflectance Distribution Function ) 는 그림 1의 (a) 에서 볼 수 있듯이 빛이 입사한 지점과 반사되는 지점이 동일하다는 가정에서 만들어져 있다.

그림 1. (a) BRDF 와 (b) BSSRDF 에서의 빛의 산란.

출처 : https://graphics.stanford.edu/papers/bssrdf/bssrdf.pdf


그러나 SSS 를 계산하려면 Figure 1 의 (b) 와 같이 입사한 지점과 반사되는 지점이 다르다. 그러므로 아래와 같은 BSSRDF( Bidirectional Scattering-Surface Reflectance Distribution Function ) 을 사용해야 한다.

그림2. BSSRDF 모델.

출처 : https://graphics.stanford.edu/papers/bssrdf/bssrdf.pdf

편집자 주 :

앞에서 언급한 피부, 대리석, 우유, 양초 등을 이런 모델을 통해 렌더링하면 더욱 사실적인 결과를 산출한다. 여기에서는 피부를 중심으로 이야기할 것이다.

피부를 제대로 렌더링하기 위해 BSSRDF 를 실시간 그래픽스에 적용하는 것은 어렵다. 너무 무겁기 때문이다. 그래서 최적화를 위해 Texture-Space SSS 나 Scren-Space SSS( S5 ), Pre-Integrated SSS 등 여러가지 기법들이 만들어지게 됐다. 하지만 이런 기법들은 여전히 모바일에서 사용하기에는 무겁다.

그래서 Texture-Space SSS 나 Screen-Space SSS 의 개념을 기반으로 모바일에서도 사용할 수 있을 정도의 가볍고 근사된( approximated ) SSS 를 만드는 것을 목표로 했다.

일단 앞에서 언급한 두 가지 모델에 대해서 살펴 보도록 하겠다.

그림 3. Texture-Space Blur.

출처 : https://developer.download.nvidia.com/books/HTML/gpugems/gpugems_ch16.html

그림 3 은 Texture-Space( UV-Space ) 에서 라이팅 결과를 블러( Blur )해서 BSSRDF 를 흉내내는 것을 보여 준다. BSSRDF 에서, 블러의 크기는 빛이 입사된 지점과 반사된 지점 간의 차이를 나타내기 위해서 사용된다.

그림 4. Texture-Space SSS 와 Screen-Space SSS 의 비교.

출처 : http://www.iryoku.com/stare-into-the-future

그림 4 에서는 Texture-Space 블러와 Screen-Space 블러의 차이를 보여주고 있다.

그림 5. Screen-Space 블러에서 SSS 까지의 과정.

출처 : https://www.derschmale.com/blog/wp-content/weights.jpg

그림 5 는 Screen-Space 에서 블러한 결과를 사용해서 SSS 의 느낌을 달성하는 방법에 대해서 보여 주고 있다.

여기에서는 Texture-Space 와 Screen-Space 기법의 장단점에 대해서 논의하지는 않겠다. 이 기법들을 실제로 구현해 보면 자잘한 문제들을 가지고 있기 때문에 그것을 해결하는 방법까지 논의하면 할 이야기가 굉장히 많기 때문이다. 

어쨌든 여기에서 중요한 점은 대부분의 기법들이 라이팅 결과를 블러해서 SSS 효과를 만들고 있다는 것이다.

Normal Blur SSS 는 "모든 라이팅을 노멀 벡터와 라이트 벡터의 연산이라고 볼 때, Blur( dot( N, L ) ) 과 dot( Blur( N ), L ) 은 어느 정도 유사성을 띄고 있지 않을까?" 라는 아이디어에서 시작했다.

그림 6. 3x3 노멀 블러 커널.

그림 6 과 같은 커널을 사용해서 노멀맵을 블러한다고 가정해 보자( 여기에서 편의상 L 은 Directional-Light Vector 라 가정한다 ). 그러면 다음과 같은 결과를 얻을 수 있다.

위의 식은 다음과 같다.

실제로는 내적 결과를 0 이하로 잘라내는 과정인 max( dot( N, L ), 0 ) 을 수행하지 않았기 때문에 완전히 같다고는 할 수 없지만 근사치로는 쓸만하다고 할 수 있다. 포인트 라이트와 같은 punctual 라이트를 사용하면, 각 픽셀에서의 라이트 벡터는 달라지지만, 주변 픽셀을 블러한 것이므로 근사치로 사용하는 데 무리가 없다고 생각했다.

그러므로 노멀 벡터를 미리 블러해서 디퓨즈 라이팅을 계산하면 어느 정도 SSS 결과를 근사계산할 수 있다고 생각했다. 그리고 이 방법의 가장 큰 장점은 노멀 텍스쳐 한 장을 더 사용하고 dot( N, L ) 연산을 한 번 더 하는 정도의 비용으로 SSS 를 근사계산할 수 있다는 것이다. 문제는 "어느 정도로 SSS 가 근사되느냐" 이다.

 

그림 7. Object-Space Normal Map 블러. (좌) 원래 버텍스 노멀, (우) 블러된 버텍스 노멀.

일단 이해하기 쉽게 Object-Space Normal Map 을 뽑아 보았다. 여기에서는 블러를 할 것이므로 픽셀 노멀이 아니라 버텍스 노멀을 사용했다. 그리고 실제 적용도 버텍스 노멀에서 뽑아 낸 값으로 적용한다.

샘플에 사용된 모델은 Virtual Model 에서 무료로 제공하는 Louise 모델이다.

그림 8. Normal Blur SSS 결과. Unity3D, Android Platform. Custom PBR, Beckmann Specular.

그림 9. Normal Blur SSS 결과. Unity3D, Android Platform. Custom PBR, Beckmann Specular.

위 샘플들은 모두 Unity3D 의 Android Platform 에서 렌더링되었다. Custom PBR 셰이더를 사용했으며 Specular 는 Beckmann 모델을 사용했다. Normal Blur SSS 의 결과는 상당히 만족할만 했다. 실제로 사용된 노멀맵은 그림 10 과 같다.

그림 10. Louise 에서 사용된 2 장의 노멀맵.

실제로 이 기법을 모바일 기기에서 테스트해 봤을 때 최신 하드웨어에서는 사용했을 때와 그렇지 않을 때의 차이가 거의 없을 정도였다. 일반적인 렌더링 연산에서 늘어난 것은 블러된 노멀맵에 대한 한 번의 샘플링 비용과 dot( N, L ) 연산 몇 개 정도이다. 그러므로 최신 하드웨어에서는 차이를 거의 느낄 수가 없었다.

효과를 더욱 극단적으로 보이게 하기 위해서 과장된 다른 샘플의 예를 들어 보겠다. 아래 모델은 Free 3D Model 에서 무료로 제공되는 3D Scan Head 이다.

그림 11. 과장된 효과를 보여 주는 샘플.

+ Recent posts