실감 공통편 에너지 실드
안녕하세요 박현상입니다
이번에는 에너지 실드라고 하는
반투명한 쉐이딩 기법에 대해서 다루게 될 것입니다
Translucent라고 하는 반투명 셰이더의 특징과 함께
포지션과 삼각함수의 사인 함수를 이용한
시각효과를 다루게 됩니다
또한 정적인 형태의 셰이더가 아닌
시간에 따른 변화를 구현해 보겠습니다
Fresnel과 Depth Fade
실습을 위해서 콘텐츠 폴더에 에너지 실드라는 폴더와 함께
머티리얼도 만들어주도록 하겠습니다
머티리얼로 M_EnergyShield라고 생성해서
머티리얼 창을 먼저 열어주겠습니다
우리가 그전까지 표현해 봤던 셰이더들은
대체로 이런 3D 오브젝트 표면에 질감을 나타내거나
어떤 특수한 효과를 넣기 위해서 사용했는데
투명해진다고 하더라도 보이느냐 안 보이느냐와 같은
이런 Blend Mode에 Masked와 같은 설정을 이용했습니다
반면에 이번에 사용할 것은
반투명한 이미지가 보여야 되기 때문에
Translucent라고 하는 Blend Mode를 이용해서
셰이더 제작을 할 겁니다
Translucent 같은 경우에는 지금 보는 것처럼
일반적인 PBR 셰이더의 파라미터들이
상당수 비활성화되는 것을 볼 수가 있습니다
물론 여러분들이 PBR의 효과까지 같이 사용하면서
반투명한 이미지를 얻길 원하신다면
여기 보이는 Translucency라는 항목에서 라이팅 모드를
여기 있는 Surface 항목을 이용해서 활성화해 주시면
PBR 모드는 사용할 수 있지만
현재 제가 사용할 부분에서는
Metalic이라든가 Specular 같은 데이터들
Roughness 같은 것들은 사용하지 않을 예정이기 때문에
리셋 버튼으로 다시 Translucent의 가장 기본형인
Volumetric NonDirectional 상태로 예제를 진행할 겁니다
우선은 에너지 실드 효과를 위해서
Fresnel이라고 하는 노드부터
먼저 생성해서 보여드리도록 하겠습니다
Fresnel이라는 노드를 그대로 Opacity에 사용할 건데
이렇게 사용해 보면 가운데는 지금 뚫려 보이고
가장자리로 가면 지금 보시는 것처럼 이렇게
약간의 음영이 보이죠
실제 이것을 Opacity가 아닌 Ctrl을 눌러서
노드를 Emissive로 다시 재연결해 보면
가장자리는 하얗게 지금 보이죠
가운데는 회색으로 보이는데
사실 이것은 회색이 보이는 게 아니고요
Base Color를 블랙으로 바꾸신다면
블랙의 컬러가 보이게 될 겁니다
Fresnel이라는 노드에 대해서 우선 설명을 드리자면
여러분들이 Dot 연산, 내적에 대해서 이해하실 필요가 있습니다
앞 강의에서 내적을 이야기할 때
기준이 되는 벡터와 또 다른 비교하고자 하는 벡터
두 개를 비교해서 이 두 번째
임의로 A와 B로 나눠 보면
B 벡터가 A의 몇 퍼센트 위치에 있느냐
이것을 비교하는 연산이라고 설명드린 바가 있습니다
그래서 같이 이렇게 마주보고 있다면
이때는 1이라는 값이 나오고요
90도로 꺾여 있다면 이때는 0이라는 값
완전히 등지고 있다면 이때는 -1이라는 값
1에서부터 -1까지 이렇게 값의 결과치를 보여주게 되는데
실제로 Fresnel이 하는 일은
이렇게 반원이 있다고 가정을 해보겠습니다
그리고 카메라가 바라본다고 했을 때
바라보는 3D의 노멀 방향과 카메라 방향의 벡터
이걸 임의로 카메라 벡터라고 얘기를 할게요
노멀의 방향과 카메라 벡터를 비교해서
이것들이 각각 몇 퍼센트를 나타내고 있는지 수치화한 것인데요
엄밀하게는 카메라 벡터는 아닙니다
엄밀하게 얘기하면 카메라를 바라보는 버텍스에
흔히 뷰 벡터라고 카메라를 바라보는 이 벡터와
비교를 한 데이터이긴 한데
결국 비교를 해보면 카메라를 이렇게 바라보겠죠
그러면 결국 90도가 되면 0이라는 값이 나오고
카메라를 똑바로 마주보고 있다면
1이라는 값이 나오게 될 겁니다
뒷면은 -1까지 있겠죠
그래서 결국에는 1에서부터 -1까지 구체가 있다고 하면
이런 결과치를 가지고 역으로 이걸 뒤집은 겁니다
이런 결과를 뒤집어서 마주 보고 있을 때
Dot 연산에 의한 결과로만 따지면
카메라를 똑바로 바라보는 이 지점
우리의 Sphere로 치면 이 지점은
0이라는 값이 나오게 했고요
90도로 꺾여 있는 지점은 1이라는 값이 나오게
값을 뒤집은 겁니다
그래서 Fresnel 같은 경우에는 가장자리 값이
일반적인 내적의 연산 결과와는 다르게
뒤집혀서 1이라는 값을 출력을 하고요
정면을 마주보는 곳이 0이라는 값을 출력하게 됩니다
그래서 일반적으로 벡터를 비교할 때 결과와
실제 Fresnel이 출력하는 결괏값이 약간 차이가 있다
이 정도까지만 이해하고 계셔도 됩니다
물론 이것을 그대로 사용하게 되면
안쪽에 무조건 0%가 되면서 뻥 뚫려 보였죠
그렇기 때문에 이걸 그대로 사용하지는 않고
Lerp를 통해서 반투명하게 해줄 겁니다
LinearInterpolate를 통해서
Alpha에다가 Fresnel 값을 연결해 주고요
그리고 Lerp 된 결과를 Opacity에다가 연결해 주겠습니다
이때 0의 값이 출력이 되는 곳에다가
투명도 0이라고 입력하는 게 아니라
약간 비쳐 보이게 0.3이라고 입력을 할 거고요
B의 값은 1 그대로 완전히 다 보인다는 뜻으로
1이라고 입력을 할 겁니다
그러면 정면에서는 이제 완전히 뚫려 보이는 게 아니라
30%만 투과돼서 보이고
여기 있는 가장자리에는
온전히 오브젝트가 가지고 있는 이 컬러 값 자체가
그대로 다 보이기 때문에
100% 보이고 있는 상황이라고 이해하시면 됩니다
이전에 있던 Opacity Mask 같은 경우에는
0 또는 1이라는 출력값만 가지고 있던 거에 반해서
Opacity 자체는 0에서부터 1까지
반투명해 보이는 0.3이나 0.5와 같은 값들을 지원합니다
여기에서 가운데에서부터 서서히 보이게 되는 끝자락까지
0에서부터 1까지 값이 서서히 변할 때
그 변화되는 정도를
여기 있는 ExponentIn 값을 통해서 제어하게 됩니다
그래서 Exponent 값을 만약에 0으로 둔다면
이렇게 완전히 블랙인 상태죠
1로 둔다면 그라데이션의 범위가
여기에 잠시 표시를 하면
여러분들 눈으로 보이는
대략 반투명해 보이는 50% 정도의 구간이
이쯤이라고 가정하겠습니다 Exponent 1일 때
그러면 여기 있는 값을 2나 3으로 점점 늘려갈수록
50%의 위치가 점점 밀려나게 될 겁니다
이러한 이유는 기본적으로 0에서 1까지
이렇게 선형이라고 하는
우리가 흔히 Linear 하다고 얘기하는
이러한 그래프가 있다고 가정을 해 보면요
이 중간에 우리가 입력을 0.5를 하면
출력이 0.5가 된다는 의미겠죠 이런 식으로
반면에 Exponent는 지수라는 얘기죠
우리가 흔히 2의 n승 할 때
이 n에 해당하는 지수 값을 의미하기 때문에
제곱의 의미로 생각하시면 됩니다
그래서 우리는 0.5를 제곱하게 되면
0.5가 같이 곱해지니까 0.25가 되겠죠
그럼 이것을 그래프로 그려보면
이렇게 볼록한 형태가 될 겁니다
지수 값에 따라서 이것이 점점 더 커짐에 따라서는
그 곡선의 기울기가 이런 식으로 더 볼록하게 바뀌겠죠
우리가 입력한 값보다 훨씬 더
0.5보다는 어두운 값을 출력하게끔
0.5의 위치가 계속해서 낮아지는 겁니다
이런 식으로 반투명한 정도를
우리가 지수를 이용해서 컨트롤해 봤습니다
에너지 실드 효과를 위해서
Fresnel을 사용하는 이유가 기본적으로는
우리가 흔히 에너지 내지는
자기장의 느낌을 표현하고자 할 때
현재는 블랙이라서 좀 티는 덜 나는데요
보통 가장자리의 색을 조금 더 밝게 표현을 하고
안쪽은 투명하게 표현하는 것이 일반적입니다
그래서 일반적으로는 Fresnel 노드를 사용하는 것이고요
여기에서 한번 Lerp를 이용해서
컬러 값도 다르게 표시를 해 보겠습니다
우선 Constant3Vector를 이용해서
총 2개의 Constant3Vector를 만들고요
잠시 Fresnel은 아래로 치워두겠습니다
그리고 여기에서 마찬가지로 Lerp를 이용해서
그대로 Fresnel을 연결해 줄 겁니다
안쪽에 해당하는 A 영역에는 짙은 파란색을 넣어서
A 영역에다가 연결할 거고요
꼭 파랑이 아니어도 됩니다
단지 자기장의 느낌을 표현하는 데
주로 이런 밝은색의 하늘색 같은 것들이 많이 쓰여서
이렇게 하는 거고요
바깥쪽에는 A에 꽂은 것보다는 조금 더 밝은 색을 쓸 건데
다만 여기에 들어가는 값은
블루 값이 조금 더 발광이 될 수 있게끔
각각의 값을 한 3배 정도 밝게 해서
B에다가 연결해 줄 겁니다
그러고 나서 Emissive Color에 연결을 해 보면
바깥쪽은 밝게 발광을 하고요
안쪽은 푸르스름한 빛이 도는 것처럼
묘사해 줄 수가 있습니다
여기에다가 한 가지 효과를 더 추가해 보도록 하겠습니다
이번에 사용할 노드의 이름은
Depth Fade라고 하는 노드입니다
이것을 단순하게 Opacity에만 연결을 해서
미리보기 상에서는 어떤 건지 잘 티가 안 나죠
그래서 이것을 적용한 상태로
월드에다가 한번 배치를 실제로 적용해서
효과에 대한 설명을 이어가 보겠습니다
Place Actors - Shapes 항목에서 Sphere를 먼저
월드 상에 일부분이 겹쳐진 형태로 적용을 하고요
우리가 만든 에너지 실드
현재 제작 중인 이것을 골라서
우리가 배치한 Sphere의 머티리얼에다가
연결해 주도록 하겠습니다
그리고 이게 크기가 작으면 티가 잘 안 나니까
트랜스폼의 Scale 값을 약 5배 정도 키워주면
오브젝트가 맞닿은 이 경계면을 보게 되면
지금 보는 것처럼 이렇게 반투명하게
일부분이 표현된 것을 확인하실 수가 있죠
그래서 멀리서 보면 이렇게 보일 겁니다
맞닿은 경계는 0이라는 값이 나오고요
Fade Distance에 의해서 100 유닛까지
서서히 투명도가 1까지
좀 더 정확하게는 투명도라기보다는
출력되는 값 자체가 1까지
이렇게 표현되게끔 출력해 줍니다
근데 이것을 그대로 사용하는 게 아니고요
일반적인 에너지 실드 특수 효과나 이런 것에서
보통 Depth Fade의 역할은
이러한 경계를 오히려 명확하게 표현하기 위해서 사용하기 때문에
Depth Fade의 값을 OneMinus로 뒤집어서
그대로 Opacity에다가 한번 연결해 보겠습니다
화면상에서도 아주 좁은 영역만 나오고 있죠 저장하고요
월드 상에서도 보면 지금 보는 것처럼
이제는 0이었던 값이 1에서 0을 빼면서
1로 출력이 되게 됐고
1이라는 값이 1이 빠지면서 0으로 출력되게 되었습니다
근데 지금과 같은 상태면 겹쳐있는 영역이
프론트 영역만 이렇게 보이기 때문에
여백을 클릭하시거나 혹은 마스터 노드를 선택하셔서
Two Sided 옵션을 체크해 주셔서
뒷면까지 모두 보일 수 있도록 하면
맞닿은 경계 전체를 우리가 시각화해서 볼 수 있게 되죠
지금과 같은 상태에서 앞서 만들어놨던 Fresnel과 함께
한번 이 두 가지 효과를 믹싱해 보겠습니다
지금 맞닿은 경계 이쪽은 1이라는 값이 나오고 있고요
만약에 우리가 Fresnel을 적용한다고 했을 때
제가 지금 녹색으로 그리고 있는 이 선
구체의 외곽선에 해당하는 부분이 마찬가지로
1이라는 값을 출력하게 됩니다
보통 여러분들이 이런 새로운 효과를 봤을 때
내가 무엇을 해야 될지 모르겠다면
가장 보편적인 선택은 두 가지입니다
이 두 가지 값을 Multiply 하거나
혹은 Add 해주는 거죠 더해주는 거죠
실제 우리가 이 효과를 합쳤을 때
이걸 Multiply 한 결과를 확인해 보면
안쪽에서는 지금 잘 티가 안 나죠
근데 여기에서 보면 오히려 Fresnel에 의한 효과는 안 보이죠
어떻게 보면 당연하죠
여러분들이 헷갈릴까봐 녹색으로
Depth Fade의 값으로 먼저 적어서 보여드리면
3D 오브젝트가 맞닿은 경계를
원래는 0인데 우리가 OneMinus 해서
1로 출력하게끔 해놨고요
이 100 유닛이라는 거리가 지나면서부터
나머지 전체 구간을 우리는 전부
원래는 1이 출력되는 걸 OneMinus로 빼서
0이 출력되게 해놨죠
빨간색으로 Fresnel의 값을 적어 보면
경계의 영역은 1이 출력이 되고요
안쪽에 있는 영역은 0의 값이 출력이 됩니다
당연히 0이 출력되는 부분은 여기도 마찬가지겠죠
여기도 마찬가지일 거고요
그리고 저 위에 갔을 때는
구체의 경계 부분에 해당하는 것은
1이라는 값이 출력이 되겠죠
반면에 Depth Fade는 맞닿은 경계 위쪽은
0이라는 값이 출력되니까
둘이 곱해봐야 0밖에 안되겠죠
그러면 Opacity 0이라는 수치는
결과적으로 보이지 말라는 뜻이니까
마찬가지로 여기에 있는 Depth Fade와 1이
Fresnel의 0과 곱해진다면 결국엔 0이겠죠
그러면 이 두 가지 효과가
그렇게 보기 좋은 상태는 아닐 겁니다
그러면 일단 Multiply는 우리가 사용해야 될 효과에서
Delete 해서 제외를 시켜주시고
Add에다가 이 두 가지 효과를 섞어서 보면
이렇게 Apply를 해 보겠습니다
현재 Fresnel과 Depth Fade가 Add가 된 상태입니다
그러면 이번엔 마찬가지로 이제는 원래 값이 아닌
OneMinus 된 출력 값만 적어 보면 경계는 1이고요
여기서부터는 0, 0, 0이 되겠죠 경곗값은 모두 다
대푯값들만 이렇게 적어 보면
Fresnel 같은 경우에는 카메라가 마주 보는 곳은 0
대푯값들이 0이 될 거고요
경곗값은 모두 다 1이 될 겁니다
그럼 1과 1이 더해지면 결과적으로는 2가 될 거고요
여기 있는 0과 1이 더해져도 최소한 1은 되겠죠
0과 0이 더해지는 이 중앙 부분이라고 하면
여기가 이제 진짜 보이지 않는 0 상태
Opacity가 0 값이 되는 거니까
결과적으로는 가장자리 Fresnel의 효과와
Depth Fade의 효과가 겹쳐져서
우리가 의도한 형태대로 보이게 될 겁니다
이것을 앞서 사용했던 Lerp에 그대로 적용할 건데요
이렇게 투명도와 Emissive Color
두 가지 Lerp 효과를 그대로 적용해 봤습니다
Apply를 눌러서 보게 되면
이렇게 효과가 중첩되어 있는 걸 보실 수가 있는데
이제 여기에서 여러분들이 하나 주의하셔야 될 거
여기에 들어가는 값들이 지금 최댓값은 2인 상황입니다
그래서 가능한 Lerp에 넣으실 때
안정적으로 여러분들이 값을 출력하고 싶다면
Saturate라는 노드를 이용해서
출력되는 값이 0에서 1 사이의 범위가 되게끔
지금 Add가 됐을 때는 0에서 2까지였던 값의 범위가
Saturate를 통해서 0에서 1 사이가 된 거죠
이런 식으로 안정적으로 넣어주시는 게
Lerp의 공식을 생각해 봤을 때
조금 더 효과를 균일하게 만들어 낼 수가 있습니다
이제 여기에다가 우리가 필요한 파라미터들을 만들어서
약간의 변화를 줘보도록 하겠습니다
우선은 이 Fresnel의 경계
흰색에서 서서히 안쪽으로 빠지는
경계에 대한 범위를 조절하기 위해서
ExponentIn에다가 ScalarParameter를 이용해서
이 파라미터의 이름은 FresnelExp라고
이렇게 대푯값을 적도록 하고요
Depth Fade 같은 경우는
Opacity 값은 조절할 필요 없이
Fade 되는 거리 값을 조절하기 위해서
마찬가지로 ScalarParameter를 이용해서 FadeDist
Distance를 줄여서 쓴 겁니다 FadeDist라고
이 값은 기본값이 100이 되고
FresnelExp 값은 이전과 같이 2로 맞춰주도록 하겠습니다
이렇게 먼저 두 개의 가장 주요한 효과들에 대해서
파라미터들을 만들어 줬고요
나머지 컬러 값들도 오른쪽 클릭해서
Convert to Parameter로 해가지고 Inner Color
마찬가지로 Side Color 이런 식으로
컬러 값을 하나 더 이렇게 표현하도록 할 겁니다
Opacity도 마찬가지겠죠
ScalarParameter를 이용해서 InnerOp
A쪽이 안쪽입니다 가운데 영역
그리고 똑같이 ScalarParameter를 이용해서
SideOp로 각각의 파라미터 값을 놔두고
기본값은 0.3, SideOp는 1이 되게끔 저장해 보겠습니다
지금은 Depth Fade에 대한 구체적인 설명을 위해서
간단하게 예제용 머티리얼을 하나 따로 만들었고요
우선은 Depth Fade가 어떻게 그려지는지
그리고 Translucent라고 하는 기능이
어떻게 작동되는지에 대해서 설명해 드리도록 하겠습니다
Depth Fade라고 하면 기본적으로 Depth
깊이에 대한 값을 이용해서 시각화하는 기능인데요
여기에서의 Depth는 일반적으로
앞에 살짝 생략되어 있는 표현이
카메라로부터의 거리가 얼마나 되느냐
이것이 생략이 되어 있는 상황입니다
그래서 잠시 레벨에서 Lit 모드를
Buffer Visualization에 Scene 전체 오브젝트에 대한
Depth 값을 보여줄 수 있는
Scene Depth라는 항목으로 선택해서 보겠습니다
지금 보시면 카메라로부터의 거리가
멀어지면 멀어질수록 점점 하얘지는 것을 확인하실 수 있는데요
근데 특이한 것이 Translucent는
Scene Depth라고 하는 데이터에는
포함되어 있지 않습니다
다시 한번 Lit 모드로 돌아가서 보겠습니다
분명히 여기에는 구체는 있지만
Buffer Visualization - Scene Depth를 다시 한번 선택해 보면
원래 구체가 있던 것을 제가 한번 선택해 볼게요
이렇게 선택해 보면
구체라고 하는 3D 오브젝트는 존재하지만
깊이를 가늠하는 Depth 값에는
포함되어 있지 않다는 것을 확인하실 수가 있는데요
이제는 Lit 모드로 가서
방금 전에 만들었다고 설명드린
Pixel Depth라고 하는 또 다른 데이터가 있습니다
이것을 한번 구체에 그대로 전달해 보겠습니다
여전히 반투명한 상태고요
이 거리 값이 지금 대략
700 유닛 정도 떨어져 있다고 텍스트로 나오는데
여기에 마치 깨져 보이는 글자는
각각의 픽셀마다, 픽셀 한 칸 한 칸마다
카메라로부터의 거리가 미묘하게 다르다 보니까
이 구간에 대해서 같고
이 구간들이 각자가 다 다른 값들을 가지고 있는 겁니다
그렇기 때문에 글자가 좀 깨져 보이는 거고
단위가 낮아지면 낮아질수록 훨씬 더 겹침이 심하죠
이 아래쪽이 소수점입니다
그래서 거리가 많이 떨어져 있으면
500 유닛, 600 유닛 이런 식으로 800 유닛
점점 이렇게 거리가 계산이 되고 있죠
더 멀어지면 네 자리까지도 올라가요
그리고 점점 가까이 가면
수치가 변화되는 것을 보실 수가 있죠
여기에서 Scene Depth와 Pixel Depth의 값을
응용하는 방법에 대해서 얘기해 보겠습니다
우선 A 지점이라고 부르겠습니다
그리고 중간에 여기를 B 지점이라고 부를 거예요
B 지점을 기준으로 한번 생각을 해 봅시다
B 지점은 Scene Depth의 값과 Pixel Depth의 값이
이 맞닿은 경계 부분은 꼭 A 지점이 아니라고 하더라도
여기 오브젝트와 맞닿아 있는 경계는 같을 겁니다
Scene Depth랑 Pixel Depth를 한번 빼 보면
A 지점은 이 두 개의 값이 같으니까 0이 나오겠죠
반면에 허공에 있는 B 지점 같은 경우에는
Scene Depth 같은 경우에는
B 지점에 보이는 Scene Depth는
이 구체가 없는 것처럼 인식할 테니까
이 구체가 눈에 안 보이는 것처럼
이렇게 인식을 할 테니까
뒤에 보이는 이 벽의 거리 값이 나올 겁니다
훨씬 멀기 때문에 카메라로부터 거리가
우리가 방금 전에 감춰놨던
우리가 지금 예제를 적용하고 있는 구체보다는 뒤에 있으니까
Scene Depth의 값이 Pixel Depth의 값보다는 크기 때문에
무조건 0보다는 이 값의 차이를 구해보면 거리가 커지겠죠
Scene Depth에서 Pixel Depth를 빼면 0보다는 크다
그게 1만큼 크든, 100만큼 크든, 1000만큼 크든 상관없이
무조건 크게 나올 겁니다
그렇기 때문에 이 결괏값
Scene Depth와 Pixel Depth를 뺀 결괏값에다가
나누기 Distance 값
기본값 거리 값이 100이었죠
100만큼을 해주게 되면
여기 있는 경계는 0이 나왔을 거고요
100 유닛만큼 올라간 이 지점은 1이 나올 겁니다
실제로는 여기서 100 유닛만큼
바닥에서부터 100 유닛만큼 정도겠죠
Depth 값은 이 지점에 있는 Depth 값을 가져올 테니까
그리고 훨씬 더 뒤에 있는 B 지점 같은 경우에는
100보다도 크기 때문에
2가 됐든, 3이 됐든, 혹은 50이 됐든
100보다는 훨씬 더 멀기 때문에 더 큰 값이 나올 겁니다
그래서 실제로 우리가 사용했던
Depth Fade를 그대로 구현해 보면요
한번 구현해 보겠습니다
나머지 노드들을 지워주고요
우선 Scene Depth라는 노드를 받아오고
Scene Depth에서 Subtract로 Pixel Depth 값을 빼주고
이 빠진 값에서 Divide로 거리 값이 기본값 100이었죠
이것을 Opacity에 연결해 주고 저장해 보겠습니다
그러면 이렇게 현재 딱 이 거리 만큼
맞닿은 경계 지점이 여러분들은
지금 0%라서 잘 안 보일 테니까
여기에다 제가 일부러 딱 지점을 맞춰놨습니다
이게 딱 100 유닛 되는 거리 만큼이죠
이 거리 만큼 빠져 있는 걸 확인하실 수가 있고요
지금 우리가 만든 이 노드를 바꿔서
Depth Fade랑 비교를 해 보면요
그대로 Apply 하겠습니다 저장도 하고요
결괏값이 같은 걸 보실 수가 있죠
만약에 여기에 200을 입력하면
두 배만큼 더 거리가 멀어지는 거니까
두 번째 칸까지 가는 거고
당연히 여기에도 200만큼 입력해서
그대로 연결해서 저장해 보면
Apply를 눌러 보면 결괏값이 같죠
그래서 3D가 렌더링 될 때 Translucent 같은 경우에는
Scene Depth의 영역에서는 빠지고
Pixel Depth 문자 그대로 3D 표면이 가지고 있는
그 표면에 대한 위치 값은 가지고 있다
그래서 화면 전체를 계산할 때는 빠지지만
개별적인 데이터는 가지고 있기 때문에
지금 여러분들이 보시는 것처럼
Depth Fade와 같은 효과를
이 두 개의 값의 차이를 이용해서 만들어 줄 수 있는 거고요
또 Scene Depth에서 빠지기 때문에
한 가지 특이한 증상이 있습니다
바로 그림자가 없다는 거죠
다른 오브젝트들은 이렇게 그림자가 있죠
반면에 Translucent는 기본적으로
그림자가 생기지 않습니다
그래서 여러분들이 Buffer Visualization의 Scene Depth
이 영역에서 빠져 있는 것에 대해서
하나 확실하게 기억하고 계시면
이걸 응용해서 또 다른 재미있는 효과들도
만들어 보실 수가 있을 겁니다
이제 원래대로 머티리얼을 되돌리고요
우리가 만들던 에너지 실드로 다시 되돌리고
Scale을 한번 키워보겠습니다
좀 뒤로 많이 빠져서요
Scale을 키우게 되면 오브젝트의 경계가
다른 3D 오브젝트와 맞닿을 때
이런 식으로 점점 하얗게 표시되는 것을 확인하실 수가 있죠
줄어들면 마찬가지로 이런 식으로 다른 오브젝트들과
서로 상호작용이 일어나는 것을 보실 수가 있습니다
이 상호작용이라고 하는 것이 반드시
우리가 어떤 기능을 만들어서
프로그래밍적으로 버튼이 눌려야만 되거나
이런 것들이 아니고
단순히 셰이더를 짜는 것만으로도 이렇게
주변에 있는 액터들과 서로 상호작용을 일으킬 수도 있습니다
이제 머티리얼을 다시 열어서
나머지 효과들을 마무리 짓도록 하겠습니다
포지션 시각화
이 두 가지 효과들이 모두 겹쳐 있는데 이걸 좀 뒤로 빼고
이번에는 새로운 효과를 한번 만들어 볼 겁니다
보통 에너지라고 하면 일정한 파장이나 주기를 가지고 있죠
그래서 위에서부터 아래로 흘러내린다거나
이런 선 같은 것들이 잘게 표현이 되는 묘사들을 종종 하는데
그러한 묘사를 위해서는
우리가 포지션 값을 이용해서 묘사하게 될 겁니다
우선 World Position이라는 노드를 먼저 가지고 오겠습니다
여기에다가 Dot Product를 이용해서
우리가 임의로 정한 방향대로 물결치게 만들 겁니다
그래서 Dot 연산으로 Vector Parameter를 이용해서
이거는 Direction이라고 이름 지어주도록 하겠습니다
이 두 가지 값을 비교해서 노드를 만들 건데요
우선 Direction에다가는 여러분들이 알기 쉽게 Z축으로
플러스 방향으로 값을 설정해 놓겠습니다
이 결괏값을 비교해 보면
이거 잠깐 앞으로 끌고 와서 보겠습니다
원래 노드가 좀 많은데
Opacity에다가 연결해 놓고 보면 지금 보는 것처럼
이렇게 반구의 형태로 보이죠
큐브를 봐도 마찬가지로 반입니다 실린더도 마찬가지고
원래 보이던 길이의 절반만 보이는 걸 알 수가 있습니다
앞서서 Dot 연산 같은 경우에는
값의 범위가 -1에서 1까지라고 설명해 드렸습니다
당연히 벡터 같은 경우에는 값이 달라질 수가 있기 때문에
우선은 이것을 Normalize 해서
길이를 단위 벡터로 만들어 주고요
포지션 값도 마찬가지로 Normalize 해서
단위 벡터로 만들어 줄 겁니다
실제로 이걸 아주 가까이서 당겨 보게 되면
아주 약한 그라데이션이 있는 것을
확인할 수가 있는데요 보이시죠?
원래 이 값이 -1에서 1까지라는 얘기는
이 경계 있죠 이 얕은 경계가 0이고요
약간 잘 보이는 이 부분이 1인 겁니다
이 위로는 1보다 큰 값이고 이 뒤로는 -1인 거죠
그래서 이렇게 보이는 건데
이걸 Normalize 해서 결과를 확인해 보면
조금 더 그라데이션이 부드러워진 것은 확인할 수 있지만
여전히 절반만 그리는 것으로 확인이 되죠
다시 구체로 바꾸도록 하고요
이렇게 반구의 형태로 명암이 조금 부드러워지긴 했죠
이제는 Normalize를 하다 보니까
Up이라는 벡터와 포지션 각각의 벡터 값들이 모두 비교되면서
여기 있는 것들이 모두 다 비교가 되면서
그라데이션이 생긴 건데
이것을 0에서 1 사이 값으로 바꿔보겠습니다
이때 많이 사용하는 노드가 Remap이라는 노드입니다
Remap인데 결국에 우리가 필요한 건
0에서 1 사이이기 때문에
별도의 출력되는 값을 따로 정할 필요 없이
0에서 1 사이라는 값이 정해져 있는
RemapValueRangeNormalized라는 노드를 사용할 거고요
여기에서 인풋되는 Low 값
가장 작은 값과 가장 높은 값은 Constant 노드를 이용해서
하나는 -1로 Low에 연결해 줄 거고요
하나는 1로 최댓값을 High에 연결해 줄 겁니다
그러고 나서 결과를 Opacity에 연결해 보면요
온전히 구체의 모양이 거의 다 보이고 있죠 이런 식으로
출력되는 값이 0에서 1로 변동이 일어났습니다
여기 출력되는 값을 0에서 1이라고 정해주도록 하겠습니다
이 포지션의 값을 그래서 우리가
그라데이션 되는 방향을 만약에 빨간색으로 만들면
그라데이션 되는 방향이 오른쪽에서 왼쪽으로
이렇게 방향이 바뀐 것을 확인하실 수가 있죠
이제 줄무늬 패턴을 만들어 주기 위해서
연산이 된 영역까지만 선택해서 뒤로 빼겠습니다
여기에다가 Sine이라고 하는
여기에서 여러분들이 조심하셔야 될 것
제가 사용하는 Sine은 삼각함수의 Sine입니다
그래서 Sine고요
또 다른 Sign이라고 발음되는 것이 있습니다
이거 헷갈리시면 안 되고 Sine으로 넣어주시면 됩니다
Sine이란 노드를 사용해서
물결치는 듯한 파동 효과를 만들어 줄 건데
이것을 그대로 Remap에다가 넣어보도록 하겠습니다
그러면 중간이 빈 것처럼 이렇게 표현이 될 겁니다
당연히 Direction을 바꾸게 되면
만약에 여기에서 그린 값을 바꾸게 되면
이 물결치는 중간에 비어있는 영역이 그린에 의해서
이런 식으로 휘어져서 보이는 것을 확인할 수가 있죠
혹은 B에다가 넣으면 이렇게
대각선 방향을 향하게도 만들 수 있습니다 보이시죠?
근데 줄무늬가 하나밖에 없기 때문에
이것을 Dot에서부터 Multiply 해서
Sine에다가 연결해 주고요
여기에 있는 Multiply는 ScalarParameter를 이용해서
줄여서 lineFreq라고 입력하고
기본값을 30 정도만 입력해 보겠습니다
그럼 지금 보시는 것처럼 줄무늬 패턴이
이렇게 생성된 걸 확인하실 수가 있는데
이제 우리는 이 패턴을 나중에 흘러가게 만들 거고요
이렇게 생성된 줄무늬 패턴
이걸 여러분들 임의에 따라서
5만큼 입력해서 패턴을 다르게 보이게 만들 수도 있습니다
이건 여러분들이 임의로 하시면 되고요
Sine 노드에 대한 설명을 하면
우리가 흔히 삼각함수에서 얘기하는 Sine 값이 맞습니다
우리가 삼각함수 얘기할 때
Cosine, Tangent, 마지막으로 Sine 해가지고
중학교 수학 때 이런 것들을 배웠는데
이때 얘기하는 이 Sine 값입니다
그래서 이것을 그래프 상으로 그려보면
X축으로 어떠한 값이 입력되든지 간에 출력되는 것은
값의 범위가 1에서부터 -1까지 이렇게 돼서
영점이라고 했을 때 0에서부터 이렇게 값이 1까지 커졌다가
내려왔다가 이렇게 다시 돌아오는
그래서 일정한 주기를 가지고 있는 Sine 그래프가 만들어지죠
그래서 이런 것들을 배우셨을 겁니다
1이 되는 이 지점은 π/2고요
다시 0이 되는 지점은 π
-1이 되는 지점은 3/4π
마지막으로 끝에 다시 0이 되는 지점은 2π
그래서 이것이 이렇게 원주율을 나타낼 때
원의 한 바퀴 둘레를 의미하는 게 2π라고 얘기하잖아요
어떠한 값을 넣든 여기가 100이 들어가든 1000이 들어가든
결국 그 값에 맞춰서 이렇게 나타내는데
우리는 이것을 한 주기라고 부릅니다
그래서 Sine 값을 잠깐 보여드리면
Sine 값을 끊고 그대로 Opacity에다가 연결해놓고요
Sine에다가 Constant 노드를 이용해서
이건 값을 설명하기 위한 거니까
여러분들은 따라 하지 않으셔도 됩니다
이 그래프에 의하면 0을 넣으면 그대로 0이니까
아무것도 안 보이는 게 맞겠죠
반대로 출력되게 하고 싶으면 π/2 값이니까
3.14이니까 1.07 얼마 정도를 넣으면
값이 1이 되겠네라고 생각하실 텐데 잘 보세요
여기서 1.07 얼마를 넣는다고 하더라도
여전히 지금 보시면 값이 출력되는 걸 확인하실 수가 있죠
마찬가지로 3.14를 넣고 보시면
다시 보이는데?라고 생각하실 수 있습니다
1.07이나 3.14나 혹은 2π에 해당하는 6.28을 넣어도
값이 보이는데?라고 생각하실 수가 있는데
실제로 1이 출력되는 것은 0.25입니다
0.5를 입력하면 0이고요
0.75를 입력하면 -1인데 보이진 않죠
그리고 1을 입력해도 0입니다
1.07을 입력했을 때는 이미
값이 1까지는 아니라고 해도
반투명하게 보인다는 것은 어느 정도 출력되고 있다는 뜻이죠
이것을 여러분들이 수학 시간 때
Sine 그래프를 이해하실 때는 이런 식으로
각 대푯값마다 값을 외우셨을 텐데요
언리얼에서는 이것이 약간 다르게 작동합니다
하나의 주기로 보고
주기의 1/4의 위치, 2/4의 위치, 3/4의 위치
마지막으로 1의 위치, 1주기의 위치
이런 식으로 인식을 하기 때문에
아까 전에 제가 0.25라고 값을 넣었고
0.5라고 넣었고 0.75 그리고 1이라고 넣었죠
실제 Sine 값이 아까 전처럼 1.07을 넣게 되면
1.07은 결국 한 바퀴 돌아서 다시 이만큼 온 것이기 때문에
대략 여기 언저리쯤 위치하게 될 겁니다
그래서 눈에 보였던 거고요
언리얼에서는 Sine 값에다 넣어줄 때
지금 보시는 것처럼 이런 식으로
하나의 주기 값에 의해서 값이 결정이 된다고 이해하시면 되고
그렇기 때문에 여기에 우리가 -1에서 1까지를 넣은 것을
5배로 뻥튀기 했죠
지금 lineFreq 값을 5배를 했기 때문에
-5에서 5까지 값을 출력하겠죠
이게 곱하기가 되면서
그러면 총 10번의 주기가 생기게 된 겁니다
-5에서 한 번, -4에서 쭉 가서 4에서부터 5까지 해서
총 10번의 주기가 생기게 된 겁니다
그렇기 때문에 여러분들이 lineFreq에 넣게 되는 값은
결국 우리가 몇 개의 줄무늬를 만들게 될 거냐와 같습니다
그래서 이것을 Sine 값에 다시 연결하고
Constant는 지우도록 하겠습니다
이렇게 보게 되면 5라고 넣었기 때문에
줄이 총 10개가 생긴 것을 확인하실 수가 있죠
근데 이렇게 줄이 생겼다고 해서
그대로 사용하는 건 아니고요 움직여야겠죠
움직여야 됩니다 이 값들이
그래서 여기에다가는 한 번 더 Add를 통해서
Sine에다가 연결을 해주고요
Add에다가 지속적으로 움직이게 하고 싶다면
지속적으로 움직인다는 얘기는
시간이 지나야지만 해결이 되기 때문에
Time이라는 노드를 연결해 줄 겁니다 이런 식으로
그러면 지금 보는 것처럼
이렇게 그래프가 움직이는 것을 확인하실 수 있죠
이렇게 생각하시면 돼요 이미 줄무늬는 있고요
우리가 보여줄 범위를 결정하는데
이 범위 자체를 움직인다고 생각하시면 됩니다
시간에 따라서 계속해서 일정한 방향으로
이 범위가 이렇게 움직이는 거죠
옆으로 서서히 가서 계속해서 다음번 줄무늬를 보여주고
이런 식으로 이동하는 것들을 우리가 눈으로 확인하고 있다
이렇게 생각하셔도 되고
혹은 구체는 가만히 있고
이 줄무늬들 자체가 Add를 통해서
값이 이동하고 있다고 생각하셔도 됩니다
어느 쪽이든 결과적으로는 같으니까요
Time마저도 바꿀 수가 있습니다
Time도 Multiply를 이용해서
원래는 시간 값이 정확하게는 초 단위로 값이 전달되는데
Multiply를 이용해서
이게 1이면 당연히 원래 속도 그대로겠죠
1초에 일정한 유닛만큼 이동할 건데
이것을 5초로 입력하면
5배를 입력하면 그만큼 빨라지는 거고
0.3으로 입력하면 30%의 속도로 움직이게 되겠죠
그래서 여기 있는 Time에다가 Multiply 된 이것도
ScalarParameter를 이용해서
Time Scale이라는 값으로
기본값은 1이 되게끔 이렇게 표현을 해봤습니다
이렇게 표현하고 나면 이제 다시 Remap을 통해서
Opacity에 꽂아 넣을 수 있게
정말 다행히도 Dot도 -1에서 1까지고
Sine도 출력되는 값이 -1에서 1까지입니다
그것을 우리는 어떻게?
Remap을 통해서 0에서 1 사이로 바꿔서
Opacity에다가 전달해 주게 되겠죠 이런 식으로
이렇게 Remap까지 만들어진 노드를
Saturate와 Fresnel과 Depth Fade가 연결되었던
이 노드 사이에다가 한 번 더 Add 해주도록 하겠습니다
Add의 원리는 앞서서 설명했으니까 생략하겠습니다
그리고 최종 결과를 다시 Opacity에
Lerp된 결과를 연결해 보면
선이 아주 두껍기 때문에 원래 있던 형태가 잘 안 보입니다
그래서 이 선의 두께를 조절하기 위해서 Result
Remap의 결과에다가 Multiply를 이용해서
이를테면 이 선의 선명한 정도를 50%만 표현해라 해서
Add 해주게 되면 조금 덜해지죠
이를테면 0.3만 선명해라라고 하면
조금 더 선이 이렇게 보이게 되죠
Sign에다가는 중간에 이 사이에다가
Power라는 노드를 이용해서 지수 값을 이용해서
선의 두께를 이렇게 조절해 줄 수도 있습니다
보이시죠? 선의 두께가 바뀐 거
지수 값이 1일 때, 지수 값이 5일 때
아주 얇게 선이 표현된 것을 확인하실 수가 있습니다
그래서 이런 식의 과정을 거친다면
우리가 에너지 실드를 표현할 때
조금 더 다채로운 효과들을 만들어 줄 수가 있고요
여기에서 Power를 이용한 두께나
Multiply를 이용한 투명도의 정도
이것들을 전부 다 파라미터로 빼두면 좋겠죠
Power에서는 이것을 ScalarParameter로 빼서
lineWidth로 라인의 두께로 지정해 놓고
기본값은 2로 두겠습니다 얇게
1.2 이런 식으로 하셔도 상관없습니다
0으로 하면 이렇게 띠처럼 나오는 거고 1 하셔도 되고
그리고 Remap에서 Multiply한 값은
ScalarParameter로 빼서 lineOp라고 적어서
이것을 0.3 정도 되도록 만들겠습니다
이렇게 만들어진 효과를 인스턴스로 만들어서요
월드 상에서 정상적으로 우리가 마음대로
변화를 줄 수 있는지 한번 확인해 볼 건데요
우선 인스턴스를 열어주고 창에서 한번 보겠습니다
지금 이렇게 흘러가고 있죠
파라미터들을 뽑는 이유가 있는데요
우선 이 인스턴스를 먼저 구체에 적용하고요
드래그해서 그래서 보면 여기 있는 구체에
인스턴스가 제대로 전달이 되었는지 확인하시고
여기 있는 파라미터에서 지금 보시면
Depth Fade의 두께와 Fresnel이 된 두께는 얼추 비슷한데
라인의 두께가 너무 두껍죠
그렇다면 lineWidth를 이렇게 선택하셔서
Exponent 값, 제곱이 됐던 값을 조금 키워주시면
선의 두께가 얇아지면서
Depth Fade와 유사하게 맞춰지는 것을 보실 수가 있고요
Time Scale을 이용해서
더 빠르게 움직이게 한다든가 이런 식으로
너무 빠르네요 4배 정도 했더니
한 2배만 하도록 하겠습니다
2배 정도 빠르게 움직이게 한다든가
Direction 값을 이용해서
레드에다가 마이너스 값을 넣으면
이런 식으로 방향도 바뀌게 되고
여러분들이 붉은색을 넣으셔도 되고요
Inner Color에 이런 식으로
Side Color는 유사하게 주황색 이런 식으로 색을 쓰시되
조금 밝게 빛나라고 레드나 그린, 블루에다가 1보다 큰 값을
이를테면 레드 8이나 블루 0.2 이런 식으로 해서
더 밝게 빛나게 만드는 것도 가능합니다
그래서 각각의 값들을
여러분들이 오브젝트 크기라든가 이런 거에 맞춰서
수정해서 쓰시면 되기 때문에
이 각각의 파라미터들의 역할에 대해서
내가 어느 부분을 어떻게 뺄 거다라는 걸 잘 계산하셔서
묘사를 해주시는 것이 중요합니다
이번 시간에는 반투명 셰이더를 통해
렌더링되는 원리를 파악할 수 있었습니다
이를 시각화하는 연산 기법과
시간을 이용한 움직임을 만드는 등
기존 PBR 셰이더와는 다른 접근 방식으로 표현하였습니다
시각적으로 다양한 표현들을 위해서는
수학적인 이해가 반드시 필요하지만
그렇다고 해서 그렇게 어렵지 않은
그리고 어렵다고 하더라도 이미
머티리얼 에디터를 통해서 충분히 쉽게 활용할 수 있게끔
기능들이 제공된다는 것을 아셨을 겁니다
수학이라고 해서 너무 어렵게 생각하지 마시고
계속해서 다양한 효과들을 학습해보시면 좋을 것 같습니다
그럼 이번 시간 학습한 내용을 정리하면서 마무리하겠습니다
감사합니다
Fresnel과 Depth Fade
머티리얼 설정: 콘텐츠 폴더에 EnergyShield 폴더 생성 후 M_EnergyShield 머티리얼 생성
반투명 설정을 위해 Blend Mode를 Translucent로 선택
Fresnel: 카메라가 바라보는 각도와 버텍스의 노멀 벡터를 비교하여 0~1 값을 출력
Lerp 생성, A : 0.3, B : 1, Alpha : Fresnel 연결 후 Opacity에 연결
미리보기를 스피어로 변경하면 중앙은 30% 투명도, 바깥 경계는 100%
Depth Fade 3D 오브젝트가 맞닿은 경계를 시각화
OneMinus 후 Fresnel과 Add
Add 된 결과 Saturate 적용 후 각각 Lerp의 Alpha에 연결
파라미터 변환 Emissive Lerp A : Inner Color, B : Side Color
Opacity Lerp A : InnerOp, B : SideOp
Fresnel ExponentIn : FresnelExp
Depthfade FadeDistance : FadeDist
포지션 시각화 Absolute World Position 생성 후 normalize
VectorParameter 생성(Direction) 후 normalize
Dot(내적) 노드 생성 후 A : 월드 포지션 노멀라이즈 한 결과, B : Direction 파라미터 노멀라이즈 한 결과 연결
RemapValueRangeNormalized 노드 생성 후 Input : 내적 결과 입력
Input Low : Constant(-1) 노드 연결, Input High : Constant(1) 노드 연결
Multiply 생성, A : Dot 결과, B : ScalarParameter 생성(LineFrq, 5)
Sine 노드 생성 후 입력에 Multiply 된 결과, 출력은 Remap Input에 연결
Time 노드와 Multiply 생성 후 A : 타임 노드, B : ScalarParameter 생성(TimeScale, 1)
Add 생성 후 A : lineFreq 곱셈 결과, B : Time 곱셈 결과, 출력을 Sine에 입력
Power 노드 생성 후 Base : Sine, Exp : ScalarParameter(linewidth, 1)
출력 결과는 Remap Input에 연결 (라인의 두께 설정)
Multiply 생성 후 A : Remap Result, B : ScalarParameter(lineOp, 0.3) (라인의 투명도 설정)
Add 노드 생성 후 A : Fresnel과 Depthfade가 더해진 결과, B : lineOp를 곱한 결과
Add 출력은 Saturate에 연결