본문 바로가기
튜터리얼_스터디

(셰이더그래프)아티스트를 위한 URP 셰이더 Shader #13_1 - Custom Light 1

by 대마왕J 2021. 12. 17.

이번엔 책으로 따지면 흠 NdotL 이니까.. 301페이지쯤 되겠네요 

셰이더 그래프 Shader Graph 로 커스텀 라이트 Custom Light 를 만드는걸 시작하겠습니다 

안내 
여기 나오는 내용은 유니티 쉐이더 스타트업에 나오는 예제를 최신 URP에 맞추어 예제를 번역한 내용입니다. 
때문에 이론적 내용이 상당히 간략하거나 불친절하며, 예제에 대한 설명도 축약되어 있기 때문에
책과 같이 보시는 것을 추천하는 바입니다.

 

에또 ... 노말과 라이트 벡터를 dot 연산하는건 이미 책에 이론이 잘 나와 있어요. 벡터가 뭔지, 노말이 뭔지, dot 이 뭔지...
그래서 라이트 디렉션을 찾아보려면 ...??? 

몰 ? 루

없어요 ㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋ

이걸 왜 안만들었느냐... 뭐 여러가지 이유가 있지만 요즘 엔진은 라이트 공식이 복잡해지고 엮인게 많아지면서 아티스트가 이걸 건드리는걸 그다지 좋아하지 않아요. 옛날과는 다르다 이거지 . 이 구조까지 막 가지고 만지는건 애들은 가라 애들은 가 

 

그래서 뭐 그래도 굳이 하려면 .. 라이트 디렉션이나 칼라는 따로 받아와야 해요. 으쩔 수 없지. 커스텀 노드를 소환한다!!!

 커스텀 노드란?

노드는 뭐 잘 아시다시피 코드(함수) 로 되어 있는 덩어리라고 할 수 있습니다. 
커스텀 노드란, 이 함수를 직접 짜서 없던 노드를 만들어 내는 것이라고 할 수 있죠 

hlsl로 하신 분들에게는 아 이 뭐 쉽구만 이러겠지만
노드로만 하신분에게는 생명의 위협을 느끼게 할 수 있는 무시무시한 도전!! 

 

커스텀 노드 만들기 

일단 커스텀 노드부터 만들 수 있어야겠죠 

쉬워요. Custom Fuction 이라고 하는 노드를 하나 꺼내 놓으면 됩니다. 

그리고 나서 Graph Inspector를 켜서 좀 만져줄게 있는데요, 

커스텀 펑션에서는 조금 주의해야 할게 이 Precision (정밀도) 입니다. 
코드의 정밀도인데요, float 과 half 는 사실 별 상관 없다고 늘 말해 왔지만
여기서는 다릅니다. 여기서는 철저하게 지켜 줘야 해요. (사실 오늘은 아니지만)

왜냐면 .. 만들어지는 함수 이름이 이 Precision 에 맞춰서 자동으로 접미어가 붙어 버리거든요. 
그래서 이걸 안 맞춰 주면 에러가 뜨는 모습을 볼 수 있습니다. 매우 중요. 

Node Settings 에서 이 노드의 정밀도도 맞춰 주고, 
Graph Settings 에서 이 그래프 전체의 정밀도도 같은걸로 맞춰 주면 됩니다. 
아 여기서 말하는  Single이 float 이라고 생각하시면 돼요 

(사실 Graph Precision 만 Single로 해 놓고 Node Settings의 Precision 은 Use Graph Precision 으로 하면 알아서 따라가니까 더 편하죠 )  

 

 

라이트 디렉션 받아오기 

그럼 우선 카와이하게 라이트 디렉션만 받아오는 노드를 만들어 보지요 

아 그전에 , 그래프를 Lit에서 Unlit으로 바꿔주세요. 
왜냐면 라이트 계산을 우리가 할거잖아요? 그러니 당연히 Lit으로 하면 안되는거죠 

 

자 그럼 본격적으로 커스텀 노드를 선택하고, 아래처럼 만들어 줘요 

Type은 String으로 해주세요. 이건 여기다가 직접 코드를 쓰겠다는 말. 
그리고 Name을 써주세요 이게 생겨나는 함수의 이름이 될 거예요. 

자 그럼 Body 가 있죠? 이제 여기다가 코드를 직접 쓰면 돼요 

이렇게 써주세요 

Light light = GetMainLight( );
Direction = light.direction;

그럼 에러가 나죠? 정상입니다. 에러가 나야 해요. 

저기 빨강 말풍선이 보입니다. 셰이더 그래프 에러 보는건 좀 안좋아서, 저 말풍선을 눌러 봐야 해요. 
애초에 코드를 짜라고 만들어 놓은 놈이 아니라.. 

그럼 158번줄에 Light가 뭐냐라고 나오는데... 저건 뭐.. 일단 무시하셔도 됩니다.. 
저거 해결법은 따로 있으니까요 

무엇보다 지금은 에러가 두 개가 나와야 정상인데, 저것만 보인다는게 더 문제입니다. 그게 더 중요한데. 

각설하고 , 에러 잡죠. 

아래처럼 바꿔 씁시다 .

#ifdef SHADERGRAPH_PREVIEW 
    Direction = half3(1,1,1);
#else
    Light light = GetMainLight();
    Direction = light.direction;
#endif

#ifdef문으로 SHADERGRAPH_PREVIEW 라고 되어 있는데요
이건 '셰이더 그래프일때에는 이걸 실행시켜라 라는 말이고 
Direction = half3(1,1,1); 이걸 실행하란 말입니다. 

그리고 # else 로 
'위의 경우가 아니면 아래걸 실행시켜라' 라는 말이죠. 
그리고 아까 에러가 났던 Light light 부분이 여기 있습니다. 

즉 위에 에러났던 unrecognized identifier 'Light' 는 셰이더 그래프 인터페이스에서는 작동 안하는 거라 에러가 났던거구요, 지금 그래서 셰이더 그래프로 프리뷰 보여줄때랑 실제 계산될 때 두 가지로 나눠서 #ifdef를 해 줬으니 그 에러는 사라졌습니다. 

 근데 이번엔 다른 에러가 생기죠? 이번엔 Direction 이 뭐냐.. 라는 건데요. 
뭐 변수 선언도 안하고 막 썼으니 당연하지요 ㅋㅋㅋ
그러니 출력변수로 Direction 을 해 줍시다. 단위는 당근 Vector3로. 

이렇게 , Outputs에다가 Direction 이라는 같은 이름의 Vector3 출력변수를 선언해 주면 됩니다. 
저 Body 안에 있는 코드가 Output으로 출력되어 나간다는 뜻이예요. 

그럼 짜잔 - 에러가 사라졌습니다. 

뿐만 아니라, 출력으로  Direction 이 생겼습니다 ! 첫 커스텀 노드를 만들었네요! 

이걸로 간단히 NdotL을 만들어 볼까요 

그럼 라이트 디렉션도 나왔겠다, 노말벡터만 있으면 NdotL  이 나올 수 있겠군요 

이건 간단합니다. Normal Vector를 World Space로 꺼내서 Dot연산해주면, (그리고 이 셰이더를 오브젝트에 적용시켜주면)

이렇게 간단한 Rambert 라이팅 연산을 할 수 있습니다. 

후후 하지만 이제부터죠. 또 기대해 주세요 

 

블로그 주인장에게 커피값을 후원할 수 있습니다! 

 

반응형

댓글