안녕하세요, 흑기사 입니다. 
 지난 시간에는 텍스처를 적용하여 fixed function shader를 어떻게 작성할 수 있는지를 알아보는 시간을 가졌습니다. 이번 시간에는 텍스처 활용에 대해서 좀 더 알아볼까 합니다.
 
 아! 갑자기 오브젝트에 텍스처 두 장을 입혀보고 싶은 생각이 드는군요. 별다른 이유는 없고, 그냥 문득 그런 생각이 떠올랐습니다; 그럼 한번 시작해볼까요?

 우리가 해야 할 일은 매우 명확합니다. 일단 텍스처를 위한 프로퍼티가 하나 더 추가하고, 텍스처를 적용하여 연산하기 위해 기존 SetTexture 외에 또 다른 SetTexture 커맨드를 추가해 주면 끝입니다.

 따라서 새롭게 작성된 셰이더 코드는:

Shader "2Textures" { 
    Properties { 
         _MainTex("Texture"2D) = "white" {} 
         _SubTex("Texture"2D) = "white" {} 
    } 
    SubShader { 
           Pass { 
               SetTexture [_MainTex] { 
                 Combine texture DOUBLE 
               } 
                                                 
               SetTexture [_SubTex] { 
                 Combine texture * previous 
               } 
           } 
    } 
}

어라... 근데 뭔가 예전 코드에 비해 갑자기 허전해졌습니다!
네, 그렇습니다... 이번에는 라이팅 연산은 제외하고 순수하게 텍스처만 합성하여 오브젝트에 적용해볼까 합니다. 따라서 재질과 라이팅에 관한 코드는 과감하게 삭제하였습니다. 혼란스러워 하지 마시길 바랍니다.(오히려 코드는 더 간단해졌습니다!)

 코드를 한번 살펴보도록 하겠습니다. 진한 글씨로 표시된 부분을 주목할 필요가 있군요. 일단 라이팅 연산을 배제했기 때문에 기존에 SetTexture 연산을 정의할 때 사용하던 primary 가 없어졌군요. 이전 결과값이 없으므로, 그냥 첫번째 텍스처 색상값만 두 배 연산하도록 했습니다. 그리고 다음에 등장하는 두번째 SetTexture 커맨드를 보시면 뭔가 새로운 것이 등장했습니다. 바로 previous 라는 녀석인데, 이것은 바로 직전의 SetTexture에서의 연산를 통해서 나온 결과값을 의미합니다. 따라서 지금 코드에서는 previous 는 앞서 _MainTex 색상값을 두배한 값을 가리키게 됩니다.

이번에는 인스펙터창을 살펴볼까요? 
우리는 여기서 서로 다른 2장의 텍스처를 설정하게 됩니다:

그래서 적용 결과는:

적절히 두 이미지가 합성되어서 나오는군요...  
음, 근데 이번에는 생각보다 그렇게 재밌지는 않았군요. 그럼 다른 것을 하나 더 해보겠습니다.
 이번에는 벽돌 텍스처 이미지 대신, 아래의 캐릭터 이미지를 덧붙여 보겠습니다. 

 이전과는 상황이 좀 다릅니다. 이번에는 검정부분은 적용되어선 안되고, 캐릭터 부분은 적용하되 이전 텍스처 이미지와 섞이지 않도록 합니다. 쉽게 다시 말하면, 캐릭터 모양의 스티커를 떼어서 구(sphere)에 붙인다고 생각하면 되겠습니다.


 만약 앞서 작성한 셰이더 코드를 그대로 사용하면 어떤 결과가 나올까요?
 결과는 이렇게 됩니다:

당연하겠지만.. 원치 않은 결과가 나왔습니다. 단순히 텍스처 색상값을 곱했기 때문에 캐릭터는 이전 텍스처 이미지와 섞여버렸고, 출력하고 싶지 않은 검정부분은 그대로 그려질 수 밖에 없군요. 이거 뭔가 다른 조치가 필요하다는 것이 느껴집니다.


우선 우리는 원하는 것을 얻기 위해서 캐릭터 텍스처의 알파값을 사용하기로 합니다. 사실 지금 사용하는 캐릭터 텍스처 이미지의 알파값을 확인해보면 다음과 같이 제작되었습니다:

그러니까 캐릭터 부분은 알파값이 1 이고, 다른 검정색으로 칠해진 부분은 알파값이 0 이었군요. 음, 그렇다면 해당 알파값의 비중만큼 해당 캐릭터 텍스처의 색상을 반영하도록 한다면 원하는 결과를 얻을 수 있을 것 같습니다. (즉, 알파값이 0인 경우에는 캐릭터 텍스처 색상값을 적용하지 않게 되겠죠.)


이것을 위해 마지막 SetTexture 커맨드의 블럭의 코드를 다음과 같이 수정하겠습니다:

 SetTexture [_SubTex] { 
       Combine texture lerp(texture) previous 
 } 

lerp() 라는 것이 등장했군요. 음, 뭔가 어려운 듯이 보이지만 알고보면 간단한 구문입니다:
 
 A lerp (B)  C
 
A와 C를 보간하여 결과값을 만들게 되는데, 그 기준값으로 B의 알파값를 사용하겠다는 것을 의미합니다. 즉, B의 알파는 0~1의 범위를 가지며 B = 1일 경우엔 결과는 A가 되며, B = 0일 경우에 결과는 C가 됩니다. 따라서 이번 예제에서는 캐릭터 텍스처의 알파값을 이용하여, 적절히 두 텍스처의 색상값을 취하여 원하는 결과를 얻어낼 수 있는 것입니다.

결국 최종 코드와 결과는:

Shader "2Textures" { 
    Properties { 
         _MainTex("Texture"2D) = "white" {} 
         _SubTex("Texture"2D) = "white" {} 
    } 
    SubShader { 
           Pass { 
               SetTexture [_MainTex] { 
                 Combine texture
               } 
                                                 
               SetTexture [_SubTex] { 
                 Combine texture lerp(texture) previous 
               } 
           } 
    } 
}

 이번 시간은 여기까지 입니다.
 감사합니다~



'Unity' 카테고리의 다른 글

유니티 셰이더의 기초 #6  (17) 2013.10.14
유니티 셰이더의 기초 #5  (8) 2013.08.19
[Tip] 디바이스에서 Debug.Log 출력하지 않기  (0) 2013.08.13
유니티 셰이더의 기초 #3  (5) 2013.08.13
유니티 셰이더의 기초 #2  (0) 2013.08.13
Posted by 흑 기사
,