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

게임 스토리와 연출

기획 2012. 6. 10. 22:26
Posted by 월하

거의 두 달 보름만에 쓰는 글이군요. ㄷㄷㄷ

 

덕분에 글 쓰기 버튼이 어디 있는지 찾는라 참 힘들었네요.

 

하지만....

 

 

14.37%의 위엄.jpg

 

 

이 정도면 대충 놀고 먹으며 글 써도 되잖아요?

 

....죄송합니다. 때리지만 말아 주세요.

 

흠흠.....

 

 

 

많은 게임들이 고유의 스토리를 담고 있습니다.

 

심지어 테트리스마저 공주를 구출하는 아름다운 스토리가 들어 있죠.(제 기억이 정확 하다면...)

 

 

[이미지 중앙의 코사크 기병대 의상을 한 저 아저씨가 주인공!!]

 

 

 

 

과거 콘솔 게임과 패키지 게임을 구매할 때 스토리는 중요 요소 중 하나였습니다.

 

하지만 요즘 온라인 게임을 즐기는 대다수의 사람들은 스토리를 무시하고 있습니다.

 

왜그럴까요? 스토리가 재미 없어서??

 

와우를 즐기는 유저들은 와우의 스토리가 아주 멋지다고 합니다.

 

그런데 정작 어떤 스토리가 멋있냐고 하면 우물쭈물 합니다.

 

그럼에도 불구하고 왜 스토리가 좋다고 할까요?

 

솔직히 말하면 와우같은 스토리는 다른 온라인 게임에도 수두룩 빽빽 하다고 생각 합니다.

 

그럼 와우의 스토리... 가 가지는 매력은 뭘까요?

 

그것은 전달 방식과 연출의 차이라고 생각 합니다.

 

 

 

 

간단하게 퀘스트를 볼까요?

 

휴먼 캐릭터를 만들면....

 

데피아즈단을 잡으라고 합니다.

 

레벨이 오르면... 데피아즈단을 잡으라고 합니다.

 

레벨이 또 오르면..... 데피아즈단을 또 잡으라고 합니다.

 

레벨이 더 오르면..... 다시 데피아즈단을 잡으라고 합니다.

 

...... 이놈들은 허구헌날 데피아즈단만 잡으라고 합니다.

 

 

베네사 벤클리프양

 

대격변으로 넘어 와서 베네사 벤클리프양의 등장으로 다시 데피아즈단이... OTL

 

 

그간 퀘스트 텍스트를 안 읽고 넘어간 유저들도 "대체 데피아즈단은 뭐 하는 녀석들일까?" 라는 의문이 생기게 만들죠.

 

이게 정말 중요한 요소 입니다.

 

여타 온라인 게임을 보면 퀘스트안에 엄청난 정보, 이야기들을 집어 넣는 경우가 있습니다.

 

한번에 엄청난 이야기를 풀어 놓죠.

 

유저들이 그걸 읽을까요??

 

 

뭔가 구구절절한 사연이 있는거도 같지만 그딴건 잘 모르겠고 거대 랩터 새끼 6마리만 처치하면 되는 퀘스트

 

 

 

 

 

 

예전에 퀘스트를 만들때 클라팀에게 부탁해서 HTML태그를 사용 할 수 있게 해달라고 했습니다.

 

그래서 중요 키워드마다 색깔넣고 볼드체로 꾸며보았죠.

 

그래도 유저들은 텍스트를 읽지 않는다는 결론이 나오더라군요.

 

왜그럴까.... 고민을 해보니 간단하게 결론이 나더라구요.

 

경쟁 입니다.

 

조금이라도 더 빨리 퀘스트를 완수하고 보상을 받고 조금이라도 더 빨리, 더 강해지려는....

 

어차피 퀘스트 지문을 안 읽어도 퀘스트 목표에 관련 정보가 다 뜨니 지문 자체는 별 의미가 없죠.

 

하지만 방금 예시로 든 와우의 경우는 어떨까요?

 

계속해서 반복을 시킵니다. 자쯩날 정도로, 귀찮을 정도로...

 

그래서 유저 스스로 하여금 궁금증을 자아내도록 하는거죠.

 

그렇기 때문에 스토리 전달력이 여타의 게임보다 높다고 할 수 있죠.

 

솔직히 와우의 스토리가 그렇게 뺴어나다고는 생각되지 않습니다.

 

설정? 세계관? 확장팩을 거듭 할 수록 스스로 뭔가 붕괴되는 모습을 보여주죠.

 

그럼에도 불구하고 저런 장치들이 스토리 전달력을 극대화 하여 주고 유저들에게 좋은 스토리라인이다...

 

라는 착각을 심어주게 됩니다.

 

그럼 반복적인 퀘스트가 스토리 전달력을 높이는 주 동력일까요?

 

 

 

 

와우의 퀘스트를 보면 저렇게 무자비하게 반복 작업을 시키는 퀘스트는 그렇게 많지 않습니다.

 

와우의 스토리 전달력은 연출에 있습니다.

 

와우의 퀘스트를 진행하면 정말 멋진 연출이 많습니다.

 

NPC와 함께 뭔가를 진행 하고 심지어 주변 환경이 바뀌거나.....

 

유저가 뭔가 와우의 세계관에 어떤 영향을 준다는게 확연하게 느껴지게 되죠.

 

 

 

그럼 이 쯤에서 디아블로3 이야기를 해 볼까요?

 

디아블로3.... 참 잘만든 게임 입니다. 정말로요! 딱 액트2 까지만요.

 

 

벨리알... 유저들과 사투를 벌이다 체력이 좀 떨어지면 변신! 을 하죠.

 

그 엄청난 포스와 위용! 정말 한 액트의 보스다운 모습을 보여 줍니다.

 

그런데... 액트3 부터는 뭐죠?

 

 

액트 4..... 디아블로는 더 심합니다.

 

물론 3편에서의 디아블로 정체... 는 아주 약간의 놀라움이 있지만.....

 

역시나 액트3 못지 않은 엉망인 스토리와 연출은 정말 짜증날 뿐입니다.

 

 

디아블로 2를 해 보신분은 아시지만 2편에서의 디아블로는 저렇지 않았죠.

 

뭔가 오망성(이었나?)에서 봉인을 하나씩 풀고 디아블로를 꺼내고....

 

덩치나 외형은 3편보다 빈약하지만 등장하기까지의 과정이 정말 잘 짜여져 있죠.

 

그에반해 3편에서 디아블로의 등장은 스토리와 연출 모두 정말 빈약 합니다.

 

 

디아블로3.....

 

마치 액트2의 벨리알이 최종 보스이고 나머지는 그냥 보너스 스테이지 같은 느낌을 받게 하는거죠.

 

난이도의 문제도 있고(벨리알이 아즈모단이나 디아블로보다 더 부서워요.) 연출의 문제도 있고....

 

여러모로 디아블로3는 액트2 까지만 재미있는 게임으로 기억에 남을거 같습니다.

 

-=

 

원래 쓰려고 한건 이게 아니라 밸런싱 관련 이야기 였는데....

 

어쩌다 디아3 때문에 쌓인 스트레스 때문에 ㄷㄷㄷㄷㄷ

 

반응형
,
Posted by 김포프

요즘, 사랑에 빠졌습니다. 이름도 깔삼한 Unity입니다. 처음으로 '아~ 이것보다 뛰어난 놈은 못만들겠구나'라고 생각이 든 엔진이라죠. 물론 이유는 에디터가 너무 좋아서입니다. 그 전에 섹시한 언리얼 양을 볼때도 '뭐, 이정도 쯤이야 나도 언제나 만들 수 있지' 하고 생각했었는데 유니티양 앞에선 무릎을 꿇었답니다.


근데 며칠전에 은근 짜증나는 면을 발견했죠.. 바로 유니티의 UV좌표계.


보통 전(그리고 다른 그래픽 프로그래머들도 아마..?) 텍스쳐에 UV 좌표계를 다음과 같이 입힙니다. 왼쪽위(0,0), 오른쪽아래(1,1)로요.


(0,0)        (1,0)                 

  +-----+-----+

  |     |     |

  |     |     |

  +-----+-----+

  |     |     |

  |     |     |

  +-----+-----+

(0,1)        (1,1)


이렇게 좌표계를 대입하면 UV 좌표계가 텍스처 메모리 레이아웃과 일치한다는 장점이 있지요. 따라서 UV좌표를 기반으로 텍스처 조작(texture manipulation)을 하면 매우 직관적이고 쉽습니다. UV좌표를 써서 텍스처의 일부를 복사해내는 게 그 좋은 예겠죠.


근데, 유니티 양은 뭔 이유에선가 UV좌표를 좀 다르게 매핑합니다. 왼쪽아래(0,0) 오른쪽위(1,1)로요.. 즉 위아래가 뒤집힌 현상.. -_-



(0,1)        (1,1)                 

  +-----+-----+

  |     |     |

  |     |     |

  +-----+-----+

  |     |     |

  |     |     |

  +-----+-----+

(0,0)        (1,0)



무엇이라!? 왜 이따위로 사는거야!? 철썩~ -_-;;; 이 따위로 UV좌표를 매핑해놓은 수학책이 분명 있습니다. 하지만 이렇게 해서 얻는 실용적인 이익을 도무지 떠올릴 수가 없네요. 때로는 저희 렌더링 프로그래머들이 그냥 특정한 표기법에 익숙하다는 이유로 잘못된 결정을 내리는 경우가 있습니다. 이것도 그런 경우라고 생각합니다.


만약 제가 간과한 장점이 있다면 제발 알려주세요. 제가 사랑하는 유니티 양을 매도하고 싶진 않습니다. 하지만... "전통적으로 그래왔으니 이 방법이 맞아." 따위의 논의는 삼가해 주시기 바랍니다.






반응형

'프로그래밍' 카테고리의 다른 글

std::function이 좋네.  (12) 2012.06.17
유니티는 C#으로 작성했다?  (9) 2012.06.17
유니티 엔진의 멀티플랫폼 심장 Mono  (15) 2012.06.05
자기만의 게임엔진을 만들어보자! #2  (11) 2012.06.03
Screen Space Decal  (20) 2012.06.01
,
Posted by 밥을먹는선비


1. 모노란 무엇인가?


유니티 엔진으로 스크립트를 코딩하다보면 MonoDeveloper라는 것이 있습니다. 편집기 인데 좀 유니티와는 다른 느낌에다가 닷넷툴같은 느낌을 주면서 닷넷이라고 보기엔 먼가 좀 이상하고 머 그런 느낌인데요.


일단 많은 사람들이 유니티엔진을 선호하는 이유중 하나가 손쉬운 멀티플랫폼 확장성을 들수가 있습니다. 유니티도 초반에 그문제에 대한 고민을 많이했었을겁니다. 그래서 찾은 방안이 모노라는 오픈소스 프로잭트 였다고 합니다. 그럼 어떻게 모노가 멀티플랫폼을 가능하게 하는것일까요?


2. 닷넷프레임워크


원래는 MS에서 닷넷을 만든 이유는 자바에 대응하기위해서 자사의 운영체계(운영체계에 상관없는것이라는 말이 더맞기합니다.)가 도는 시스템에서는  모든 닷넷프레임워크용 프로그램을 구동시킬수있는 환경을 만들자는 원대한 꿈을 가지고 만든것임에는 분명하지만...사실 초창기에는 일반사용자들에게 많은 혼란을 야기 했었습니다. 일반인들에게는 개념이 좀 어려웠던거죠. 그래서 닷넷기반으로 프로그램을 만들경우 기존 윈도우어플과는 다르게 닷넷버전이 맞지않을경우 실행이되지않는 문제가 발생하곤 했습니다.

그리고 여기서 드는 의문중에 하나가 '그럼 리눅스에 닷넷후레임워크가 깔린다면 그럼 닷넷어플이 실행되는건가?' 입니다.

당연지 되죠!

하지만 MS에서 절대로 안만들어줄게 분명하지만요.

왜냐구요?

바로 여기서 사기업표준의 딜래마를 만나게됩니다. 운영체계를 팔아서 먹고 사는 회사의 한계를 여실히 보여주는 씁쓸한 경우인데요. 닷넷이라는 신기술이 자사의 주력상품의 매출을 떨어뜨리게할순없지않습니까?


닷넷프레임워크 자체는 그다지 나쁘지 않습니다. 다만 M$라는 사기업에서 만든게 좀 아쉬운것이지요.




3. ECMA


MS .Net Framework는 유럽표준 기술규약에 등록되어있습니다. 

사실 MS같은 회사가 머가 아쉬워서 표준 기술규약에 등록 시킨이유가 먼지 궁금할수있는데요. 저도 기관이나 관공서에 소프트웨어를 납품하기 전까지는 이런것이 왜필요한지 몰랐었습니다.

기관에 소프트웨어를 납품하기위해서는 그 소프트웨어 기술에 대한 신뢰가 있어야합니다(문서상으로 말이지요 ㅡ.ㅡ;;). 그것을 보장받기 위해서 가장 확실한 방법은 표준기관에서 등록을하고 인증을해주면 그걸가지고 다시 이렇게 검증된기술이다. 라는 식으로 문서를 작성하게 됩니다.

그래서 MS같은 큰회사도 자사기술이 기관등에서 쓰이도록 유도하려고 기술표준 심사를 받고 등록을 한것이지요. 사람들에게 기술공개해서 널리 이롭게 할려는 목적은 절대로 아닙니다.


그러던 어느날 일당의 해커들이 작당을하여(사실 관계는 확인못함) 모노라는 프로잭트가 오픈소스형태로 시작이됩니다. ms 공개한 닷넷 후레임워크 규약을 분석하여 독자적으로 리눅스,맥,안드로이드 아이폰, 닌텐도위 등등 에서 동작하는 닷넷후레임워크를 만들게 됩니다. 


사실 이렇게 무단으로 가져다 쓰면 어떡하나? 걱정하시는 분들도 있을지모르겟는데요. 사실 법적으로는 전혀 문제될것이 없습니다.

이 경우는 안드로이드 개발환경에 자바가 사용되어서 요즘 오라클이 구글을 제소한사건의 경우와 좀 유사합니다. 그러나 이것은 자바라는 상표권 침해에 대해서 이의를 제기한 사건입니다.

모노의 경우는 구글안드로이드처럼 닷넷후레임워크라는 이름을 사용하지않았고 이미 표준기술로 공개된 규약만을 따른것뿐이므로(이것을 문제 삼으면 printf라는 이름으로 함수를 만들면 특허료를 내야겟지요 ㅡ.ㅡ;;) 전혀 문제될것이 없습니다. 라고 모노 개발팀에서 밝히고 있습니다.

 

4. 해피엔딩?





모노를 사용하면 일단 닷넷기반으로 만들어진 라이브러리를 가져다 마음대로 사용할수있습니다. 쉽게 말하면 스크립트언어를 사용하면 대부분 기존 라이브러리와 호환문제 때문에 골치 아픈데 이부분을 해결해주는것이지요.

 

그리고 닷넷 프레임워크의 특성상 언어에 종속되지않는 개발환경을 만들수있습니다. CLR(Common Language Rumtime) 덕분에 자바스크립트와 C#을 서로 섞어가며 코딩을 할수있습니다.


또한 스크립트언어가 텍스트 상태로 매번 실행할때 해석되는것이 아니라 컴파일이 된후 바이너리가 CLR에서  실행되는 방식이므로 자바스크립트를 사용하건 c#사용하건 속도의 저하가 발생하지않습니다. 


모노를 유니티엔진에 도입하면서 부터 유니티엔진이 대중적인 사랑을 받게 되기시작했습니다. 물론 그전에도 맥os쪽에서는 나름 지명도가 있었던 기억이 있습니다. 게임엔진쪽보단 쓸만한 인테리어 시뮬레이션(실내 조명쪽) 해주는 툴정도로 알고 있었죠. 그때가 2005년도 정도 엿던거로 기억이 납니다.

모노와 유니티의 밀월관계가 얼마나 돈독한지 보여주는 예가 유니티를 위해  모노팀에서 모노디벨로퍼를 계속 업그래이드해주는 배려(?)에서 알수가있습니다.  사실 모노디벨로퍼는 유니티에서 만든것이 아니고 모노프로잭트것을 가져다 그대로 쓰는것입니다.


암튼 그렇게 몇년이 지난 2009년에 다시 한번 접한 유니티 엔진은 정말 환골탈피한모습으로 다가왔는데요. 그 중하나가 다양한 플랫폼을 지원한다는 것이였습니다. 그 당시 야심차게 일리히트로 멀티 플랫폼 게임엔진 사업을 하던 저에게는 정말 심각한 타격을 주었는데요. 사업을 접으면서 여러가지를 많이 배웠습니다.  이 세상에는 댓가없는 일이없다는 교훈을 배웠다는걸로 만족을 했습니다. 총을들고 나와야할 전쟁에 철광석만 들고  나온격이였더군요. 그러니 당연히 결과는 뻔한것이였고요. 지금와서 생각해보면 비슷한 시기에 일리히트에 모노를 올리자는 논의가있었는데 그냥 지나쳐버린게 무척 아쉬움이 남습니다. 그때 일리히트엔진 개발자분은 webGL(HTML5)쪽을 선택하셨는데 물론 아직 그것에 대한 결과를 논하기엔 이르겠죠.


그리고 모노라는 프레임웍은 좀 불안한것도 사실입니다. 왜냐하면 모노는 일종의 사생아(부잣집의 숨겨둔 자식같은) 이기 때문입니다. 물론 언리얼같은 적자를 사용하려면 엄청난 댓가가 따르지만요.  좀 이른감이있지만 모노의 대안으로 html5 이면 어떨까 하는 생각도 요즘 조심스럽게 합니다.  그러기에 분명히 한계는 존재할거같습니다. 가까운미래에 우려스러운일이 생길거같은 예감은 들지만 일단은 현재의 상식적인 정답은 모노를 사용한 유니티이지 않을까 합니다.  





반응형
,
Posted by 대마왕J

안녕하세요 호주갔다온 대마왕입니다 이힛.
짧지만 일에 방해되기는 충분히 긴 정도로 갔다왔기 때문에 역시 이번에도 내용은 짧습니다.
요샌 이래저래 일이 겹쳐서 - 한 일주일 앓아 눕기도 하고 - 여유시간을 내기가 쉽지가 않아요
더 얘기하면 만수무강 기원하는 글이 좌르륵 달릴거기 때문에 여기서 끝.

 호주의 Light 는 참 ... 대단하더군요.

 

오늘은 이전 시간에 이은 라이트 얘기를 마무리하도록 해 보지요.
세부적으로 꼼꼼하게 따지면 더 많지만, 일단은 '이정도만 알아두어도 프로그래머가 무시하지는 못한다' 수준의 지식을 목표로 정리해 보고 있습니다. [각주:1] 저도 아는게 쥐뿔만큼이라는게 문제

지난 번 11강에서 배웠던 내용을 한 마디로 정리해 보면 일단 이거지요 이거.

빛이랑 직각이 되는 부분이 가장 밝다

 

네네. 이거 뭐 주어도 없는 글입니다만 일단 이정도로 알아두도록 합시다.

이걸 말하려고, '멀리 떨어진 오브젝트가 더 밝다' 라는 상식에서 벗어난 주장으로 환기효과를 노려 보았습니다. 굉장히 중요한 진리 뭐 그런거 아니예요. 그러니까 11강은 사실 낚시  

11강에서 말한 것 처럼 멀면 더 밝아지는 3d 의 빛에서는 함정이 하나 있죠.
그 함정은 'Point light 일 때만" 이라는 것입니다.[각주:2]  (spot 라이트도 point와 같은 종류의 라이트라고 할 수 있지요. )

그럼 다른 라이트가 또 무엇이 있었지요?
넹 바로 Direct light 입니다.[각주:3]

 

이 라이트는 성격이 좀 달라요. 그리고 3DMAX에 있는 녀석은 게임안에 있는 조명과도 좀 많이 다릅니다. 다른 조명보다도요. 일단 이 Direct light 란 녀석을 알아보도록 하지요. 이 light는 꽤 중요한 light예요.

일단 , 3Dmax 에서는 이렇게 생겼지요.

 

원통이네요.

원통이예요.

원통이군요.

원통하군요.

네 그냥 원통이지요. 그래서 그런지, 그래픽 아티스트들은 다이렉트 라이트를 이 '원통' 모양이라고 생각하는 사람들이 많습니다. 시작점이 있고, 넓이가 있지요. 끝 점도 있 (...다고 느껴집니다만 사실 써보면 끝은 없습니다) 어 보이구요.

그림으로 표현하자면, 이런 모양의 빛 덩어리가 다이렉트 라이트라고 그래픽 아티스트들은 느끼게 됩니다.

두둥

이건 좀 이해해 줘야 해요. 맥스 라이트가 저렇게 생겨먹었잖아요. 그림을 보고 배우는 아티스트들에게 저런 그림을 보여줬으니까 당연하지요. 그래서 그냥 3D max로 배운 초보 그래픽 아티스트들은 Direct light가 저렇게 생긴줄 알고 있는 경우가 많습니다.

그런데 라이트를 좀 사용해본 그래픽 아티스트들은, 맥스에서 다이렉트 라이트가 사실은 이렇다는걸 느끼게 됩니다. 생각이 좀 바뀌게 되는 거지요.

 

끝이 없지요.

 네, 뭐 이건 어쩔 수 없습니다. 태어나서 처음 만져본 3D 프로그램의 라이트가 진짜 저렇게 생겼고 저렇게 작동하니까요.
당연히 이게 전부다라고 생각하는건 너무나도 당연합니다. 심지어 3D max 교재에서도 저런식으로 라이트를 설명합니다.
시작 지점이 있고, 넓이가 있습니다.

 

 

그렇지만 프로그래머들이 배우는,  게임에서 쓰는 다이렉트 라이트는 위와 다른 개념으로 설명하곤 합니다. 
프로그래머들의 책에서는 보통 이렇게 표시해요.

 

 읭?

화살푭니다. 저건 아무리 봐도 화살표잖아요.
혹은 이렇게 표시하기도 합니다.

 

 

의의읭?

 

화살표가 늘었습니다. 이게 뭘까요? [각주:4]

이게 프로그래머들이 인식하는 "Direct light"입니다 뭘까요? 뭐가 다른 걸까요?

사실 그림으로 설명하기 힘든 개념인건 사실입니다. 저건 벡터(Vector) 를 나타내는 표시로,
게임에서의 Direct light는 - 프로그래머들이 이해하는 Direct light는 - 위에서 설명한 그래픽 아티스트의 Direct light와 개념이 좀 다릅니다. 뭐가 다르냐고요?

1. 시작점의 개념이 없습니다.

말그대로 시작점이 없습니다. 끝 점도 없구요. 무한대에서 시작해서 무한대로 끝나는 빛입니다.

2. 범위의 개념이 없습니다.

이것도 말그대로입니다. 원통형? 그런거 없습니다. 넓이도 무한대입니다.[각주:5]

3. 그러므로 빛의 방향과 크기만이 있습니다. 다른건 없어요.

크기도 사실은 단위벡터 처리하는 경우가 대부분이라... 사실 사용할때에는 빛의 방향밖에 없습니다. 그게 정보의 전부입니다. 범위나 시작점 모두 Max에서 '추가적으로' 만든 기능일 뿐입니다.  

시작도 없고 끝도 없으시며 그 넓이도 존재하지 않으시고,
오직 한 방향만 존재하실 뿐이어다.

 

지저스돋네

 

그리고 추가적으로 여기서 알 수 있는 이 '위엄있는' Direct light에 대한 정보는 다음과 같습니다.

1. 가벼운 Light이다.

공식적으로 '가장 가벼운' light는 Ambient light입니다. 그렇지만 Ambient light는 이걸 과연 light라고 불러도 될 것인가 싶을 정도로 light같지 않은 light여서, 사실상 공식적으로 조명처럼 사용되는 light중 가장 가벼운 것은 Direct light라고 말해도 과언이 아닐 정도입니다. [각주:6]

생각해 보세요. 
Point light는 시작점이 어디인지 알고 있어야 하고, 그 점에서 내 위치가 어디인지를 알아야 빛의 각도가 나옵니다. 알아야 할 데이터가 많아요.  

Spot light는요? Point light의 데이터에다가 이번에는 제한되는 빛의 각도 정보까지 있어야 해요! 얼마나 정보가 많겠어요?

그치만 Direct light는 시작점도 없고 끝도 없고 어딜가도 같은 방향의 빛이 조사되기 때문에, 매우 계산하기 간편한 조명입니다. 그래서 그림자들이 생길 때에도 주로 Direct light 기반에서만 생기곤 하죠.

2. 태양 빛을 표현할때 많이 쓴다.

'태양은 Point light잖아요? 그럼 Point light를 써야지 왜 Direct light를 씀? ' 이라고 물으실 분도 계시겠지만...
네 , 맞습니다. 태양은 엄밀히 얘기하면 point light예요. 그치만.

 

 

크기차가 이래서야 ... 태양이 쏘는 빛이 Point light 보다는 Direct light처럼 오겠지요. 거리도 좀 머나요 ... 그럼 더 당연하죠. 그래서 Direct light로 대충 표현해도 별 상관 없는 것입니다.  

무시하면 안됩니다.

 

3. Direct light는 오브젝트가 어디에 있건 똑같은 밝기이다.

네.. 제가 맨 위에서 말하고 싶던 부분이 이것입니다.
당연하지요! 모든 빛이 모든 부분에서 같은 각도로 조사되는데, 가까이 있던 멀리 있던 상관 없잖아요? 빛이 확산되거나 감쇄되지 않는 완전한 '이상적인' 상태라면, 오브젝트는 어디에 있어도 똑같은 빛을 받을 수 밖에 없습니다! Point light와는 다르다는 거지요 !! [각주:7]

 

포인트 라이트 다이렉트 라이트

일단 이렇게 거리가 무시되구요.

 

구석에 놓아도 OK

이렇게 구석에 놓아도 상관 없습니다.
3D 게임의 맵에디터를 사용하신 분이라면 아실텐데요. Direct light는 정말 맵 구석에다가 대충 박아 놓아도 아무 문제 없습니다. (조작성때문에 가운데에 놓으시겠지만)

4. 대신 기울어지면 밝기가 떨어진다.

이건 뭐 상식적으로도 당연하게 알고 계신 것이지만, 한번 써 봤습니다.
이제 이 단순한 개념을 직접 만들어 보셔야 하거든요 우후후 :)

 

그리고 프로그래머들은 이 개념으로 처음부터 배운 거지요.
여기서 우리 그래픽 아티스트들의 Direct light에 대한 개념의 괴리가 생깁니다.
자, 이제 다음 시간부터는 '직접' 이 라이트의 계산을 만들어 보면서, 프로그래머가 생각하는 Light의 개념을 몸으로 익혀 봅시다!! 우리 그래픽 아티스트들은 몸으로 익히는데 능하니까요!!!

 

예고 (두둥)

 

  1. 요샌 그런 프로그래머가 거의 없어졌지만, 옛날엔 지식 부족하다고 경멸의 눈으로 아티스트를 바라보던 프로그래머도 있었지요 [본문으로]
  2. 실은 'point light와 spot light일때' 입니다만, spot 라이트는 point light에서 빛의 한계각도를 제한한 것 뿐이기 때문에 거론하지 않았습니다. [본문으로]
  3. 다이렉트 라이트, 혹은 디렉셔널 라이트라고 부르기도 합니다. 저도 막 섞어 부를지도 모릅니다... [본문으로]
  4. 다시 말씀드리자면 이 강의는 그래픽 아티스트 입장에서 본 강연입니다. [본문으로]
  5. Max 를 좀 깊게 다뤄보신 분은 max의 Direct light에 "Overshoot" 라고 하는 체크박스가 있는걸 찾으실 수 있습니다. 이걸 켜면, 범위가 무한대가 됩니다. [본문으로]
  6. SH(Spherical Harmonics) 라이트 같은건 뺍시다 (...) 너무 깊이 들어가면 그래픽 아티스트들 마음이 다쳐요 ... [본문으로]
  7. 물론 이런 거리에 따른 감쇄(attenuation)을 계산하여 시뮬레이트 해주면 거리에 따라 연하게 만들어 줄 수도 있습니다 당연히. 그렇지만 여기는 원천적인 기술을 얘기하므로 그 얘기는 하지 않았습니다. [본문으로]
반응형
,
Posted by 알 수 없는 사용자

안녕하세요? 디퍼드H 입니다. 혹시 저의 강의를 기다리신 분 있나요? (없진 않겠죠? ㅡ.ㅡa) 갑작스런 싱가폴 친구들의 등장과 함께, 남의 집에서 얹혀살기(무지 불편했다는...), 이사까지...(조만간 다시 이사를 해야하는 실정입니다. 뭔가 복~~잡한 사연으로 인해) 여러일들 때문에 강의가 늦게 올라오고, 늦게 올라온 것도 모자라, 내용이 많이 부족하거나 적을 수도 있는 사연을 이해.. 이해 해주길 바라면서, 강의를 시작해보죠.

사실 저번 강의를 올리면서, 많은 고민을 했었습니다. 그 고민의 이유는 바로 메세지 시스템인데요. 사실 메세지 시스템은 저의 강의 가장 핵심적인 부분이기도합니다. 원래, 엔진을 처음 만드시는 분들 또, 학생(막 게임 프로그래밍에 접하신분들)을 위해서 강의를 하기에는 바로 메세지 시스템을 설명하기에는 조금 무리가 있다고 판단을 했거든요. 헌데, 예상외로 메세지 시스템에 대해 많이 궁금하신분들이 많아, 이번 강의는 메세지 시스템에 대해서 한번 짚고 넘어가고자 합니다.  물론 학생 분들이나 엔진을 처음 만드시는 분들은 아, 대충 이런 이야기이구나! 하고 넘어가더라도, 문제가 없을 겁니다. 왜냐? 시간이 지나서 다시 다룰거거든요. 전체적으로, 심도 있는듯 없는듯 한번 저의 메세지 시스템에 대해 한번 보도록 하죠.

제가 메세지 시스템을 만들때, 보통 롤 모델이 필요했습니다. 어떻게 만들어야 가장 효과적일까? 그렇게 생각하다보니 제일 먼저 떠오르는것이 우체국시스템이더군요. 우체국을 모르시는 분들은 없을거라 생각합니다. 우체국의 시스템은 오랫동안 아직도 유지되어 오고 있습니다. 이것은 바로, 그 시스템이 효과적이다라는 의미이겠죠. 이렇게 생각하면서 저는 메세지 시스템의 롤 모델은 우체국에서 이용되는 시스템(편지겠죠.) 정하고 메세지 시스템을 설계했었습니다. (사실 저 같은경우 어떠한 시스템이라던가 그외 필요한 것을 구현할때에는 보통 주위를 많이 이용하는 편입니다. 크게 많이 도움이 되더군요.) 우리가 보통 편지를 보내고 또, 다른사람에 받는데 까지에는 다음과 같은 방법이 이용됩니다. 우선 우린 편지를 씁니다.(편지를 쓸때에는 보내는사람, 받는사람, 주소, 그리고 내용이 들어가죠.) 편지는 편지통으로 들어가고, 그 편지는 우체국으로 모입니다. 우체국에서는 이편지를 주소에 따라 편지를 배정하고, 마침내 편지는 받는사람에게 가죠. 설마, 이렇게 편지가 여러분들께 가는것은 모르는 사람들은 없겠죠? (있다면 큰일입니다!) 이제 이 시스템을 우리가 구현할 메세지 시스템에 알맞게 바꾸어나가보도록 하죠. 우선 아래의 그림을 봅시다.

 

모든걸 다 넣으려고 하니, 그림이.. 크군요. 아무튼, 위의 그림을 보시면 이상한 클래스 이름들이 눈에 띕니다. 메세지 매니저 뭐 이름 그대로 아주 직관적이라 메세지를 처리하는곳이구나 라는게 감이 오지만 ISociable 클래스는 무엇인가? 라는 의문점이 생깁니다. 제가 메세지 시스템을 구현할 때, 정말 알맞은 변수명을 찾으려고 고생을 했는데 나온것이 ISociable 이었습니다. 우리 이전에 말했던 우체국 시스템(자꾸 우체국 시스템하니 좀 많이 어색한 것 같군요. 정말로 어색하지만 양해 부탁드립니다)을 이용해서 말한다면 주소 등록본(?) 아니 주민등록본(?) 과 비슷한 메세지(편지)를 서로 주고 받을 수 있도록 해주는 클래스라고 생각하시면되겠습니다. 편지를 주고 받는다 = 대화를 한다 -> 사회적이군! 이라는 결론으로 ISociable라고 지었는데, 개인적인 의견으로는 뭐 알맞다고 생각합니다(사실 멋지다고 생각한다는...)  이 클래스에는 메세지와 관련된 메소드와 변수를 가지고 있습니다.

 

프로그래머는 역시 코드로 보는게, 바로 뙇(요즘 이게 대세더군요) 감이 오실겁니다. 이전에 설명한 내용이라 넘어가도록 하죠. 다음은 ISociable을 관리하는 객체인 ISociableManager가 있습니다. 우체국으로 생각한다면, 우체국의 중요부서중 하나라고 생각하시면됩니다. 나머지 하나는 물론 메세지 매니저죠. ISociableManager와 MessageManager의 상호작용으로 우체국의 역활인 메세지를 받아 저장하고, 매 프레임 마다 메세지를 Dispatch를 한다고 보시면 됩니다.  ISociableManager는 메세지를 Dispatch하는 역활을 맡고 있고, MessageManager는 메세지를 메세지 큐에 매 프레임마다 들어오는것을 보관하고 관리를 합니다. 우선 아래의 그림을 보도록 하죠.

 

위 그림은 그래픽 시스템에서 다이렉트x의 초기화를 위해 윈도우 값이 필요해, 윈도우 핸들값을 메세지를 요구할 경우를 가정해서 관계도를 나름 멋지게(?)그려보았습니다. 사실 그림과 간단하게 붙어있는 설명들을 읽으시면, 뙇 어떻게 MessageManager와 ISociableManager 상호작용을 해서 메세지 시스템이 구현되는지 한눈에 아실거라 생각이 들지만, 그렇지 않을 분들을 위해 설명을 시작하도록하죠. 이 예시만 이해가 되신다면, 여러분도 여러분만의 메세지 시스템 구현을 위한 준비가 되었다고 봐도 될 것입니다.

우선 윈도우 시스템과 그래픽 시스템은 ISociable클래스를 상속받아, 메세지 주고 받을 수 있습니다.(코드적으로 설명하자면, 윈도우 시스템과 그래픽 시스템은 RecvMessage 메소드를 들고 있고, ISociableManager에 등록도 되어 있다는 말이겠죠?) 윈도우 시스템에서는 메세지를 우선 메세지 매니저로 메세지를 보냅니다.  메세지 매니저는 그 메세지를 매니저가 가지고 있는 메세지 큐에 넣습니다. 다음 프레임에 메세지 매니저에서는 메세지가 Dispatch 되어야하는지 우선 확인을 합니다. 후일 메세지 시스템 구현 부분에서 자세하게 다루게 되겠지만, 메세지 클래스는 여러가지 멤버 변수들을 가지고 있습니다. 그 중 하나인, DelayTime의 멤버변수는 언제 메세지가 Dispatch되어야하는가를 가리키는 변수명입니다. 만약 DelayTime이 1.0f의 값을 가지고있다면 1초 후에 이 메세지를 Dispatch해야 한다는 것을 의미합니다. 게임 엔진이 60fps로 돌아간다고 가정했을때, 이 메세지는 약 60프레임 이후 메세지가 Dispatch 된다는 것을 의미합니다. 메세지 시스템에서는 매 프레임마다 이 변수의 값에서 -0.166666f 값을 빼주면서 0 이하가 된다면 이 메세지는 처리되어집니다. 메세지 처리가 준비되었을때, 메세지 시스템에서는 DispatchMessage 메소드를 실행시키기 시작합니다. 이 메소드는 메세지에서 수신자의 id혹은 이름을 꺼내서 ISociableManager에 등록되어있는 ISociable객체를 찾아서 RecvMessage 함수를 실행시킵니다. 예시로 돌아가서, 메세지에서는 수신자가 WindowSystem으로 되어 있었습니다. 현재 윈도우 시스템은 ISociableManager에 등록되어 있고 결국 메세지 매니저에서는 윈도우 시스템에서 구현된 RecvMessage 함수를 실행시키고 이 함수내에서 윈도우 핸들을 달라는 메세지에 알맞는 행동이 구현되어 있을 것입니다.  그럼 윈도우 시스템은 아마 윈도우 핸들 값을 동봉한 메세지를 날려주겠죠?(데이터를 어떻게 동봉하는가?는 후일 구현부분에서 다룰것입니다.)

지금까지 여러분들과 함께 메세지 시스템은 어떻게 만들것인가? 만들어지는가? 에 대해서 확인해보았는데요. 오늘은 자세한 듯하면서, 또 어찌보면 아닌듯이 알아보았습니다. 어떤분들은 지금까지의 내용으로도 충분히 여러분만의 메세지 시스템을 만들 수 있다고 생각이 듭니다. 여러분들은 충분히 할 수 있습니다! 이번강의에서 일부러 메세지 클래스를 어떻게 만드는건가? 또 MessageManager와 ISociableManager 구현과 팁은 포함시키지 않았습니다. 이 내용은 후일 강의를 진행해 나가면서, 때가 되면 다루어 보도록 하겠습니다. (많은 댓글과 열혈한 성원은 강의 진행에 무지 도움이 되어 메세지 시스템 구현 강의가 빨리 진행될 것을... 알려드립니다 ~ ㅋ^^) 사실 오늘 넘 정신이 없다보니 중간중간 여러분들이 이해 안되는 부분이 있을 수 있을거라 생각이 (엄청) 듭니다. 여러분들 중 이해가 안되거나 궁금한 내용은 댓글로 남겨주신다면 최대한 성실히 답변해드리도록 하겠습니다.

 

반응형
,
Posted by 알 수 없는 사용자

안녕하세요. 2달 동안 놀아버린 랩하는좀비, 랩좀비군입니다. 오랜만이네요. 회사에서 막히는 일이 있어서 이것에 대해서 신경쓰고 있다보니, 글을 게시하는 것을 까맣게 잊고 있기는 개뿔, 그냥 안쓰고 있었습니다(...). 아직 문제는 풀리지 않았는데, 계속 생각하고 있어봤자 답은 나오지 않을 것 같아서 머리도 정리할 겸 이제 게시하네요. 실은 5월 17일에 게시 할려고 했는데, 블리자드의 은혜가 5월 15일이어서 잠시 잠적했습니다. 글은 썩어가고 있고, 작성자는 돌아오지 않고 있고, 리플은 달리고 있고, 가정이 무너지고, 사회가 무너지고, 악마 사냥꾼의 랩은 올라가고!!

이번에 구현해 볼 기능은 Screen Space Decal(이하 SSD) 기능입니다. Deferred Decal이라고도 하지요. 언차티드에서도 사용했고, 저번에 게임테크 2012에서 발표한 KUF에서도 잘 사용하고 있더군요. 그리고 우리의 꽃미남 천재 프로그래머이신 포프님이 참여하신 스페이스 마린에서도 잘 사용하고 있는 기능입니다. 스페이스마린의 SSD기능은 포프님이 KGC2012에 소스까지 공개하신다고 하니 기대를 해 보아요. 

그만큼 싸고(많이 싸지는 않은 것 같습니다. 아직 저희도 공격적으로 사용하고 있지 않아서 측정을 안해봤습니다.), 구현하기도 쉽고 해서 앞으로 이 기능이 세상을 널리 이롭게 하지 않을까 합니다. 이건 뭐 초딩도 20분이면 구현할 수도 있는 -하지만 전 하루 걸림 음하하- 기능이니 모두 구현해 보아요.

아무튼, 잡설은 이정도로 하고, 하나하나 썰을 풀어보도록 하겠습니다.

데칼에는 다음의 4가지 기능이 들어가 있어야 훌륭한 데칼 시스템이라 할 수 있습니다.

1. Scene의 Albedo뿐만 아니라, Normal, Specular Factor 등등 다른 surface들의 값들을 변경할 수 있어야 합니다.
2. Decal은 모든 동적인 것과 정적인 폴리곤의 표면에 잘 붙어야 합니다.
3. Decal은 붙는 표면에 따라서 잘라지거나 감싸거나 할 수 있어야 합니다.
4. Decal은 복잡하게 생긴 메쉬에도 잘 붙어야 합니다.

1번은 Deferred Rendering 시스템으로 렌더링 파이프라인이 구성되어 있다면 쉽게 적용할 수 있습니다.
문제는 2 ~4번까지인데, 기존의 데칼시스템으로는 조금 힘든 문제였습니다.

우리가 지금까지 구현했던 데칼 시스템은 - 이하 Forward Decal. 정확한 명칭은 저도 잘 모르겠습니다. 아시면 알려주세요.-

1. 데칼이 붙을 장소의 버텍스 정보를 알아온다.
2. 알아온 버텍스들을 잘 연결해서 이쁜 모양의 표면을 만들어 준다.
3. Z-Fighting이 발생하지 않도록 카메라와 거리를 이용해서 잘 조절하여 표면의 위쪽에 위치시켜 준다.

이런 방식으로 하고 있었지요. 위의 문제에 대해서,

2번의 동적인 메쉬일 경우 매 프레임 갱신되는 버텍스의 위치를 알고 있어야 했으며,
3번일 경우, 버텍스의 위치에 따라서 많은 계산을 통해서 잘 일그러지 않게 만들어야 했습니다.
4번은 그냥 계산하면 되지만 버텍스의 갯수가 많아질 수록 연산량이 많으 늘어나서 성능에 영향을 끼칩니다. 거기에다가 Scene의 LOD까지 가세해 버리면 이건 뭐 아오 빡쳐! LOD 하지마! 상태가 되었습니다.

하지만 SSD에서는 완벽하지는 않지만 기존의 구현과는 다르게 2, 3, 4번의 문제를 쉽게 해결 할 수 있는 방향이 있습니다. 여기서는 그 방법에 대해서 설명하진 않겠습니다. 저도 여기까지는 구현하지 않았거든요. 저는 직접 구현하지 않은 거 아니면 썰을 풀지 않습니다. 신용100%. 필요하면 그 때 구현하기로 하고, 역시나 올 말의 잘생기신 포프님의 발표를 기대해 보아요. 흐흐

SSD의 최고 장점은 말 그대로 화면 공간(Screen Space)에서 데칼을 그리는 것에 있습니다. FD에서는 버텍스의 위치값을 참조하면서 Z-Fighting이 발생하지 않도록 이것 저것 매직 밸류를 테스트하면서 많은 시간을 소모했던 것에 반해서 SSD는 그런 문제가 전혀 없습니다. 말 그대로 이미 렌더링된 2D화면에 덧칠하는 방법이거든요. 그래서 FD와는 다르게 카메라를 눕혀서 본다고 해도 데칼이 붕~ 뜨거나 하진 않습니다. 게다가 버텍스 정보를 가지고 있을 필요도 없구요. Depth Texture를 알고 있어야 한다는 제약이 있지만, 요즘에는 기본적으로 Depth를 먼저 렌더링하지 않을까 하는 생각이 듭니다. PostEffect 만들 때 참
조하면 좋기도 하구요.

그럼 어떻게 구현해야 하는지 하나 하나 스텝으로 알아보도록 하지요.

1. Depth를 화면에 렌더링합니다.
Depth를 렌더링하는 이슈는 여러 가지가 있습니다. w로 나눌 것인지, far plane 상수를 두고 나눌 것인지 등등, 이것들은 상관 없고 나중에 Depth값을 이용해서 Decal의 Local공간으로 변환을 할 수 있는 방법만 알고 계시면 됩니다. 전 far plane의 상수값을 두어서 실행했습니다.

2. 데칼을 렌더링하기 위한 기하구조를 만듭니다.
모양은 Box나 Sphere가 주로 사용되는 것 같습니다. 여기서는 그냥 Box를 사용하도록 하지요.

3. 이제 이놈을 화면에 렌더링하면서 Local위치를 가지고 UV를 계산해 냅니다.
위치는 표면에 위치하도록 하면 되겠지요? UV까지 잘 계산하였다면 다음과 같이 화면에 데칼용 Box가 렌더링됩니다.

  

간단한 Shader코드는 다음과 같습니다.

float pixelDepth = tex2D(depthtex, vPos);     //Depth값을 알아옵니다.
float3 worldPos = ComputeWorldPos(uv, pixelDepth); //Depth값을 이용해서 WorldPos를 계산합니다.
float3 decalLocalpos = worldPos * invWorldTM; //WorldPos를 Decal의 Local공간으로 이동시킵니다.
float2 decalUV = decalLocalpos.xy + 0.5f; // 0.5를 더해서 0.0과 1.0 사이로 맵핑시킵니다.

4번째 줄에서 0.5를 더한 이유는 Decal의 Local Vertex의 위치가 -0.5 ~ 0.5로 맵핑되어 있기 때문입니다.
즉, 2번에서 Box형 기하구조를 생성할 때, Vertex의 위치값을 -0.5와 0.5를 이용해서 만드시면 됩니다.
조금만 생각해 보시면 쉽게 알 수 있으니 그냥 스무스하게 넘어가겠습니다.

5. 이제 렌더링되는 부분이 아닌 다른 모든 부분을 AlphaTest나 AlphaBlending으로 날려버립니다. 
어느 것으로 할지는 렌더링 되는 데칼에 따라 다릅니다. 뭐 쉬운 부분이니까 잘 하시면 됩니다. 간단한 셰이더 코드는 다음과 같습니다.

float dist = abs(decalLocalPos.z);        //Decal의 Local깊이를 구합니다.
float scaleDistance = max(dist * 2.0f, 1.0f); //Local깊이를 0.0과 1.0으로 맵핑시킵니다.
float fadeOut = 1.0f - scaleDistance;     //이제 FadeOut값을 구해서..
float4 Color = decalColor;                //최종 칼라를 구해주고
Color.a *= fadeOut;                       // FadeOut값을 곱해주면 표면의 부분 이외는 사라지게 됩니다.

   

...어라 되었네요? 이건 뭐 초딩도 30분이면 할 수 있는..
3D들도 새로 나온 기술들을 보면 어려워 보이지만 실제로 구현해보면 '와 쉽네잉' 이라는 생각이 드는 게 대부분인 것 같습니다.
좀 더 많은 정보를 원하시는 분은 게임 엔진 젬스 1권에 내용이 나와 있으니 참고하시길 바랍니다.

자 그럼 랩좀비군은 이만 총총총. 

반응형
,