주의 : 번역이 개판이므로 이상하면 원문을 참조하세요.

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

원문 : How To Split Specular And Diffuse In Real Images


How To Split Specular And Diffuse In Real Images

실제보다는 어렵다고 생각하는 것을 정리해 두십시오. 제가 집에서 만든 것은 실제 이미지에서 diffuse 요소와 specular 요소를 분리하는 편광을 사용하는 기능입니다. 아티스트들은 사진 레퍼런스를 찾기 위해 많은 시간을 들입니다. 하지만 specular 와 diffuse 를 분리하는 것은 재질을 이해하는 데 있어 도움을 줍니다. 타이틀 이미지에서( 역주 : 여기에는 타이틀 이미지가 없습니다. 첫 번째 이미지를 의미합니다 ), 왼쪽은 diffuse 만 나온 것이고, 중간은 diffuse 와 specular 가 같이 나온 것이고, 오른쪽은 specular 만 나온 것입니다. 제가 여기에 대한 전문가는 아니지만, 그것을 이해하는 방식에 대해서 이야기하고자 합니다.

 

 1. Original

 Image:

 

 2. Diffuse Only:

 

 3. Specular Only:

 

이걸 스스로 하고 싶다면, 다음과 같은 것들이 필요합니다:

1. 수동 모드로 찍을 수 있는 카메라. 예를 들면 SLR.

2. 카메라를 만지지 않고 여러 장을 찍을 수 있도록 해 주는 원격 셔터 콘트롤러.

3. 광원. 저의 경우에는 Ikea 에서 산 램프를 사용합니다.

4. 편광 필름 몇 개. 저는 polarization.com 에서 구합니다. 여러분은 "Fully Laminated Linear Polarizer Sheets" 를 원할 겁니다. Linar 필터인지 확인하세요. Circular 필터를 구하시면 안 됩니다.

초기 단계에 컴퓨터 그래픽스에서는 오브젝트가 diffuse 반사와 specular 반사를 모두 가지고 있다고 가정했습니다. 어떤 빛이 표면을 비추고 있고 그 근처에 카메라가 있다고 가정해 봅시다. 그런데 이런 모델은 엄청나게 단순화된 모델입니다.

표면을 비추는 일부 빛들은 엣지( edge, 역주 : 그림에서 표면의 테두리를 의미하는 듯 )에서 몰래 빠져 나갑니다. 우리가 백색 빛과 파란색 표면을 가지고 있다면, 그 빛은 백색으로 그냥 남아 있을 겁니다. 우리는 이것을 specular 라고 부르죠.

어떤 빛은 표면에 의해 흡수될 것입니다. 일부 전자들은 소멸될 것이고, 새로운 포톤들이 랜덤한 방향으로 방출될 겁니다. 만약 우리가 백색 빛과 파란색 표면을 가지고 있다면, 방출되는 빛은 파란색이 겁니다. 우리는 이를 diffuse 라고 부릅니다.

여러분은 이미 그 사실을 알고 계실 겁니다. 그렇지 않다면 이제 알게 됐겠죠. 흥미로운 점은 그 빛이 편광될( polarized ) 수 있다는 것입니다. 여러분의 친구인 wikipedia 에 가면 더 많은 것을 배울 수 있을 겁니다. 게다가 specular 빛은 자신의 입사 편광( incoming polarization )을 유지하지만 diffuse 빛은 그렇지 못합니다. 그래서 diffuse 빛은 랜덤한 방향으로 랜덤한 편광을 가진채 다시 전파되는 겁니다. 우리는 그것을 비편광되었다( unpolarized )고 말할 수 있죠( 역주 : [ 편광으로 입체 영화를 본다 ] 에 좀 더 쉬운 설명이 있습니다 ).

여기에 장치가 있습니다.

매우 기본적입니다. 저는 카메라의 모든 설정을 수동 모드로 만들었습니다. 이런 의미죠:

1. 수동 노출( exposure, 역주 : [ 이제 노출을 조정해 보자 ] 를 참조하세요 ).

2. 수동 조리개( aperture, 역주 : [ 이제 노출을 조정해 보자 ] 를 참조하세요 ).

3. 수동 화이트 밸런스( white balance, 역주 : [ 화이트 밸런스 완벽 컨트롤하기! ] 를 참조하세요 ).

4. 수동 감도( ISO, 역주 : [ 카메라 감도( ISO )란? ] 을 참조하세요 ).

5. 자동 초점( Auto Focus ) 끄기.

6. 색상 프로우파일( profile )을 Adobe 98 이 아니라 sRGB 로 설정( 표준 감마 스페이스 색상 공간, 역주 : [ RGB 색공간 ] 을 참조하세요 ).

그리고 원격 셔터에서 손가락을 살짝 뗍니다. 그런 방식으로 저는 카메라에 손대지 않고 여러 장의 사진을 찍습니다. 만약 여러분이 카메라를 손대서 여러 장의 사진을 찍는다면, 정렬이 흔들릴 것이라고 생각합니다. 그리고 우리는 광원을 가지고 있습니다. 이제 광원에 대해 자세히 살펴 보죠.

광원은 그냥 Ikea 에서 사온 할로겐( halogen, 역주 : 발음이 핼러즌 ㅡㅡ ) 램프입니다. 하지만 그 앞에 선형 편광 필터가 달려 있습니다. 그 필터를 전기식 테이프( electrical tape )로 붙였습니다. 왜냐하면 저는 품격이 있는 사람( claasy guy )이니까요. 경고를 하나 하자면, 할로겐 램프는 엄청 뜨거워지므로 제 편광 필터가 녹아버려서 좀 휘었습니다.

이제 우리가 할 일은 두 개의 사진을 찍는 겁니다. 그렇지만 카메라 앞에 편광 필터를 달 것입니다. 카메라와 광원에 모두 편광 필터를 달아야 한다는 것을 기억하세요. 만약 제가 비디오 게임 프로그래머가 되기 위해 LA 에 왔다고 생각한다면, 잘못 생각하고 계신 겁니다. 손 모델의 꿈을 꾸고 있는 동안 돈을 버는 방법일 뿐입니다( 역주 : 안 웃김 ㅠㅠ ).

편광 필터에 오렌지색 테이프가 보이세요? 저는 이제 편광 필터를 90 도 회전시킬 것이고 다른 사진을 찍을 겁니다. 오렌지 테이프가 어떻게 이동했는지 확인해 보세요.

이제 우리가 찍은 첫 번째 사진이 있습니다. 정렬이 완벽하게 되었다면, 그 안에 specular 가 전혀 없을 겁니다. 물론 보통 그런 경우는 있을 수가 없죠. 왜냐하면 손으로 정렬을 완벽하게 하는 것은 불가능하기 때문입니다.

이것이 어떻게 동작할까요? 편광이 표면에 비춥니다. Specular 빛은 표면에서 반사되어서 카메라로 들어 오죠. 그 빛은 편광 필터에 도달하고, 그 편광 필터는 빛의 편광에 대해 수직으로 정렬되어 있습니다. 그러면 편광 필터에 의해 모든 것( specular )이 흡수됩니다. 반면에 diffuse 빛은 표면에 의해 흡수되기는 하지만 비편광된 상태로 다시 방출됩니다. 그래서 편광 필터는 diffuse 빛의 절반만 흡수합니다. 그리고 나머지는 카메라로 들어 오게 되죠. 그래서 그 이미지는 50% 의 diffuse 와 0% 의 specular 를 가집니다. 이제 두 번째 이미지를 보죠.

이 녀석은 카메라로 향하는 specular 빛에 대한 편광이며 편광 필터에 대해 정렬되어 있습니다. 그래서 모든 빛이 통과하게 되죠. 반면에 diffuse 빛은 여전히 비편광 상태이며, 절반이 흡수됩니다. 이 이미지는 50% 의 diffuse 와 100% 의 specular 를 가집니다.

만약 첫 번째 이미지를 A 라고 하고 두 번째 이미지를 B 라고 한다면, diffuse 이미지는 2 * A 이고 specular 이미지는 B - A 입니다. 물론 이 이미지들은 sRGB 프로우파일로 저장되어 있습니다. 그래서 두 개의 이미지를 비교하고 그것들을 분리해서 각 결과를 sRGB 이미지로 만드는 쉐이더 코드를 만들었습니다. 항상 그렇듯이, 이 코드를 실제로 테스트해 본 건 아닙니다.

float LinearToSrgb(float val)
{
   float ret;
   if (val <= 0.0)
      ret = 0.0f;
   else if (val <= 0.0031308f)
      ret = 12.92f*val;
   else if (val <= 1.0f)
      ret = (pow(val, 0.41666)*1.055f)-0.055f;
   else
      ret = 1.0f;
   return ret;
}

float SrgbToLinear(float val)
{
   float ret;
   if (val <= 0.0f)
      ret = 0;
   else if (val <= 0.04045f)
      ret = val / 12.92f;
   else if (val <= 1.0f)
      ret = pow((val + 0.055f)/1.055f,2.4f);
   else
      ret = 1.0f;
   return ret;
}

int g_bSpecOrDiff;

float4 ps_main( float2 texCoord  : TEXCOORD0 ) : COLOR
{
   float3 srcA = tex2D(Texture0, texCoord ).rgb;
   float3 srcB = tex2D(Texture1, texCoord ).rgb;
   float3 linA = SrgbToLinear(srcA);
   float3 linB = SrgbToLinear(srcB);
   float3 linDiff = linA*2;
   float3 linSpec = linB-linA;
   float3 texDiff = LinearToSrgb(linDiff);
   float3 texSpec = LinearToSrgb(linSpec);
   float3 ret = g_bSpecOrDiff ? texDiff : texSpec;
   return ret;
} 

만약 이 코드가 맞다면 여러분의 diffuse 이미지는 다음과 같이 보일 겁니다:

그리고 specular 이미지는 다음과 같이 보일 겁니다:

이 절차는 완벽한 것은 아닙니다.

1. 보통 diffuse-only 이미지에서 약간의 specular 를 포함하게 될 것입니다.

2. 어떤 물체들에 대해서는 별로 좋은 결과를 내지 못합니다. Specular-only 이미지에서, 손잡이가 약간 푸르스름합니다. 저는 손잡이가 유전체( dielectric )여서 ( 역주 : 빛의 ) 주파수를 약간 교란한다고 생각합니다.

3. 만약 specular 나 diffuse 이미지가 1.0 에서 잘린다면( clamping ), 그런 픽셀들은 엉망이 될 겁니다. 그럴 때는 노출값을 낮추는 것이 좋습니다.

4. 원격 셔터를 사용하십시오. 그렇지 않으면 정렬 문제가 생길겁니다.

별로 문제가 많이 발생하지 않고 여러분만의 specular/diffuse 분리를 해낼 수 있었으면 좋겠네요.

휴~ 긴 글이었습니다.

+ Recent posts