炸殺
카테고리
작성일
2020. 5. 31. 20:25
작성자
炸殺

이전 커스텀라이트 포스트에 이어 오늘은 림라이트를 만들어보겠습니다!

그 전, 이전 포스트에서 공부했던 커스텀 라이트를 만들어보며 복습합시다!

 

 

사실 저번 포스트에서 만들었던 램버트 커스텀 라이트는

 

이렇게 써주면 한 방에 완성이 됩니다.

 

 

RimLight

 

 

 

림라이트란?

피사체 뒤에서 강한 조명을 주어 피사체의 위나 측면 모서리 등,

외곽의 실루엣을 따라 빛의 테(Rim)을 보여지는 것을 RimLight라고 합니다.

 

주로 피사체를 배경으로부터 돌출되게 하거나 인물 주위에 후광과 같은 테두리를 만들어 냄으로써 화면의 부조효과를 더욱 돋보이게 하기 위하여 사용합니다. 게임에서는 림라이트만을 보이게 하여 홀로그램이나, 이펙트등으로 사용되기도 합니다.

 

 

 

림라이트는 물체의 뒤에서 강한 빛을 쏴 '외곽선이 빛나게' 만드는 것입니다.

쉐이더에서는 어떻게 외곽선만 빛나게 만들 수 있을까요?

 

 

 

일단 가장 먼저 카메라를 조명으로 만들어봅시다.

 

카메라를 조명으로 사용하면 언제나 카메라가 바라보는 방향과 맞닿는 면이 가장 밝아지게 됩니다.

카메라의 벡터를 조명 벡터로 사용해버리는 것이죠. 카메라 벡터는 엔진 내에서 불러와야하는 값이기 때문에

Stuct에서 [ float3 viewDir ]를 작성하여 받아와 줍니다.

 

그리고 lightDir대신 viewDir를 Normal 백터와 내적 연산하게 되면

카메라의 백터와 마주보는 노말 백터일 수록 각도차이가 적어지기 때문에

카메라가 바라보는 쪽은 언제나 밝아지고, 카메라를 바라보지 않는 쪽은 반드시 어두워지게 됩니다. 

 

 

이렇게 카메라가 바라보는 곳은 반드시 밝아짐에따라

오브젝트의 '외곽은 반드시 어두워지고 있는 것'을 확인할 수 있습니다.

 

 

이처럼 Rim은 카메라가 향하는 방향(View direction)에 큰 영향을 받는데요,

이를 통하여 Rim이 프레넬(Fresnel)의 개념에 포함된다는 것을 알 수 있습니다.

 

프레넬을 간단히 설명하면 각도에 따른 반사율로 같은 물체라도 보는 각도에 따라 반사되는

빛의 세기가 달라지는 현상을 말합니다. 물체를 바로 아래에서 내려다 봤을 땐 반사율이 높지 않았던 물체가 비스듬히 바라보았을 땐 높은 반사율을 가지고 있는 것 처럼 보이는 현상이죠. 

모든 물체에서 프레넬 현상이 나타나며, 이 중 역광에 의해 일어나는 현상이 '림라이트 현상'입니다.

 

 

 

흑백을 뒤집어 준다면 외곽만 밝게 만들 수 있지 않을까요?

내적연산을 한 결과값에 'one minus', 반전(invert)을 해줍시다.

 

내적연산을 할 경우 결과에 -1이 포함 되니 saturate를 해주자.

외각으로 갈 수록 어두워 졌던 것이 반전되어 외각으로 갈 수록 하얗게 되었습니다!

하지만 림라이트라기에는 흰부분의 영역이 너무 넓습니다. 외각'선'처럼 보이도록 만들어줍시다.

 

 

 

pow ( x , 제곱할 수)

 

power는 힘이란 뜻도 있지만 프로그레밍에서의 power는 '제곱'을 의미합니다.

 

포토샵의 곡선(Curves)와 비슷한 원리.

즉,

이거랑 같습니다.

이렇게 단순 무식하게 곱하는 쪽이 더 가볍기 때문에 아직도 종종 이 방법이 쓰입니다만

요즘엔 하드웨어 성능이 좋아져서 큰 차이는 없습니다.

제곱할 수가 적는다면 저렇게 무식하게 곱하고, 제곱할 수가 많다면 pow를 사용합시다.

 

 

림라이트 같아졌다!

 

이제 이 림라이트에 색도 넣어주고, 강도도 조절 할 수 있도록 프로퍼티로 빼봅시다!

 

 

노말맵도 넣어주었다!

Color 프로퍼티 앞에 [HDR]을 작성해줄 경우 코드에서 1이상의 수를 곱해주지 않아도

인터페이스에서 HDR을 조절하여 블룸 효과를 사용할 수 있게 해줍니다. 

 

빛이여!!!!!

 

 

 

 

응용

 

 

그럼 이런식으로 외곽선만 살아있고 안쪽은 투명한 홀로그램을 만들려면 어떻게 해야할까요?

 

 

 

가장 먼저 투명도를 가져올 수 있도록

RanderType Transparent로 변경하고, "Queue" = "Transparent" 를 적어줍니다.

Queue는 오브젝트가 그려지는 순서를 정해주는 태그로,

위의 코드는 Transparent를 제일 위에 보이게 해줘!라고 명령해주는 것.

태그를 적지 않아도 운이 좋으면 정상적으로 출력되지만 자칫 불투명으로 출력해버릴 수 있으니 의도에 따라 작성해줍시다.

 

마지막으로

#pragma surface surf Lambert 뒤에 alpha:blend 를 적어줍니다. 이제 반투명이 가능해졌습니다!

 

 

Alpha는 float의 값을 가지고 있으며, 내적 연산의 값 역시 float입니다. 그렇다는 말은?

Alpha에 viewDir와 Normal Vector를 내적한 값을 넣는다면??

 

Alpha에 rim을 넣어주었다.

 

림라이트만 남았습니다!

 

rim에는 0과 1사이의 값만 남아있기 때문에 0인 부분은 투명이, 1인 부분은 불투명으로 적용되게 됩니다.

Emission에도 rim을 넣어줄 경우 분홍색에서 검은색으로 빠지는 Emission에 알파가 적용되어

반투명한 부분이 검정색이 되므로 지워줍시다! (그걸 의도하시는 거라면? 적어둡시다..)

 

 

 

 

 

 

Sin(_Time.y)

 

이제 홀로그램이 깜빡이는 효과를 넣고싶어!!

오브젝트가 깜빡이기 위해선 알파가 0이 되었다가 1이 되었다가를 반복한다면 깜빡거리는 효과가 나올 것입니다.

지난 포스트에서 배웠던 Time함수를 사용하면 되지 않을까요?

 

하지만 Time은 단순히 유니티가 켜진 순간부터의 시간을 계산합니다..

그냥 Time만 곱한다면 이미 수없이 흘러버린 시간이 곱해져......그냥 한없이 계속 밝아져만 가겠죠.

 

이렇게.....

 

여기서 사용할 수 있는 것이 바로 Sin그래프 입니다. 내적 연산할 때 공부했던 그 친구! 

 

sin은 1에서 -1까지의 값을 반복한다.

 

 

이 안에 time을 넣어 이 그래프가 계속 반복하도록 만들어줍시다.

 

 

깜빡이긴 하는데...이상한 초록색이 보인다.

잘 깜빡이다 갑자기 거무튀튀한 초록색이 보이는 이유는 바로 sin값에 마이너스(-)가 포함되어있기 때문입니다.

마이너스 값을 없애주는 방법은 다양합니다.

 

 

 

 

  • Saturate

 

첫번째로 Saturate를 이용하여 0~1범위 외의 수를 잘라주는 방법입니다.

 

 

너무 느려서 속도 조절 프로퍼티를 만들어 곱해줬습니다.

 

Saturate를 사용하여 음수값을 잘라줄 경우 0이하의 값은 0으로 고정되어 깜빡임과 깜빡임 사이에 공백이 생깁니다.

 

 

 

 

 

 

  • *0.5+0.5 (Half Lambert)

 

하프 램버트 공식은 1에서 -1사이의 값을 1에서 0사이의 값으로 압축시키는 공식입니다.

꼭 라이팅에만 쓰라는 법은 없죠, 어차피 다 숫자니까요!

 

 

 

 

 

사라지고 나타나는 것이 부드럽게 전환되는 것을 확인할 수 있습니다.

 

 

 

 

  • 절댓값(abs)

 

Abs(Absolute Value)는 절댓값이란 뜻으로 양수는 양수, 음수는 양수로 취급해버립니다.

앞에 마이너스가 붙어있던 말던 뒤에 있는 숫자만 사용하는 것이죠. 

 

음수가 양수로 바뀌어 버린다.

공이 통통 튀는 듯한 느낌으로 깜빡이는 효과가 적용되었습니다. 마치 비상 점멸등같은 느낌도 납니다.

 

 

 

 

 

 

 

WorldPos와 frac

 

뭔가 더 홀로그램스럽게 줄무늬가 흘러가도록 만들어봅시다. 

이번에 사용해볼 것은 바로 WorldPosfrac입니다.

 

 

 

  • WorldPos

먼저 WorldPos는 말 그대로 월드의 좌표로,

Emission에 출력했을 시 오브젝트를 움직이면

월드의 포지션에 따라 색상이 변화하는 것을 확인할 수 있습니다. 

 

WorldPos도 ViewDir와 마찬가지로 엔진에서 받아와야하기 때문에 struct Input에서 불러와 줍니다.

여기서 WorldPos의 y축만 받아오면

 

 

0이상은 점점 흰색, 이하는 검정색

 

 

  • frac 

frac은 분수(fraction)이란 뜻으로 정수를 잘라내고 오직 소수 값만 받아오는 함수입니다.

즉, 1.0이던 2.0이던 결국 0, 2324.2 던 3423423432.2던 결국 0.2가 되어 1이상의 값은 나올 수 없게 됩니다.

 

 

 

 

이 둘을 아까 만들었던 림라이트 쉐이더에 적용해주게 되면...

 

WOW

 

선의 개수와 선이 흘러가는 속도도 조절할 수 있도록 프로퍼티도 만들어 줍시다.

 

최종 코드
완성!

 

 

 

지난 강의에서 배웠던 마스킹 텍스쳐와 UV 애니메이션을 이용하면 이런 효과도 줄 수 있다.

 

쉴드 받는 기분~~
마스킹 텍스쳐를 사용하니 뭔가 홀로그램 영상 통화를 하는 느낌이다.