본문 바로가기

유니티 쉐이더 스타트업

[ 유니티 쉐이더 스타트업 ] 08 . SurfaceOutputStandard 사용하기

[ Standard Shader (스탠다드 쉐이더) ]

[ 물리 기반 쉐이더 ]

유니티 5.0이 되면서 , 유니티도 물리 기반 쉐이더 시스템을 도입하였다 .

 

물리 기반 쉐이더란 ?

=>주변 환경에 따른 재질 변화를 물리 법칙에 기반하여 실시간으로 재질을 구현해주는 사실적인 쉐이더 표현 기법이다 .


[ Standard Shader ]

유니티의 기본 쉐이더 Standard Shader는 대표적인 물리 기반 쉐이더이다 .

지금까지 사용했던 o.Albedo / o.Emission등이 모두 물리 기반 쉐이더의 요소이다 .

 

SurfaceOutputStandard 구조체의 요소는 다음과 같다 .

struct SurfaceOutputStandard
{
    fixed3 Albedo;
    fixed3 Normal;
    fixed3 Emission;
    half Metalic;
    half Smoothness;
    half Occlusion;
    half Alpha;
}

복잡한 물리 기반 쉐이더의 라이팅 구조를 볼 필요 없이

위의 구조체에 알맞은 값을 넣어주어 간편하게 사용 할 수 있다 .


[ Methalic 과 Smoothness ]

[ Methalic / Smoothness 사용하기 ]

먼저 , 텍스쳐 한 장 만을 출력하는 쉐이더를 생성한다 .

이제 Smoothness 와 Metallic을 프로퍼티에 생성하고 , surfaceoutputStandard 구조체 안에 넣어주자 .

이제 두가지 값을 사용 할 수 있다 .


[ Methalic / Smoothness ]

Metallic은 재질이 금속이냐 , 아니냐를 결정한다 .

0은 비금속 , 1이면 금속 재질이다 .

 

이때 , Metallic이 0이면 스페큘러 라이트가 흰색에서 명도의 차이만 보이며,

1이면 스페큘러 컬러가 Albedo에 넣은 색이 된다 . (금속은 고유 스페큘러 컬러가 있기에)

Metallic는 텍스쳐를 받아 사용도 가능한데 , R 채널을 사용한다 .

https://gamedevforever.com/17

 

물체 표면의 스페큘러 칼라에 대하여.

안녕하세요 Silverchime 이라고 합니다 실버차임입니다 치매가 아닙니다 ;ㅅ; 현재 T사의 TG프로젝트에서 배경쪽과 TA로 일하고 있습니다. 쟁쟁하신분과 차마 비교할 수는 없는데다, 평소에 항상 왜?

gamedevforever.com

 

 

Smoothness는 재질이 미끄러운지 거친지를 결정한다 .

0이면 완벽히 거칠어 난반사만 일어나고 , 1이면 매끄러워 정반사만 일어난다 .

Smoothness 는 텍스쳐를 받아 사용도 가능한데 , A 채널을 사용한다 .

 

Standard Shader라는 물리기반 렌더링의 기본 개념은 에너지 보존 법칙

(나가는 빛의 양은 들어오는 빛의 양을 넘을 수 없다)로 설명 가능하다 .

 

위의 두값은 0,1등의 극단적인 값은 사용하지 않는게 정확한 물리기반 쉐이더를 다루는 방법이다 .

 


 

[ Normal map ]

[ normal map ]

Normal Map은 실제 디테일이 없는 부분을 디테일 있게 보이기위한 눈속임 맵이다 .

일반적으로 푸른색이며 , 빛을 속이기 위한 백터 데이터들로 이루어진 텍스쳐 파일이다 .


[ normal map 만들기 ]

툴에서 Normal Map 생성하는 방법

  • 지브러시/ 머드박스 등의 스컬핑 툴을 이용
  • 3D 프로그램에서 하이 폴리곤 모델링을 렌더 투 텍스쳐를 이용
  • 이미지의 음영을 기반으로 간단하게 NormalMap을 추출하는 크레이지 범프 또는 B2M 툴을 이용

유니에서 Normal Map 생성하는 방법

텍스쳐 파일에서 Texture Type을 Normal map을 변경하고 , Create from grayscale을 한다 .

이후 , Blumpiness와 Filtering을 조절한후 Apply 해준다 .

파일의 포맷도 DXTnm으로 변경됨을 볼 수 있다 .

 


[ normal map 입력받기 ]

Normal Map백터 데이터로 이루어진 일종의 수치들의 집합에 가깝지만 ,

해당 형식은 텍스쳐이기에 일반 텍스쳐를 받는것과 동일하게 프로퍼티를 만들어 준다 .

 

이때 , _BumpMap이라는 변수명은 유니티 내장 다른 쉐이더가 저 명칭을 사용하기에 NormalMap이 아닌

_BumpMap으로 변수명을 짓는다 . (호환성을 위해)

 

다만 현 상태는 일반적인 텍스쳐를 받는것과 다름이 없다 .

Normal Map은 일반적인 게임용 텍스쳐 포맷인 DXT1 DXT5와 다르게 DXTnm 형식을 사용한다 .

(플랫폼에 따라 다를 수 있다 .위의 예시는 PC플랫폼이 안드로이드는 etc 포맷을 사용함)

이는 일반적인 텍스쳐 압축에 의한 NormalMap의 품질 저하를 막기위해 만든 AG파일 포맷이다 .

NormalMap의 R과 G의 퀄리티를 최대한 보전하여 A와 G에 넣어 저장한다 .

 

해당 R과 G는 Normal Map 의 X 와 Y로 계산되며 , Z는 삼각함수를 이용하여 수학적으로 추출된다 .

그렇기에 이 텍스쳐를 NormalMap으로 생성해내려면 앞의 공식이 적용된 함수를 이용하면 간편하다 .

 

float y = UnpackNormal (float4 x);

 

이는 다음과 같이 사용한다 .

해당 함수 사용시 다음의 주의사항이 있다 .

  • UnpackNormal은 반드시 float4를 받아야 한다.
  • 해당 함수의 결과물은 float3로 받아야 한다 . fixed4로 받으면 에러가 난다 .

또한 위와 같이 도출된 n 값을  나누어 x와 y의 특정 숫자를 곱하면 NormalMap의 강도를 조절 할 수 있다 .

2를 곱하면 2배 강해지고 0.5를 곱하면 강도가 절반으로 줄어든다 .

 

 


 

[ Occlusion ( 오클루젼 ) ]

[ Occclusion ]

https://velog.io/@15ywt/%EA%B7%B8%EB%9E%98%ED%94%BD%EC%8A%A4-AOAmbient-Occlusion

 

[그래픽스] AO(Ambient Occlusion)

그래픽스 기술인 Ambient Occlusion 컨셉 정리일단 용어부터 알아보자, Ambient는 '주변'이라는 뜻이고Occlusion은 '폐색'이라는 뜻이다. 대충 주변이 가려졌다는 뜻이다.영문 Wikipedia에서 찾은 정의는 다

velog.io

 

Occlusion은 Ambient(환경) Occlusion(차폐)이라고 불린다 .

구석진 부분의 추가적인 음영을 표현하는 기능을 가지고 있다 .

 

일반적으로 환경광 (Ambient Color)로 가득 차 있는 세상에서 그림자가 드리워진 부분도 사방에서 오는 환경광 정도를 받고 있는 것이 일반적이다 .

 

하지만 , 매우 구석지거나 물체들에 가려져 환경광이 닿지 못하는 부분은 더욱 어두워지는데 이를

Ambient Occlusion이라고 한다 .

 

Occlusion 맵 역시 여러가지 툴에서 추출 가능한 텍스쳐이다 .

Surface Output에서는 float으로 값을 받고 있다 . 해당 맵의 사용시 구석진 부분이 강조된다 .


 

[ Occlusion 사용하기 ]

Occlusion의 사용은 일반적인 텍스쳐를 받아 사용하는 방법과 동일하다 .

다만 , Occlusion맵은 독립된 UV가 아닌 MainTex의 UV를 같이 사용해야 정상 작동한다 .

 

그러나 Occlusion은 float 값을 받는 변수이다 .

위의 상황에서는 float4를 넣고 있는 상황인데 이때는 float4의 r만 사용하고 있는 것이다 .

 

r값 하나만을 위하여 텍스쳐를 추가하는 것은 낭비이다 . 이를 해결하기 위해

MainTexture의 알파채널을 Occlusion 맵으로 사용하는 것은 어떨까?

 


 

[ 응용해보기 ]

[ 응용 ]

4개의 텍스쳐를 버텍스 컬러의 값에 따라 모두 표현하는 텍스쳐이다 .

여기에 노말맵을 더해보자 .

노말맵을 위한 텍스쳐를 추가하려 하자 위와 같은 에러가 발생한다 .

이는 쉐이더 2.0 의 한계를 벗어나는 텍스쳐 인터폴레이션을 했을때 일어나는 에러 메시지이다 .

이는 #pragma target 3.0을 명시함으로 해결 할 수 있다 .

그런데 해당 결과값의 음영이 충분치 못함을 볼 수 있다 .

 

빛의 기본원리를 생각해보면 Normal Map 즉, 울퉁불퉁한 질감은 빛의 음영으로 느끼게 된다 .

빛 외에 또한 Specular (반사광)역시 역할을 함을 볼 수 있다 .

 

그렇기에 Specular를 보여 줄 수 있는 옵션 Smoothness / Methalic을 추가해주자 .

Specular의 추가로 더 리얼한 느낌을 준다 .


[ 특정 부분에만 Specular 적용하기 ]

위 부분 즉 , 버텍스 컬러의 b 부분에만 Smoothness를 적용하려면 어떻게 해야 할까?

 

위와 같이 Smoothness에 IN.color.b를 더해주면 된다 .

또한 , 특정 부분의 Smoothness를 인스펙터를 통해 조작 할 수도 있다 .

즉, _Smoothness 인터페이스의 값으로 버텍스 컬러 r 채널의 강도를 조절할 수 있게 하여

Smoothness를 조절 할 수 있게 한 것이다 .