꽃미남 프로그래머 김포프가 창립한 탑 프로그래머 양성 교육 기관 POCU 아카데미 오픈!
절찬리에 수강생 모집 중!
프로그래밍 언어 입문서가 아닌 프로그래밍 기초 개념 입문서
문과생, 비전공자를 위한 프로그래밍 입문책입니다.
jobGuid 꽃미남 프로그래머 "Pope Kim"님의 이론이나 수학에 치우치지 않고 실무에 곧바로 쓸 수 있는 실용적인 셰이더 프로그래밍 입문서 #겁나친절 jobGuid "1판의내용"에 "새로바뀐북미게임업계분위기"와 "비자관련정보", "1판을 기반으로 북미취업에 성공하신 분들의 생생한 경험담"을 담았습니다.
Posted by 대마왕J

간만입니다. 우후후

연재가 늦은 이유는 여행을 좀 갔다와서 .. .후후후

 

상하이의 야경은 좋군요.

 

 

대륙의_문화컬쳐.jpg

 

 

자 그러면 오늘은 또 재밌는걸 해보요 우후후
오늘 할 건 이겁니다.

File:Toon-shader.jpg

툰 셰이더! [각주:1]

그렇습니다. 만화처럼 나오게 만드는 저 셀 셰이딩. 저걸 해 보도록 하겠습니다.
보통, shader의 진짜 강점을 아티스트들이 매우 표면적으로 느끼게 되는 순간이 저걸 하는 순간이지요.

 

그럼 일단 만화처럼 보이는 툰 셰이딩에 대해 생각해 봅시다. 툰 셰이딩은 어떤 특징을 가지고 있나요?

1. 외곽선이 있다

2. 음영이 2~3 톤으로 되어 있다.

 

물론 아닌 경우도 있지만, 보통 저런 식으로 되어 있습니다.

이미지 출처 : http://www.nocutnews.co.kr/show.asp?idx=465574

이것은 셀 에니메이션의 특성상, 투명한 합성수지에 애니메이션 캐릭터를 그릴 때 그림자를 부드럽게 그려서 작업하면 효율이 너무나 떨어졌기 때문에 대량 생산을 위해 만들어진 방식으로, 게임에서는 굳이 이 방식을 사용할 이유는 없지만 이 방식을 흉내내서 셀 에니메이션 처럼 보이게 하는 방식이지요. [각주:2]

일단 첫 번째로 외곽선은... 지금 설명하기에 좀 이릅니다. shader FX로 실습하기 좀 까다로운 면이 없지 않거든요.
그래서 실습하려면 shader가 아닌 MAX의 기능을 좀 이용해야 합니다.

일단 뭐 외곽선에 대한 이론은 여기를 보시면 됩니다.

http://gamedevforever.com/18

그래서 외곽선은 다음 시간에 합니다.
왜냐하면...

귀찮으니까요.

 

그러니 일단 오늘은 음영을 구현하는 것만 해 보죠.

 

음영이라... 음영을 ... 셀 에니메이션에는 2도나 3도 쯤 단계로 하잖아요?
우리도 그걸 만들어 보죠. 어떻게 하면 될까요?

다시 이 그림에서부터 시작해 봅시다.

이 그림을 좀 더 자세히 보면요..

 

뭐  이런 거 아니겠습니까. 1.0 ~ -1.0 까지의 음영의 변화 말이죠. 요런 식으로 숫자로 되어 있다는거, 다 아시잖아요?

이제 이걸 셀 에니메이션 스타일로 만드는 것은 아주 간단합니다.

... 자, 생각해 보죠.

1.0~0.7 까지를 흰 색으로 칠하라고 하고
0.7~ 0.0 까지를 회색으로 칠하라고 하고
0.0 ~ -1.0 까지를 검은색으로 칠하라고 할 수 있다면?

 

네 이렇게 몇 단계로 나눠서 강제로 색을 지정할 수 있다면... 그렇습니다. 그렇다면 방법이 뭔가 보이지요?

 

 

자, 간단하니까 실습해 봅시다.

그럼 이제 간단하게 답이 나온 것 같으니까 실습을 한 번 해 보도록 하죠.

일단 먼저 필요한 것은 흔하디 흔한 램버트 공식의 조명입니다.

 

흔합니다. 근데 Prevent Negative Result는 꺼주세요

Prevent Negative Result가 켜져 있으면 음수가 전부 0으로 바뀌므로, 이런 특이한 작업을 할 때는 꼭 꺼 누는 것이 좋습니다. 

 

그럼 여기서 아까 이론대로 만들어 보죠

드디어 if문의 출현입니다.

프로그래밍 모르신 분들도 if 문에 대해서는 들어보셨을 겁니다. 이런걸 '분기문' 이라고 하죠.

'만약 ~ 하면 ~ 하고 아니면 ~ 해라' 뭐  이런 식입니다.

제가 셰이더 처음 배울때만 해도 if문을 쓰면 대박 느려지니까 쓰지 말라고 했지만, 요즘엔 뭐 그래픽 카드 성능이 좋아져서 그런거 신경 안쓰나 봅니다.

자 그럼 if문이 어딨을까요?

 

요기있지요

일종의 연산이니까 Math에 있는거죠. IF then Else 라고 씌여 있지요?
이 말은 단순히 IF 문으로 끝난다는게 아니라 Else 까지 되어 있다는 말이지요. [각주:3]

그럼 if 노드의 구조를 보겠습니다.
조금 어려우니까 크게 보죠.

 

 

일단 if A = B 라는 그림이 있지요? 이것은 "만약 A와 B가 같을 때" 라는 의미일 겁니다. 네 그렇죠.
입력 (InputA / B) 는 float 값을 받고,
출력(Output 1/2) 값은 아무거나 나갑니다.

그리고 Input A 가 있고 Input B 가 있습니다.
즉 이 Input A 와 Input B에 같은 값이 들어가면 결과는 '참' 이라는 것입니다.

그렇다면 이렇게 '참' 일 경우에는 뭘 뱉어낼까요? (출력해 낼까요?)

참일 경우에는 Outout 1 을 출력해 냅니다! 무슨 값을 출력해 낼지는 지금은 모르지요. 저기에 어떤 값을 연결하느냐에 따라 다르겠지요.

그렇지만 거짓일 경우에는? Output 2를 출력해 낼겁니다! 즉 Output 2 에다가는 거짓일 경우에 출력할 값을 내놓으면 되겠지요.

 

이게 뭔소리야...

 

네, 조금 어려운 설명이 나오니까 머리아파하시는 분들이 약 296분쯤 계시는군요.

말로 하니까 좀 힘들어요 확실히. 그래서 퀴즈를 내 보겠습니다.

 

자아. 위와 같은 그림이 있습니다 .

Input A와 B에는 각각 1이라는 숫자가 들어갔습니다.

Output 1과 2에는 각각 흰색과 붉은 색이 들어갔구요.

그럼 이 상태에서 출력되는 색상은 흰색일까요 붉은 색일까요?

답은 다음 블럭을 긁으시면 나옵니다.

답은 흰색입니다. A 에 들어간 숫자도 1이고 B에 들어간 숫자도 1입니다. 즉 A=B 라는 말은 '참' 이 됩니다.
그러므로 '참' 에 해당하는 '흰색' 이 출력되겠지요.  

 

두 번째 문제입니다. 이번엔 조건이 바뀌었습니다 ! A=B 가 아니라는 점을 주의하세요!

다음 경우에는 무슨 값이 나올까요?

 

역시 답은 다음 블럭을 긁으시면 나옵니다 .

조건을 보시면 A가 B보다 크다라고 합니다.
그런데 조건을 보시죠 A는 1이고 B는 2입니다.
A>B 라는 조건인데, 1>2 이라는 거죠. 이게 맞습니까? 틀리죠?
그럼 '거짓' 입니다. 그러면 붉은색이 출력될 겁니다!!

자, 이렇게 if문에 대한 기본 개념이 끝났습니다.

if문의 조건식은 이렇게 한 두 개가 아니라, 여러 개가 있습니다.
if 노드를 선택하고 메뉴를 보시면 선택할 수가 있지요

 

 

무슨 메뉴가 있는지 봅시다

Equal (A==B) : A와 B가 같을 때 [각주:4]
Greater Than (A>B) : A가 B보다 클 때
Less Than (A<B) : A가 B보다 작을 때
Greater or Equal (A>=B) : A가 B보다 크거나 같을 때
Less or Equal (A<=B) : A가 B보다 작거나 같을 때
Not Equal (A!=B) : A와 B가 같지 않을 때 [각주:5]

전부 다 필요하지는 않겠지만 3-4개 정도는 쓸모가 있을 것 같네요.

자 이제 if문에 대한 모든 걸 알았습니다. 이제 본격적으로 작업을 시작해 보죠

 

사실 어려워요. 풋. 어렵지 않다고 하는건 다 거짓말이예요. 이걸 알아들은 당신들이 천재일 뿐이예요. 후훗.

 

작업을 시작합시다.

일단 if문에 들어가는 숫자가 float 이라는것은 중요합니다. 한 자리의 숫자가 들어간다는 거지요.
다행히 dot공식에서 출력되는 숫자도 한 자리의 float 숫자입니다.

그러므로 여기에다가 끼워 주면 좋겠지요 [각주:6]

 

바로 저기가 1~ -1 까지 값이 나오는 그 구간이잖아요. 색이 곱해진 다음은 값이 순수하게 되지 않기 때문에 그 전에 해야만 합니다 .

 

자 저기에 if문을 넣죠

이렇게 만들어 봅시다.

 

위의 노드를 해석해 보겠습니다.

일단 A 에 입력된 값은 dot공식입니다. 1에서부터 -1 까지의 값이 들어오겠지요.
B에 입력한 값은... 0으로 했습니다. 즉, A 값이 0보다 크면 참이란 말입니다. 현재 이런 상태입니다.

그리고 출력값은, 참일때 흰 색으거짓일 때 (A값이 0보다 같거나 작으면 거짓) 에는 붉은 색이 나오게 만들어 진 것입니다.

 

이 그림을 다시 보시면, 어디가 흰 색일지 어디가 붉은 색일지 알 수 있으시겠지요?

자 이렇게 해서 ... 출력을 최종 색상 출력에 연결해 줍시다.

 

짜잔.

 

 

오오 셀 셰이딩입니다!!!! 만화처럼 나와요!!! 외곽선은 아직이지만 외곽선은 아직이지만 외곽선은 아직이지만 외곽선은 아직이지만 외곽선은 아직이지만 외곽선은 아직이지만 외곽선은 아직이지만 외곽선은 아직이지만 외곽선은 아직이지만 외곽선은 아직이지만 외곽선은 아직이지만 외곽선은 아직이지만 외곽선은 아직이지만 외곽선은 아직이지만 외곽선은 아직이지만 외곽선은 아직이지만 외곽선은 아직이지만 외곽선은 아직이지만 외곽선은 아직이지만 외곽선은 아직이지만 외곽선은 아직이지만

 

기분이 좋아지는군요. 이걸 한 번 더 응용하면 두 단계도 가능할 듯 합니다! 해볼까요!!!

 

 

 

근데... shader FX에서는 안됩니다 (OTL)
음영을 두 개로 주는게 안된다고요. 하나밖에 안됩니다. 흐규흐규

이런게 노드 구조의 한계에요.

셰이더를 직접 코딩한다면 이렇게 하면 돼요
if (A>0)
 { 흰색을 내놓아라 }
else if (A>-0.5)
{ 뻘겅색을 내놓아라}
else
{검은색을 내 놓아라}

이런 식으로 if문을 여러 번 거치게 할 수 있어요. 혹은 if문 안에 if문을 넣을 수도 있어서, 이론적으로는 무한대로 계산하게 할 수 있구요.

하지만 노드는 안돼요 OTL 노드는 정해진대로 써야만 하니까요. 아니면 else if 노드를 만들어 준다던가...
이런 식으로 제약이 있을 수 밖에 없는게 노드 구조입니다. 어쩌겠습니까. 그래서 아티스트용이라는 거지요. 사실 최적화도 안좋고 해서, 코딩 좀 해보면 정말 별로인 구조예요 ㅎㅎ

하지만 즐겁거든요 ㅋ

뭐 어쨌건 결론적으로 shader FX에서는 if문은 한 번 밖에 못쓰게 되는군요. 그러므로 2단계 외에는 안되겠습니다. 아쉽네요.

 

추가로 pope 스승님 책에서 보면 ceil 함수를 이용해서 하는 법이 있습니다. 이걸 이용하면 여러 단계로 만들 수 있어요.
shaderFX에서도 동일한 노드가 있습니다.  이름이 좀 달라요. "Round" 라고 하는 노드입니다.
이 노드 옵션에 보면 Round UP(Ceil) 이라고 하는 올림 기능이 있습니다. 이걸 이용하면 포프님 책에서 있는대로 똑같이 만들 수 있어요.
근데 왜 그걸로 안했냐고요? ... ㅋㅋ
그건요.. .그건 너무 기계적으로 일정 비율마다 딱딱 끊어주는거라 안이쁘거든요 OTL
아티스트들은 원하는 곳에 끊고 싶어하니까요. ㅋㅋㅋ 그래서 안했어요.
게다가 색상도 맘대로 집어 넣을 수도 없구요..

그래도 혹시나 해보고 싶은신 분들은 노드를 공개해 드릴테니까 참고해서 해 보세요 :)

 

[각주:7]

 


 

그럼 다음 시간에는 외곽선에 대해 해보는 것을 목표로 잡아 보도록 하겠습니다.
아마 shader FX 보다는 MAX 시간이 되지 않을까 싶지만.. 뭐.. 어쨌건..

 

단신:

유니티에 플러그인 식으로 들어가 있는 노드 구조의 shader 에디터인 SSE 라는 녀석이 있습니다.
shaderFX보다 무척 안이쁘지만 그런대로 쓸만한 녀석이라 그 녀석으로 연재를 할 수 있을까 싶어서 봤습니다만
몇 가지 치명적인 단점 때문에 안하고 있었는데요,
이번에 유니티 코리아의 더스틴 스승님께서 SSE를 친히 개조해 주셔서 잘 하면 쓸 수 있게 될 것 같습니다.
조금 더 만져보고 괜찮으면 다다음 시간부터 한번 그걸 연재해 볼까 생각하고 있습니다.

  1. 뭐.. 셀 셰이딩이라던가 등으로 불리기도 합니다. [본문으로]
  2. 요즘에는 이런 전통적 방식의 셀 셰이딩 외에 새로운 느낌으로 응용된 셀셰이딩도 사용되곤 합니다. [본문으로]
  3. 뭔 소린지 모르겠으면 그냥 그런가보다 하세요 [본문으로]
  4. 어째서 A=B 가 아니라 A==B인지 궁금하신 분들이 계실 겁니다. 프로그래밍에서 등호 = 는 오른쪽의 값을 왼쪽에 집어 넣으라고 하는 명령어입니다. 그래서 같다라는 의미로 사용할 때에는 두 개를 써서 == 이렇게 표현합니다. 나중에 코딩할때에도 매우 유용한 상식이므로 알아두면 좋습니다 [본문으로]
  5. 이것 역시 유용합니다. "같지 않다"라고 하는 ≠ 이 표시는 특수문자이기 때문에, 프로그래밍에서는 != 라고 표현을 합니다. 여기 있는 표현 모두 프로그래밍 에서 쓰이는 표현이므로 매우 유용합니다 :) [본문으로]
  6. 그냥 따라하지 말고 왜 그런지 생각하고 해요!!! [본문으로]
  7. 보고 분석이 잘 안되시면... 혹시 뭐... 위 노드에 대해 해설해 달라는 리플이 100개쯤 달리면 또 모르죠.. 후후후 [본문으로]

댓글을 달아 주세요

  1. 산수 2013.01.06 00:55  댓글주소  수정/삭제  댓글쓰기

    첫글인가요! 오늘 다봐버렸습니다.너무 너무 재미있고 유익해요! 알고싶은게 너무 많은데 기다리는시간에 또보고 복습합니다. 유익한 튜토 감사합니다.

  2. 산수 2013.01.06 01:06  댓글주소  수정/삭제  댓글쓰기

    연재가 이제 거의 끝나가고있는듯한데요 실무에서 캐릭터에 들어가는 일반적인 쉐이더는 보통 뭐뭐있을까요? 그리고 요새들어 유행하고있는?? 그런 쉐이더들은 뭘까요?

    • Favicon of https://gamedevforever.com 대마왕J 2013.01.06 03:27 신고  댓글주소  수정/삭제

      사실 제대로 쓰려면 한 100부쯤 써야 할 것 같습니다 ㅎㅎ 17부나 되었는데 이 정도 진도밖에 못나가서... 실무에서 캐릭터에 들어가는 셰이더들의 기능은 보통 ... 램버트(혹은 하프램버트나 오렌_네이어)나 퐁 등의 조명 계산으로 시작하고, 스페큘러가 추가되며 (퐁이면 추가가 기본이겠지요) 거기에 림라이트까지 추가하는게 아주 간략한 기본이고요. 거기에 추가로 품질이 높아진다면 SSS 기능을 추가하는 경우가 많구요 엠비언트 큐브를 이용한 IBL 환경 조명 추가, 혹은 Probe를 이용해서 SH 라이트를 추가한다던가.. 하는 각종 기능들이 추가되는게 요즘 추세입니다.
      그리고 위에 씌여진 것들을 일반적인 방법으로 쓰지 않고 조금씩 뒤틀어서 사용하기도 하지요.. 아 .. 그거까지 말하면 정말 100부 .. OTL

    • 산수 2013.01.06 09:17  댓글주소  수정/삭제

      오~ 되게 방대하고 디테일한부분이네요 설명 감사합니당

  3. 마루 2013.01.07 17:21  댓글주소  수정/삭제  댓글쓰기

    ShaderFX 에서는 텍스쳐를 uv에 값을 변경해서 인자로 받지는 못하나요?
    카툰렌더링 중에서 텍스쳐를 인자로 받아서 처리하는 셰이더가 있습니다만...

  4. Hybrid 2013.01.07 21:58  댓글주소  수정/삭제  댓글쓰기

    빨리 책 써주세요ㅜㅜ

  5. peri 2013.01.13 02:44  댓글주소  수정/삭제  댓글쓰기

    강의 이번에도 정말 잘 봤습니다!
    유니티 에셋스토어에서 플러그인들을 보다 보니, 셰이더 에디터와 같은 노드구조로 C#코딩까지
    할 수 있게 비쥬얼 툴로 만들어 놓았더라구요. 신기했습니당 ㅎㅎ..
    OOP구조형까지 어느정도 다룰 수 있는 모양이라, 셰이더 노드 에디터들도 빠른 속도로 발전해서 디자이너들이
    더 수월하게 원하는 작업을 할 수 있게 되었으면 좋겠습니다.