2022년 12월 26일 월요일

Unity Shader기초1

Unity Shader기초1

Shader 왜 사용할까요?

Shader는 추상적인 수치인 물체의 점,선,면,색상값을 계산하여 그래픽적인 출력이 가능하도록 처리하여 주는 것을 말합니다.
게임이나 그래픽 프로그램처럼 이미지처리를 빠르게 해야하는 프로그램에서는 그래픽처리를 담당하는 그래픽카드에 명령을 내려 결과를 가져올 수있도록 하는게 효율적입니다.
이러한 과정을 위해서 Shader라는 것이 생겨났고, Shader 를 지원하는 프레임워크,장비 에서는 Shader를 사용하여 여러가지 화면 효과를 낼수 있게 됩니다.
Shader가 다른 객체(조명등)와의 상호관계를 바탕으로 물체를 최종 그래픽결과물로 가시화 시키는 것을 Rendering이라고 합니다.
따라서 그래픽결과물이나 게임화면은 Rendering된 결과물이라고 볼수있습니다.

Shader 기초

셰이더(shader)는 실제로 입력된 메쉬(Grid)와 입력 텍스처 또는 색상을 지정된 방식으로 결합한 다음 출력하는 역할을 하는 작은 프로그램입니다. 그래픽 장치는 이 출력을 기반으로 화면에 이미지를 그릴 수 있습니다.
즉, 그래픽 카드는 우리가 작성한 Shader를 읽어서 자동으로 실행하고 결과를 돌려줍니다.
따라서 우리는 Shader언어를 사용하여 작성한 파일을 유니티나 기타 개발플랫폼에 던져주면 해당 플랫폼이 그래픽카드에 전달하여 결과물을 돌려받을수 있는 것입니다.

Shader 작성은 Shader언어라는 구조화된 형식으로 언어에 포함된 여러가지 함수들을 이용하여 작성하면 됩니다. 언어형식은 거의 통일되었지만 플팻폼 또는 그래픽카드제조사에 따라 조금씩 다를수도있습니다.

  • HLSL(High Level Shader Language) : Unity, Unreal에서 사용, 일반적으로 많이 사용
  • CG (C for Graphic) : NVIDIA(그래픽카드제조사)에서 제작한 언어 - GLSL(OpenGL): 고전적으로 사용하던 언어
    서로다른 3개 이지만 큰 맥락은 거의 같기 떄문에 하나만 배우면 되므로 걱정할 필요없습니다.

일단 Shader 작성에도 최근에는 여러가지 방식의 Shader가 있는데 크게보면

  • Surface Shader : 대부분의 작업을 GPU가 그래픽처리에 필요한 라이트,노말,행렬등을 자동으로 수행해주며 비교적 간단하게 사용할수있습니다. 고전적인 Shader방식입니다.
  • Fragment Shader : 기존의 Surface Shader보다 더 자세한 부분까지 제어해서 다양한 효과를 작성할수 있습니다. 최근에는 이를 더 많이 사용합니다.

Unity 에서 Shader만든다고 한다면 Fragment Shader 를 작성하는 것이며, 언어는 HLSL과CG를 사용합니다.

Unity 에서 Shader사용하기

Unity에서 Shader를 생성하는 방법은 두가지가 있습니다.

  • Shader Graph를 통해서 드래그드롭 방식으로 만드는 방법
  • Shader 스크립트파일을 만들어서 직접 코드를 수정하면서 만드는 방법

Shader Graph 를 이용하여 Material생성

Shader Graph는 Shader언어를 직접 작성하지 않고도 유니티에서 제공하는 비쥬얼 툴을 보면서 쉐이더를 생성할 있는 기능입니다.
Shader Graph 파일작성 -> Material(재질)에 Shader를 지정 -> 게임오브젝트에 Material적용 순서대로 입니다.
일단 Asset에서 적당한 폴더에서 Create Shader Graph 까지 가보면 URP, Built-in, Blank Shader, SubGraph가 있습니다.(2021.3.14f버젼)

먼저 Universal Render Pipline의 약자입니다. 프로젝트 생성시 URP를 선택했다면 이 옵션이 보입니다. Pipeline이라는 단어에서 알수있듯이 화면을 렌더링할때에 파이프라인에 추가기능을 끼워넣어서 최종 결과물에 여러가지 효과를 줄수 있습니다.
URP의 특징은 이 파이프라인으로 그리기 시스템을 C#로 커스터마이즈 할 수 있는 것입니다.
만일, 일반 프로젝트로 생성했다면 Asset폴더에서 Rendering-> URP Asset( with Univesal Render)를 추가해야합니다.
URP의 하위메뉴로는

  • Lit Shader Graph : 씬의 라이트에 의한 영향을 받는 Shader를 만들때 사용합니다. 라이트에 영향을 받아서 물체에 광채, 반사광 등이 표현됩니다.
  • Unlit Shader Graph : 씬의 라이트에 의한 영향을 받지않는 Shader를 만들때 사용합니다. 라이트의 영향을 받지 않기 때문에 무광의 물체가 표현됩니다.
  • Sprite Custom Lit Shader Graph : 씬의 라이트에 의한 영향을 받는 Shader를 만들때 사용합니다. ???
  • SpriteUnlit Shader Graph : 씬의 라이트에 의한 영향을 받지않는 Shader를 만들때 사용합니다. 2D용 Sprite에 적용합니다.
  • Sprite Lit Shader Graph : 씬의 라이트에 의한 영향을 받는 Shader를 만들때 사용합니다. 2D용 Sprite에 적용합니다.
    Built-in은 Unity자체의 렌더파이프라인을 말합니다. ( 빌트인 렌더 : docs.unity3d.com/Manual/built-in-render-pipeline.html )
    Built-in 하위메뉴로는
  • Built-in Lit Shader, uilt-in unlit Shader : URP환경이 아닌 Unity순수 Build-in 렌더러에서 작동하는 Shader도 Graph형태로 만들수 있도록 해줍니다.
    Blank Shader Graph : 아무것도 설정되어있지않는 Shader Graph를 생성합니다.
    SubGraph : (모듈형태같은) Shader를 생성합니다. 생성된 SubGraph는 여러곳에서 모듈처럼 사용가능합니다.

일반적으로 Lit Shader, Unlit Shader를 주로 사용하며 SubGraph로 모듈화해서 사용하기도 합니다.

Shader Graph생성후 물체에 적용하기

Shader Graph에서 그래프를 생성한후 재질에 적용하여 물체에 재질을 입히면 그래프에서 작성한 대로 재질효과가 나타납니다.
1.Assets/Texture같은 적당한 폴더에서 마우스 오른쪽버튼을 눌러서, Create -> Shader Graph -> URP -> Lit Shader Graph 를 선택하여 이름을 적당히 입력합니다.(예:SampleShader1)
2.만든 파일을 더블클릭하면 편집화면이 보이는데, 가운데 보이는 (Vertext - Fragment)가 Master Stack영역으로 최종결과물이 되는 시점을 나타냅니다.
Shader 에서 지원하는 여러가지 기능들을 추가하고 붙여서 최종적으로 Master Stack에 그래프가 연결하면 되는 것입니다.
Master Stack에 항목을 추가하여 결과물에 영향을 주는 효과들을 추가할수 있습니다.
지금 우리는 물체의 금속성 속성을 3.[Add Block Node]판넬에서 입력항목에 Alpha를 입력하고, Universal Render PipeLine->alpha를 선택하여 추가합니다.
4.추가된 alpha속성의 왼쪽에 수치(현재 x1) 가 있습니다.이값을 조절하면 Main Preview 영역의 임시물체(공이지만 바꿀수 있어요)에 적용된 재질의 투명도가 바뀌게 됩니다.0.5정도로 바꿔봅니다.
Base Color의 왼쪽 작은 색상박스를 선택해서 색상도 바꾸어봅니다. Alpha왼쪽의 입력박스가 검은색으로 되어있다면 밑의 4-1을 수행해보시고 Shader Graph탭을 Close한다음에 다시 Shader Graph창을 열면 됩니다.
4-1.이때 미리보기 영역에 투명도가 적용이 안되는 경우가 있습니다. 이는 현재 샘플의 표면타입이 Opacue(불투명) 상태이라 그런것입니다.
Graph Inspector->Graph Settings-> Univesal -> Surface Type 을 Transparent로 바꾸어 주면 투명하게 보입니다.
혹시 Allow Meterial Ovverride가 체크되어있지않다면 체크합니다.
5.그래프 편집기 상단의 Save Asset을 반드시눌러서 저장합니다.
6.지금까지는 Shader Graph에서 쉐이더 그래프를 만들었으니 재질을 만들어서 앞서 만든 shader를 지정하면 과정5에서 만들어준 설정대로 재질이 생성되는 것입니다.
7.Material을 Assets/Texture같은 적당한 폴더에서 Create -> Meterial을 선택하여 이름을 지정하고 생성하면 되는데, 이때 주의할점은
과정 1에서 생성한 Shader Graph파일을 선택한후에 마우스의 오른쪽 버튼을 눌러서 Create -> Meterial로 생성해야 Shader와 Material두개가 서로 연결되게 됩니다.
8.과정 7처럼 안하고 안하고 그냥 빈공간에서 마우스의 오른쪽 버튼을 눌러서 Create -> Meterial로 생성했다면, Shader Graph파일을 선택한후에 Material파일에 잡아끌어 파일에 붙여서 서로 연결되도록 해야하고, Material파일의 선택해서, Surface Option이 Shader Graph파일에서의 Graphic Inspector 창에 있던 값과 같은지 확인해야합니다.
같이 않다면 Material 파일의 Surface Option도 같은 상태가 되도록 해야 합니다.
9.재질이 준비되었으니 Scene에 적당한 Sphere 게임오브젝트를 만들고 과정8의 재질을 잡아끌어 공객체에 붙여봅니다.

Shader Graph의 속성값을 Unity 에디터에서 제어하기

앞서만든 Shader Graph 에 투명도(alpha) 값을 쉐이더내부가 아닌, 유니티 에디터(인스펙터)에서 제어할수있도록 해봅시다.
1.Shader Graph에서 그래프 편집기로 다시 가서, 아까 만든 파일인지 확인합니다.
2.화면맨왼쪽에 아까만든 파일이름이 있는 판넬고 [+] 버튼이 보입니다. 이를 유니티에서는 Blackboard(칠판)이라고 하는데 이곳에 별도의 속성을 추가하여 Shader Grade의 각요소들이 참조하여 사용할수있도록 합니다.
3.[+]를 클릭하면 여러가지 입력설정가능항목 들이 나오는데, 우리가 사용할것은 0~1 소수점으로 Alpha값을 변경하려고 하기에 float(소수)를 선택합니다.
4.적당한 이름을 입력하면 , 항목이 추가됩니다. Shader Graph 에디터 가운데 빈공간에 잡아끌어서 던져놓습니다. 그러면 같은이름의 동그란 버튼의 노드(노드라고 합니다.)가 화면에 추가됩니다.
4-1.blackboard에 추가되면 화면 오른쪽의 Graph Inspector->node Setting에 여러가지 설정이있는데, 이중 Default값만 0.5로 해봅니다.
5.화면 에 추가된 노드의 오른쪽에 파란색빈 동그라미가 조그맣게 있는데 이곳을 선택하여 마우스로 다른노드의 왼쪽에 붙여주면 서로 이어졌다는 그래프가 보이며 서로 연결되게됩니다.
6.우리는 alpha값을 수정할거니까 Master Stack(Fragment)의 Alpha에 과정5의 예처럼 연결해봅니다.
7.이제 과정 4에서 만든 이름으로 유니티 에디터의 해당 게임 오브젝트를 선택하여 Material->Surface Input에 해당 항목이 추가되어 있을겁니다.
8.이제 과정 4에서 만든 이름으로 추가된 항목의 값을 바꾸어 보면 게임화면에서도 적용되어 지는것을 볼수 있습니다.

Shader Graph의 속성값을 Unity 스크립트에서 제어하기

유니티 에디터의 인스펙터에서 조절이 가능하다는 얘기를 스크립트에서 해당컴포넌트를 불러서 프로그램적으로도 조절이 가능하다는 얘기입니다.
1.유니티 데이터의 인스펙터에서는 앞서만든 alpha 값조절용 노드(앞의 과정4에서만든놈의 이름)의 참조이름을 자동으로 알아서 처리해주었습니다.
개발자가 직접이를 하기 위해서는 (앞의 과정4에서만든놈의 이름)에 대한 참조이름(닉네임과 같은)을 알아야하는데, 이를 확인하려면 앞서했던 예제의 4-1 에서 보았던
node setting창에서 Reference라는 항목의 값(주로 언더바랑 과정4에서의 이름, 예 _MyFloat)을 메모해둡니다.
2.새로운 유니티 스크립트를 아무데서나 만들고, 앞서만든 게임 오브젝트에 잡아끌어던져 추가합니다.
3.아래와 같이 스크립트를 입력하면 게임오브젝트의 투명도가 0~1 을 계속 반복하게 됩니다.
public class alphaedit : MonoBehaviour
{
private Material _alpha;
public float _currentAlpha = 0f;
void Start()
{
_alpha = GetComponent().material;
_alpha.SetFloat("_ValueAlpha", _currentAlpha);
}

// Update is called once per frame  
void Update()  
{  
    _currentAlpha += 0.01f;  
    if (_currentAlpha > 1f) _currentAlpha = 0f;  
    _alpha.SetFloat("_ValueAlpha", _currentAlpha);  
      
}  

}

Tip

Shader Graph 선 안보일때

Preference -> General -> Device to Use 를 바꾸어 보면 됩니다.

0 comments:

댓글 쓰기