이전 포스팅 요약

이전 포스팅에서는 UV에서의 Offset과 Tiling 기본 이론을 바탕을 응용하여 간단한 물쉐이더, 불쉐이더를 제작했다.

 

 

Unity Surface Shader 기초 3강 - 버텍스 컬러 응용

버텍스 컬러란?

1개의 버텍스에는 여러가지 정보가 존재하는데 대표적으로 좌표(Position), UV(Tex coord), Light UV, 컬러(Color),

노말(Bump) 등이 존재한다.

그 중에서 일반적으로 텍스처로 색을 입히는게 아닌 버텍스만의 고유 색상값이 존재한다.

이 색상 값을 이용하여 다양한 방면으로 이용 할 수 있다.

 

모델에 페인트 칠을 할 수 있거나.

 

위 이미지는 하나의 3D 모델로 양끝 부분의 버텍스 컬러를 검은색으로 만든 모델이다. 이를 이용하여

버텍스 컬러을 알파 값으로 사용하여 위와 같이 이펙트에 응용 할 수 있다.

그래서 이번 포스팅에서는 버텍스 컬러값을 이용하여 쉐이더에서 응용하는 법을 포스팅한다.

 

버텍스 컬러 자료 만들기

기본적으로 버텍스 컬러의 색상 값은 float4(1,1,1,1)로 흰색이다.

버텍스 컬러를 조작하는 방법은 크게 두 가지가 있다.

-1. 3ds Max와 같은 3D툴에서 그리는 것

-2. 엔진 자체 기능 이용하기

 

현재 유니티 자체에서는 버텍스 컬러를 조작 할 수 있는 기능이 없다.

하지만 "Poly Brush"라는 무료 에셋을 이용하면 가능하다.

유니티 에셋 스토어에서 에셋을 설치하고

 

메뉴 상단의 Tools->Polybrush->Polybrush Window을 클릭하여 우측 사진과 같은 Poly brush 에디터를 킨다.

버텍스 위치 조작 등 여러 기능이 있지만 이번 포스팅에서는 버텍스 컬러를 그리는 용도로만 사용한다.

 

Poly brush 에디터에서 상단의 3번째 메뉴 버튼이 버텍스 컬러를 그릴 수 있는 메뉴이고

하단에서 색상을 선택하여 유니티 월드상에 메쉬에 버텍스 컬러를 그릴 수 있다.

 

Plane 오브젝트 한 개를 만들어서 버텍스 컬러를 그리지만 반응이 없다.

이유는 유니티 엔진 기본 쉐이더에서는 버텍스 컬러를 출력하는게 아니라 텍스쳐 색상을 출력하게 작성되어 있기

때문이다.

 

버텍스 컬러를 출력하는 쉐이더를 만들어 보자.

 

버텍스 컬러 쉐이더 만들기

Shader "Custom/Sha_5st_2"
{
    Properties
    {
      
    }
    SubShader
    {
        Tags { "RenderType"="Opaque" }
       

        CGPROGRAM
       
        #pragma surface surf Standard 

        struct Input
        {
			float4 color:COLOR;
        };

        void surf (Input IN, inout SurfaceOutputStandard o)
        {
			o.Emission = IN.color.rgb;
        }
        ENDCG
    }
    FallBack "Diffuse"
}

sㅜ새 쉐이더를 만들어서 위 코드로 만들었다.

 

 struct Input
 {
 	float4 color:COLOR;
 };

위 코드는 버텍스에서 받는 정보 중 버텍스 컬러를 받는 변수이다.

:COLOR 처럼 특이한 형태로 변수가 만들어 졌는데 이것을 시맨틱 표시자라고 한다. 시매틱 변수의 뜻은 

이 변수의 "의미"를 GPU에 알린다는 뜻이며 Surface가 아닌 Fragment쉐이더에서는 대부분 이런 형태의 변수가

사용된다.

o.Emission = IN.color.rgb;

그래서 최종적으로 Emission에 버텍스 컬러 변수의 rgb를 넣어서 쉐이더를 완성하고 Polybrush를 이용하여 버텍스 컬러를 그리면 결과물을 확인 할 수 있다.

 

Plane 오브젝트를 한개 만들어서 위 사진과 같이 각 채널 별로 버텍스 컬러를 그렸다.

 

이제 버텍스 컬러 값을 이용하는 쉐이더를 작성해보자

 

텍스쳐 마스킹

이전에 Plane오브젝트에 버텍스 컬러로 각 채널별 색상을 그렸고 이 버텍스 컬러의 색상값을 기반으로 

텍스쳐를 마스킹해보겠다.

 

 

    Properties
    {
        _MainTex_1 ("Albedo_1 (RGB)", 2D) = "white" {}
		_MainTex_2 ("Albedo_2 (RGB)", 2D) = "white" {}
		_MainTex_3 ("Albedo_3 (RGB)", 2D) = "white" {}
		_MainTex_4 ("Albedo_4 (RGB)", 2D) = "white" {}
    }
    SubShader
    {
        Tags { "RenderType"="Opaque" }
     
        CGPROGRAM
      
        #pragma surface surf Standard 
     
        sampler2D _MainTex_1;
		sampler2D _MainTex_2;
		sampler2D _MainTex_3;
		sampler2D _MainTex_4;

        struct Input
        {
            float2 uv_MainTex_1;
			float2 uv_MainTex_2;
			float2 uv_MainTex_3;
			float2 uv_MainTex_4;

			float4 color:COLOR;
        };
		 

우선 텍스쳐 4개를 입력 받을 수 있게 Properties 인터페이스와 SubShader에 변수 설정을 하고

Input에 UV입력 받는 변수 4개와 버텍스 컬러 값을 입력받을 color변수를 작성한다.

 

다음 좌측 사진의 버텍스 컬러 값에 맞게 해당 자리에 텍스쳐를 출력해야한다.

void surf (Input IN, inout SurfaceOutputStandard o)
{
  fixed4 c_1 = tex2D(_MainTex_1, IN.uv_MainTex_1);
  fixed4 c_2 = tex2D(_MainTex_2, IN.uv_MainTex_2);
  fixed4 c_3 = tex2D(_MainTex_3, IN.uv_MainTex_3);
  fixed4 c_4 = tex2D(_MainTex_4, IN.uv_MainTex_4);

  o.Albedo = c_1.rgb;

  o.Albedo = lerp(o.Albedo, c_2, IN.color.r);
  o.Albedo = lerp(o.Albedo, c_3, IN.color.g);
  o.Albedo = lerp(o.Albedo, c_4, IN.color.b);
}

IN.color로 버텍스 컬러 값에 접근할 수 있고 이 값을 이용하여 lerp함수로 다수의 텍스쳐를 합쳤다.

 

기본 원리는 1번 텍스쳐으로 기본을 깔고 그 위부터 lerp함수에 현재 Albedo값, 합칠텍스쳐, 버텍스 컬러 채널값을 넣어서 완성 시켰다.

 

추가 정보 : 터레인

유니티에 지형을 만드는 기능인 터레인에는 Poly brush에서 버텍스칼라를 색칠 한 것과 비슷한 텍스처 그리는

기능이 있다.  

 

텍스쳐를 4개 등록하고 색칠을 하고 터레인이 저장된 폴더를 보면 위 사진과 같은 데이터를 확인 할 수 있다.

만약 텍스처를 4개를 초과해서 등록하게 되면 새로운 이미지가 생성되는 것을 확인 할 수 있고.

이것으로 터레인에서 텍스처를 그리는 원리도 이전에 버텍스 컬러 기반으로 텍스처 마스킹하는 쉐이더와 비슷한 원리임 을 확인 할 수 있다.

 

 

 

 

 

 

 

 


WRITTEN BY
CatDarkGame
Technical Artist dhwlgn12@gmail.com

,