이것저것

[UNITY] 쉐이더 4장 - 버텍스 컬러 본문

[유니티] Unity3D/Unity Shader

[UNITY] 쉐이더 4장 - 버텍스 컬러

Patch_JA 2019. 4. 12. 23:00
728x90

 

저번 포스팅에서는 Time 변수와 UV Animation, UV 채널 그리고 불 이펙트 만들어 보기 등을 실습하였다.

이번 포스팅에서 다룰 내용으로는 버텍스 컬러(Vertex Color)를 배우고 실습해 보겠다.

 

⊙ 버텍스 컬러 (Vertex Color)

버텍스 컬러(Vertex Color)가 무엇?

말 그대로 버텍스에다가 직접 색을 칠하는 것이다. 

예를 들어 빨간색과 초록색으로 면에 칠해놓고 각 색 영역에 맵핑들을 넣을 수 있다.

보통은 모델링 프로그램에서 사용하는 것인데, 엔진에서도 사용이 가능하다.

그중에서 엔진으로부터 사용 가능한 정보들이 5가지가 존재하는데

위치, UV, 컬러, 노멀, 탄젠트 이다.

 

 

유니티에서 버텍스 컬러(Vertex Color)

< 에셋주소 : https://assetstore.unity.com/packages/tools/modeling/polybrush-beta-111427 >

유니티에서는 버텍스 컬러 페인팅 기능을 기본적으로 지원하지 않기 때문에

에셋에서 다운로드하여서 사용해야 한다. 에셋 스토어에서 PolyBrush를 검색하면

나오는 에셋을 프로젝트에 적용시킨다.

 

 

프로젝트에 적용시켰다면 다음으로 매번 세팅했었던

기본형 셰이더와 마테리얼 그리고 Plane오브젝트를 준비한다.

 

 

기본 세팅이 완료되면 유니티 상단에 에셋으로 추가된 [Tools 탭]이 보일 것이다.

해당 탭에서 [Polybrush Window]를 눌러서 창을 띄운 후 원하는 곳으로 박제시켜둔다...

혹은 단축키 '컨트롤+쉬프트+V'로 켤 수 있다.

 

 

[Polybrush 창]에서 상단에 3번째에 있는 ['Paint Vertex Color'탭]을 선택해준다.

하단에 컬러 마스크에서 색상을 레드(1, 0, 0) 색상으로 변경해준다.

 

 

GIF에서는 칠하는 곳이 잔상으로 남는데 실제 실습을 했을 때 아무런 변화가 없는 것처럼 보인다.

 

왜냐하면 셰이더에서 버텍스 컬러를 출력하지 않고 있기 때문이다..

한번 색상을 띄우도록 코드를 수정해보자.

 

버텍스 컬러를 사용하기 위해 Input 구조체에 float4 color : COLOR를 추가해 주고

명확하게 보기 위해 Albedo대신 Emission에 IN.color.rgb를 추가해주었다.

여기서 궁금한것이 있을것이다. 바로 color:COLOR 라는 변수..

:COLOR 이것을 시맨틱 표시자라고 한다.

 

여튼 결과를 확인해보면..

보이지 않았던 버텍스 컬러가 보이기 시작했다..

 

 

⊙ Texture Splatting 흉내내기

텍스쳐 스플래팅이란 간단하게 말해서 여러 타일의 텍스쳐를 부드럽게

섞이게 하는 방법이라고  생각하면 된다. 

좀 더 검색해보니 "서페이스 상의 텍스쳐들을 알파 맵을 사용 하여 서로 블렌딩 하는  방식을 말한다"라 

간단하게 쓰여있었다...

 

시작 전에 일단 검은색으로 해두는 게 보기에도 편하다.

[PolyBrush창]에서 항상 색을 지정할 때 기본적으로 제공되어있는

컬러를 사용하지 말고 직접 색상 값을 지정해서 사용하자..

기본 제공되어있는 색상 중 검정이나 빨간색을 누르면 완벽한 해당 값이 아니다..

 

레드(1,0,0), 그린(0,1,0), 블루(0,0,1), 블랙(0,0,0) 이렇게 4가지 색을 구분하여 칠해 놓는다.

그다음 코드에서 텍스쳐 4장을 받도록 코드를 추가한다.

 

 

텍스쳐 4장이 들어가는 것을 확인하였다.

이번에는 색상별로 각 텍스쳐들이 적용되도록 해보자.

 

lerp함수를 이용하여  레드에 tex1 그 외에는 tex2를 넣게 하였다.

그런데 결과를 확인해보면..?

 

레드그린이 서로 바뀐 것으로 보인다.

해결하려면 그냥 lerp 인자 값을 서로 바꿔주면 된다.

o.Emission = lerp(tex2, tex1, IN.color.r);

정상적으로 레드에 벽돌 타일의 텍스쳐가 들어간 것을 확인했다.

그렇다면 이번엔 색상별로 타일들을 전부 넣어보자.

r, g, b, black 순서대로 맞게 칠해진 것을 볼 수 있다.

 

여기서 미세 퀴즈(?)

lerp함수를 쓰지 않고도 띄울 수 있을까?

우선 lerp함수 속내용의 공식을 확인해보자.

어.. 숫자만 봐도 조금 머리 아프다.. 이해하면 좋겠지만 일단은 공식만 갖다가 써보자..

lerp함수를 사용하지 않고 공식으로 구현해도 결과값은 똑같은 것을 볼 수 있다.

 

⊙ NormalMap 적용하기

 

일반적인 텍스쳐와 다른 점이라면 surf함수에서 

UnpackNormal 함수 가 등장한다.

UnpackNormal함수에 tex2D 함수를 사용하여 노말 맵을 적용시키게 되어있다.

 

저장하고 결과를 확인해보러 간다.

그러나 실행했는데 혹시라도 위 사진과 같은 에러가 뜬다면?

당황하지 말자.. 에러가 당연한 것이다.

 

상단 #pragma surface 아래 #pragma target 3.0 코드를 추가시켜준다.. 

 

저저번 포스팅에도 아마 잠깐 언급하긴 했었지만 #pragma target 코드를 입력하지 않으면

기본적으로 target 2.5로 디폴트로 잡히게 된다. 그러나 해당 버전에서는 노말 맵을 소화해내지 못하고

에러를 뱉어낸 꼴이라고 보면 될 것 같다. (한계에 도달..)

 

*추가적으로 노말맵을 4개 추가해도 에러가 날 수 있는데 이것 또한 target 3.0이 버티지 못하는 것이다..

target 3.5 이상으로 올려주면 해결이 된다. ( ㅂㄷㅂㄷ ) 

 

노말맵이 적용된 걸 볼 수 있다.. 음.. 그런데 뭔가 부족해 보인다.

조금만 수정해보자.

o.Normal에  float3(bump1.r * 2, bump1.g * 2, bump1.b); 로수정하여

노말을 두배로 강하게 주고 Emission을 Albedo로 변경해본다.

조금이나마 강해진 것을 볼 수 있다. Directional Light를 움직여서 확인하면 더 잘 보인다.

 

 

⊙ 젖은 타일 만들기

< https://docs.unity3d.com/Manual/SL-SurfaceShaders.html >

SurfaceOutputStandard 구조체를 다시 봐보면 내부에 

Metallic과 Smoothness도 존재하는데 이것들을 한번 추가해보자.

 

인터페이스를 추가해서 확인해도 좋고 바로 값을 입력해 넣어도 상관없다.

본인은 확인하기 편하기 위해 인터페이스를 빼서 만들었다.

 

질감이 확연히 달라지는 것을 볼 수 있다. 조절하여 적당한 값을 맞추면 된다.

 

 

일부 컬러에 노말맵 입히기

4개 색상 중에 원하는 색상에만 노말맵을 입히기 위해서는

아래 코드를 이용하면 뒤에 컬러값만 바꿔서 원하는 부분에 노말맵을 입힐 수도 있다.

o.Normal = lerp(bm1, float3(0, 0, 1), 1 - IN.color.r);

 

이미지 좌측부터 R->G->B

Time 변수를 활용한 물 흐르기

저번 포스팅에서 배웠던 Time변수를 사용하면 물이 흐르는 것 또한 표현 가능하다.

float3 bm1 = UnpackNormal(tex2D(_BumpMap, IN.uv_BumpMap  + sin(_Time.y/15)));

 

오클루전 ( Occlusion )

오클루전이라는 단어는 많이 들어봤지만 사실 정확하게 알고있지는 않다.

유니티 오클루전 맵 도큐멘션을 봐서는 조명에 따라 특정 부분을 음영처럼 빛을

덜 받게 하는 것 같다.

 

오클루전을 적용하기 위해선 텍스쳐처럼 똑같이 하나 만들어준다.

그런 다음 o.Occlusion 에다가 텍스쳐를 적용시켜준다.

 

텍스쳐와 빛에 따라 달라지는 것을 확인할 수 있다. 

이로써 셰이더의 기초가 끝나게 된다..

 

 

[출처]

에셋 주소 : https://assetstore.unity.com/packages/tools/modeling/polybrush-beta-111427 

SurfaceOutputStandard : https://docs.unity3d.com/Manual/SL-SurfaceShaders.html

오클루전 맵 : https://docs.unity3d.com/kr/2017.4/Manual/StandardShaderMaterialParameterOcclusionMap.html

Comments