<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/atom10full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><feed xmlns="http://www.w3.org/2005/Atom" xmlns:openSearch="http://a9.com/-/spec/opensearch/1.1/" xmlns:georss="http://www.georss.org/georss" xmlns:gd="http://schemas.google.com/g/2005" xmlns:thr="http://purl.org/syndication/thread/1.0" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" gd:etag="W/&quot;CEYCRn0zeyp7ImA9WhVTEE8.&quot;"><id>tag:blogger.com,1999:blog-5281384917275132568</id><updated>2012-02-24T03:36:07.383+09:00</updated><category term="Python" /><category term="이것 저것" /><category term="Lighting" /><category term="북미취업" /><category term="Shadow Map" /><category term="최적화" /><category term="Gamma" /><category term="물리" /><category term="게임업계" /><category term="갈렉산드리아" /><category term="리눅스" /><category term="인생조언" /><category term="수학" /><category term="Toon" /><category term="잡담" /><category term="Shader" /><category term="음악" /><category term="도서" /><category term="개발" /><category term="스크럼" /><category term="Photoshop" /><category term="Tool" /><category term="쓰레기" /><category term="C++" /><category term="PHP" /><category term="KGC" /><category term="포프의 쉐이더 입문강좌" /><category term="Rants" /><category term="Graphics" /><category term="Linux" /><category term="Unity" /><category term="DXT" /><category term="디버깅" /><category term="웹 개발" /><category term="Ubuntu" /><category term="DirectX" /><category term="개발일지" /><category term="Autodesk" /><title>블라인드 렌더러</title><subtitle type="html">캐나다 Relic에서 시니어 렌더링 프로그래머 일을 하고 있는 포프입니다. 물론 다른 짓(?)도 종종 잘합니다.</subtitle><link rel="http://schemas.google.com/g/2005#feed" type="application/atom+xml" href="http://kblog.popekim.com/feeds/posts/default" /><link rel="alternate" type="text/html" href="http://kblog.popekim.com/" /><link rel="next" type="application/atom+xml" href="http://www.blogger.com/feeds/5281384917275132568/posts/default?start-index=11&amp;max-results=10&amp;redirect=false&amp;v=2" /><author><name>Pope</name><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="33" height="30" src="http://2.bp.blogspot.com/_BBDmHdyx8wo/SfTUvbwSs-I/AAAAAAAAAYk/P1yurbiaKZM/S220/650px-Triskele-hollow-triangle.svg.png" /></author><generator version="7.00" uri="http://www.blogger.com">Blogger</generator><openSearch:totalResults>75</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>10</openSearch:itemsPerPage><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/atom+xml" href="http://feeds.feedburner.com/kblog-blindrenderer" /><feedburner:info uri="kblog-blindrenderer" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><link rel="license" type="text/html" href="http://creativecommons.org/licenses/by-nc-nd/2.0/" /><logo>http://creativecommons.org/images/public/somerights20.gif</logo><feedburner:feedFlare href="http://add.my.yahoo.com/rss?url=http%3A%2F%2Ffeeds.feedburner.com%2Fkblog-blindrenderer" src="http://us.i1.yimg.com/us.yimg.com/i/us/my/addtomyyahoo4.gif">Subscribe with My Yahoo!</feedburner:feedFlare><feedburner:feedFlare href="http://www.bloglines.com/sub/http://feeds.feedburner.com/kblog-blindrenderer" src="http://www.bloglines.com/images/sub_modern11.gif">Subscribe with Bloglines</feedburner:feedFlare><feedburner:feedFlare href="http://fusion.google.com/add?feedurl=http%3A%2F%2Ffeeds.feedburner.com%2Fkblog-blindrenderer" src="http://buttons.googlesyndication.com/fusion/add.gif">Subscribe with Google</feedburner:feedFlare><feedburner:feedFlare href="http://www.live.com/?add=http%3A%2F%2Ffeeds.feedburner.com%2Fkblog-blindrenderer" src="http://tkfiles.storage.msn.com/x1piYkpqHC_35nIp1gLE68-wvzLZO8iXl_JMledmJQXP-XTBOLfmQv4zhj4MhcWEJh_GtoBIiAl1Mjh-ndp9k47If7hTaFno0mxW9_i3p_5qQw">Subscribe with Live.com</feedburner:feedFlare><feedburner:feedFlare href="http://www.hanrss.com/add_sub.qst?url=http%3A%2F%2Ffeeds.feedburner.com%2Fkblog-blindrenderer" src="http://static.hanrss.com/images/add_to_hanrss2.gif">Subscribe with HanRSS</feedburner:feedFlare><entry gd:etag="W/&quot;D0QDQHo9eCp7ImA9WhRaGUk.&quot;"><id>tag:blogger.com,1999:blog-5281384917275132568.post-959908757036441174</id><published>2012-02-13T16:50:00.002+09:00</published><updated>2012-02-23T06:16:11.460+09:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2012-02-23T06:16:11.460+09:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="인생조언" /><category scheme="http://www.blogger.com/atom/ns#" term="게임업계" /><category scheme="http://www.blogger.com/atom/ns#" term="개발" /><title>청소년 게임문제는 권위를 잃은 부모의 문제이다.</title><content type="html">한참 번역일을 할 때였던 2006년에 "PC와 비디오 게임: 친구인가 적인가?(PC and Video Games: Friends or Foes?)"란 제목의 컨퍼런스 회의록을 번역한 적이 있었는데 거기서 나왔던 내용 중에 아직까지도 뇌리에 강하게 남아있는 내용이 있었죠. 근데 요즘 한국에서 일어나는 게임규제에 대한 꼴갑과 관련이 있다는 생각이 들어 제 블로그에 짧게 올려봅니다.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;대충 번역:&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;blockquote class="tr_bq"&gt;
권위(authority)라는 단어의 기원은 라틴어로 ‘저술하다(author)’란 뜻에서 유래했습니다. 오늘날 부모들은 더 이상 이 세계에 대한 설명을 저술할 능력이 없습니다. 즉 부모들이 현 세계를 마땅히 설명할 능력이 없으므로 권위에 도전을 느끼는 것입니다. 현세계에 대한 개념조차 없는 부모들이 자녀들의 뉴미디어 사용을 적절히 제한할 수 있을 턱이 없죠. 부모들은 아이들이 미지의 가상세계에 빠지는 것을 두려워합니다. 오히려 아이들이 이로부터 영감을 받을 수 있다는 사실을 아직 깨닫지 못하고 있죠. 그래서 부모들은 가상 기술을 거부하기 위해서 필사적으로 아이들의 시간을 컨트롤하려 하죠.&amp;nbsp;부모들이 가장 두려워하는 것이 중독입니다. 그저 언론매체에서 마땅한 단어가 없어 중독이란 단어를 사용했을 뿐인데 부모들이 이걸 마약중독처럼 엄청 무시무시한거라 생각해버리는 어이없는 일이 발생했죠.&lt;/blockquote&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;원문:&lt;/b&gt;&lt;br /&gt;
&lt;blockquote class="tr_bq"&gt;
As&amp;nbsp;you may know, authority comes from&amp;nbsp;Latin “author”, and today, parents are&amp;nbsp;no longer able to author an explanation&amp;nbsp;of the world. So it means that they&amp;nbsp;have a problem of authority because it&amp;nbsp;is impossible for them—they lack the&amp;nbsp;concepts, the words—to author a good&amp;nbsp;explanation of the world.&amp;nbsp;So it means that they&amp;nbsp;have a problem of authority because it&amp;nbsp;is impossible for them—they lack the&amp;nbsp;concepts, the words—to author a good&amp;nbsp;explanation of the world. No wonder&amp;nbsp;we have some problems with authority!&amp;nbsp;It is impossible for parents to forbid the&amp;nbsp;use of new media because they know&amp;nbsp;that it could be closing off the future&amp;nbsp;of their kids: while scared to see their&amp;nbsp;kids being aspirated by this unknown&amp;nbsp;virtuality, they are not yet able to realize&amp;nbsp;that their kids could be inspired by&amp;nbsp;it. So, in a desperate effort, parents today&amp;nbsp;try to control time, refusing virtual&amp;nbsp;technologies.&amp;nbsp;They are afraid above all by addiction. It&amp;nbsp;is a media term: addiction. And they are&amp;nbsp;afraid by this word “addiction” because&amp;nbsp;it conjures up pictures related to drug&amp;nbsp;experiences. &amp;nbsp;&lt;/blockquote&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
이미 해외에서는 5~6년전에 이렇게 올바른 논의가 진행되었었는데... 대체 너넨 뭐하는거니?
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5281384917275132568-959908757036441174?l=kblog.popekim.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/OVvDvry0YazB6W9dSNCAz7VyCms/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/OVvDvry0YazB6W9dSNCAz7VyCms/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/OVvDvry0YazB6W9dSNCAz7VyCms/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/OVvDvry0YazB6W9dSNCAz7VyCms/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/kblog-blindrenderer?a=QNoHs0jcAqQ:t3YsIz_c8Ak:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/kblog-blindrenderer?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/kblog-blindrenderer?a=QNoHs0jcAqQ:t3YsIz_c8Ak:63t7Ie-LG7Y"&gt;&lt;img src="http://feeds.feedburner.com/~ff/kblog-blindrenderer?d=63t7Ie-LG7Y" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/kblog-blindrenderer?a=QNoHs0jcAqQ:t3YsIz_c8Ak:4cEx4HpKnUU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/kblog-blindrenderer?i=QNoHs0jcAqQ:t3YsIz_c8Ak:4cEx4HpKnUU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/kblog-blindrenderer?a=QNoHs0jcAqQ:t3YsIz_c8Ak:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/kblog-blindrenderer?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/kblog-blindrenderer/~4/QNoHs0jcAqQ" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://kblog.popekim.com/feeds/959908757036441174/comments/default" title="댓글" /><link rel="replies" type="text/html" href="http://kblog.popekim.com/2012/02/blog-post_13.html#comment-form" title="2개의 덧글" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/5281384917275132568/posts/default/959908757036441174?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/5281384917275132568/posts/default/959908757036441174?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/kblog-blindrenderer/~3/QNoHs0jcAqQ/blog-post_13.html" title="청소년 게임문제는 권위를 잃은 부모의 문제이다." /><author><name>Pope</name><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="33" height="30" src="http://2.bp.blogspot.com/_BBDmHdyx8wo/SfTUvbwSs-I/AAAAAAAAAYk/P1yurbiaKZM/S220/650px-Triskele-hollow-triangle.svg.png" /></author><thr:total>2</thr:total><feedburner:origLink>http://kblog.popekim.com/2012/02/blog-post_13.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DkcCRn84eSp7ImA9WhRbGEs.&quot;"><id>tag:blogger.com,1999:blog-5281384917275132568.post-8293692125560592716</id><published>2012-02-10T17:54:00.001+09:00</published><updated>2012-02-10T17:54:27.131+09:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2012-02-10T17:54:27.131+09:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="잡담" /><category scheme="http://www.blogger.com/atom/ns#" term="음악" /><title>[작업중] 음악: Out of Reach 도입부</title><content type="html">오늘밤 쓴 곡... 아직 도입부 뿐이지만 꽤 맘에 든다.. 일단 Out of Reach라고 제목을 붙였다... 꽤 맘에 드는 도입부이므로... 언젠간 끝낼 가능성이 높지 않을까... 하고 생각만 한다...&lt;br /&gt;
&lt;br /&gt;
&lt;iframe frameborder="no" height="166" scrolling="no" src="http://w.soundcloud.com/player/?url=http%3A%2F%2Fapi.soundcloud.com%2Ftracks%2F36148040&amp;amp;show_artwork=true" width="100%"&gt;&lt;/iframe&gt;&lt;br /&gt;
&lt;br /&gt;
피드백은 내 &lt;a href="https://www.facebook.com/pages/%ED%8F%AC%ED%94%84/300204113370792"&gt;페이스북 (원맨) 밴드 페이지&lt;/a&gt;로.... 고고고?&lt;br /&gt;
&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5281384917275132568-8293692125560592716?l=kblog.popekim.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/TGRDgEEgA3bYyDSIn7AyofSuZfI/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/TGRDgEEgA3bYyDSIn7AyofSuZfI/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/TGRDgEEgA3bYyDSIn7AyofSuZfI/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/TGRDgEEgA3bYyDSIn7AyofSuZfI/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/kblog-blindrenderer?a=RxOZHjvAjtM:JTecDnWaACA:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/kblog-blindrenderer?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/kblog-blindrenderer?a=RxOZHjvAjtM:JTecDnWaACA:63t7Ie-LG7Y"&gt;&lt;img src="http://feeds.feedburner.com/~ff/kblog-blindrenderer?d=63t7Ie-LG7Y" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/kblog-blindrenderer?a=RxOZHjvAjtM:JTecDnWaACA:4cEx4HpKnUU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/kblog-blindrenderer?i=RxOZHjvAjtM:JTecDnWaACA:4cEx4HpKnUU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/kblog-blindrenderer?a=RxOZHjvAjtM:JTecDnWaACA:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/kblog-blindrenderer?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/kblog-blindrenderer/~4/RxOZHjvAjtM" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://kblog.popekim.com/feeds/8293692125560592716/comments/default" title="댓글" /><link rel="replies" type="text/html" href="http://kblog.popekim.com/2012/02/out-of-reach.html#comment-form" title="5개의 덧글" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/5281384917275132568/posts/default/8293692125560592716?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/5281384917275132568/posts/default/8293692125560592716?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/kblog-blindrenderer/~3/RxOZHjvAjtM/out-of-reach.html" title="[작업중] 음악: Out of Reach 도입부" /><author><name>Pope</name><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="33" height="30" src="http://2.bp.blogspot.com/_BBDmHdyx8wo/SfTUvbwSs-I/AAAAAAAAAYk/P1yurbiaKZM/S220/650px-Triskele-hollow-triangle.svg.png" /></author><thr:total>5</thr:total><feedburner:origLink>http://kblog.popekim.com/2012/02/out-of-reach.html</feedburner:origLink></entry><entry gd:etag="W/&quot;A0UGSHo9cSp7ImA9WhRbGU0.&quot;"><id>tag:blogger.com,1999:blog-5281384917275132568.post-5246298943557588536</id><published>2012-02-10T09:30:00.000+09:00</published><updated>2012-02-11T06:27:09.469+09:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2012-02-11T06:27:09.469+09:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="잡담" /><title>구글 플러스 프로필(한국어)을 만들었습니다.</title><content type="html">사실 예전부터 영어로 구글 플러스를 써오긴 했었는데... 요즘들어 점점 절 추가하시는 분들이 많아지고 해서... 그냥 한국어 계정으로 구글 플러스를 하나 더 열었습니다. (제가 언어를 섞는걸 별로 안좋아해요.. 아무래도 이쪽에 있는 친구들이 제 트위터나 구글 플러스를 구독하는데.. 거기에 알아듣지 못하는 언어가 절반이면 좀 그래서.. -_-)&lt;br /&gt;
&lt;br /&gt;
자 뭐든간에:&lt;br /&gt;
&lt;a href="http://plus.google.com/107616282454541805236"&gt;&lt;b&gt;&lt;span id="goog_668171160"&gt;&lt;/span&gt;포프의 구글+ 프로필&lt;/b&gt;&lt;span id="goog_668171161"&gt;&lt;/span&gt;&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5281384917275132568-5246298943557588536?l=kblog.popekim.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/u6VzJ_HSbNoL-5Jr3JAwe8BRjyA/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/u6VzJ_HSbNoL-5Jr3JAwe8BRjyA/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/u6VzJ_HSbNoL-5Jr3JAwe8BRjyA/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/u6VzJ_HSbNoL-5Jr3JAwe8BRjyA/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/kblog-blindrenderer?a=Mw6lzFjIrX0:_rnigJfugpQ:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/kblog-blindrenderer?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/kblog-blindrenderer?a=Mw6lzFjIrX0:_rnigJfugpQ:63t7Ie-LG7Y"&gt;&lt;img src="http://feeds.feedburner.com/~ff/kblog-blindrenderer?d=63t7Ie-LG7Y" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/kblog-blindrenderer?a=Mw6lzFjIrX0:_rnigJfugpQ:4cEx4HpKnUU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/kblog-blindrenderer?i=Mw6lzFjIrX0:_rnigJfugpQ:4cEx4HpKnUU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/kblog-blindrenderer?a=Mw6lzFjIrX0:_rnigJfugpQ:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/kblog-blindrenderer?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/kblog-blindrenderer/~4/Mw6lzFjIrX0" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://kblog.popekim.com/feeds/5246298943557588536/comments/default" title="댓글" /><link rel="replies" type="text/html" href="http://kblog.popekim.com/2012/02/blog-post_10.html#comment-form" title="0개의 덧글" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/5281384917275132568/posts/default/5246298943557588536?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/5281384917275132568/posts/default/5246298943557588536?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/kblog-blindrenderer/~3/Mw6lzFjIrX0/blog-post_10.html" title="구글 플러스 프로필(한국어)을 만들었습니다." /><author><name>Pope</name><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="33" height="30" src="http://2.bp.blogspot.com/_BBDmHdyx8wo/SfTUvbwSs-I/AAAAAAAAAYk/P1yurbiaKZM/S220/650px-Triskele-hollow-triangle.svg.png" /></author><thr:total>0</thr:total><feedburner:origLink>http://kblog.popekim.com/2012/02/blog-post_10.html</feedburner:origLink></entry><entry gd:etag="W/&quot;Ak8BQXo4fip7ImA9WhRbFko.&quot;"><id>tag:blogger.com,1999:blog-5281384917275132568.post-712649962994626784</id><published>2012-02-08T14:25:00.000+09:00</published><updated>2012-02-08T14:27:30.436+09:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2012-02-08T14:27:30.436+09:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="인생조언" /><category scheme="http://www.blogger.com/atom/ns#" term="게임업계" /><category scheme="http://www.blogger.com/atom/ns#" term="개발일지" /><category scheme="http://www.blogger.com/atom/ns#" term="잡담" /><category scheme="http://www.blogger.com/atom/ns#" term="쓰레기" /><category scheme="http://www.blogger.com/atom/ns#" term="개발" /><title>거짓말로 버티고 사는 개발자...</title><content type="html">&lt;br /&gt;
최근에 회사를 &lt;strike&gt;떠나야 했던&lt;/strike&gt; 떠난 개발자가 있다. 뭐 짧게 짧게 여러 회사를 옮겨다녀야 하는 인간 중 하나인데.... (뭐, 그래야 하는 이유는 대충 다들 알테고).... 어쩌다 오늘 그 인간의 블로그를 보게 되었는데 본인이 회사를 떠나게 된 이유를 설명하고 있었다. 나를 비롯한 많은 울 회사 직원들이 이 글을 아주 즐겁게 봤는데... 이게 세계 최고의 판타지 소설 '반지의 제왕'을 연상시키기 때문이라지....?&lt;br /&gt;
&lt;br /&gt;
&lt;table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;&lt;a href="http://4.bp.blogspot.com/-709r3JsPAqo/TzH16omZqrI/AAAAAAAAA0w/SOtgAO6QwyM/s1600/Smeagol.jpg" imageanchor="1" style="margin-left: auto; margin-right: auto;"&gt;&lt;img border="0" src="http://4.bp.blogspot.com/-709r3JsPAqo/TzH16omZqrI/AAAAAAAAA0w/SOtgAO6QwyM/s1600/Smeagol.jpg" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="tr-caption" style="font-size: 13px;"&gt;&lt;b&gt;이미지 출처:&lt;/b&gt;&amp;nbsp;http://images.wikia.com/lotr/images/9/9e/Smeagol.jpg&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;br /&gt;
뭐, 굳이 그놈이 한 모든 거짓말들을 들추어 낼 생각은 없다. 어차피 이 업계에서 머무르려면 그놈은 그런 거짓말을 해야만 할테니까... 그냥 조만간 이놈이 밴쿠버 밖에서 직장을 찾아야 할 꺼라고만 추측한다. 이미 이 도시에서 꽤 유명하더군.... ㅎㅎ... 그 외에도 괜히 여기 까발려서 명예훼손죄로 고소 받는 것도 좀 귀찮고... 뭐 실제 고소 들어오면 어차피 내가 이길 게 뻔하니 그것도 꽤 재밌을 거 같긴 하다. &amp;nbsp;내가 하는 말은 모두 사실이거든.... (괜히 법대 나온게 아니라니까? -_-) 그냥 아무것도 모르는 똘아이하고 상대하는 게 골치아프니 귀찮은 것일뿐.... &amp;nbsp;그래도 개인적으로 물어오는 사람이 있다면 당연히 주저하지 않고 말해줄거다. 뭐든간에 난 솔직하고 직설적인 놈이어서.. 절대 거짓말도.. 숨기지도 않으니까...&lt;br /&gt;
&lt;br /&gt;
거짓말 이야기가 나왔으니 말인데... 난 의견/판단 &amp;lt;--&amp;gt; 사실을 구분하는 법을 매우 잘 알고 있다. 법대 괜히 나온게 아니라니까.....? -_- 마찬가지 이유로 내가 그놈을 거짓말쟁이라 부르는 이유도 그놈이 허위사실을 유포하기 때문이지 그놈의 말도안되는 판단이나 의견 때문이 아니다. 그래도 정말 스스로 자기주장이 사실이라 믿고 있다면.... 그놈은 엔지니어가 될 최소한의 자질조차 갖추지 못했다는 증거일 뿐... 아니면 &lt;a href="http://www.baekammh.or.kr/"&gt;&lt;b&gt;여기&lt;/b&gt;&lt;/a&gt;가 그놈의 새 전세방이 될지도....&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="http://3.bp.blogspot.com/-1GtuWmfQc7Y/TzHxID7riZI/AAAAAAAAA0k/WcSapXOodB8/s1600/funny-pictures-you-say-psycho-like-its-a-bad-thing.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://3.bp.blogspot.com/-1GtuWmfQc7Y/TzHxID7riZI/AAAAAAAAA0k/WcSapXOodB8/s1600/funny-pictures-you-say-psycho-like-its-a-bad-thing.jpg" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br class="Apple-interchange-newline" /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5281384917275132568-712649962994626784?l=kblog.popekim.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/MlRa6keCPnvCeMMob_q_C_SolvE/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/MlRa6keCPnvCeMMob_q_C_SolvE/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/MlRa6keCPnvCeMMob_q_C_SolvE/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/MlRa6keCPnvCeMMob_q_C_SolvE/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/kblog-blindrenderer?a=VFbM5zIzAnQ:MP43D7Sc948:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/kblog-blindrenderer?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/kblog-blindrenderer?a=VFbM5zIzAnQ:MP43D7Sc948:63t7Ie-LG7Y"&gt;&lt;img src="http://feeds.feedburner.com/~ff/kblog-blindrenderer?d=63t7Ie-LG7Y" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/kblog-blindrenderer?a=VFbM5zIzAnQ:MP43D7Sc948:4cEx4HpKnUU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/kblog-blindrenderer?i=VFbM5zIzAnQ:MP43D7Sc948:4cEx4HpKnUU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/kblog-blindrenderer?a=VFbM5zIzAnQ:MP43D7Sc948:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/kblog-blindrenderer?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/kblog-blindrenderer/~4/VFbM5zIzAnQ" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://kblog.popekim.com/feeds/712649962994626784/comments/default" title="댓글" /><link rel="replies" type="text/html" href="http://kblog.popekim.com/2012/02/blog-post_08.html#comment-form" title="6개의 덧글" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/5281384917275132568/posts/default/712649962994626784?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/5281384917275132568/posts/default/712649962994626784?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/kblog-blindrenderer/~3/VFbM5zIzAnQ/blog-post_08.html" title="거짓말로 버티고 사는 개발자..." /><author><name>Pope</name><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="33" height="30" src="http://2.bp.blogspot.com/_BBDmHdyx8wo/SfTUvbwSs-I/AAAAAAAAAYk/P1yurbiaKZM/S220/650px-Triskele-hollow-triangle.svg.png" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://4.bp.blogspot.com/-709r3JsPAqo/TzH16omZqrI/AAAAAAAAA0w/SOtgAO6QwyM/s72-c/Smeagol.jpg" height="72" width="72" /><thr:total>6</thr:total><feedburner:origLink>http://kblog.popekim.com/2012/02/blog-post_08.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DUEHSHs4fCp7ImA9WhRbFko.&quot;"><id>tag:blogger.com,1999:blog-5281384917275132568.post-7788665355151443263</id><published>2012-02-08T09:30:00.000+09:00</published><updated>2012-02-08T14:07:19.534+09:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2012-02-08T14:07:19.534+09:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="북미취업" /><category scheme="http://www.blogger.com/atom/ns#" term="개발" /><title>게임개발자 북미취업 가이드 부록 B: 아티스트 포트폴리오 모음</title><content type="html">&lt;br /&gt;
&lt;div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;
&lt;div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;
&lt;div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;
&lt;div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;
&lt;div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;
&lt;div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;
&lt;b&gt;&lt;span class="Apple-style-span" style="font-size: small;"&gt;&lt;br class="Apple-interchange-newline" /&gt;게임개발자 북미취업 가이드 시리즈 목차&lt;/span&gt;&lt;/b&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;
&lt;div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;
&lt;div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;
&lt;div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;
&lt;div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;
&lt;div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;&lt;span class="Apple-style-span" style="font-size: small;"&gt;&lt;a href="http://kblog.popekim.com/2010/07/1.html"&gt;1편: 소개 및 저술방침&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span class="Apple-style-span" style="font-size: small;"&gt;&lt;a href="http://kblog.popekim.com/2010/07/2.html"&gt;2편: 북미 게임개발 근무환경/취업시장&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span class="Apple-style-span" style="font-size: small;"&gt;&lt;a href="http://kblog.popekim.com/2010/07/3.html"&gt;3편: 취업을 위한 필수/선택요건 - 면접절차&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span class="Apple-style-span" style="font-size: small;"&gt;&lt;a href="http://kblog.popekim.com/2010/08/4.html"&gt;4편: 실전 가이드&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://kblog.popekim.com/2010/08/5.html"&gt;5편: 실제 취업사례 - 포프&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;span class="Apple-style-span" style="font-size: small;"&gt;&lt;a href="http://kblog.popekim.com/2010/08/6.html"&gt;6편:&amp;nbsp;실제 취업사례&amp;nbsp;- 다른 사람들&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span class="Apple-style-span" style="font-size: small;"&gt;&lt;a href="http://kblog.popekim.com/2010/09/7.html"&gt;7편: 질문/답변&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://kblog.popekim.com/2011/05/blog-post.html"&gt;부록 A: 원화 아티스트 포트폴리오 모음&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://kblog.popekim.com/2012/02/b.html"&gt;부록 B: 아티스트 포트폴리오 모음&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;
&lt;div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;
&lt;div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;
&lt;div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;
&lt;br class="Apple-interchange-newline" /&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;br /&gt;
&lt;br /&gt;
예전에 &lt;a href="http://kblog.popekim.com/2011/05/blog-post.html"&gt;원화 아티스트들 포트폴리오&lt;/a&gt;를 올리고 난 뒤, 다른 아티스트들의 포트폴리오도 링크걸어달란 요청이 좀 있었는데 게을러서 이제서야 올립니다. (실은 책 작업하면서 이걸 좀 모아야 했다는... -_-) 렐릭 뿐만 아니라 그냥 제가 같이 일해봤었던 아티스트들의 포폴을 모두 긁어왔습니다. -_-; 학교졸업 포폴부터 실제 경력 포폴까지 다양하군요.&lt;br /&gt;
&lt;br /&gt;
저번가 마찬가지로 이 사람들 포폴 웹사이트 보시고 동기부여가 되시거나 '이 정도면 뭐 나도 할 수 있겠군~' 정도의 거만함(?)을 키우시기 바랍니다. ^^&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-family: inherit;"&gt;&lt;b&gt;3D 아티스트&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;&lt;span style="font-family: inherit;"&gt;&lt;a href="http://www.adriendebos.com/"&gt;Adrien Debos&lt;/a&gt;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style="font-family: inherit;"&gt;&lt;a href="http://junh79.cgsociety.org/gallery/"&gt;Jun Huang&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style="font-family: inherit;"&gt;&lt;a href="http://clockworkbeetle.com/"&gt;David Clement&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style="font-family: inherit;"&gt;&lt;a href="http://www.krop.com/kg_art/"&gt;Kim Gill&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style="font-family: inherit;"&gt;&lt;a href="http://www.etctsao.com/"&gt;Eric Tsao&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style="font-family: inherit;"&gt;&lt;a href="http://www.etctsao.com/"&gt;Eric Testroete&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style="font-family: inherit;"&gt;&lt;a href="http://huaite.blogspot.com/"&gt;Dave Wang&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;애니메이터&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://panholzer.org/richard/"&gt;Richard Panholzer&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.christinehubbard.com/"&gt;Christine Hubbard&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.senglau.com/"&gt;Seng Lau&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.milanblue.blogspot.com/"&gt;Dennis Kang&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;br /&gt;
&lt;b&gt;기타 아티스트(FX &amp;amp; UI)&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://www.stumaxwell.com/"&gt;Stuart Maxwell&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.jerahdesigns.com/"&gt;Jerah Regualos&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;br /&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5281384917275132568-7788665355151443263?l=kblog.popekim.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/wn8WwU-JMqHY-jsv3GOn0sTxH1I/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/wn8WwU-JMqHY-jsv3GOn0sTxH1I/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/wn8WwU-JMqHY-jsv3GOn0sTxH1I/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/wn8WwU-JMqHY-jsv3GOn0sTxH1I/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/kblog-blindrenderer?a=Qf9UTTLnwOk:JiocT8DECsc:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/kblog-blindrenderer?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/kblog-blindrenderer?a=Qf9UTTLnwOk:JiocT8DECsc:63t7Ie-LG7Y"&gt;&lt;img src="http://feeds.feedburner.com/~ff/kblog-blindrenderer?d=63t7Ie-LG7Y" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/kblog-blindrenderer?a=Qf9UTTLnwOk:JiocT8DECsc:4cEx4HpKnUU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/kblog-blindrenderer?i=Qf9UTTLnwOk:JiocT8DECsc:4cEx4HpKnUU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/kblog-blindrenderer?a=Qf9UTTLnwOk:JiocT8DECsc:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/kblog-blindrenderer?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/kblog-blindrenderer/~4/Qf9UTTLnwOk" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://kblog.popekim.com/feeds/7788665355151443263/comments/default" title="댓글" /><link rel="replies" type="text/html" href="http://kblog.popekim.com/2012/02/b.html#comment-form" title="6개의 덧글" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/5281384917275132568/posts/default/7788665355151443263?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/5281384917275132568/posts/default/7788665355151443263?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/kblog-blindrenderer/~3/Qf9UTTLnwOk/b.html" title="게임개발자 북미취업 가이드 부록 B: 아티스트 포트폴리오 모음" /><author><name>Pope</name><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="33" height="30" src="http://2.bp.blogspot.com/_BBDmHdyx8wo/SfTUvbwSs-I/AAAAAAAAAYk/P1yurbiaKZM/S220/650px-Triskele-hollow-triangle.svg.png" /></author><thr:total>6</thr:total><feedburner:origLink>http://kblog.popekim.com/2012/02/b.html</feedburner:origLink></entry><entry gd:etag="W/&quot;C0ENSXcyeip7ImA9WhRbFk0.&quot;"><id>tag:blogger.com,1999:blog-5281384917275132568.post-5141574126763215820</id><published>2012-02-07T16:37:00.001+09:00</published><updated>2012-02-07T17:01:38.992+09:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2012-02-07T17:01:38.992+09:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="개발일지" /><category scheme="http://www.blogger.com/atom/ns#" term="잡담" /><category scheme="http://www.blogger.com/atom/ns#" term="개발" /><title>그래픽 프로그래밍 팀장이 될 뻔 했었다....</title><content type="html">난 매우 직선적인 성격이다.. 특히 회사에서 일할 땐.... 말도 안되는 개소리는 개소리라고 말해주고... 실력이 없는 놈이 정치를 하려고하면 쌍욕도 잘해준다... 사실 주변에서는 이러면 적만 만들다가 회사 짤리니 조심하란 이야길 하는데... 내 자세는 언제나..&lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;b&gt;'그러던가?&lt;/b&gt;'&lt;br /&gt;
&lt;br /&gt;
였다. 실력 하나로 믿고 살아온 인생.... 괜히 누구에게나 착한 척 가식떨며 내 자리 지키고 싶은 마음은 한번도 없었으니까...&lt;br /&gt;
&lt;br /&gt;
이렇게 말하면 내가 누구에게나 개판으로 대하는 인간처럼 보일지도 모르겠지만 사실 그건 아니다. 난 대우 받을 가치가 있다고 생각하는 개발자들에게는 정말 잘해준다. 한마디로 직급/연차 상관없이 실력좋고 책임감있고 인간되었으면(가식이 아닌 진짜 인간) 존경해준다.&lt;br /&gt;
&lt;br /&gt;
사실 얼마 전까지는 이런 성격때문에 난 적이 꽤 많다고 생각해왔다. 그런데 최근 들어 그보다 아군(?)들이 더 많다는 사실을 깨닫게 되는 계기가 있었다. 다음은 그 이야기... (내 잘난 척 할거니... 보기 싫음 닫으삼.... 경고했음..... -_-)&lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="http://2.bp.blogspot.com/-TOhqNSy3cQM/TzDaIoMuZrI/AAAAAAAAACA/fkEJbsbwqGc/s1600/funny-pictures-kitten-is-a-leader.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em; text-align: center;"&gt;&lt;img border="0" src="http://2.bp.blogspot.com/-TOhqNSy3cQM/TzDaIoMuZrI/AAAAAAAAACA/fkEJbsbwqGc/s1600/funny-pictures-kitten-is-a-leader.jpg" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;br /&gt;
이번에 렐릭에서 pre-production에 들어가는 프로젝트가 하나 있다. 그 팀에서 그래픽 쪽 일이 좀 많아서 그래픽 팀 리드가 필요하단다. 원래 그 일을 맡기려고 채용했던 놈이 하나 있었는데 실력이 너무 형편없고 구라만 까고 정치만 하는 개늠... -_- 그래서 오늘부로 퇴사... 따라서 저번주부터 새로운 그래픽 팀 리드를 찾으려고 했단다. 윗선에서는 새로운 사람을 채용하려고 구인공고를 낸다 했다지... 근데 그 이야기들을 팀원들 중에 4명(내가 아는 것만)이 나를 그자리에 추천했단다. (현재 그 팀 규모는 15명정도? pre-production이니까 아직 팀 크기가 좀 작다) 여기서 더 재밌는 사실은 그 4명이 합심해서 날 추천한게 아니라... 한 명씩 따로 자기 생각에 내가 좋을거 같아서 추천했단다. 다른 사람들이 날 추천하는 것도 모른 채.... 다들 나랑 스페이스마린 팀에서 같이 일했던 동료들이었고... 하는 일들도 테크니컬 아티스트 감독부터 원화 아티스트, 그리고 내가 그래픽 팀 팀장이 되면 내 밑에서 일하게 될 쥬니어 그래픽 프로그래머까지 다양....&lt;br /&gt;
&lt;br /&gt;
이렇게 산발적으로 여러명이 추천을 하니 그제서야 나의 가치(?)를 알아본 윗선들이 급하게 나를 현재 팀(다크사이더 2 팀)에서 빼가서 그 팀의 그래픽 리드로 앉히려고 했지만... (민주주의의 승리....?) 다크사이더 2 게임의 출시가 6월달이라 그쪽에서 날 놔줄수 없다고, 나 빼가면 울 모회사 THQ에게 이르겠다고(?) 해서 어쩔수 없이 못빼간단다... -_- (민주주의는 개뿔...?)&lt;br /&gt;
&lt;br /&gt;
솔직히 팀장이 안된건 좀 아쉽다. 오랜만(한 15년? 아니 학교에서 한거 따지면 7년인가...)에 팀장질을 다시 해보고 싶은 욕심도 있었지만... 더 큰 이유는 나를 팀장으로 모시고(?) 싶어하는 사람들이 눈에 밟힌다고 할까?&amp;nbsp;특히 내 밑에서 일하게 될 그 쥬니어 그래픽 프로그래머는 실력에 비해 몸값이 저평가된 경우라, 팀장이 되면 곧바로 내 직급 정도까지 승진(3단계 승진해서 선임으로 -_-... 연차는 안되는데 실력은 거의 나랑 삐까하다고 생각.. 나보다 나을지도?)을 시켜주고 싶었거든...&lt;br /&gt;
&lt;br /&gt;
어쨋든 날 추천했던 놈들에게 이런 이런 이유로 그래픽 팀장이 안된다는 사실을 알려주니 말도 안된다며 화내는 놈도 있었고... 그냥 아쉬워 하는 놈도 있었고... '그래서 이번 게임 6월에 끝나면 뭐할건데?'라고 물어보는 놈들도 있었다. '뭐, 딱히 갈 팀이 없으면 짤리지 않겠어?'라고 하니 혹시라도 그런 일 생기면 자기도 그 날 사표낸다는 놈들까지 -_-;&lt;br /&gt;
&lt;br /&gt;
참, 고맙단 생각이 들었다. 나와 같은 가치 -- 실력위주, 정직함 그리고 integrity(한국어로 뭔지 모름 -_-) -- 를 가지고 개발을 하는 사람들이 있다는 게... 그리고 그 사람들이 내 리더쉽을 믿어 준다는게...&lt;br /&gt;
&lt;br /&gt;
나는 언제나 상향식 변화(bottom-up change)를 선호한다.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5281384917275132568-5141574126763215820?l=kblog.popekim.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/_GgRCBBZTQuQ0rhWCygM43D_zxY/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/_GgRCBBZTQuQ0rhWCygM43D_zxY/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/_GgRCBBZTQuQ0rhWCygM43D_zxY/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/_GgRCBBZTQuQ0rhWCygM43D_zxY/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/kblog-blindrenderer?a=-XC21eksQlk:WivRwvNKZBc:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/kblog-blindrenderer?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/kblog-blindrenderer?a=-XC21eksQlk:WivRwvNKZBc:63t7Ie-LG7Y"&gt;&lt;img src="http://feeds.feedburner.com/~ff/kblog-blindrenderer?d=63t7Ie-LG7Y" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/kblog-blindrenderer?a=-XC21eksQlk:WivRwvNKZBc:4cEx4HpKnUU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/kblog-blindrenderer?i=-XC21eksQlk:WivRwvNKZBc:4cEx4HpKnUU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/kblog-blindrenderer?a=-XC21eksQlk:WivRwvNKZBc:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/kblog-blindrenderer?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/kblog-blindrenderer/~4/-XC21eksQlk" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://kblog.popekim.com/feeds/5141574126763215820/comments/default" title="댓글" /><link rel="replies" type="text/html" href="http://kblog.popekim.com/2012/02/blog-post_07.html#comment-form" title="10개의 덧글" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/5281384917275132568/posts/default/5141574126763215820?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/5281384917275132568/posts/default/5141574126763215820?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/kblog-blindrenderer/~3/-XC21eksQlk/blog-post_07.html" title="그래픽 프로그래밍 팀장이 될 뻔 했었다...." /><author><name>Pope</name><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="33" height="30" src="http://2.bp.blogspot.com/_BBDmHdyx8wo/SfTUvbwSs-I/AAAAAAAAAYk/P1yurbiaKZM/S220/650px-Triskele-hollow-triangle.svg.png" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://2.bp.blogspot.com/-TOhqNSy3cQM/TzDaIoMuZrI/AAAAAAAAACA/fkEJbsbwqGc/s72-c/funny-pictures-kitten-is-a-leader.jpg" height="72" width="72" /><thr:total>10</thr:total><feedburner:origLink>http://kblog.popekim.com/2012/02/blog-post_07.html</feedburner:origLink></entry><entry gd:etag="W/&quot;D08CSXs9cCp7ImA9WhRbFUg.&quot;"><id>tag:blogger.com,1999:blog-5281384917275132568.post-6490721131379947867</id><published>2012-02-06T04:04:00.000+09:00</published><updated>2012-02-07T04:17:48.568+09:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2012-02-07T04:17:48.568+09:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Unity" /><category scheme="http://www.blogger.com/atom/ns#" term="Tool" /><category scheme="http://www.blogger.com/atom/ns#" term="개발" /><title>유니티에서 topology가 같은 캐릭터간에 애니메이션 공유하기...</title><content type="html">&lt;table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style="text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/-mBOZNyARPrU/TzAnKMXEGfI/AAAAAAAAA0U/HI9rrxk1PQY/s1600/sharing_anim.jpg" imageanchor="1" style="margin-left: auto; margin-right: auto;"&gt;&lt;img border="0" height="446" src="http://2.bp.blogspot.com/-mBOZNyARPrU/TzAnKMXEGfI/AAAAAAAAA0U/HI9rrxk1PQY/s640/sharing_anim.jpg" width="640" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="tr-caption" style="text-align: center;"&gt;&lt;b&gt;이미지 출처&lt;/b&gt;: http://answers.unity3d.com/questions/191282/sharing-animations-between-models.html&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;br /&gt;
본(bone)의 길이가 다른 캐릭터들 사이에서 애니메이션을 공유하려고 한다고 생각해 보죠. 물론 각 캐릭터마다 애니메이션을 따로 만들어주면 좋겠지만 인력이 부족한다던가... 그런데 이렇게 본의 길이가 다른 캐릭터터들 사이에서 애니메이션을 공유할 수 있을까요? 뭐 되니까 이글을 쓰는거죠... -_-; 평행이동과 확대/축소를 사용하지 않으면 가능합니다. 달리 말하면 회전만 이용하면 된다는거죠. 이렇게 생각해보면 이해가 쉬워요. 본인의 오른쪽 팔꿈치를 안쪽으로 90도만큼 회전시켜 보세요. 이제 본인보다 키가 작은 친구에게 똑같이 오른쪽 팔꿈치를 90도만큼 회전시키라고 하는거죠. 그러면 둘의 포즈가 똑같죠? &amp;nbsp;바로 이 원리 입니다. 이해 되죠?&lt;br /&gt;
&lt;br /&gt;
결국 3DS Max가 뱉어내는 데이터가 어쨌던간에 애니메이션에서 회전만 적용시킬 수 있는 방법만 있으면 되는건데... 유니티에서 이런 걸 공식적으로 지원해주는 찾으려고 포럼을 뒤졌지만 그런것 같진 않더군요. 그러면 파이프라인 어딘가에서 회전 이외의 키프레임 정보를 지워버리는 방법이 없을까 찾아봤지요. 불행히도 딱히 대답을 찾을 순 없었습니다.&amp;nbsp;&lt;strike&gt;심지어는 물어보는 사람조차 없더군요.&lt;/strike&gt;&amp;nbsp;(이 글 쓰고 나서 &lt;a href="http://answers.unity3d.com/questions/191282/sharing-animations-between-models.html#comment-191370"&gt;이 질문을 한 사람을 찾았으나 마땅한 답변이 없더군요. 지금 달린 답변은 제가 이 글 쓰고 난 뒤 단 것 -_-.&lt;/a&gt;)&lt;br /&gt;
&lt;br /&gt;
뭐든간에 좋은소식은...... 제가 그 꼼수를 찾아냈다는 거지요. 무핫핫..... :D&lt;br /&gt;
&lt;br /&gt;
이렇게 했답니다. (코드는 조 밑에~)&lt;br /&gt;
&lt;ol&gt;
&lt;li&gt;Asset/Editor 폴더 안에 ConvertToRotationOnlyAnim.cs 라는 스크립트 파일을 만듭니다.&lt;/li&gt;
&lt;li&gt;이 스크립트를 호출하는 메뉴 항목을 만듭니다.&lt;/li&gt;
&lt;li&gt;Unity에 애니메이션을 import 해옵니다. (Unity가 애니메이션 파일이라고 생각하는 한 어디서 이 애니메이션을 만들었는지는 상관없습니다.)&lt;/li&gt;
&lt;li&gt;import해온 애니메이션 애셋에 마우스 오른쪽 버튼을 누르고, 단계 #2에서 추가했던 메뉴 아이템을 선택합니다.&lt;/li&gt;
&lt;li&gt;이제 스트립트 안에서 propertyName 필드 중에 "m_LocalRotation"이란 이름을 포함한 놈만 복사합니다.&lt;/li&gt;
&lt;li&gt;이제 _rot 애니메이션 클립을 게임오브젝트의 애니메이션 컴포넌트에 대입합니다.&lt;/li&gt;
&lt;li&gt;시작 버튼을 누르고..... 즐거워 해봅시다.. 얼씨구나.. 지화자~ -_-&lt;/li&gt;
&lt;/ol&gt;
&lt;div&gt;
그리고 이게 위에서 말씀드린 스크립트의 전체 소스코드. 주석을 잘 달아놨으니 영어공부할겸..... 대충 보고 이해하세요. ㄱ ㄱ ㅑ ~ -_-&lt;br /&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;using UnityEditor;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;using UnityEngine;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;using System.IO;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;public class ConvertToRotationOnlyAnim&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;{&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; &amp;nbsp; [MenuItem("Assets/Convert To Rotation Animation")]&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; &amp;nbsp; static void ConvertToRotationAnimation()&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; &amp;nbsp; {&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; // Get Selected Animation Clip&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; AnimationClip sourceClip = Selection.activeObject as AnimationClip;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; if (sourceClip == null)&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; {&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; Debug.Log("Please select an animation clip");&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; return;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; }&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; // Rotation only anim clip will have "_rot" post fix at the end&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; const string destPostfix = "_rot";&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; string sourcePath = AssetDatabase.GetAssetPath(sourceClip);&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; string destPath = Path.Combine(Path.GetDirectoryName(sourcePath), sourceClip.name) + destPostfix + ".anim";&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; // first try to open existing clip to avoid losing reference to this animation from other meshes that are already using it.&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; AnimationClip destClip = AssetDatabase.LoadAssetAtPath(destPath, typeof(AnimationClip)) as AnimationClip;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; if (destClip == null)&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; {&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; // existing clip not found. &amp;nbsp;Let's create a new one&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; Debug.Log("creating a new rotation only animation at " + destPath);&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; destClip = new AnimationClip();&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; destClip.name = sourceClip.name + destPostfix;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; AssetDatabase.CreateAsset(destClip, destPath);&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; AssetDatabase.Refresh();&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; // and let's load it back, just to make sure it's created?&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; destClip = AssetDatabase.LoadAssetAtPath(destPath, typeof(AnimationClip)) as AnimationClip;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; }&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; if (destClip == null)&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; {&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; Debug.Log("cannot create/open the rotation only anim at " + destPath);&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; return;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; }&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; // clear all the existing curves from destination.&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; destClip.ClearCurves();&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; // Now copy only rotation curves&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; AnimationClipCurveData[] curveDatas = AnimationUtility.GetAllCurves(sourceClip, true);&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; foreach (AnimationClipCurveData curveData in curveDatas)&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; {&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; if (curveData.propertyName.Contains("m_LocalRotation"))&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; {&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; AnimationUtility.SetEditorCurve(&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; destClip,&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; curveData.path,&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; curveData.type,&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; curveData.propertyName,&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; curveData.curve&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; );&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; }&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; }&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; Debug.Log("Hooray! Coverting to rotation-only anim to " + destClip.name + " is done");&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; &amp;nbsp; }&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;}&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5281384917275132568-6490721131379947867?l=kblog.popekim.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/JAq74TEPiM_Wi9MdAxNatZHEp18/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/JAq74TEPiM_Wi9MdAxNatZHEp18/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/JAq74TEPiM_Wi9MdAxNatZHEp18/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/JAq74TEPiM_Wi9MdAxNatZHEp18/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/kblog-blindrenderer?a=uIMvM_FzqlI:GMBPwMiBELI:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/kblog-blindrenderer?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/kblog-blindrenderer?a=uIMvM_FzqlI:GMBPwMiBELI:63t7Ie-LG7Y"&gt;&lt;img src="http://feeds.feedburner.com/~ff/kblog-blindrenderer?d=63t7Ie-LG7Y" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/kblog-blindrenderer?a=uIMvM_FzqlI:GMBPwMiBELI:4cEx4HpKnUU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/kblog-blindrenderer?i=uIMvM_FzqlI:GMBPwMiBELI:4cEx4HpKnUU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/kblog-blindrenderer?a=uIMvM_FzqlI:GMBPwMiBELI:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/kblog-blindrenderer?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/kblog-blindrenderer/~4/uIMvM_FzqlI" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://kblog.popekim.com/feeds/6490721131379947867/comments/default" title="댓글" /><link rel="replies" type="text/html" href="http://kblog.popekim.com/2012/02/topology.html#comment-form" title="8개의 덧글" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/5281384917275132568/posts/default/6490721131379947867?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/5281384917275132568/posts/default/6490721131379947867?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/kblog-blindrenderer/~3/uIMvM_FzqlI/topology.html" title="유니티에서 topology가 같은 캐릭터간에 애니메이션 공유하기..." /><author><name>Pope</name><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="33" height="30" src="http://2.bp.blogspot.com/_BBDmHdyx8wo/SfTUvbwSs-I/AAAAAAAAAYk/P1yurbiaKZM/S220/650px-Triskele-hollow-triangle.svg.png" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://2.bp.blogspot.com/-mBOZNyARPrU/TzAnKMXEGfI/AAAAAAAAA0U/HI9rrxk1PQY/s72-c/sharing_anim.jpg" height="72" width="72" /><thr:total>8</thr:total><feedburner:origLink>http://kblog.popekim.com/2012/02/topology.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DEQGQXg8fSp7ImA9WhRbEUo.&quot;"><id>tag:blogger.com,1999:blog-5281384917275132568.post-2162983937964453706</id><published>2012-02-02T18:52:00.000+09:00</published><updated>2012-02-02T18:52:00.675+09:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2012-02-02T18:52:00.675+09:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Photoshop" /><category scheme="http://www.blogger.com/atom/ns#" term="개발" /><title>포토샵 CS3가 실행중이면 ESC 키가 작동하지 않는 버그 고치기</title><content type="html">&lt;br /&gt;
포토샵 CS3를 열어두면 윈도우 전역적으로 ESC 키가 먹히지 않는 문제가 있었다. 한마디로 짜증이었던 게지 -_-;;; CS5는 이 문제를 고쳤던데... CS5로 업그레이드 해달라고 회사에 부탁해도 현재 프로젝트에서 쓰는 버전이 CS3이니 그럴수 없단다...&lt;br /&gt;
&lt;br /&gt;
뭐 그래서 그냥 몇년 이렇게 쓰다가 더이상 못참아서....드디어 오늘 이걸 고쳐버렸다.. 생각보다 해결책은 간단했음... 작업 관리자를 열어서 ccc.exe라고 된 프로세스를 그냥 죽여버리면 된다. (ATI 그래픽 카드 컨트롤 패널이니 사실 별 필요도 없음..) &amp;nbsp;이제 CS3를 다시 열면... ESC 키가 제대로 작동함....&lt;br /&gt;
&lt;br /&gt;
그리고 위도우즈 키 + 실행을 눌러 시작 프로그램에서 CCC를 제거했다. 이제 CCC를 쓸 일이 있으면 그냥 손수 실행해주면 되겠지... 뭐 어차피 1년에 한 번 열어볼까 말까한 놈이니 별 문제 없을듯....&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br class="Apple-interchange-newline" /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5281384917275132568-2162983937964453706?l=kblog.popekim.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/6NaG8Kxzz8mF33oCrjgeCHWNEgo/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/6NaG8Kxzz8mF33oCrjgeCHWNEgo/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/6NaG8Kxzz8mF33oCrjgeCHWNEgo/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/6NaG8Kxzz8mF33oCrjgeCHWNEgo/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/kblog-blindrenderer?a=E5p0qPa50AY:BJXS9cVwSHs:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/kblog-blindrenderer?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/kblog-blindrenderer?a=E5p0qPa50AY:BJXS9cVwSHs:63t7Ie-LG7Y"&gt;&lt;img src="http://feeds.feedburner.com/~ff/kblog-blindrenderer?d=63t7Ie-LG7Y" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/kblog-blindrenderer?a=E5p0qPa50AY:BJXS9cVwSHs:4cEx4HpKnUU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/kblog-blindrenderer?i=E5p0qPa50AY:BJXS9cVwSHs:4cEx4HpKnUU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/kblog-blindrenderer?a=E5p0qPa50AY:BJXS9cVwSHs:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/kblog-blindrenderer?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/kblog-blindrenderer/~4/E5p0qPa50AY" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://kblog.popekim.com/feeds/2162983937964453706/comments/default" title="댓글" /><link rel="replies" type="text/html" href="http://kblog.popekim.com/2012/02/cs3-esc.html#comment-form" title="2개의 덧글" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/5281384917275132568/posts/default/2162983937964453706?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/5281384917275132568/posts/default/2162983937964453706?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/kblog-blindrenderer/~3/E5p0qPa50AY/cs3-esc.html" title="포토샵 CS3가 실행중이면 ESC 키가 작동하지 않는 버그 고치기" /><author><name>Pope</name><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="33" height="30" src="http://2.bp.blogspot.com/_BBDmHdyx8wo/SfTUvbwSs-I/AAAAAAAAAYk/P1yurbiaKZM/S220/650px-Triskele-hollow-triangle.svg.png" /></author><thr:total>2</thr:total><feedburner:origLink>http://kblog.popekim.com/2012/02/cs3-esc.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DEUEQHs9cSp7ImA9WhRbEEg.&quot;"><id>tag:blogger.com,1999:blog-5281384917275132568.post-8138557047840432165</id><published>2012-02-01T09:30:00.000+09:00</published><updated>2012-02-01T09:30:01.569+09:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2012-02-01T09:30:01.569+09:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Shader" /><category scheme="http://www.blogger.com/atom/ns#" term="Lighting" /><category scheme="http://www.blogger.com/atom/ns#" term="Graphics" /><category scheme="http://www.blogger.com/atom/ns#" term="개발일지" /><category scheme="http://www.blogger.com/atom/ns#" term="개발" /><title>새로운 기법 != 새 장난감</title><content type="html">게임데브포에버에 무슨 글을 올릴까 고민을 좀 해봤는데... 그래픽 전문자료들은 이미 다른 필자분들이 열심히 올리고 계셔서 요번에는 그냥 제 경험담을 올리도록 하지요.. (이런 글을 원하시는 분들도 꽤 계실듯...?)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
제가 이리도 오래 쉰내나도록(?) 게임 업계에 머무르는 이유 중 하나가 언제나 새로운 것들을 시도해 볼 기회가 충분하기 때문입니다. 특히나 그래픽 프로그래밍 쪽은 하루가 멀다하고 계속 발전하는 분야라서 마약처럼 매우 짜릿하죠. (마약이라고 좀 언급해두면 한국 정부에서 게임개발 셧다운제를 해주지 않을까하는 생각에...그럼 한국 게임개발자 분들도 정시퇴근 하실 수 있습니다. 회사 매출이 높으면 일찍 퇴근!)&lt;br /&gt;
&lt;br /&gt;
근데 가끔은 이런 짜릿함에 눈이 멀어 게임을 망치는 경우도 좀 있습니다. 아직 검증되지 않은 새로운 기법을 동원할 때 그에 부수하는 단점들을 간과하는 경우가 허다하거든요. 심지어는 그런 단점들이 이미 잘 알려져 있더라도 장점보다 단점을 더 크다고 착각하는 경우도 문제입니다. (보통 이미 그 기법을 사용해서 게임을 출시한 개발자들이 하는 이야길 듣는게 검증인데.... 그&amp;nbsp;개발자들이 컨퍼런스에서 발표를 할 때는 당연히 단점보단 장점을 부각시키는게 일반적이라지요.)&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;&lt;span style="font-size: x-large;"&gt;디퍼드 라이팅&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;
제가 요번에 적어드릴 경험담은 디퍼드(deferred) 렌더링에 대해서 입니다. 이미 아시는 분들은 아시겠지만 &lt;a href="http://kblog.popekim.com/2011/11/blog-post.html"&gt;&lt;b&gt;스페이스마린은 자체 개발한 디퍼드 라이팅(deferred lighting) 엔진을 씁니다&lt;/b&gt;&lt;/a&gt;. 뭐 찾아보면 좀 더 있겠지만 제가 당장 생각하는 퍼드 라이팅 렌더러의 장단점은 다음과 같습니다. (제가 생각하는 중요도 순서로...)&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;장점:&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;div&gt;
&lt;ol&gt;
&lt;li&gt;포워드(forward) 렌더링에 비해 사용할 수 있는 광원의 수가 많다. (예, '물체당 광원 3개' 라는 제한이 없어짐)&lt;/li&gt;
&lt;li&gt;대부분의 조명을 동적으로 처리함으로 아티스트들의 작업시간이 빨라진다.
&lt;/li&gt;
&lt;li&gt;화면공간에서 행하는 후처리(post-processing) 기법들을 사용하기 쉽다. (예, SSAO, Screen Space Decal 등)&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
&lt;b&gt;단점:&lt;/b&gt;&lt;/div&gt;
&lt;div&gt;
&lt;ol&gt;
&lt;li&gt;(반)투명한 물체 처리가 골아프다.
&lt;/li&gt;
&lt;li&gt;하드웨어 자체적으로 앤티에일리어싱(anti-aliansing)을 처리하기 힘들다.
&lt;/li&gt;
&lt;li&gt;메모리를 좀 더 많이 잡아먹는다. (화면 해상도 크기의 렌더타겟들이 여러 개 필요)&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
&lt;b&gt;&lt;span style="font-size: x-large;"&gt;스페이스 마린에서 디퍼드를 사용한 이유&lt;/span&gt;&lt;/b&gt;&lt;/div&gt;
&lt;div&gt;
&lt;b&gt;&lt;br /&gt;&lt;/b&gt;&lt;/div&gt;
&lt;div&gt;
&lt;b&gt;&lt;span style="font-size: large;"&gt;원래 시작은...&lt;/span&gt;&lt;/b&gt;&lt;/div&gt;
&lt;div&gt;
스페이스 마린에서 디퍼드 렌더링을 사용한 이유는 사실 역사적인 이유가 강합니다. 스페이스 마린을 만들기 전에 Grand Theft Auto 류의 오픈월드 게임을 제작하고 있었는데 이 때 (2008년 중순) 다음과 같이 디퍼드 라이팅 엔진을 판단했었습니다.&lt;/div&gt;
&lt;div&gt;
&lt;ul&gt;
&lt;li&gt;오픈월드 게임이니 광원의 수가 꽤 많겠군? 디퍼드가 좋겠어. (장점 #1)&lt;/li&gt;
&lt;li&gt;아무래도 밤낮이 바뀌는 효과가 있어야 하니 동적 조명이 좋겠는걸? (장점 #2)&lt;/li&gt;
&lt;li&gt;근데 배경이 도시니까 투명한 물체가 꽤 필요하겠는데? (단점 #1).... 으음... 뭐 투명한 물체는 디퍼드 말고 따로 포워드로 그려줘야겠군.. (&lt;strike&gt;어쩔수 없는&lt;/strike&gt;그럴듯한 해결책)&lt;/li&gt;
&lt;li&gt;근데 앤티에일리어싱은 어쩌지? (단점 #2) 아직 1~2년 남았으니 나중에 고민해보지 뭐...(대충 책임 회피 -_-)&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;
근데 이 게임이 한 6개월 만에 취소됩니다. 게임 자체에 문제는 아니었고 THQ가 구조 조정을 하면서 그 당시 스페이스 마린 게임을 개발중이던 THQ 호주 스튜디오를 문을 닫았죠. 워낙 렐릭이 워햄머 40,000 게임을 잘 만드는 회사로 유명했던지라 저희쪽에서 대신 해달라고....&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
그래서 처음부터 다시 스페이스마린을 만들었습니다. -_- (THQ 호주에서 만들어 놨던건 하나도 안썼죠.. 저희가 원하는 방향과 너무나 달라서...)&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style="font-size: large;"&gt;&lt;b&gt;그리고 다시 결정을 내리기엔...&lt;/b&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
자, 그럼 이번엔 스페이스마린을 만들기로 했으니 다시 한 번 렌더링 엔진에 대해 고민해볼 차례인데... 이 때 (2009년) 저희의 생각은 이랬습니다.&lt;/div&gt;
&lt;div&gt;
&lt;ul&gt;
&lt;li&gt;과연 광원의 수가 많을까? (장점 #1이 시들해짐)&lt;/li&gt;
&lt;li&gt;밤낮이 바뀌는 효과도 없는데? (장점 #2도 시들해짐)&lt;/li&gt;
&lt;li&gt;그런데... 아티스트들이 이미 디퍼드 라이팅에 맛을 들여서(iteration 시간이 매우 빨라졌어요... 모든게 동적 조명이니) 매우 원함... (장점 #2가 다시 살아남)&lt;/li&gt;
&lt;li&gt;또한 디퍼드에 기반해서 구현한 Screen Space Decal을 역시 아티스트들이 너무 좋아함 (장점 #3)&lt;/li&gt;
&lt;li&gt;서기 40,000년엔 투명한 유리창 따윈 이미 다 뽀개지고 없으니.. 투명한 물체는 그닥 문제가 안될 거야.. (단점 #1이 좀 완화됨)&lt;/li&gt;
&lt;li&gt;근데 앤티에일리어싱은 어쩌지? (단점 #2)요즘들어 이 분야에 대한 좀 발전이 있으니(Kill Zone 2가 SSAA를 대충 사용할 때..) 좀더 기다려보지.. (여전히 책임 회피... -_-)&lt;/li&gt;
&lt;li&gt;그럼 딱히 디퍼드를 할 이유가 없지 않아?..... 응... 없지.... 근데 이미 만들어 놓은거 다시 포워드로 돌리는 데 드는 시간과 비용이 과연 값어치가 있을까?......... 없군......&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;
그래서 결국 디퍼드로 그냥 가기로 했죠. 최소한 아티스트들이 작업을 빨리할 수 있으니까 비주얼 품질이 높아질거라 생각했거든요. 그리고 그건 현실이 되었죠. 아티스트들이 여러번 손 대니까 확실히 스페이스마린의 비주얼 퀄리티도 상승.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="http://4.bp.blogspot.com/-CsiTfQ43HOc/TyWkuImLF1I/AAAAAAAAAz8/OZuu0jidUJA/s1600/spacemarine_bigbang.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="400" src="http://4.bp.blogspot.com/-CsiTfQ43HOc/TyWkuImLF1I/AAAAAAAAAz8/OZuu0jidUJA/s640/spacemarine_bigbang.jpg" width="640" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="http://3.bp.blogspot.com/-eKybOuI1vEI/TyWk-8ge0uI/AAAAAAAAA0E/KSmzRR2eo4o/s1600/freefall.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="360" src="http://3.bp.blogspot.com/-eKybOuI1vEI/TyWk-8ge0uI/AAAAAAAAA0E/KSmzRR2eo4o/s640/freefall.jpg" width="640" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style="font-size: large;"&gt;&lt;b&gt;그래서 단점은 어케 극복을?&lt;/b&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
그리고 시간은 흐르고 흘러서 2011년 9월 스페이스 마린을 출시했죠. 그렇다면 저 단점들은 어떻게 극복 했을까요?&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
&lt;b&gt;투명한 물체&lt;/b&gt;&lt;/div&gt;
&lt;div&gt;
"서기 4만년엔 모든 유리들이 뽀작나서 더이상 투명한 물체가 없습니다 -_-;" 는 저희가 장난처럼 한 말이었는데... 사실 저희 게임에서 투명한 물체가 거의 없습니다. 종류따라 다음과 같이 처리했어요.&lt;/div&gt;
&lt;div&gt;
&lt;ol&gt;
&lt;li&gt;&lt;b&gt;알파테스트:&lt;/b&gt; 반투명 블렌딩을 하기 보다 대부분의 물체는 완전투명 아니면 완전 안투명의 두가지로 처리했습니다. 이러면 디퍼드를 사용할 수 있죠.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Screen Space Decal(SSD):&lt;/b&gt; 다른 물체의 표면에 찰싹 붙은 반투명한 물체는 SSD로 처리했습니다. &lt;a href="http://kblog.popekim.com/2011/11/blog-post.html"&gt;&lt;b&gt;SSD에 대한 자세한 내용은 위에 링크 걸어드린 발표자료를 참조하시길&lt;/b&gt;&lt;/a&gt;. 역시 깊이버퍼를 업데이트할 필요가 없는 놈들이라 디퍼드에 무난히 사용가능&lt;/li&gt;
&lt;li&gt;&lt;b&gt;특수 쉐이더:&lt;/b&gt; 머리카락에만 쓴 쉐이더인데 딱히 깊이 버퍼를 업데이트 하지 않고 머리통에 있는 법선 조명 정보를 대충 가져다가 씁니다. 즉 디퍼드도 포워드도 아닌 이상한 꼼수를 썼죠.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;파티클:&lt;/b&gt; 파티클은 여전히 포워드로 했습니다. 워낙 투명하니... 저희 파티클 시스템은 또 워낙 빨라놔서.. (파티클 질을 저렇게 해도 콘솔에서 2.75 ms 밖에 안걸림)&lt;/li&gt;
&lt;/ol&gt;
&lt;div&gt;
이래서 투명한 물체는 해결... 사실 이걸 해결할 수 있던 가장 큰 원인은 아티스트들의 워크플로우를 뚜렷하게 정했다는 거에요. 뭐는 안되고 뭐는 되고를 확실히 알려줬고.. 안되는게 있으면 그걸 성취할 수 있는 다른 방법을 제시했고요.&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
&lt;b&gt;앤티에일리어싱&lt;/b&gt;&lt;/div&gt;
&lt;div&gt;
그럼 앤티에일리어싱은 어떻게 해결을 했을까요? 사실 운이 좋았죠... -_-&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
다행히도 게임을 출시할 때쯤 해서 MLAA(God of War 3, The Saboteur)와 FXAA라는 기법들이 이미 개발되었었고... 저희도 FXAA에서 영감을 받아서 그것보다 한 0.1ms 정도 빠른 자체 기법을 개발했습니다. 한 0.8ms 걸렸죠. FXAA라고 해봐야 화면의 색상(또는 조도)을 대충 분석해서 갑자기 픽셀값이 변하는 부분을 적당히 블렌딩 해주는 기법이거든요.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
콘솔에서 사용하는 FXAA 기법은 사실 좀 화면에 흐릿해진다는 단점이 있습니다. (PC버전과 달라요) 그래도 스페이스 마린의 비주얼은 만화스럽기보단 사실적에 좀 더 가까워서... 약간 흐릿해져도 큰 문제가 없었죠.&amp;nbsp;(만화처럼 색이 강렬하고 짜잘한 디테일들이 막 들어가있으면 이렇게 흐릿해지는게 문제가 많아요.)&amp;nbsp;그래서 운좋게 대충 무사히 해결...&amp;nbsp;&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
지금와서 생각하는데 타사의 개발자들이 이런 기법들을 개발해 놓지 않았다면, 거기에서 영감을 받지도 못했을거고... 그러면 스페이스마린은 앨리어싱 때문에 꽤 타격을 받았을 거 같아요. 그렇다고 Gears of Wars 3처럼 아예 앤티 엘리어싱을 꺼버릴수도 없는거고... 운이 좋았죠. 책임회피는 했지만 운이 좋은.... -_-v&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style="font-size: x-large;"&gt;&lt;b&gt;그렇다고 다 우리처럼 운이 좋을리는 없지?&lt;/b&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="http://4.bp.blogspot.com/-EJUL0V3MoYk/TyWpBRjP9zI/AAAAAAAAA0M/BdFoir13rFA/s1600/funny-pictures-cat-calls-you-a-punk.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://4.bp.blogspot.com/-EJUL0V3MoYk/TyWpBRjP9zI/AAAAAAAAA0M/BdFoir13rFA/s1600/funny-pictures-cat-calls-you-a-punk.jpg" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
그리고 스페이스마린을 출시한 뒤, 다른 회사의 게임을 좀 도와줬습니다. 몇 년전에 출시했던 게임의 후속작인데요. 따라서 그래픽 쪽으로는 특별히 손봐줄게 없겠다고 생각했죠. 어차피 컨텐츠만 좀 바꾸면 되니까. 그래픽 쪽은 좀 빠르게 만들어주거나 눈사탕 몇 개만 슬쩍 추가...?&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
근데 ... &lt;b&gt;&lt;i&gt;아.뿔.사&lt;/i&gt;&lt;/b&gt;... -_- 소스코드를 열어보니... 포워드로 잘돌던 그래픽 엔진을 디퍼드로 바꿔버렸더군요..... 과연 왜 그랬는지 마땅히 말해주는 개발자들이 없어서.. 혼자 장단점을 따져봤습니다.&lt;/div&gt;
&lt;div&gt;
&lt;ul&gt;
&lt;li&gt;광원의 수가 전 게임에 비해 늘었니? 아니... 거의 똑같은데... (장점 #1 실패 -_-)&lt;/li&gt;
&lt;li&gt;그럼 아티스트들의 작업시간은? 그림자를 오프라인에서 baking 하지 않으니 빨라짐... (장점 #2).... 근데 그림자 품질이 오프라인 처리할 때보다 저하되서 다시 baking을 시작하고 있음.. (결국 장점 #2 실패 -_-)&lt;/li&gt;
&lt;li&gt;화면공간에서 하는 후처리 기법은? 저번 게임하고 그닥 달라진게 없음... SSAO 정도 추가했나? (미약한 장점 #3)&lt;/li&gt;
&lt;li&gt;반투명한 물체는? 화면의 절반... -_- 여전히 포워드로 처리함... 한 10 ms 걸림... 쿨럭 -_- (심각한 단점 #1)&lt;/li&gt;
&lt;li&gt;앤티에일리어싱은? 아직 구현 안했었음... &amp;nbsp;스페이스마린에서 사용한 AA를 구현해줬으니 게임자체의 색상이 화려한 편이라 흐릿함이 눈에 거슬림.... 이걸 제대로 고치려면 PC버전에서 쓰는 FXAA를 써서 3ms낭비하거나... 아니면 깊이 및 법선 비교까지 해야함. 이러면 2.6 ms 정도 걸림.... (단점 #2)&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
아무리 생각해도 디퍼드로 갈 이유가 없는 게임이더군요. 아직도 정확한 이유는 모릅니다. 왜 디퍼드로 가기로 결정했는지.... '이론상으로' 포워드보다 낫다고 생각했고... 새로운 기법에 대한 짜릿함 때문에 그렇게 결정해버린 게 아닌지.. 생각만 할뿐..... 처음 게임이 더 비주얼이 좋을 거 같아요......버럭!&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style="font-size: x-large;"&gt;&lt;b&gt;대충 정리&lt;/b&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
글만 주저리주저리 길게 쓰는 놈이라.. 대충 이 일화의 교훈(?)을 정리.&lt;/div&gt;
&lt;div&gt;
&lt;ol&gt;
&lt;li&gt;새로운 기법을 도입하기 전에는 반드시 장/단점을 반드시 따져볼 것. 특히 단점을 위주로...&lt;/li&gt;
&lt;li&gt;그 기법을 이용해서 게임을 출시한 사람들이 발표하는 장/단점은 언제나 장점에 치우쳐 있음. 단점의 심각함을 2배로 곱해서 생각할 것...&lt;/li&gt;
&lt;li&gt;그 기법을 이용해 컨텐츠를 제작할 아티스트 및 디자이너들을 프로토타입 과정에 포함시킬 것. 그 개발자들의 피드백이 좋지 않으면 그 보다 큰 단점이 없음.&lt;/li&gt;
&lt;li&gt;measure, measure and measure!: 언제나 실제로 성능을 측정해볼 것....&lt;/li&gt;
&lt;/ol&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5281384917275132568-8138557047840432165?l=kblog.popekim.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/hdgDGZucXo3rH4EZoahKJH1byEw/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/hdgDGZucXo3rH4EZoahKJH1byEw/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/hdgDGZucXo3rH4EZoahKJH1byEw/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/hdgDGZucXo3rH4EZoahKJH1byEw/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/kblog-blindrenderer?a=H7UPYAZNyxI:lHhyGVtQU1s:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/kblog-blindrenderer?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/kblog-blindrenderer?a=H7UPYAZNyxI:lHhyGVtQU1s:63t7Ie-LG7Y"&gt;&lt;img src="http://feeds.feedburner.com/~ff/kblog-blindrenderer?d=63t7Ie-LG7Y" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/kblog-blindrenderer?a=H7UPYAZNyxI:lHhyGVtQU1s:4cEx4HpKnUU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/kblog-blindrenderer?i=H7UPYAZNyxI:lHhyGVtQU1s:4cEx4HpKnUU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/kblog-blindrenderer?a=H7UPYAZNyxI:lHhyGVtQU1s:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/kblog-blindrenderer?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/kblog-blindrenderer/~4/H7UPYAZNyxI" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://kblog.popekim.com/feeds/8138557047840432165/comments/default" title="댓글" /><link rel="replies" type="text/html" href="http://kblog.popekim.com/2012/02/blog-post.html#comment-form" title="2개의 덧글" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/5281384917275132568/posts/default/8138557047840432165?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/5281384917275132568/posts/default/8138557047840432165?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/kblog-blindrenderer/~3/H7UPYAZNyxI/blog-post.html" title="새로운 기법 != 새 장난감" /><author><name>Pope</name><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="33" height="30" src="http://2.bp.blogspot.com/_BBDmHdyx8wo/SfTUvbwSs-I/AAAAAAAAAYk/P1yurbiaKZM/S220/650px-Triskele-hollow-triangle.svg.png" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://4.bp.blogspot.com/-CsiTfQ43HOc/TyWkuImLF1I/AAAAAAAAAz8/OZuu0jidUJA/s72-c/spacemarine_bigbang.jpg" height="72" width="72" /><thr:total>2</thr:total><feedburner:origLink>http://kblog.popekim.com/2012/02/blog-post.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CUINSX87eyp7ImA9WhRUGEU.&quot;"><id>tag:blogger.com,1999:blog-5281384917275132568.post-8682144682847036279</id><published>2012-01-30T09:30:00.000+09:00</published><updated>2012-01-30T09:33:18.103+09:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2012-01-30T09:33:18.103+09:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Shader" /><category scheme="http://www.blogger.com/atom/ns#" term="도서" /><category scheme="http://www.blogger.com/atom/ns#" term="Graphics" /><category scheme="http://www.blogger.com/atom/ns#" term="Toon" /><category scheme="http://www.blogger.com/atom/ns#" term="포프의 쉐이더 입문강좌" /><category scheme="http://www.blogger.com/atom/ns#" term="DirectX" /><category scheme="http://www.blogger.com/atom/ns#" term="개발" /><title>[포프의 쉐이더 입문강좌] 06. 만화같은 명암을 입히는 툰쉐이더</title><content type="html">&lt;b&gt;&lt;a href="http://kblog.popekim.com/2012/01/05-part-2.html"&gt;이전편 보기&lt;/a&gt;&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;&lt;a href="http://vsts2010.net/attachment/cfile7.uf@1207F23A4F18B1271B1162.zip"&gt;샘플파일 받기&lt;/a&gt;&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;&lt;span style="font-size: x-large;"&gt;제6장 만화 같은 명암을 입히는 툰쉐이더&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;이 장에서 새로 배우는 HLSL&lt;/b&gt;&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;ceil() - 무조건 올림 함수&lt;/li&gt;
&lt;/ul&gt;
&lt;br /&gt;
&lt;b&gt;이 장에서 새로 사용하는 수학&lt;/b&gt;&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;행렬합치기 - 여러 개의 행렬을 미리 곱해놓은 뒤, 그 결과를 정점변환에 사용해도 결과는 동일함. 단, 속도는 더 빠름.&lt;/li&gt;
&lt;li&gt;역행렬 - 반대 방향으로 공간변환을 할 때 유용.&lt;/li&gt;
&lt;/ul&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-size: x-large;"&gt;&lt;b&gt;배경&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
얼마 전에 저희 회사의 아트 디렉터가 했던 말이 있습니다. 프로그래머는 언제나 사실적인 3D 그래픽을 추구하지만, 게이머들의 보통 미적 스타일을 최대로 살린 비사실적인 그래픽에 열광한다고요. 생각해보니 &amp;nbsp;맞는 말이더군요. 프로그래머들은 언제나 수학적으로 옳은 것을 추구하려고 하지만 언제나 미적 스타일을 갖춘 게임들이 흥행을 하니까요. 스트리트 파이터 4, 팀포트리스 2, 보더랜드 등이 그 좋은 예겠죠?&lt;br /&gt;
&lt;br /&gt;
그 동안 현대 3D 그래픽의 주 초점도 사실적인 그래픽을 재현해 내는 것이었습니다. 하지만 그 와중에도 미적인 효과를 살리기 위한 비사실적 렌더링 기법들도 간간이 등장했는데요 여기서 살펴볼 툰쉐이딩(toon shading, &lt;span style="font-size: x-small;"&gt;셀 쉐이딩(cell shading)이라고도 합니다&lt;/span&gt;) 도 그 중 하나입니다. 툰(toon)이라 하면 만화(cartoon)를 뜻합니다. 만화를 보면 명암처리를 부드럽게 하는 대신에 칼같이 딱딱 끊어서 2~3 단계로 하죠? 뭐, 만화를 안보신 분들은 없을 듯 하니 다 아시겠네요. ^^ 여기서 구현할 쉐이더가 바로 그런 일을 할 겁니다. 일단 결과를 미리 사진으로 보여드리면 대충 감이 오시겠네요.&lt;br /&gt;
&lt;br /&gt;
&lt;table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style="text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/-XoVyaMxF0GY/TxiswcLfhOI/AAAAAAAAAzM/kpki_ZkLVsg/s1600/fig_06_01.jpg" imageanchor="1" style="margin-left: auto; margin-right: auto;"&gt;&lt;img border="0" height="600" src="http://1.bp.blogspot.com/-XoVyaMxF0GY/TxiswcLfhOI/AAAAAAAAAzM/kpki_ZkLVsg/s640/fig_06_01.jpg" width="640" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="tr-caption" style="text-align: center;"&gt;&lt;b&gt;그림. 6.1. 이장에서 만들어 볼 툰쉐이더&lt;/b&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;br /&gt;
위의 사진을 잘 관찰해 봅시다. 여태까지 사용했던 평범한(?) 난반사광 쉐이더와 뭐가 다르죠? 난반사광이 부드럽게 어두워지는 대신 단계적으로 팍팍 줄어든다는 거죠? 마치 계단을 걸어 내려가는 것처럼요. 그렇다면 이것을 그래프로 그려보면 어떨까요? 일반적인 난반사광의 그래프와 비교해서 보면 좀 더 이해가 쉽겠네요.&lt;br /&gt;
&lt;br /&gt;
&lt;table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style="text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/-h77xcObC9SU/Txis6HjVnHI/AAAAAAAAAzU/hjru4-ELD34/s1600/fig_06_02.jpg" imageanchor="1" style="margin-left: auto; margin-right: auto;"&gt;&lt;img border="0" height="334" src="http://3.bp.blogspot.com/-h77xcObC9SU/Txis6HjVnHI/AAAAAAAAAzU/hjru4-ELD34/s640/fig_06_02.jpg" width="640" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="tr-caption" style="text-align: center;"&gt;&lt;b&gt;그림 6.2 &amp;nbsp;일반 난반사광 그래프와 툰쉐이딩 그래프&lt;/b&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;br /&gt;
&lt;br /&gt;
위 그래프를 보니 감이 팍팍 오지 않나요? 아니라고요? 으음... 그럼 위 그래프를 표로 간단하게 정리해 보겠습니다..&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;table align="center" border="1" cellspacing="0" style="text-align: left; width: 500px;"&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;난반사광의 양&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;&lt;b&gt;툰쉐이더 값&lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;0 ~ 0.2&lt;/td&gt;
&lt;td&gt;0.2&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;0.2 ~ 0.4&lt;/td&gt;
&lt;td&gt;0.4&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;0.4 ~ 0.6&lt;/td&gt;
&lt;td&gt;0.6&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;0.6 ~ 0.8&lt;/td&gt;
&lt;td&gt;0.8&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;0.8 ~ 1&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;div style="text-align: center;"&gt;
&lt;b&gt;표 6.1 난반사광의 양과 툰쉐이더 값의 비교&lt;/b&gt;&lt;/div&gt;
&lt;br /&gt;
이렇게 비교를 하니 정말 쉽네요. 난반사광의 값을 가져다가 0.2단위로 무조건 올림을 하면 툰쉐이더 값이 나오는군요? 그럼 이 정도만 알면 툰쉐이더를 만드는 건 식은 죽 먹기일 듯 합니다. 곧바로 렌더몽키로 가 볼까요?&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-size: x-large;"&gt;&lt;b&gt;기초설정&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
렌더몽키를 실행한 뒤, DirectX 이펙트를 추가합니다. 새로 생긴 이펙트의 이름을 Default_DirectX_Effect에서 ToonShader로 바꿉니다. matViewProjection이란 행렬이 정의되어 있는 것도 보이시죠? 삭제해 주세요.&lt;br /&gt;
&lt;br /&gt;
그림 6.1에서 주전자 모델을 보여드렸었죠? 주전자는 3D 그래픽 논문에서 즐겨 사용하는 모델 중에 하나입니다. 이리저리 다양한 굴곡이 많아서 쉐이더의 결과를 딱 한눈에 살펴보기 좋다나요? 저희도 주전자 모델을 사용하겠습니다. 렌더몽키의 작업공간 패널에서 Model을 찾으세요. 이 위에 마우스 오른쪽 버튼을 누른 뒤, Change Model &amp;gt; Teapot.3ds를 선택합니다.&lt;br /&gt;
&lt;br /&gt;
툰쉐이딩을 하려면 일단 난반사광을 계산해야겠죠? 그래야 그 결과를 0.2 단위로 올림할 수 있으니까요. 그렇다면 '제4장: 기초적인 조명쉐이더'에서 그랬던 것처럼 빛의 위치와 정점의 법선정보가 필요하겠군요. 우선 빛의 위치를 변수로 선언하겠습니다. ToonShader에 오른쪽 마우스 버튼을 누른 뒤, Add Variable &amp;gt; Float &amp;gt; Float4를 선택하고, 변수의 이름을 gWorldLightPosition으로 바꿉니다. 이 변수의 값은 예전과 마찬가지로 (500, 500, -500, 1)으로 맞춰주세요. 다음은 정점에서 법선정보를 읽어올 차례입니다. Stream Mapping을 더블클릭해서 NORMAL 필드를 추가하면 되겠죠? 데이터형은 &amp;nbsp;FLOAT3, Index는 0으로 해주는 것도 잊지 마세요.&lt;br /&gt;
&lt;br /&gt;
그림 6.1을 다시 한번 봐 보죠. 주전자가 녹색이죠? 주전자의 색을 지정해주는 방법은 여러 가지가 있지만 여기서는 전역변수 하나로 전체 표면의 색을 지정해 주겠습니다. &lt;span style="font-size: x-small;"&gt;(만약 한 표면 위에서 여러 가지 색상을 사용하시고 싶으시다면 3DS MAX에서 메쉬를 만드실 때, 정점색상(vertex color)를 칠하셔도 됩니다. 그리고 정점쉐이더 입력데이터에서 COLOR0이나 COLOR1 시맨틱을 사용하시면 이 정점정보를 읽어올 수 있습니다.)&lt;/span&gt; ToonShader에 마우스 오른쪽 버튼을 누른 뒤, Add Variable &amp;gt; Float &amp;gt; Float3를 선택합니다. 새로 변수가 생기면 이름을 gSurfaceColor로 바꿉니다. 이제 이 변수 위에 마우스를 더블클릭하여 값을 (0, 1, 0)으로 변경합니다. 쉐이더에서 색상을 0~1 사이의 백분율 값으로 표현한다는 거 잊지 않으셨죠?&lt;br /&gt;
&lt;br /&gt;
이제 행렬들을 좀 추가해 주겠습니다. 여태까지 다뤘던 쉐이더 기법에서는 기초설정을 할 때마다 월드행렬, 뷰행렬, 투영행렬을 따로 정의해 줬었죠? 여기서는 조금 다른 방법을 사용하도록 하죠. 3D 그래픽에서 공간변환을 할 때, 행렬을 사용하는 이유 중 하나가 여러 행렬들을 미리 합쳐놓으면(concatenation) 불필요한 연산을 줄일 수 있기 때문입니다. 예를 들면, 정점의 위치를 공간변환 할 때 월드행렬, 뷰행렬, 투영행렬을 차례대로 곱해줘야 하죠? 이러지 말고 미리 월드행렬, 뷰행렬, 투영행렬을 곱해서 새로운 행렬을 하나 구해 놓은 뒤, 그 행렬을 정점에 곱해도 결과는 동일합니다. 그러나 성능상으로 보면 행렬을 3번 곱하는 것보다 1번 곱하는 게 당연히 빠를 테니 행렬을 미리 합치는 방법이 더 낫지요.&lt;br /&gt;
&lt;br /&gt;
여기서도 미리 행렬을 합치겠습니다. 그럼 그 결과 행렬을 건네 받을 전역변수를 하나 추해야겠죠? ToonShader에 오른쪽 마우스 버튼을 눌러 Add Variable &amp;gt; Matrix &amp;gt; Float(4x4)를 선택한 뒤, 변수명을 gWorldViewProjectionMatrix로 바꿉니다. 이제 이 변수 위에 마우스 오른쪽 버튼을 눌러 Variable Semantic &amp;gt; WorldViewProjection을 선택합니다.&lt;br /&gt;
&lt;br /&gt;
자, 그럼 이렇게 행렬을 한 번만 곱하는 건 좋은데 난반사광을 계산하려면 월드행렬이 필요했던 것 같은데요? 빛의 위치가 월드공간에 정의되어 있으니까 빛의 방향벡터를 만들려면 월드공간에서의 정점위치가 필요했었네요. 그럼 당연히 월드행렬을 곱해야겠죠. 그리고 난반사광을 구하려면 역시 월드공간에서의 정점법선도 필요했었으니 역시 월드행렬이 필요하군요. 그렇다면 월드행렬을 전역변수로 전달해줘서 이렇게 행렬곱을 두 번 더 해줘야 할까요? 뭐 그러셔도 상관 없습니다. 틀린 방법은 아니거든요. 하지만 조금만 생각을 더 해보면 행렬곱 1번만으로 똑같은 일을 할 수 있습니다.&lt;br /&gt;
&lt;br /&gt;
정점의 위치와 법선을 월드공간으로 변환하는 이유는 빛의 위치가 월드공간에 정의되어 있어서였습니다. 모든 변수가 동일한 공간에 있어야만 올바른 결과를 구할 수 있으니까요. 그럼 정점의 위치와 법선벡터를 월드공간으로 변환하는 대신에 빛의 위치를 지역공간으로 변환해버리면 어떨까요? 그러면 정점의 위치와 법선에 손을 대지 않아도 모든 매개변수들이 동일한 공간에 있겠죠? 이 방법은 행렬을 1번만 곱하니 아무래도 조금 더 빠르겠네요.&lt;br /&gt;
&lt;br /&gt;
그렇다면 월드공간을 물체공간으로 어떻게 변환할까요? 월드행렬의 역행렬(inverse matrix)을 곱하면 됩니다. 그럼 렌더몽키에 월드행렬의 역행렬도 추가해 보도록 하죠. ToonShader에 마우스 오른쪽 버튼을 누른 뒤, Add Variable &amp;gt; Matrix &amp;gt; Float(4x4)를 선택합니다. 이제 이 변수 이름을 gInvWorldMatrix로 바꿔 주세요. 마지막으로 변수 위에 마우스 오른쪽 버튼을 눌러 Variable Semantic &amp;gt; WorldInverse를 누르면 모든 설정이 마무리 되었습니다.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style="text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/-LJhAwJepX0I/TxiuWlO3qJI/AAAAAAAAAzc/fdMxstO7LSE/s1600/fig_06_03.jpg" imageanchor="1" style="margin-left: auto; margin-right: auto;"&gt;&lt;img border="0" src="http://4.bp.blogspot.com/-LJhAwJepX0I/TxiuWlO3qJI/AAAAAAAAAzc/fdMxstO7LSE/s1600/fig_06_03.jpg" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="tr-caption" style="text-align: center;"&gt;&lt;b&gt;그림 6.3. 기초설정을 마친 렌더몽키 프로젝트&lt;/b&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-size: x-large;"&gt;&lt;b&gt;정점쉐이더&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
일단 전체 소스코드부터 보여드린 뒤, 한 줄씩 차근차근 설명해드리겠습니다.&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;struct VS_INPUT&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;{&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; &amp;nbsp;float4 mPosition : POSITION;&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; &amp;nbsp;float3 mNormal: NORMAL; &lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;};&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;struct VS_OUTPUT&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;{&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; &amp;nbsp;float4 mPosition : POSITION;&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; &amp;nbsp;float3 mDiffuse : TEXCOORD1; &lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;};&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;float4x4 gWorldViewProjectionMatrix;&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;float4x4 gInvWorldMatrix;&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;float4 gWorldLightPosition;&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;VS_OUTPUT vs_main( VS_INPUT Input )&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;{&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; &amp;nbsp;VS_OUTPUT Output;&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; &amp;nbsp;Output.mPosition = mul( Input.mPosition, gWorldViewProjectionMatrix );&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; &lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; &amp;nbsp;float3 objectLightPosition = mul( gWorldLightPosition, gInvWorldMatrix);&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; &amp;nbsp;float3 lightDir = normalize(Input.mPosition.xyz - objectLightPosition);&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; &lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; &amp;nbsp;Output.mDiffuse = dot(-lightDir, normalize(Input.mNormal));&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; &lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; &amp;nbsp;return( Output );&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; &lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;}&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;&lt;span style="font-size: large;"&gt;정점쉐이더 입출력데이터 및 전역변수&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;
조명(난반사광)을 계산하려면 법선이 필요하죠? 따라서 정점쉐이더 입력데이터로 위치와 법선이 필요합니다. &lt;span style="font-size: x-small;"&gt;(정점마다 색을 지정해주셨다면 float3 mColor : COLOR0; 도 추가하셔야 합니다. Stream Mapping에서도 COLOR0을 더해주는 거 잊지 마세요.&lt;b&gt;)&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;struct VS_INPUT&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;{&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; &amp;nbsp;float4 mPosition : POSITION;&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; &amp;nbsp;float3 mNormal: NORMAL; &lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;};&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
정점출력데이터도 별로 어렵지 않습니다. 난반사광을 계산한 뒤, 픽셀쉐이더에 전달해 주는 게 전부입니다. &lt;span style="font-size: x-small;"&gt;(마찬가지로 정점마다 색을 지정해주셨다면 &amp;nbsp;float3 mColor: COLOR0;도 추가하셔야 합니다.)&lt;/span&gt; &amp;nbsp;이게 잘 이해가 안 되시는 분들은 '제4장: 기초적인 조명쉐이더'를 다시 한 번 읽어 주세요.&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;struct VS_OUTPUT&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;{&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; &amp;nbsp;float4 mPosition : POSITION;&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; &amp;nbsp;float3 mDiffuse : TEXCOORD1; &lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;};&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
이제 전역변수로는 위에서 설명 드렸던 행렬 2개와 광원의 위치를 선언해야겠네요.&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;float4x4 gWorldViewProjectionMatrix;&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;float4x4 gInvWorldMatrix;&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;float4 gWorldLightPosition;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
이러면 앞서 렌더몽키 프로젝트에 더했던 변수들을 다 처리한 거 같죠? 이제 정점쉐이더 함수를 보겠습니다.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;&lt;span style="font-size: large;"&gt;정점쉐이더 함수&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;
우선 정점쉐이더의 가장 중요한 임무를 수행하겠습니다. 정점의 위치를 투영공간으로 가져옵니다. 월드행렬, 뷰행렬, 투영행렬을 하나로 미리 합쳐버렸으니 코드 한 줄로 이런 일을 할 수 있겠네요.&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;VS_OUTPUT vs_main( VS_INPUT Input )&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;{&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; &amp;nbsp;VS_OUTPUT Output;&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; &amp;nbsp;Output.mPosition = mul( Input.mPosition, gWorldViewProjectionMatrix );&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
이제 난반사광의 양을 계산할 차례입니다. 앞서 말씀 드렸듯이 빛의 위치를 지역공간으로 변환한 뒤, 모든 계산을 이 공간에서 해보겠습니다. 우선 빛의 위치를 지역공간으로 변환합니다.&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; &amp;nbsp;float3 objectLightPosition = mul( gWorldLightPosition, gInvWorldMatrix);&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
이제 광원의 위치에서 현재 위치(이미 지역공간에 있습니다)를 가리키는 방향벡터를 만듭니다. 이 방향벡터의 길이를 1로 만드는 것도 잊지 말아야겠죠?&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; &amp;nbsp;float3 lightDir = normalize(Input.mPosition.xyz - objectLightPosition);&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
이제 그 결과와 정점의 법선(역시 지역공간에 존재합니다) 간의 내적을 구하면 난반사광의 양을 구할 수 있습니다.&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; &amp;nbsp;Output.mDiffuse = dot(-lightDir, normalize(Input.mNormal));&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
위에서 법선의 길이를 1로 만들기 위해 normalize()함수를 호출한 거 보이시죠? 보통 정점버퍼로부터 곧바로 가져온 법선은 이미 정규화가 되어있는 게 보통이나 혹시나 해서 normalize()를 한 번 더 호출해 봤답니다.&lt;br /&gt;
&lt;br /&gt;
이제 가볍게 Output을 반환합니다.&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp;&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt; &amp;nbsp;return( Output );&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; &lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;}&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
정점쉐이더 함수는 별로 어려운 게 없었습니다. '제4장: 기초적인 조명쉐이더'에서 다 배웠던 내용이니까요. 그냥 다른 공간을 사용했다는 게 좀 다른 내용이지만 그리 어렵지 않게 이해하시리라 믿습니다. 이제 픽셀쉐이더를 살펴보겠습니다.&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-size: x-large;"&gt;&lt;b&gt;픽셀쉐이더&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
정점쉐이더에서와 마찬가지로 전체 소스코드부터 보여드립니다.&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;float3 gSurfaceColor;&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;struct PS_INPUT&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;{&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; &amp;nbsp;float3 mDiffuse : TEXCOORD1;&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;};&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;float4 ps_main(PS_INPUT Input) : COLOR&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;{ &lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; &amp;nbsp;float3 diffuse = saturate(Input.mDiffuse);&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; &lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; &amp;nbsp;diffuse = ceil(diffuse * 5) / 5.0f;&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; &lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; &amp;nbsp;return float4( gSurfaceColor * diffuse.xyz, 1);&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; &lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;}&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
우선 전역변수와 픽셀쉐이더 입력데이터를 정의하죠. 표면의 색상을 전역변수로 선언하고 정점쉐이더에서 계산을 마친 난반사광의 양을 입력데이터로 받겠습니다.&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;float3 gSurfaceColor;&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;struct PS_INPUT&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;{&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; &amp;nbsp;float3 mDiffuse : TEXCOORD1;&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;};&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
이제 픽셀쉐이더 함수를 봅시다. 우선 mDiffuse에서 저희에게 별 의미가 없는 0 이하의 값을 잘라 냅니다.&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;float4 ps_main(PS_INPUT Input) : COLOR&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;{ &lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; &amp;nbsp;float3 diffuse = saturate(Input.mDiffuse);&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
이제 이 값을 0.2단위로 딱딱 잘라야겠네요. 0.2단위로 무조건 올림을 하면 된다고 했었죠? HLSL에서 무조건 올림을 하는 함수는 ceil()입니다. &lt;span style="font-size: x-small;"&gt;(영어로 ceiling이 '천장'이라는 뜻이니까, ceil을 &amp;nbsp;'천장으로 올리다' 정도로 생각하시면 이해에 도움이 되실 겁니다. 이 반대로 무조건 내림을 하는 함수로 floor()입니다. 이것은 '바닥으로 내리다' 정도로 이해하세요.)&lt;/span&gt; 근데 ceil() 함수는 언제나 바로 위의 정수로만 올림을 한다는군요. 저희는 0.2단위로 올림을 해야 하는데 어쩌죠? 다음과 같이 간단히 곱셈과 나눗셈을 하면 됩니다.&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; &amp;nbsp;diffuse = ceil(diffuse * 5) / 5.0f;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
위 공식(?)을 자세히 살펴보죠. diffuse가 0~1 사이의 값이니 여기에 5를 곱하면 범위가 0~5가 될 것입니다. 여기에 ceil()을 적용하면 그 결과값이 0, 1, 2, 3, 4, 5중에 하나가 되겠죠. 이제 이 값을 5로 나누면 최종 결과값이 0, 0.2, 0.4, 0.6, 0.8, 1 중에 하나가 될 겁니다. 이게 바로 저희가 원하는 값 맞죠? 그림 6.2와 표 6.1를 다시 봐도 이 값이 맞네요.&lt;br /&gt;
&lt;br /&gt;
그럼 이제 표면의 색을 곱하기만 하면 끝입니다. &lt;span style="font-size: x-small;"&gt;(빛의 색상은 흰색(1, 1, 1)이라고 가정했습니다. 어떤 수에 1을 곱해도 결과는 바뀌지 않는 거 아시죠?)&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; &amp;nbsp;return float4( gSurfaceColor * diffuse.xyz, 1);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
이제 F5를 눌러 정점쉐이더와 픽셀쉐이더를 각각 컴파일 한 뒤, 미리 보기 창을 보시면 그림 6.1와 똑같은 주전자가 보이죠? 아, 배경색이 다르다고요? 미리 보기 창 안에서 마우스 오른쪽 버튼을 누른 뒤 Clear Color를 선택하시면 배경색을 바꿀 수 있습니다.&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-size: x-large;"&gt;&lt;b&gt;선택사항: DirectX 프레임워크&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
이제 C++로 작성한 DirectX 프레임워크에서 쉐이더를 사용하시고자 하는 분들을 위한 선택적인 절입니다.&lt;br /&gt;
&lt;br /&gt;
우선 '제3장: 텍스처매핑'에서 만들었던 프레임워크의 사본을 만들어 새로운 폴더에 저장합니다. 그 다음은 렌더몽키에서 사용했던 쉐이더와 3D 모델을 DirectX 프레임워크에서 사용할 수 있도록 파일로 저장할 차례입니다.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;ol&gt;
&lt;li&gt;Workspace 패널에서 ToonShader를 찾아 오른쪽 마우스 버튼을 누릅니다.&lt;/li&gt;
&lt;li&gt;팝업메뉴에서 Export &amp;gt; FX Exporter를 선택합니다.&lt;/li&gt;
&lt;li&gt;위에서 새로 만든 폴더를 찾아 그 안에 ToonShader.fx란 이름으로 파일을 저장합니다.&lt;/li&gt;
&lt;li&gt;이제 Worspace 패널에서 Model을 찾아 오른쪽 마우스 버튼을 누릅니다.&lt;/li&gt;
&lt;li&gt;팝업메뉴에서 Save &amp;gt; Geometry Saver를 선택합니다.&lt;/li&gt;
&lt;li&gt;위에서 새로 만든 폴더를 찾아 그 안에 Teapot.x란 이름으로 파일을 저장합니다.&lt;/li&gt;
&lt;/ol&gt;
&lt;br /&gt;
&lt;br /&gt;
이제 비주얼 C++ 에서 프레임워크의 솔루션 파일을 엽니다.&lt;br /&gt;
&lt;br /&gt;
우선 예전에 있던 전역변수들부터 살펴보겠습니다. gpTextureMappingShader 변수가 있는데 이 변수가 언급되어 있는 곳을 모두 찾아 gpToonShader로 바꿉니다. gpSphere변수도 똑같은 방법으로 모두 gpTeapot으로 바꿔 줍니다. 텍스처 변수, gpEarthDM도 있네요. 여기서는 텍스처를 전혀 사용하지 않으니 gpEarthDM변수를 사용하는 코드를 모두 찾아 삭제해주세요.&lt;br /&gt;
&lt;br /&gt;
이제 새로 추가해야 할 전역변수들을 알아볼까요? 새로 추가해야 할 전역변수는 빛의 위치와 표면의 색상밖에 없는 것 같군요. 다음의 코드를 추가합니다.&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;// 광원의 위치&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;D3DXVECTOR4 gWorldLightPosition = D3DXVECTOR4(500.0f, 500.0f, -500.0f, 1.0f);&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;// 표면의 색상&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;D3DXVECTOR4 gSurfaceColor = &amp;nbsp; &amp;nbsp; &amp;nbsp; D3DXVECTOR4(0, 1, 0, 1);&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
위 코드에서 전역변수를 선언할 때 렌더몽키에서 사용했었던 값도 그대로 대입해줬습니다.&lt;br /&gt;
&lt;br /&gt;
이제 LoadAssets() 함수로 가서 로딩해올 쉐이더와 모델의 이름을 각각 Toonshader.fx와 Teapot.x로 바꿔줍니다.&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;bool LoadAssets()&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;{&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; &amp;nbsp; // 텍스처 로딩&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; &amp;nbsp; // 쉐이더 로딩&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; &amp;nbsp; gpToonShader = LoadShader("ToonShader.fx");&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; &amp;nbsp; if ( !gpToonShader )&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; &amp;nbsp; {&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; return false;&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; &amp;nbsp; }&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; &amp;nbsp; // 모델 로딩&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; &amp;nbsp; gpTeapot = LoadModel("Teapot.x");&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; &amp;nbsp; if ( !gpTeapot )&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; &amp;nbsp; {&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; return false;&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; &amp;nbsp; }&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; &amp;nbsp; return true;&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;}&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
다음은 실제로 장면을 그리는 RenderScene() 함수입니다. 행렬 2개를 새로 전달해줘야 했었죠? 월드/뷰/투영행렬을 합친 행렬과 월드행렬의 역행렬이었습니다. 우선 월드행렬의 역행렬을 구해봅시다. 월드행렬을 구했던 코드 아래에 다음의 라인을 추가합니다.&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; &amp;nbsp; // 월드행렬의 역행렬을 구한다.&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; &amp;nbsp; D3DXMATRIXA16 matInvWorld;&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; &amp;nbsp; D3DXMatrixTranspose(&amp;amp;matInvWorld, &amp;amp;matWorld);&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
위 코드에서 사용한 D3DXMatrixTranspose() 함수는 전치행렬(transpose matrix)을 구합니다. 여기서 역행렬 대신에 전치행렬을 구한 이유는 월드행렬이 직교행렬이기 때문이죠. 직교행렬의 전치행렬은 역행렬과 같습니다.&lt;span style="font-size: x-small;"&gt;(이에 대한 증명 및 자세한 설명은 이미 시중에 나와있는 훌륭한 수학책을 참고하시기 바랍니다. 참고로 순수하게 역행렬을 구하시려 한다면 D3DXMatrixInverse() 함수를 쓰시면 됩니다.)&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
이제 월드/뷰/투영행렬을 서로 곱할 차례입니다. D3DXMatrixMultiply() 함수를 사용하겠습니다.&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; &amp;nbsp; // 월드/뷰/투영행렬을 미리 곱한다.&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; &amp;nbsp; D3DXMATRIXA16 matWorldView;&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; &amp;nbsp; D3DXMATRIXA16 matWorldViewProjection;&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; &amp;nbsp; D3DXMatrixMultiply(&amp;amp;matWorldView, &amp;amp;matWorld, &amp;amp;matView);&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; &amp;nbsp; D3DXMatrixMultiply(&amp;amp;matWorldViewProjection, &amp;amp;matWorldView, &amp;amp;matProjection);&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
월드행렬 X 뷰행렬 X 투영행렬 순으로 곱해준 거 보이시죠?&lt;br /&gt;
&lt;br /&gt;
이제 위에서 만들었던 두 행렬을 쉐이더에 전달해 주겠습니다. 예전에 사용했던 SetMatrix() 함수 호출들을 다 지우시고 아래의 코드를 대신 삽입해주세요.&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; &amp;nbsp; // 쉐이더 전역변수들을 설정&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; &amp;nbsp; gpToonShader-&amp;gt;SetMatrix("gWorldViewProjectionMatrix",&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;amp;matWorldViewProjection);&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; &amp;nbsp; gpToonShader-&amp;gt;SetMatrix("gInvWorldMatrix", &amp;amp;matInvWorld);&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
마지막으로 광원의 위치와 표면의 색상을 전달해주는 것도 잊지 마셔야겠죠?&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; &amp;nbsp; gpToonShader-&amp;gt;SetVector("gWorldLightPosition", &amp;amp;gWorldLightPosition);&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; &amp;nbsp; gpToonShader-&amp;gt;SetVector("gSurfaceColor", &amp;amp;gSurfaceColor);&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
이제 코드를 컴파일 한 뒤, 프로그램을 실행하시면 빙글빙글 도는 주전자를 보실 수 있을 겁니다. 아무래도 회전을 하니까 손잡이나 주둥이에서 툰쉐이더 효과가 더 잘 나타나죠?&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-size: x-large;"&gt;&lt;b&gt;정리&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
다음은 이 장에서 배운 내용을 짧게 요약해 놓은 것입니다.&lt;br /&gt;
&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;툰쉐이더는 비실사 렌더링 기법 중에 하나이다.&lt;/li&gt;
&lt;li&gt;툰쉐이딩은 난반사광을 단계적으로 감소시키는 것에 지나지 않는다.&lt;/li&gt;
&lt;li&gt;행렬들을 미리 곱해놓으면 공간변환을 더 빨리 할 수 있다.&lt;/li&gt;
&lt;/ul&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;div style="text-align: right;"&gt;
&lt;b&gt;다음편 보기&lt;/b&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5281384917275132568-8682144682847036279?l=kblog.popekim.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/Tgn0dOyVhlPHabCjg1MwAgUc3EU/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/Tgn0dOyVhlPHabCjg1MwAgUc3EU/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/Tgn0dOyVhlPHabCjg1MwAgUc3EU/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/Tgn0dOyVhlPHabCjg1MwAgUc3EU/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/kblog-blindrenderer?a=e0VazTAFdSM:2-oZd9XrTCw:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/kblog-blindrenderer?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/kblog-blindrenderer?a=e0VazTAFdSM:2-oZd9XrTCw:63t7Ie-LG7Y"&gt;&lt;img src="http://feeds.feedburner.com/~ff/kblog-blindrenderer?d=63t7Ie-LG7Y" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/kblog-blindrenderer?a=e0VazTAFdSM:2-oZd9XrTCw:4cEx4HpKnUU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/kblog-blindrenderer?i=e0VazTAFdSM:2-oZd9XrTCw:4cEx4HpKnUU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/kblog-blindrenderer?a=e0VazTAFdSM:2-oZd9XrTCw:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/kblog-blindrenderer?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/kblog-blindrenderer/~4/e0VazTAFdSM" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://kblog.popekim.com/feeds/8682144682847036279/comments/default" title="댓글" /><link rel="replies" type="text/html" href="http://kblog.popekim.com/2012/01/06.html#comment-form" title="16개의 덧글" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/5281384917275132568/posts/default/8682144682847036279?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/5281384917275132568/posts/default/8682144682847036279?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/kblog-blindrenderer/~3/e0VazTAFdSM/06.html" title="[포프의 쉐이더 입문강좌] 06. 만화같은 명암을 입히는 툰쉐이더" /><author><name>Pope</name><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="33" height="30" src="http://2.bp.blogspot.com/_BBDmHdyx8wo/SfTUvbwSs-I/AAAAAAAAAYk/P1yurbiaKZM/S220/650px-Triskele-hollow-triangle.svg.png" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://1.bp.blogspot.com/-XoVyaMxF0GY/TxiswcLfhOI/AAAAAAAAAzM/kpki_ZkLVsg/s72-c/fig_06_01.jpg" height="72" width="72" /><thr:total>16</thr:total><feedburner:origLink>http://kblog.popekim.com/2012/01/06.html</feedburner:origLink></entry></feed>

