[ 오브젝트에 마테리얼 적용해보기 ]
[ Surface 쉐이더를 Material에 적용하기 ]
Assets에서 Create - Shader - Standard Surface Shader로 새로운 Surface 쉐이더를 생성해준다 .
Assets에서 Create - Material을 통해 새로운 마테리얼을 생성해준다 .
1 - 2 순으로 드레그 앤 드롭하여 쉐이더를 마테리얼에 -> 마테리얼을 오브젝트에 적용해준다 .
[ 쉐이더 코드를 열어 이름을 바꾸기 ]
[ Surface 쉐이더 열어보기 ]
생성했던 Surface 쉐이더를 더블클릭하면 위와 같이 비주얼 스튜디오를 통해 열 수 있을 것이다 .
그 전에 배운 구조를 볼 수 있고 , 일반적으로 {} 를 통해 구분하고 있다 .
[ 쉐이더 이름 바꾸기 ]
상단의 쉐이더 코드 첫줄을 원하는 이름으로 변경한다 .
이때 "/"는 쉐이더의 위치를 일종의 트리구조로 만들 수 있다.
상단의 경우 Custom - Yeo - NewShader의 위치에 생성된다 .
중요한건 " "로 문장이 닫혀 있어야 한다.
[ 쉐이더 Properties 제작하기 ]
[ 쉐이더 Properties ]
전체적으로 보면 쉐이더는 크게 세 부분으로 나눌 수 있다 .
이중에서 1번 영역이 Properties 영역이다 .
해당 부분은 Material에서 다음과 같은 인터페이스로 볼 수 있다.
이때 , 여기에 사용되는 인터페이스를 만드는 방법은 다음과 같다 .
- Float을 받는 인터페이스
- _Name ( "display name", Range (min,max) ) = number
- _Name ( "display name", Float ) = number
- _Name ( "display name", int ) = number
- Float4를 받는 인터페이스
- _Name ( "display name", Color ) = (number,number,number,number)
- _Name ( "display name", Vector ) = (number,number,number,number)
- 기타 Sampler를 받는 인터페이스
- _Name ( "display name", 2D ) = "name"{ options }
- _Name ( "display name", Rect ) = "name"{ options }
- _Name ( "display name", Cube ) = "name"{ options }
- _Name ( "display name", 3D ) = "name"{ options }
이상의 프로퍼티들을 각자 알아보자 .
[ Properties - Range ]
_Name ( "display name", Range (min,max) ) = number
해당 기능은 최소값 / 최대값으로 이루어진 슬라이더가 나오는 명령이다 .
각 부분을 알아보자 .
- _Name : 해당 기능의 변수명 . _는 외부에서 입력 받았음을 표시한다 . 이때 , 한글/띄어쓰기/_외의 특수문자/숫자시작/예약여 (color - float 등)는 사용하면 안된다 . 또한 변수명은 고유해야 한다 .
- "display name" : 해당 기능의화면에 나타나는 글자.사용처를 알 수 있게 이름을 짓는게 좋다 . +한글 가능
- Range(min,max) : 최대 , 최소값이 있는 슬라이더를 만든다. 또한 쉐이더는 소수점을 가진 숫자를 쓰므로 입력되는 값은 소수점을 가진 숫자인 float이다 .
- number : 쉐이더가 처음 만들어 질 때의 초기값이다 . 이후 조절된 값으로 변경된다 .
[ Properties - Float ]
_Name ( "display name", Float) ) = number
해당 기능은 한자리의 소수점을 입력받는 인터페이스를 만들어준다 .
Range와 달리 범위제한이 없기에 아티스트의 자유도를 극도로 주고 싶거나 결과를 예측하기 어려울때 사용한다 .
[ Properties - Color ]
_Name ( "display name", Color) ) = (number,number,number,number)
해당 기능은 Color 인터페이스를 만들어준다 .
R/G/B/A 4가지 숫자를 입력 받으므로 float4를 받게 된다.
[ Properties - Vector ]
_Name ( "display name", Vector ) ) = (number,number,number,number)
float4를 직접 숫자로 입력받는 인터페이스를 만들어준다 .
[ Properties - tex2D ]
_Name ( "display name", 2D ) ) = "name" { options }
2d 텍스쳐를 받는 인터페이스를 만들어준다 .
float 계열로 분류되지 않는 sampler들이다 .
텍스쳐는 UV좌표와 함께 계산되어야 float4로 출력될 수 있기 때문에 , 아직 UV와 계산되지 않은 텍스쳐는
색상 (float4)으로 나타낼 수 없다 .그래서 이때까지는 sampler라고 부른다 .
[ 색상 출력하고 연산하기 ]
[ 쉐이더의 구조 ]
앞서 살펴봤던 영역을 다시 보자 .
1번은 프로퍼티 영역이었다.이번에는 2,3 번에 대해 알아보자 (3번은 2번 내부에 속해있다)
그중에서도 CGPROGRAM ~ ENDCG로 끝나는 부분은 유니티 자체 스크립트가 아닌
cg언어를 이용해서 쉐이더를 직접 짜는 부분이다 .
3번 영역을 다시 나누자면 다음과 같이 분류가 가능하다 .
- 1번은 설정 부분이다 . 전처리혹은 스니핏이라고 부른다 .쉐이더의 조명계산 설정 혹은 기타 세부적인 분기를 정한다
- 2번은Input이라는 이름의 구조체이다 . 엔진으로부터 받아와야 할 데이터가 들어간다 .
- surf라는 이름의 함수 영역이다.색상 이미지 출력되는 부분을 만들 수 있다 .
- 1,2,3 에 속하지 않은 부분이다 . 일종의 빈자리이지만 꽤 중요한 부분이다 .
[ Surf 함수 뜯어보기 ]
void Surf (Input IN , inout SurfaceOutputStandard 0) {}
출력을 담당하는 surf 함수의 구조를 살펴보자 .
void를 return 하고 인자로 Input In과 inout (받기도 하고 집어넣기도 한다 )으로 SurfaceOutputStandard o를 수행한다.
여기서 SurfaceOutputStandard는 무엇일까?
struct SurfaceOutputStandard
{
fixed3 Albedo;
fixed3 Normal;
fixed3 Emission;
half Methalic;
half Smoothness;
half Occlusion;
half Alpha;
}
이 구조체는 유니티 내부의 다른 인클루드 파일에 정의되어 있으며 , 보이지 않지만 자동 로딩된 상태라 이해하자 .
즉 , 7개의 변수를 불러 간단히 값을 집어 넣는것만으로 출력값을 만들 수 있다 .
cf ) float / half / fixed
- float : 실수
- half : float의 1/2 크기
- fixed : half의 1/2크기
[ 색상 출력 - Albedo ]
일단 Metalic과 Smoothness는 지워준다 .
위의 o.Albedo의 뜻은 SurfaceOutputStandard안에 있는 Albedo변수라는 뜻이다 .
이후 , 다음과 같이 Albedo에 빨간색을 값으로 넣어준다 .
다음과 같이 출력됨을 알 수 있다.
이때 , 빛의 영향을 받음을 볼 수 있다 . 이는 조명연산을 추가로 받기 때문이다 .
[ 색상 출력 - Emission ]
이번에는 Albedo 대신 Emission을 넣어준다 .
빛의 영향을 받지 않음을 볼 수 있다.
이는 조명연산을 받지 않아 조명과 상관없는 순수한 색만이 출력되기 때문이다 .
만약 Emission,Albedoi가 같이 쓰인다면 둘의 값은 최종적으로 더해지기에 필연적으로 밝아진다 .
[ 색상 연산하기 ]
위와 같이 float3를 더할 수 있다. (포토샵의 Linear Dodge (Add)와 같다)
위와 같이 float3를 곱할 수 도 있다 . (포토샵의 Multiply와 같다)
0~1의 범위를 넘어가는 연산의 결과 (2,0,0)이 일반적 빨강(1,0,0)과 같음을 볼 수 있다 .
모니터에서 1이상의 색은 1과 같이 보이기때문인데 내부적으로는 실제 데이터 (2,0,0)으로 저장됨을 주의해야 한다 .
이렇게 1보다 밝거나 0 보다 어두운 색이 있어서 그것이 존재하고 계산되는 상태를 HDR (High Dynamic Range)라 한다 .
cf ) 연산의 규칙
- 연산은 같은 자리수 끼리 가능하다. ex ) float4와 float3는 연산이 불가하다 .
- 예외적으로 한자리는 언제나 가능하다 ex) float3(1,0,0) + 1
[ 변수를 이용하기 ]
[ 변수 넣어보기 ]
myColor라는 float4 변수를 정의하고 Albedo에 해당 변수를 넣었다 .
변수를 통해 색이 적용됨을 볼 수 있다 .
그런데 float3인 Albedo에 float4가 들어갔다 .이는 잘못된 방식이지만 오류를 내지 않을 뿐이다.
이를 myColor.rgb를 넣어줌으로 해결하였다 .
[ RGB의 순서 바꾸기 ]
1 . grb로 순서를 바꿀 수도 있다 . 그결과로 (0,1,0)인 초록이 나왔다 .
2 . 이렇게 rrr과 같이 하나의 요소만 사용 할 수도 있다.
그 결과로 (1,1,1)인 흰색이 나왔다 .
3 . 또한 연산과 같이 한자리수인 1을 넣어도 (1,1,1)을 넣은것과 같이 동작한다 .
4 . 변수의 부분값을 사용해도 마찬가지이다. 이를 스위즐링이라고 한다.
5 . 또한 이렇게 float2를 내부에 넣어 사용 할 수도 있다.
위의 값은 결국 flaot(1,1,0)의 결과인 노랑이 나올 것이다 .
[ 외부의 입력값 출력해보기 ]
[ 색상을 입력받아 출력해보기 ]
Properties에 MyColor라는 인터페이스를 생성한다 . 이때 , Color가 float4라는 점을 기억하고 있자.
이때 , CGPROGRAM ~ ENDCG사이에 함수 혹은 구조체 안에 들어가있지 않은 빈공간인 1,2를 볼 수 있다 .
이 공간이 변수를 선언 할 수 있는 공간이다 .
해당 영역에 _MyColor를 선언해주자 . 이때 ,주의할 점은 해당 변수가 쓰이기전 선언을 해주어야 한다는 점이다 .
이제 사용은 간단하다 . 선언한 변수를 Albedo값으로 넣어준다 .
이때 , Albedo는 float3인 RGB만 사용하므로 Color의 rgb만 사용해준다 .
이와 같이 MyColor프로퍼티에서 내가 지정한 색으로 Spere의 색이 바뀜을 볼 수 있다 .
[ 외부입력값 조합하기 ]
Properties에 MyRed/ MyGreen / MyBlue라는 인터페이스를 생성해서 Albedo의 RGB를 각각 조절하자 .
먼저 인터페이스를 생성한다 .
변수를 선언한다 .
surf 함수에 다음과 같이 사용한다 .
위와 같이 RGB 프로퍼티를 각각 조절하면 조합하여 Spere의 색을 정할 수 있다 .
[ 색상의 밝기 조절하기 ]
Properties에 MyBrightDark라는 인터페이스를 생성해서 Albedo의 RGB를 각각 조절하자 .
먼저 인터페이스를 생성한다 .이때 , 범위가 -1 ~ 1인 이유는 밝음과 어두움을 표현하기 위해서이다 .
동일하게 변수를 생성한다 .
다음과 같이 Albedo값에 MyBrightDark를 더해줌으로 밝기를 조절한다 .
다음과 같이 사용 할 수 있다 .
[ 프로퍼티 깔끔하기 지우기 ]
[ 지워보기 ]
surf 함수에서 사용하지 않을 것들을 삭제해서 깔끔하게 정리해보자 .
다음은 사용하지 않는 _Color를 삭제해보자.
마지막으로 _MainTex를 삭제하자 .
다음과 같은 에러를 볼 수 있다 .
Input 구조체에 아무 멤버가 없다는 에러인데 , 이 말은 해당 구조체는 비어있으면 안된다 .
이 부분에 들어갈 문구는 지정되어 있고 , 아무거나 쓰면 안된다 .
일단 , 다음과 같이 써준다 .
다시 에러가 생성된다 . 아까 지운 c를 Alpha에서 참고하고 있기에 생긴 문제이다 .
1로 설정 , 불투명하게 설정한다.이제 정상 작동한다 .
마지막으로 최소한으로 남기기 위해 다음의 것들을 지운다 .
LOD는 이 쉐이더의 환경 설정에 따른 옵션 값에 대한 내용이며 ,
#pragam target 3.0은 쉐이더 모델 3.0 이상에서만 돌아가게 함으로 복잡한 코드를 쓸 수 있게 제한을 풀어주는 기능이다 .
위의 기능들은 초급단계에서 당장은 사용하지 않기에 일단 지워주자 .
최종적으로 다음의 코드로 깔끔해졌다
'유니티 쉐이더 스타트업' 카테고리의 다른 글
[ 유니티 쉐이더 스타트업 ] 06 . UV를 이용하는 법 배우기 (0) | 2023.08.10 |
---|---|
[ 유니티 쉐이더 스타트업 ] 05 - 2 . Surface Shader를 활용한 텍스쳐 제어 (0) | 2023.08.07 |
[ 유니티 쉐이더 스타트업 ] 04 . 쉐이더랩에 관하여 (0) | 2023.07.31 |
[ 유니티 쉐이더 스타트업 ] 03 - 2 . 렌더링 파이프 라인 - 레스터라이저와 프래그먼트 셰이더 (0) | 2023.07.24 |
[ 유니티 쉐이더 스타트업 ] 03 - 1 . 렌더링 파이프 라인 - 정점 조립과 버텍스 셰이더 (0) | 2023.07.23 |