이것저것

[UNITY] 라이팅 1장 - 기본 이론 본문

[유니티] Unity3D/Unity Shader

[UNITY] 라이팅 1장 - 기본 이론

Patch_JA 2019. 4. 20. 23:43
728x90

 

 

이번장에서는 라이팅 이론에 대해서 다룰 예정이며 유니티를 가지고 작성된다.

 

간단한 용어 정리

Ambient Light 간정광에 의한 난반사

Diffuse Light 직접광에 의한 난반사

Specular Light 정반사

 

Digital Light의 기본 개념

현실을 '흉내 내는' 3가지의 라이트가 있다.

포인트 라이트 ( Point Light 혹은 Omni Light )

점(Point) 모양의 광원으로 사방으로 뻗어 나가는 특성이 있기 때문에 둥근 모양의

라이트가 필요한 곳이나 특정 범위에 둥글게 라이트가 필요할 때 많이 사용된다.

디렉셔널 라이트보다 무겁기 때문에 성능에 신경을 쓰면서 작업해야 한다.

 

스팟 라이트 ( Spot Light )

특정 부분을 강조하고 싶을 때 사용하면 좋다. 스팟 라이트 역시나 성능에 신경을

쓰면서 사용해야 한다.

 

디렉셔널 라이트 ( Directional Light )

라이트의 강도와 컬러 등의 정보를 제외하면 로테이션만 담긴 '방향'이란 정보밖에 없고,

각도를 기울수록 어두워진다. 시작점이나 끝점이 없어서 라이트 중에서 성능상 가장 가벼운 라이트이다.

 

현실의 빛과 컴퓨터 그래픽의 빛

현실에서는 물체가 빛을 받을 때 가까이 있는 물체가 더 밝고 뒤에 있는 물체는 빛이 사방으로 튕기면서 더 어두워 보인다. 하지만 컴퓨터 그래픽에서는 현실처럼 대기 중에 분자 등으로 인한 빛의 산란하는 것들을 구현하기 힘들다.

그래서 이미지처럼 각도에 따라 빛을 계산하기 때문에 가까이 있는 물체보다 뒤에 있는 물체가 더 밝게 표현된다.

 

방향과 벡터

라이트나 표면에는 모두 방향이라는 것이 존재한다.

위 화살표처럼 화살표의 길이는 크기이고,

방향을 가리키는 곳을 벡터의 방향이다.

즉 쉽게 말해 화살표나 방향을 앞으로 벡터(Vector)라고 부른다.

 

 

벡터는 방향과 크기만 중요하기 때문에 위치는 전혀 의미가 없다.

위 좌측 이미지처럼 위치가 틀려도 방향과 크기는 같기 때문에 결과는 같다.

또한 벡터를 float들로도 표현할 수가 있는데 좌측 이미지처럼 2차원에서는 float2로 표현할 수

있고, 우측 사진처럼 3차원에서는 float3로 모두 x, y, z를 표현할 수 있다.

 

벡터의 크기가 1인 벡터를 단위 벡터(Unit Vector)라고 한다.
벡터의 크기를 1로 만드는 행위정규화(Normalize)라고 한다.

 

 

벡터의 덧셈

백터의 덧셈은 각 성분을 더해주는 것이고, 삼각 형법, 평행 사변 형법에 의하여 정의된다.

두 벡터의 시작점과 끝점을 연결하면 새롭게 하나의 벡터가 생겨나는데 그 벡터의 방향과 크기가

두 벡터의 방향과 크기이다.

 

벡터의 뺄셈

두 벡터의 뺄셈은 뒤에 있는 벡터가 앞에 있는 벡터를 바라보는 벡터를 구할 수 있게 된다.

즉 벡터 A와 B가 있고 A-B일 때 B의 끝점에서 A의 끝점을 바라보는 방향을 얻을 수 있다.

 

벡터의 스칼라 곱

각 성분에 특정 수치를 더하는 것을 스칼라 곱이라 한다.

* 여기서 말하는 스칼라는 크기만 있고 방향이 없다. 벡터는 크기와 방향이 있다.

이때 곱하는 값이 음수면 벡터의 방향이 뒤집히게 된다.

예를 들어 10, 20, 30의 값을 가진 벡터가 존재할 때

0.5를 곱하면 5, 10, 15의 값을 가지게 된다.

 

벡터의 내적

내적은 스칼라곱(Scalar Product) 또는 닷(Dot Product)라고도 하며, · (Dot) 기호를 사용한다.

내적을 구하는 방법은 두 가지가 있다.

 

첫 번째로 좌표값의 각 성분을 곱해서 더하는 방법.

 

두 번째 방법은 벡터의 크기를 곱하는 것이다.

 

벡터의 외적도 있지만 너무 길어질 것 같으니 다음 장에서 포스팅하겠다..

외적까지 하게 되면 너무 길어질 것 같다. 다음에 더 깊이 들어갈 때 한 번 더 작성하겠다.

 

물리 기반 렌더링

PBR(Physically Based Rendering)이라고 부른다.
처음 디즈니에서 기술을 공개하였고, 이후 디즈니 PBR을 축약하여 게임엔진에 적용되기

시작했다. 셰이더 하나로 모든 재질을 퉁칠 수 있게 하여 아티스트들이 원하는 질감을 구현할 수 있도록 만들었다고 하는 것 같다. 

유니티에서도 PBR을 좀 더 쉽게 다룰 수 있게 하려고 가이드 표를 제공한다.

수치만 바꿔주면 자동으로 알아서 척척 바꿔주는 PBR을 빼고

PBR이 없던 예전으로 돌아가 구형 라이트 셰이더들을 구현해보자. 당연히 비 물리 기반일 것이다.

 

구형 라이트 셰이더 ( Non - PBS )

유니티 4 까지는 기본적으로 사용된 조명이다. 적당히 생략되고 가벼운 조명에 호환성도 좋고 가벼워서 지금도 많이 쓰며 사실상 PBR도 여기서부터 시작되었다.

대표적으로 Lambert BlinnPhong이 존재한다.

 

간단하게 Lambert와 BlinnPhong 셰이더를 구현해보자.

Lambert 

기본 셰이더를 만들고 난 뒤 CGPROGRAM위치에서

#pragma 쪽에 Standard을 지우고 Lambert로 교체해준다.

Lambert로 변경 후 실행하게 되면 에러가 뜨게 된다. 

 

해당 셰이더를 쓰기 위해서는 기존에 사용하던

SurfaceOutputStandard 구조체가 아닌

SurfaceOutput 구조체를 사용해야 한다.

 

막상 실행해보면 빛 때문에 눈으로 확인하기 힘들다.

아까 작성했던 Lambert 코드 옆에 noambient 코드를 추가시켜주자.

 

Lambert는 Diffuse 연산은 되지만 Specular 연산은 전혀 되지 않기 때문에

Specular 연산이 들어가 있지 않는 Lambert 가 완성되었다.

 

 

Blinn-Phong

BlinnPhong을 쓰기 위해서는 Lambert와 똑같이 코드를 바꿔주기만 하면 된다.

하지만 BlinnPhong을 쓰기 위해서는 추가적으로 예약어 변수가 하나 들어가게 된다.

Properties에 _SpecColor라는 예약어를 작성해주어야 하고 주의할 점은

Properties에만 작성되어야 하고 외부로는 빼서 사용하면 에러를 내게 된다.

왜 만들었냐고 물어본다면.. 나도 모른다.. 그렇게 만들어졌다..

o.Specular로 쨍한 정도를 조절할 수 있고

o.Gloss로 Specular의 강도를 있고 없고를 조절할 수 있다.

 

신형 라이트 (PBR/PBS)

물리 기반을 이용한 라이팅 셰이더이다.

Standard와 StandardSpecular가 있는데, Standard 같은 경우 기본으로 적용되어 있던 것이라

바로 StandardSpecular를 구현해보도록 하겠다.

 

구형 라이트 때처럼 StandardSpecular를 위한 구조체가 따로 존재하는데

SurfaceOutputStandardSpecular를 넣어주면 된다.

 

Face Normal과 Vertex Normal

 

Face Normal

면이 가지고 있는 노말

버텍스 노말처럼 부드럽게 표현할수 없다.

 

Vertex Normal

점이 가지고있는 노말

face normal을 보완하기위해 개발되었고 부드러운 면을 표현할수 있다.

 

 

 

 

Comments