유니티2022. 3. 29. 02:31

0. 3주차 보충

셰이더의 나눗셈은 가급적 곱셈으로 진행하는게 좋다. (최적화 측면)

굳이 이유가 궁금해서 찾아보았는데 이 링크에 잘 설명되어있다. 컴퓨터의 연산과정과 관련된 것.

 

수학적으로 0으로 나누는 것은 불가능하다.

아래 영상을 참고하면 이해하기 쉬울것이다.

다만 어쩔수없이 셰이더를 구성하면서 나누기를 사용하는 경우도 생긴다.

프로그래밍이라면 0으로 나누는 경우를 조건문으로 제외하면 되지만 셰이더에서는 복잡한 조건문을 구성하기 힘들다.

결론은...0대신 0에 가까운 작은 값을 사용한다!

ex) 나누는 값에 대한 최소,최대치 지정시 0.001~1 로 지정한다.


1 - 1 . Keyword

Keyword 노드는 셰이더 그래프 상에서 정적분기를 사용할 수 있게 해주는 노드이다.

불린(boolean)은 논리적 데이터 유형으로 참(true) or 거짓(false) 값만을 가질 수 있다.

< Keyword 노드 >
< 인스펙터 상에서 보이는 모습 예시 >

1 - 2 . Shader Feature, Multi Compile

위 처럼 셰이더 그래프 상에서 Keyword 노드를 통해 분기가 남아있을때 유니티는 On과 Off 모두 계산해놓는다.

이를 멀티컴파일 이라고 하며 이 과정에서 셰이더 베리언트가 생성된다.

동일한 셰이더를 각각 다른 Material에 할당한 경우 한 곳에서 셰이더 코드를 작성하고 유지하며, 프로젝트에서 더 적은 셰이더 에셋을 사용할 수 있다.

< 셰이더를 컴파일 할 떄 임시로 에디터에 보이는 모습 >

Keyword 노드를 사용할 때 Definition를 잘 설정해주어야한다.

Shader Feature : 재질에 설정된 경우만 컴파일

Multi Compile  : 재질과 관계 없이 모든 경우의 수를 컴파일

 

ex) 다른 재질의 오브젝트 A와 B에 X셰이더가 적용되었다. A와 B 모두 True로 설정되어있다.

< Keyword 노드 세팅 Definition >
< SF 와 MC 간단이해 >
< 설정에 따라 달라지는 베리언트 수 >

여기서 기억해둘 점은 SF사용되지 않는 배리언트는 게임 빌드에 포함시키지 않는다.

단, SF로 빌드된 셰이더에서 실행 중 컴파일 되지않은 셰이더로 변경될 경우 빌드에 포함되어있지않아

의도치 않은 마젠타가 보일 수 있다.

 

< Scope 설정 >

해당 키워드의 사용범위를 Scope를 통해 설정할 수 있다.

셰이더 베리언트를 사용할 때 Unity에서 키워드가 256개로 제한되고 이 중 약 60개가 내부적으로 사용된다.

실제로 사용 가능한 키워드는 더 적으므로 큰 프로젝트의 경우 Keyword 사용 제한을 고려하여 내부의 룰에 의거해서

사용하도록 한다.

 

1 - 3 . 셰이더 폭발

 

키워드에 의한 정적 분기는 파생 버전의 셰이더(배리언트)를 자동 생성한다.

키워드의 종류가 많아질수록 배리언트의 수는 제곱으로 증가한다.

다양한 조건에서 불필요한 코드를 줄이기위해 필요한 기능이다.

하지만, 이런 조건이 많아지면 오히려 배리언트의 숫자가 기하급수적으로 증가해 셰이더 수가 증폭된다.

이를 셰이더 폭발이라고 한다.

< 3가지 Shadow 조건과 Fog 여부 / 총 6개의 배리언트가 생성된다. >

1 - 4 . SRP Batcher

 

DrawCall은 CPU가 GPU한테 그려라 명령을 내리는 작업이다.

쉽게 말해 화면에 보이는 오브젝트들을 그리라고 하는 명령이라고 생각하면 된다.

유니티에서는 DrawCall + SetPass Call Batch 숫자로 환산한다.

 

SetPass Call이 무엇인가?

 

우선, CPU는 렌더링해야 할 것들을 Command Buffer라는 곳에다 명령이라는 형식을 전달을 한다.

그다음, 화면에 그려질 오브젝트들을 위해 필요한 정보들이 충분히 쌓이면 GPU에게 넘긴다.

< 출처 : 유니티 코리아 유투브 채널의&amp;amp;amp;nbsp; [Dev Weeks : 성능을 고려한 파이프라인. Universal Render Pipeline >

매테리얼에 필요한 정보들이 가장 많은 부하를 일으키게 된다.

그래서 따로 모아서 처리하게 되는데, 매테리얼과 셰이더 관련된 커맨드들을 모아서 Set Pass Call라고한다.

해당 명령의 공통점은 GPU에 상태값을 전달하는 명령이다.

따라서 SetPassCall을 줄일수록, 상당히 많은 부하를 잡을 수 있다고 한다.

같은 매테리얼을 사용하게 되면 한 번에 그리게 되고,

반대로 다른 매테리얼을 사용한 오브젝트가 있다면 따로 그리게 될것이다.

그 이유는 같은 매테리얼을 쓰면 SetPassCall에 해당하는 명령들을 첫번째 오브젝트 그릴 떄 전달했던 값을

그대로 쓰면 되기 때문이다.

 

즉, SetPassCall을 줄일수록 GPU에 주는 부하가 적어지고, 이는 최적화로 연계된다.

SetPassCall을 최대한 적게 호출하면서 DrawCall을 수행하는 것을 유니티에서 배칭이라고 표현한다. 

 

기본적으로 매테리얼이 달라지게되면 렌더링을 따로 하게 되어, SetPassCall이 늘어나게된다.

하지만 SRP Batcher는 SetPassCall을 더 크게 셰이더 단위로 묶어준다.

매테리얼이 달라져도 셰이더가 같으면 하나로 묶어서 처리해준다는 것이다. 

 

URP 12.1.4부터 SRP Batcher 옵션이 기본적으로 숨겨져있다. Preferences > Core Render Pipeline > Additional Properties > Visibility를 All Visible로 변경하면 모두 보인다.

 

예시를 통해 이해를 해보자

 

위쪽 오브젝트 5개는 텍스처를 다르게 넣어 매테리얼은 다르지만 같은 셰이더를 사용하고 있다.

아래쪽도 텍스처를 다르게 넣어 매테리얼을 달리하고 각 색마다 서로 다른 셰이더를 사용하고 있다.

각 그룹별로 오브젝트를 1개씩 차례대로 활성화시키면 Stats창에서 어떤 변화가 있을까?

 

위쪽의 경우 Batches만 늘어나고 SetPassCall은 늘어나지 않는다.

하지만 아래쪽의 경우 Batch, SetPassCall 모두 늘어나는 모습을 확인 할 수 있다.

 

같은 셰이더를 사용하는 다른 매테리얼이 많을 경우, SRP Batcher를 통해 최적화에 도움을 줄 수 있는 것이다.

 

 


2 - 1 . 커스텀 라이팅

셰이더 그래프 12.1.4 기준으로 Light Direction 설정해주는 노드가 없다.

이렇게 유니티의 기본 노드들이 원하는 기능을 모두 해결해줄수는 없다.

그에따라 유니티에서는 Custom Function 노드를 통해 직접 HLSL코드를 입력하여 셰이더 그래프에 사용할 수 있도록

기능을 제공하고있다.

 

Create Node > Utility > Custom Funcion 의 경로를 통하여 생성할 수 있다

 

<Custom Function 노드의 Node Setting>

Precision & Preview - 정밀도를 선택한다. Inherit 는 기존 걸 사용하고, Single은 32Bit, Half는 16Bit 정밀도이다.)

Type - 외부 파일을 선택할지, 직접 HLSL 코드를 입력할지 선택한다.

Name - HLSL 코드의 함수명을 입력한다.

Source - 외부 파일 에셋을 선택한다. Type 이 File 아닌 String일 경우 Body로 변경된다.

 

Node Setting 상의 Inputs, Outputs 이 HLSL 코드의 입,출력과 일치해야한다. (이름, 정밀도)

 

< 좌측 / Source 로 가져온 코드 원본 , 우측 / Node Setting 의 Input 과 Output >

*Name이 공백이거나 다른이름인 경우에도 에러가 나기때문에 보라색으로 표시하였음

< 좌측 / Input 에 Evil 이라는 원본에 없는 입력이 있어 에러가 난 모습 , 우측 / Input과 Output이 일치한 예시 >

 

2 - 2 . 벡터

 

게임 속에 존재하는 모든 오브젝트들은 어느 위치에 존재하거나, 어딘가를 향해 이동한다.

이런 오브젝트의 위치와 이동 등에 대해서 다루는 도구가 벡터이다.

벡터는 간단하게 요약하자면 공간에서 방향(Direction)과 크기(Magnitude)를 표현하는 도구로서 주로 화살표로 표시되는 개념이다.

여기서 공간은 2차원 혹은 3차원으로 정의되며, 유니티에서도 2차원과 3차원의 벡터만 사용한다.

 

< 방향, 좌표 >

위와 같이 평면에 벡터가 표시하는 좌표까지 화살표를 그리는 것으로 방향을 표시할 수 있다. 

또는 x축과 y축의 교차지점을 원점으로 가정할 때 오브젝트가 해당 벡터 위치에 있다하면, 그 오브젝트가 원점으로부터 (3,4)의 위치에 있다는 좌표의 개념으로도 활용 할 수 있다.

< 크기 >

또는 서로 다른 방향을 가리키는 2 벡터를 두고, 같은 방향으로 놓고 비교하면 빨간 화살표가 더 긴 것을 알수있다.

1초 동안 각 벡터의 길이만큼 이동한다 가정할때는 같은시간이라면 빨간화살표가 더 빠르게 이동하는 속력으로  

또는 두 개의 벡터의 길이를 비교하면서 두 벡터의 크기를 비교할수도있다.

 

< 벡터의 덧셈 >
<벡터의 덧셈>

위 이미지는 벡터의 덧셈 과정이다. v1(2,3) + v2(5,2) -> v1+2(7,5)

설명을 위해 v2 벡터를 공중에 뜬 화살표로 표현하였다.

이렇게 벡터는 공중에 떠있는 화살표로 표현할 수 있지만, 벡터는 원점을 기준으로 한다.

< 예시 >

유니티의 빛의 방향벡터는 어디에 있어도 동일하다.

 

2 - 3 . 삼각함수 의 기초(?)

 

한번은 알고리즘의 간택을 받아 반드시 들어봤을 전설의 노래의 링크가 있다면 삼각함수도 무섭지 않다...!

또한, 삼각함수를 이해하기 쉽게 도움을 주는 사이트도 있다.

<&nbsp;https://www.mathsisfun.com/algebra/trig-interactive-unit-circle.html >

2 - 4 . Dot Product ( 내적 )

 

유니티 상에서 라이팅 등의 연산을 진행할때 가져오는 노멀벡터의 값은 1이 되도록 자동화되어있다. (?)

빛의 방향 벡터와 면의 노멀 벡터를 Dot 하면 Cos 계산이 진행된다.

<내적은 계산 방법이다.>

 

{"originWidth":300,"originHeight":240,"style":"alignCenter","caption":"<

 

 

2 - 5 . Lambert Cosine 법칙

 

우선 Lambertian surface에 대해 알아보자.

Lamberitan surface는 모든 방향에서 보아도 똑같은 밝기로 보이는 표면을 뜻한다.

보통 우리가 이동하면서 한 지점을 바라볼 때 보통 표면을 보는 위치에 따라 밝기가 변한다. 아래 그림처럼 한 지점에서 반사하는 빛은 방향에 따라 다르기 떄문이다.

하지만 Lambertian surface는 모든 방향으로 같은 양의 빛을 반사하여 관찰자의 위치에 관계없이 같은 밝기로 보인다.

< 출처 : https://blog.naver.com/jetarrow82/221252045857 >

램버트 코사인 법칙은, 램버시안 반사율을 가지는 램버시안 표면에서

어떠한 빛이 들어오는 각도에 따라 반사되는 빛의 양이 다르다는 것이다.

이는 Cosine 법칙을 따른다.

 

< 동일한 면적으로 빛이 들어올 때 입사각에 의해 빛의 양이 달라진다. >

45도 위치가 0.5가 아니라 값이 0.707이 되고 계속 밝다가 어느순간 훅 어두워지는 점은 코사인 그래프와 연관지어

생각해보면 이해하기 쉽다.

< 코사인 함수 그래프 >

이미지 출처

 

 

이러한 원리는 Lamber Lighting에 사용된다.

빛의 방향과 면의 방향을 Dot(점곱/벡터의 내적) 연산하는 것이다.

< 간단 렘버트 라이팅 예시 >

[커스텀라이트코드]

더보기

예시에 사용된 커스텀 라이팅 코드는 아래 링크이다.

https://github.com/Unity-Technologies/ShaderGraph-Custom-Lighting

 

GitHub - Unity-Technologies/ShaderGraph-Custom-Lighting: A sample project showcasing a simple method to calculate custom lightin

A sample project showcasing a simple method to calculate custom lighting inside of Shader Graph for the Lightweight Render Pipeline. Includes a sample toon shaded scene and example assets. Built fo...

github.com

 

해당 프로젝트는 2019.2 버전을 기준으로 제작된 코드이다.

 

이로인해 상위 버전에서 버전이 맞지 않아 [ Invalid conditional expression ] 이라는 에러가 발생한다.

아래와 같이 조치한다면 에러가 사라진다.

 

아직 알쏭달쏭한 내용

더보기

3. 커스텀 라이팅 진행

 

< 램버트 라이트 적용 / 상단 접은글의 커스텀 라이팅 코드가 적용되어있다. >

간단 램버트 라이팅을 표현한 셰이더 그래프 예시와 다른점이 있다.

커스텀노드의 Output에 DistanceAttend와 ShadowAtten이 있다.

 

ShadowAtten은 그림자와 관련된 것이다.

DitstanceAtten은 라이트의 Culling Mask와 관련된 값이다.

현재 오브젝트가 속한 레이어(마스크?)와 라이트의 Culling Mask에 의해

오브젝트가 라이트의 영향을 받는다면 이값은 1이되고 받지 않는다면 0이 된다.

 

Culling Mask가 무엇인지 몰라서 찾아보았는데, 이 링크에서 예시를 통해 이해할 수 있었다.


이어서 위 셰이더 그래프에 이어서 그림자를 받도록 해보자.

유니티가 기본제공 Lit 에는 그림자 관련 키워드가 자동제공되어 잘 작동하지만

위 셰이더 그래프는 Unlit 환경이므로 해야할 일이 추가적으로 있다.

 

그림자 관련 키워드를 추가해주는 것이다.

URP 셰이더 라이브러리가 멀티 컴파일 되면서 제대로 작동하기 위해 필요하다.

Name은 틀려도 되지만 Reference가 정확해야 한다.  (앞에 밑줄이 있기도 없기도 하니 주의)

< 해당 노드들은 exposed 될 필요가 없다 >

유니터 기본셰이더 라이브러리들의 조건분기들이 그림자를 제대로 연산하기위해 필요한데, Unlit에는 이 내용이 포함되어 있지않다. 이러한 이유로 Unlit에서 커스텀라이팅을 진행하면사 그림자 처리작업이 필요하다면 해당 키워드를 추가할 필요가 있다.

Definition은 Multi Compile을 권장하고 Scope는 Global로 한다.

실제로 셰이더 그래프 상에서 쓰이진 않지만 존재하는 것만으로 그림자 처리에 도움이 되는 목적의 키워드이다.

 

참고로, 그림자를 위한 위 3가지 키워드 외에도 다른 목적으로 필요한 다른 키워드들도 존재한다.

 

< 키워드가 추가되었다. >
< 조치 후 예시 >

다음으로 환경광을 받도록 조치한다.

아래 강조 표시한 부분이 추가된다.

<환경광 적용>

마지막으로 Fog 적용이다.

Fog는 Lerp로 계산하기에 Lerp 노드에 대해 할 필요가 있다.

Lerp는 Linear Interpolation, 선형 보간을 말하는데, 간단하게 말해서 '두 개를 섞는다'이다.

 

< Lerp 노드 예시 >

다시 셰이더 그래프로 돌아가보자 Lerp 노드에서 T 인풋으로는 Fog노드의 Density(밀도)가 들어갔다.

< Fog Applied를 보면 Lerp가 적용된 것을 볼 수 있다. >

안개가 아주 짙게 깔린 상황에서 기존 재질의 컬러와 무관하게 포그의 색으로 보인다는 점을 생각하면 

Lerp노드를 활용한 이유를 이해할 수 있다.

< 좋은 예시일지는 모르겠다만... Eternal Darkness의 스크린샷 >

 

 


 

 

 


참조한 글 리스트

Unity 3D :: 게임 최적화 기법 https://loadofprogrammer.tistory.com/148

Unity 메뉴얼/셰이더 베리언트 및 키워드 https://docs.unity3d.com/kr/2019.4/Manual/SL-MultipleProgramVariants.html

Batch 및 SetPass Calls https://shkim0811.tistory.com/42

[Unity3D] Vector - 좌표와 속도를 다루기 위한 도구 https://wergia.tistory.com/209

[베개발] 02. 유니티 셰이더그래프 https://rusalgames.tistory.com/18

램버시안 코사인 법칙이란 https://iskim3068.tistory.com/76

램버시안 반사 https://blog.naver.com/jetarrow82/221252045857

 

그리고

 

교수님의 열정으로 가득한 수업자료

 


'유니티' 카테고리의 다른 글

8(+1)주차  (0) 2022.05.04
7(+1)주차  (0) 2022.04.26
6주차  (0) 2022.04.13
5주차  (0) 2022.04.06
3주차  (0) 2022.03.24
Posted by 텃파