Unity Shader Graph #0

a-a·2024년 4월 5일

UnityShader

목록 보기
1/6

색의 표현 방법

24bit 컬러에서 흰색을 만들려면 R 255 G255 B255의 값을 줘야 한다.
각 채널이 5,6,5bit가 되는 16bit 컬러에서는 R32 G64 B32가 흰색이다.
-> 압축 범위에 따라 포맷이 모두 다르다. (포맷이 다르단 걸 처음 알았다.)

다양한 포맷에 맞게 쉐이더를 코딩하는 것은 굉장히 머리가 아픈 일이기에 '백분율'을 사용한다. 이를 '부동소수점' float을 사용해서 표현한다.

float는 32bit(4byte)의 숫자를 나타낼 수 있다. (float, float, flaot) 으로 묶어서 RGB를 표현하고, 0~1까지의 유효한 범위를 가진다.
float은 소수점 6자리까지 유효한 범위를 가지기 때문에 모든 색을 표현 할 수 있다고 봐도 무방하다.

유니티 쉐이더

쉐이더 언어 중에서 흔히 알고있는 HLSL 말고,
유니티는 CG(C for Graphis) 언어를 사용한다. 추가로, 유니티에서 자체 제작한 쉐이더 언어도 사용한다.
유니티에서 쉐이더를 짜는 방법은 세 가지가 있다.

  1. Shader Lab
  2. Surface Shader : 상대적으로 가장 쉽고, 프로그래머가 아니더라도 배우기 쉬운 개념의 쉐이더 언어
  3. Vertex & Fragment Shader

HLSL을 사용해보았기에 CG 언어가 크게 어렵지 않았다.
다만 유니티에서 제공하는 쉐이더 구조체 안의 내용이 생소했다.
구조체 내용

struct SurfaceOutputStandard
{
	fixed3 Albedo; //빛을 반사하는 정도를 수치로 나타낸 것.
	fixed3 Normal; //노멀맵을 저장하는 용도.
	fixed3 Emission; // 그림자를 연산하지 않는다.
	half Metallic;
	half Smoothness;
	half Occlusion;
	half Alpha;
};

구조체 추가 설명

  • Albedo
    표면의 베이스 컬러를 제어한다. Albedo를 단일 값으로 지정하면 유용한 경우도 많지만 보통 텍스처 맵을 할당하는 경우가 더 많다. 알베도 텍스처에 조명이 포함되면 안된다는 것이 중요하다. 오브젝트가 표시되는 컨텍스트에 따라 조명이 추가되기 때문. 그리고 텍스처의 투명도 값도 적용된다. → 표면을 표현하기 위한 프로퍼티, 출처 : 유니티 공식 포럼
  • Emission
    엔진에서 빛은 정확하게 말하자면 ‘그림자를 만들어 주는’ 연산
    즉 해당 프로퍼티를 사용하면, ‘자체 발광’하는 듯한 효과를 줄 수 있지만, 이는 그림자 연산을 하지 않기 때문에 그렇게 보인다. 따라서 어두운 곳에서 강조된 효과를 주기 위해서 유용하게 사용되는 프로퍼티이다. 출처 : 유니티 공식 포럼
  • Normal
    Normal mapping이란 각 픽셀에 사용할 법선 정보를 담고 있는 텍스쳐를 이용해 평평한 표면을 울퉁불퉁하게 보이게끔 만드는 기법이다.
    추가로 Parallax occlusion mapping 라는 심화 기술이 있다고 한다.
    측면에서 봤을 때 입체감을 주고 (높이 맵 이용) + 인접 픽셀과의 높이차를 구한 뒤 그림자를 입히는 기법이 사용

연산 테크틱 기법 이름
1. ‘One Minus’ : 반전(invert), 예) (1,0,0) → (0,1,1)
2. ‘Swizzling’ : (스위즐링) : 각 채널을 섞어 다른 결과를 만듦

텍스처는 ‘sampler2D’로 가져온다.
텍스처를 입힌다는 것은 픽셀 하나하나씩 찝어내어 오브젝트의 지정된 위치에 박아주는 것이다.
찝어내는 것은 Sampling(표본 추출)이라고 한다. ‘지정된 위치’를 알 수 있는 것이 UV 좌표이다.

Sampler2D ‘뭘 힙힐 것인지’
uv_MainTex ‘어디에 입혀야 하는지’로 정리할 수 있다.

  • UV
    uv의 곱셉은 타일처럼 작동한다.

빛의 종류

  1. Point (Omni) Light
  2. Spot Light
  3. Directional Light

이러한 빛을 받으면 물체에 일어나는 현상 3가지

→ Phong Reflection은 구형 쉐이더 연산이지만, 모든 빛의 연산의 기본같은 느낌으로 사용되고 있다.

Diffuse Light은 ‘퍼지다’라는 뜻을 가진 단어이다. 의미 그대로 빛의 난반사를 나타낸다. 물체에 반사된 빛이 사방으로 흩어져 확산 되면서 그 물체의 표면(질감)과 색상을 인지하게 해준다.

Amient Light은 간접광에 의한 난반사를 표현한다. 예를들어 빛이 직접적으로 닿지 않는 부분도 어느정도의 발긱를 가지고 있으며, 화창하고 맑은 날엔 흰색 건물에 드리운 그림자가 ‘파랗게’보이기도 하는 것이 그 예다.

그리고 Amient Light는 사전적으로 ‘주변’이라는 뜻을 가졌다. 모든 물체는 빛을 바등면 그 정도가 다를 뿐 전부 흡수하지 않고 일저양의 빛을 반사하는 성질을 가지고 있다.

하지만 ‘화이트 밸런스’때문에 우리는 인식을 잘 하지 못한다.

예를 들어 A4용지를 주황색 가로등 아래다가 두었을 때, 실제로는 종이가 주황빛을 내지만 인간은 이것을 하얀색으로 인식하는 것이 그 예다. Ambient의 존재를 의식하는 순간 세상이 다르게 보일 것이다. (…신기하다..!)

Secular Light (정반사)는 정빛의 정반사로 물체 표면에 반사되는 빛이 정확히 대칭 각도로 반사 될 때 보여진다. 흔히 물체의 가장 밝은 부분(Highlight)으로 표현 되며 Diffuse와 Specular의 비율은 반비례하게 적용된다. Diffuse가 높아지면 Specular가 줄어들고 반대로 Specular가 높아지면 Diffuse가 줄어드는 식.

이후에 물리 기반 쉐이더(Physically Based Renderer) PBR 기법이 생겨났다. 이전에는 조명이나 환경, 제질이 바뀐다면 그에 따른 3가지 요소를 다시 지정해줘야 했지만, 이젠 자동으로 계산해준다. 현재 가장 보편적으로 사용하고 있고, 유니티나 언리얼도 해당 기법을 사용하고 있다.

PBR에선 물체의 고유 색상(Albedo)로 두고, Duffuse와 Specular의 비율과 제질을 물체의 금속질과 거칠기를 통해서 표현하게 된다. BRDF (Bidirectional Reflectance Distribution Function)도 포함하고 있는데 BRDF는 양뱡향 반사 분포 함수로 어떤 재질이 얼만큼 기울어지면 얼마나 반사가 되는지를 표시한다.

백터의 연산

백터의 곱샘에는 내적(Dot) 연산과 외적(Cross) 연산 두 가지 유형이 있다. 이중 내적 연산(Dot Product)은 두 벡터의 각도를 나타내는 공식으로 Dot( · )으로 표기 한다.

  • 내적을 구하는 공식 두가지
    1. A(x¹,y¹)B(x²,y²) =(x¹x¹)+(y²y²)A(x¹,y¹) · B(x²,y²) = (x¹ * x¹) + (y² * y²) 
    2. AB =dist(A)dist(B)cosθA · B = dist(A) * dist(B) * cosθ

어쨋든 내적은 두 백터 사이의 각도를 구하는데 사용한다.
Normal은 Vector의 집합이라 볼 수 있다.
Normal이 오브젝트의 빛을 받아오는 형식은 크게 두가지가 있다.

  • Face Normal

    오브젝트의 면에 normal Vector를 넣어 면단위로 그림자가 지도록 만드느 방식. Face Normal을 사용할 경우 각각의 면이 도드라져 보아며, 부드러운 블렌딩을 표현할 수 없었다.
  • Vertex Normal
    Face Normal 방식의 단점을 개선한 방법

    말 그대로 Vertex(점)에 Normal을 박아넣고 버텍스 간의 사이의 값이 보간되어 부드럽게 표현되도록 만든 방식. Face Normal이 불가능한 부드러운 표현이 가능했지만, Face Normal처럼 딱딱하게 각지는 것을 표현할 수 없다는 것이다.

    이를 해결하기 위해서 같은 곳에 여러 개의 버텍스를 두는 무식한 방법으로 이 문제를 해결한다. 결과적으로 스무딩과 하드 엣지를 함께 사용할 수 있게 되었다. 이렇게 하면 면의 수만큼 폴리곤이 더 늘어난다는 것을 의미한다.

이제 빛의 연산의 기본, 내적으로 다시 돌아와서 빛의 연산을 다시 보도록 하자.
오브젝트의 버텍스에서 뻗어있는 노말 벡터와 라이트 백터가 마주볼 때, 해당 버텍스는 가장 밝아진다. ( 내적의 값이 0에 가까울수록 밝다..!) 하지만, 라이트 백터와 노말벡터가 마주보는 상태로 연산을 하게되면 결과 값에 -가 붙어버리기 때문에 라이트 벡터에 -1을 곱해주어 두 백터의 기준점을 맞추고 내적 연산을 하여 두 벡터의 각도 차를 구하게 된다.

→ 이를 노막(N)과 라이트(L)를 내적한다 하여 N·L, NdotL이라고 부른다.
백터의 내적 연산은 코사인 그래프와 일치한다.

0도1흰색
90도0검정색
180도-1검정색

profile
"게임 개발자가 되고 싶어요."를 이뤄버린 주니어 0년차

0개의 댓글