유니티2022. 5. 18. 23:35

0. 지난 강의내용 보충

 

0-1. Tag - Queue

 

기존에 Tags { "Queue" = "2001" } 이런식으로 숫자를 지정할 수 있었으나 현재는 되지 않는다.

 

0-2. SubShader - Fallback

 

SubShader 중 그 어느 셰이더도 호환되지 않을 경우 최소한 아예 렌더링 되지 않음은 피하고자 최저의 품질로 

 

1-1. HLSL - 시멘틱 (semantic)

 

변수의 의미를 표시한다.

엔진은 해당 코드에서 postion이라는게 vertex의 포지션 값이라는 것등을 알고 있지만

셰이더 코드 안에서는 position이라는 변수를 float4라는 자료형으로 선언했을뿐 엔진과 어떤 데이터로 연결되는지

어디선가는 지정해주어야하는데 이 역할을하는게 시멘틱이다.

fragment셰이더의 경우처럼 함수 뒤에 사용하면 함수의 반환값이 어떤 의미인지를 지정하게 된다.

frag라는 함수가 half4라는 형태로 리턴한 color라는 함수의 결과가 SV_Target이다 라고 선언된 것.

 

SV_Positon, SV_Target 등은 Graphics API에 전달되는 값으로 SV는 System Value의 약자이다.

 

n은 있어도 되고 없어도 되는 정수로 0부터 하드웨어가 지원하는 숫자가 써줄수있다.

TEXCOORD1, POSITION0 등

 

주요시멘틱(접은글)

 

 

1-2. HLSL - 구조체

 

구조체란 사용자 정의 데이터형으로

HLSL에서의 구조체는 보통 단순히 변수만 들고있는 구조체인데 원래 구조체는 함수도 들어있기도 하다.

 

쉽게 이해하고자하면 다음과 같이 생각하면 편하다.

 

3첩쟁반 구조체를 다음과 같이 정의하였다 해보자.

struct 3첩쟁반

{

 float 대접;

 half 종지1;

 half 종지2;

}

사용시는 아래와 같이 될것이다.

3첩쟁반 철수네;

3첩쟁반 명희네;

 

이런식으로 3첩쟁반이라는 규격의 철수네와 명희네 구조체 변수를 선언하는데 이를 또 사용할때는 아래와 같다.

철수내.대접 = 칼국수;

철수네.종지1 = 간장;

철수네.종지2 = 단무지;

 

VBA에서의 구조체

더보기
< 연출된 예시 >

예를 들어 DB 테이블에서 각 열에 들어 있는 값들을 VBA에서 가져와 변수에 담으려고 한다해보자.

여러 열들의 값을 변수로 받으려 한다면 그만큼 변수가 필요하겠지만 구조체를 사용하여 조금더 편하게 할수있다.

Secinfo 라는 구조체 안에 ID, Code, Name이라는 멤버가 포함되어 있다고 선언하였다.

(VBA에서 기본적으로 구조체는 Public으로 선언되기때문에 Public을 쓰지 않아도 됨)

 

이후 데이터갱신이라는 매크로에서

Data라는 변수를 만들면서 Secinfo라는 구조를 가진다고 선언하고 Data라는 변수의 각 멤버들에게 with문을 사용하여 값을 할당하였다.

이로서 데이터 파싱을 할때 DataID, DataCode, DataName 등의 변수를 만들고 사용하여 관리하는 대신

하나의 구조체로 묶어서 관리할수있다.

이후 데이터를 불러올때 Data.ID , Data.Name 등등 더 편리하고 직관적으로 호출해올수있을것이다.

상단은 구조체를 사용하여 vert 함수의 단일 매개변수로 IN 구조체 변수를 사용한 예시이다.

시맨틱은 Attributes안에서 지정되어있다.

 

반면 하단은 vert 함수의 매개변수들에 직접 시맨틱을 사용하였다.

구조체를 활용하지 않아 하나하나 입력변수에 넣어준 모습이다.

 

1-3. 변수의 Scope

 

변수는 선언된 위치 이후부터 유효하며, 중괄호 안에서 선언되었다면 자신이 속한 중괄호 안에서만 유효하다.

< 자신이 속하지 않은 중괄호에서는 유효하지 않다. >
< 좌 : 함수 밖에서 선언되어 사용되는 형태 / 우 : 선언한 위치 이전에 사용되어 Error가 난 형태>

1-4. Lexical Scope

 

3ds Max 스크립트에서의 Lexical Scope라는 개념이 HLSL에서도 유효하다.

하위레벨에서 동일한 이름의 변수를 선언하면 동명이인이 된다.

이름은 동일해도 서로 다른변수가 되는 것이다.

 

2-1. 전 처리 지시어

 

셰이더 그래프의 키워드 분기 역시 전처리의 한종류이다.

키워드를 통해 만들어진 분기는 하나의 셰이더가 2개의 기능을 하는것이 아닌 내부적으로 2개의 셰이더가 만들어준 것이었는데, 2개의 셰이더를 미리 만들어두는것이 전 처리이다.

 

이미지 출처 : [유니티 C# 강좌] 16. 전처리기 지시어(Preprocessor Directive) / contribut by. 코더 제로

 

전 처리 지시어는 여러가지가 있다.

  • #define - 상수나 매크로를 정의한다.
  • #error - 컴파일시 에러메시지를 생성한다. 발동과 동시에 컴파일이 중단된다.
  • 조건분기 - #elif #else #endif #if #ifdef #ifndef [ 정적 분기 ]
  • #include - 외부 파일의 코드를 삽입한다.
  • #line - 컴파일러 내부에 저장되는 라인 번호와 파일명을 특정 값으로 선언한다.
  • #pragma - 하드웨어나 OS별 기능을 제공한다.
  • #undef - #define으로 정의된 상수나 매크로를 제거한다.

2-2. 전 처리 지시어와 정적 분기

 

정적 분기를 위한 키워드는 재질에 저장되는데, 셰이더의 커스텀 에디터 코드로 설정하기도 하지만

C#코딩이 필요한 작업이다.

커스텀 에디터 코드 없이도 재질에 키워드를 세팅해주는 방법으로는 MaterialPropertyDrawer가 있다.

 

[Toggle] 방식

Toggle 키워드는 On에 해당하는 키워드 하나만 세팅한다.

셰이더 내부에서 Toggle에 의해 세팅하는 키워드는 "프로퍼티명(대문자) + 밑줄 + ON"의 규칙으로 세팅된다.

위의 경우 프로퍼티명이 _ToggleTest이므로 키워드는 "_TOGGLETEST_ON"이 되는 방식

< Pass에 전 처리 지시어로 멀티 컴파일을 걸어준다. >

위 코드에서 __ 밑줄 2개는 공백키워드로 유니티 셰이더에서 키워드가 없는것으로 인식한다.

 

< #ifdef 전 처리 지시어를 통해 재질에서 토글에 대한 체크박스가 켜져있으면 무조건 노랑이 출력된다. >
< off / on >

Toggle은 프로퍼티 이름으로 된 Float값도 생성한다.

위 예시로는 _ToggleTest이며

셰이더 코드 내부에서 half_ToggleTest;으로 변수를 선언하고 0이나 1의 값으로도 사용할수있다.

 

[Enum] 방식

KeywordEnum은 최소 2 개의 키워드가 재질에 세팅된다.

또한 아래 예시를 통해 볼때 Red, Green, Blue 또한 0,1,2 순서대로 각각 수자에 대응한다.

동일하게 아래와 같이 전 처리 지시어를 통해 멀티 컴파일을 세팅해주어야한다.

아래는 Enum에 대응하도록 작성된 셰이더 코드의 내용 발췌본이다.

 

 

여기서 Toggle방식과의 차이점이라면 Toggle은 off상태일 때 TOGGLETEST_ON 키워드가 삭제되지만

Enum방식으로 접미어로 ON/OFF라 가정할때 단순히 TOGGLETEST_OFF 키워드가 세팅되는 방식이기에

만약 단순한 On/Off 에서는 Toggle을 사용하는것이 좋다. 

< 키워드 조합 규칙 >

참고해볼만한 글 [링크]

 

2-3. 네이밍 관례와 표준

 

관례이므로 지키지 않아도 시스템에 문제가 발생하지 않는다.

셰이더도 일종의 프로그래밍 언어이고 가독성을 위해 관례적으로 지켜야하는 규칙이 있으며

업계마다 또는 플랫폼마다 미묘하게 다른 경우가 많다.

< 프로퍼티는 밑줄+대문자로 시작한다 >
< 구조체는 대문자, 멤버는 소문자로 작성 >
<함수명은 파스칼 표기>
<변수와 함수 파라미터에는 카멜표기>
< 키워드나 사전 정의는 모두 대문자 >

2-4 셰이더에서의 if 분기

 

셰이더에서 if 분기 사용에 대해서 자세히 알고 사용하고자 한다면 셰이더 내부 작동 방식을 자세히 이해해야 한다.

즉 난이도가 높다는 것으로, 보통은 if 분기 사용은 가급적이면 자제하되 필요시 사용한다 정도의 기준으로 사용하자.

참고 글 링크:

쉐이더에서 IF문이 느린이유 / by. Hybrid3D

shader에서 간단한 if문은 성능상 별 문제 없습니다. / by. nagnae blog

 

 

3-1. 좌표계, 벡터, 행렬

 

좌표계 ( Coordinate System ), 벡터 ( Vector ), 행렬 ( Matrix ) 은

플랫폼과 도구를 불문하고 셰이더에서 가장 기본이 되는 개념으로 중요하다.

 

3-2. 좌표계와 공간

 

우리가 흔히 사용하는 좌표계는 데카르트 좌표계이다.

x와 y 2개의 축으로 이루어진 2차원 좌표 평면에서 원점으로부터 각 축 방향으로 숫자를 표시하여

점의 위치를 나타내는 방식으로 z축을 추가하면 3차원 좌표계가 된다.

3-3. 유니티에서 살펴보는 좌표계

 

아래 케이지에서 구체는 각각 2m거리에 있으며 케이지의 중심은 정 중앙에 위치하여있다.

구의 부모 오브젝트가 위치가 달라졌음에도 자식오브젝트인 구의 오브젝트의 위치는

2x2mcage의 공간 속해있기에 공간이 이동함으로서 좌표는 달라지지 않은 모습이다.

 

이러한 부모자식 관계에서 끄집어냄으로서 표시되는 좌표가 월드좌표로 바뀌었다.

속한 좌표계가 월드 좌표가 된것

다른 오브젝트 (Main Camera)의 자식으로 두는 즉 공간을 변경하는 행위는 겉으로는 변화가 없지만

transform값에는 큰변화가 생겼다.

Position 뿐만아니라 비스듬한 부모오브젝트에 따라 Rotation값도 변하였다.

 

이러한 부모 변경을 통해 살펴볼 수 있는 공간은 아래 3가지가 된다.

1.오브젝트 공간, 로컬 공간

2.월드 공간

3.뷰 공간

 

그 외에도 클립 공간, 스크린 공간이란 개념도 있지만 이는 단순한 부모 변경으로 설명할 수 없는 공간 변환이 발생한다.

(차후 등장할 예정)

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

12강 (13주차 진행)  (0) 2022.06.01
11강(12주차진행)  (0) 2022.05.25
9강 (10주차)  (0) 2022.05.10
8(+1)주차  (0) 2022.05.04
7(+1)주차  (0) 2022.04.26
Posted by 텃파