본문 바로가기

Unity3D/shader_스터디

[Unity 쉐이더] 색상 연산

내용 정리

 

  • 코드 정리
  • 색상 연산
  • 연습

 


이 글은 코알못의 시점으로 작성되었습니다.

머리가 굳은 상태로 작성되었습니다.

 

 

 

저번 글에서는 이름 짓기, 인터페이스 제작을 해봤습니다.

이제 본격적으로 SurfaceShader를 구경해보겠습니다.

 

 

코드를 보면 중괄호를 통해 구역이 나눠져있습니다. 집과 같은 형태로 상상해보면 훨씬 이해하기 쉽습니다.

Shader 란 집 안에 Properties(현관)와 SubShader(마루)가 들어있고 밖에 FallBack "Diffuse"가 덩그러니 있습니다.

이건 언젠가 배우게 될 테니 지금은 무시합니다.

 

SubShader 내부에는 또 여러 종류의 방이 있습니다. Tags, Input 등 작은 방도 있고, 서프라는 옆에 괄호로 무언가가 딸려있는 큰방도 있습니다. 또 하나의 방으로는 CGPROGRAM~ENDCG가 있습니다. 이 사이의 구역에서 저번 글에서 얘기했듯이 C섭쉐이더에서 CG 사용한다는 것을 선언합니다. 

 

나머지 구분없이 나와 있는 코드들은 마루 위의 코드라고 보면 좋습니다.

 

뭐가 뭐인지 설명을 했지만 처음보는 사람 입장으로써는 안의 내용들은 여전히 보기 어렵습니다. 그렇기 때문에 먼저 정리를 해보고자합니다. 


크게 4가지 과정을 거칩니다.

  • 주석 정리
  • 줄 간격 정리
  • 위치 정리
  • 필요 없는 내용 정리

정리 후 코드 작성 시

  • 자신이 알아볼 용도로 주석 작성, 정리
에러가 나는지 안나는지 하나하나 지우면서 유니티에서 확인할 것

 

 

우선 먼저 지울 것은 //이 붙어있는 주석들입니다. 영어 문장을 보면 울렁거리는 사람이니까 한번 쓱 읽어보고 지워버립니다. 보통 그 코드의 용도 사용방법등이 적혀 있습니다.

 

 

 

자신이 보기 편한대로 여백 공간을 정리하고, 마루 위의 코드 위치도 정리합니다.

 

 

 

 

UNITY_INSTANCING_BUFFER_START(Props) 라는 것이 있습니다. 이건 더 복잡한 제작 방식이라고 하네요. 아직 기초를 배우고있기 때문에 지금은 지워줍니다. LOD, fullforwardshadows도 지워도 괜찮다고 하네요. 지워주고 에러가 나지 않는지 확인합니다.

 

 

이제 기존에 있던 변수들을 정리합니다.

변수를 정리할 때는 안에서부터 지워줘야 합니다. half _Metallic; 같이 위에서 먼저 지울 시 안에서 변수가 갈 곳을 잃어 에러가 뜨는 걸 확인 할 수 있습니다.

 

surf 내의 _Metallic 등 내부에서부터 지우면 저장을 해도 에러가 뜨지 않습니다. 빈껍데기만 밖에 남아있는건 문제가 안되니까요. 이렇게 순서대로 지우고 다시 한번씩 확인해봅시다.

 


ㄹ프 내의 코드들을 지워볼겁니다. 그 전에 뭔가 신경 쓰이는 부분이 있네요. 괄호 안에 뭐가 있죠?

이걸 먼저 간단하게 확인하고 가겠습니다.

 

(Input IN, inout SurfaceOutputStandard o)

Input, inout SurfaceOutputStandard 같은 애들은 구조체라고 합니다. 맞나요??

구조체란?- 타입이 다른 데이터를 하나로 묶는 방법

 

inout SurfaceOutputStandard 을 지금부터 가방이라고 생각합시다. 가방의 내용물이 중요합니다.

struct
SurfaceOutputStandard
{
fixed3 Albedo;
fixed3 Normal;
fixed3 Emission;
half Metallic;
half Smoothness;
half Occlusion;
half Alpha;
};

 

노드로 쉐이더를 만지작거리고 3D 그래픽도 해보신 분들이라면 자주본 단어들이 보입니다.

RGB의 float3과 A와 그 외의 float1의 정보를 담는 변수들이 존재합니다.

섭쉐이더의 코드에서

 

(Input IN, inout SurfaceOutputStandard o)

o는 위의 내용들을 불러올 때 사용할 이름을 지정해 준 것 입니다. IN도 마찬가지

어쨌든 지금은 하나하나 이해하기 어려운 상태라 이런걸 쓸 수 있겠구나 하고 넘어갑니다.

 

 

오늘은 색상 연산을 해볼 것입니다. 색상을 나타낼 때 쓰는 것은?

 

알베도와 이미션이죠.

 

그럼 나머지 Metallic Smoothness 등 다 지워버립니다.

확 다 지워볼까요? 다 지우면 아래와 같이 나타납니다.

 

처음과 비교해 많이 깨끗해졌습니다.

지정된 값이 없을때 현재는 메탈릭, 스무스니스, 알베도 까지 0으로 나타나 금속이 아니며 매끈하지않은 검은 색상의 무언가가 나왔습니다.

실제로는 쓰레기값이 들어가게 되는데 값이 정의되지않은 상태라 뭐가 들어갈지 모르니 이 상태로 두는 것은 지양합니다.

 

다 지워봤으니 이제 직접 만들어봅시다.

 


이미지 연산

알베도, 이미션을 적용해 보겠습니다.

o.Albedo = float3(1,0,0);

앞의 o은 위에서 설명했듯이 처음 SurfaceOutputStandard의 데이터를 불러오기 위한 이름입니다.

o.Emission

등으로 불러와 사용할 수 있습니다. 

 

=은 노드로 제작할 시 알베도에 적용하기 위해 선은 이어주는 것과 같습니다. 거꾸로 보면 더 쉽죠.

float3(1,0,0) 즉 빨간색을 알베도에 연결하겠다는 것과 같습니다. 뒤에 ;(세미콜론)도 꼭 붙여줍니다.

적용하고 에러가 뜨지 않는지 확인해봅니다.

 

 

Emission만 적용해봅니다.

Emission에 대하여

Emission은 3d 그래픽을 배운 사람들은 자제 발광으로 알고 있는 경우가 많습니다.

그러나 '빛이 난다' 라는 표현보다 '어두운 곳을 계산하지 않는다' 라이팅 연산을 하지 않아, 음영이 지면서 어두워지는 곳이 보이지 않는 것이라고 합니다. 1이상이 넘어갈 때부터는 빛이 난다고 할 수 있겠죠.

 

라이팅 연산을 하지 않기 때문에 가장 가벼운 색상연산이라고도 합니다.

 

사칙연산

가산혼합을 하는 빛은 서로 더할수록 밝아지며 RGB각 색의 비율에 따라 색상이 달라집니다.

더하기(+), 빼기(-), 곱하기(*), 나누기(/) 등으로 여러 색상 연산을 할 수 있습니다.

 

더하기 (flaot+float)

 

 

이번에는 float1끼리 더해봅니다. 0은 검정 1은 흰색

0.5+0.5=1(흰색)이 나오게됩니다.

 

float3+float1

서로 다른 float끼리 더하면 어떻게 될까요?

보통 같은 수끼리만 더하는 것을 지향합니다.

 

flaot1의 경우에는 모든 자리에 더해지는 방법으로 계산됩니다. 현재 float3(1.5,0.5,0.5)로 조금 밝은 빨강, 분홍색을 띄게 됩니다.

 

질문- Emission인데 옅게 그림자가 보이는 이유는 엠비언트 때문이 맞나요?

 

 

float4+float3

서로 다른 수를 더하면 원래는 오류가 뜬다고 하지만 뜨지 않네요. 반대로 할 경우에는 float4의 뒷자리 하나가 버려지게 됩니다.

 

 

곱하기(float*float)

곱할경우 1을 기준으로 이상, 이하에 따라 밝아지거나 어두워집니다. 0을 곱하면 뭐든지 0이 되죠.

 

 

 

반전(1-x)

색반전에 사용되는 공식. 위의 공식들도 우리가 흔히 포토샵에서 볼 수 있었던 효과들입니다.

나머지는 직접 해보면서 결과를 봅시다!!

 

 

 


변수 제작

변수를 제작, 알베도에 적용해 인터페이스에 까지 나타내봅시다.

 

float4 _Color;

float4인 RGBA의 정보를 담을 _Color를 만들었습니다.

 

_Color를 알베도에 가져옵니다. 이때 아무렇지 않게 지나갈 수 있지만 _Color는 float4, 알베도는 float3 이라는 것을 알고있습니다.

float3에 float4를 연결하면 남는 자리는 버려지게 됩니다. 쓰레기값을 만들지 않고, 예의를 지켜주기 위해 변수뒤에 rgb를 붙여 float3까지만 사용해 주는 겁니다.

 

 

 

 

 surf 내의 변수는 바로 적용시켜서 볼 수 있네요.

 

float4인 변수 R, G를 만듭니다. float3이어도 상관없겠죠.

그러고

R = G;

라고 선언해줍니다.

 

그러면 

 

 

 

R은 G라고 선언되었기 때문에 녹색이 나오는 것을 볼 수 있습니다.

R과 G를 더한 것을 새롭게 R로 선언할 수도 있습니다.

 

이러면 float3(1,1,0)의 결과를 볼 수 있겠죠.

 

 


 

섞기(Swizzling)

 

float3로 변환시켜주기 위해있던 rgb는 서로 위치를 바꿀 수가 있습니다!

 

아래 사진을 보면 원래 녹색이었던 R이 빨간색으로 나온 것을 알 수 있습니다.

 

색을 바꿔서보면 이해하기 쉽습니다. 간단하게 위치가 바뀐 것이죠.

 

 

 

놀랍게도 xyz로도 색상표현이 가능합니다.

RGB는 색상을 표현하고, XYZ는 방향 표현을 하는 float3의 정보입니다.

R-X

G-Y

B-Z

 

 

그래서 yyy로 흰색을 표현할 수 있는 것입니다. uvw는 안되네요. ㅎㅎ

 

 

 

 

응용

R,G,B 각각의 변수를 만들고 합쳐 인터페이스에서 슬라이더를 이용해 색상 조정을 할 수 있게 만들어보자

 

 

요렇게 

 

 

코드 확인하기

 

 


이것만해도 머리가 빙빙도네요. 다음에는 좀 더 머리를 말랑말랑하게해서 돌아오겠습니다.