성태의 닷넷 이야기
홈 주인
모아 놓은 자료
프로그래밍
질문/답변
사용자 관리
사용자
메뉴
아티클
외부 아티클
유용한 코드
온라인 기능
MathJax 입력기
최근 덧글
[정성태] Java - How to use the Foreign Funct...
[정성태] 제가 큰 실수를 했군요. ^^; Delegate를 통한 Bein...
[정성태] Working with Rust Libraries from C#...
[정성태] Detecting blocking calls using asyn...
[정성태] 아쉽게도, 커뮤니티는 아니고 개인 블로그입니다. ^^
[정성태] 질문이 잘 이해가 안 됩니다. 우선, 해당 소스코드에서 ILis...
[양승조
] var대신 dinamic으로 선언해서 해결은 했습니다. 맞는 해...
[양승조
] 또 막혔습니다. ㅠㅠ var list = props[i].Ge...
[양승조
] 아. 감사합니다. 어제는 안됐던것 같은데....정신을 차려야겠네...
[정성태] "props[i].GetValue(props[i])" 코드에서 ...
글쓰기
제목
이름
암호
전자우편
HTML
홈페이지
유형
제니퍼 .NET
닷넷
COM 개체 관련
스크립트
VC++
VS.NET IDE
Windows
Team Foundation Server
디버깅 기술
오류 유형
개발 환경 구성
웹
기타
Linux
Java
DDK
Math
Phone
Graphics
사물인터넷
부모글 보이기/감추기
내용
<div style='display: inline'> <h1 style='font-family: Malgun Gothic, Consolas; font-size: 20pt; color: #006699; text-align: center; font-weight: bold'>Shader 강좌와 함께 배워보는 XNA Framework (1) - 기초 프로그램 구조</h1> <p> Shader 강좌가 지금 "<a target='tab' href='http://vsts2010.net/'>Visual Studio 2010 팀 블로그</a>"와 <a target='tab' href='http://kblog.popekim.com/p/blog-page_17.html'>저자의 개인 홈페이지</a>에서 동시 진행되고 있는데요.<br /> <br /> 그동안 DirectX 관련해서 전혀 해본 적이 없기 때문에 낯설긴 하지만, 이번에는 견문을 넓히자는 차원에서 직접 따라해 보기로 했습니다. ^^<br /> <br /> 그런데, 소스 코드를 따라하면서 왠지 수동적인 자세로 되어버리는 것 같아서... 잠시 생각하다가 이참에 DirectX의 닷넷 버전이라고 할 수 있는 XNA Framework으로 함께 변환을 해보기로 했습니다. (참고로, XNA Framework도 처음입니다. ^^;)<br /> <br /> 우선, 오늘 글은 다음의 내용에서 사용된 Visual C++ 코드에 대한 XNA Framework 버전을 만드는 것입니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > 01. 쉐이더란 무엇이죠? Part 2 ; <a target='tab' href='http://kblog.popekim.com/2011/12/01-part-2.html'>http://kblog.popekim.com/2011/12/01-part-2.html</a> </pre> <br /> 위의 글에서는 앞으로의 Shader 강좌를 실습하기 위한 DirectX 응용 프로그램의 뼈대를 잡고 있는데요. 맨땅에 헤딩한다는 생각으로... 변환을 시작해 보겠습니다. ^^<br /> <br /> <hr style='width: 50%' /><br /> <br /> 우선, XNA Framework 프로젝트를 하나 만들어야 하는데요. Visual Studio에서 "Add New Project" 대화상자를 통해 "XNA Game Studio 4.0" / "Windows Game (4.0)" 프로젝트를 선택하시면 됩니다.<br /> <br /> 기본적으로 Program.cs와 Game1.cs 파일이 생성되는데요. 각각의 기본 코드는 다음과 같습니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > ===== Program.cs ===== static class Program { static void Main(string[] args) { using (Game1 game = new Game1()) { game.Run(); } } } ===== Game1.cs ===== public class Game1 : Microsoft.Xna.Framework.Game { GraphicsDeviceManager graphics; SpriteBatch spriteBatch; public Game1() { graphics = new GraphicsDeviceManager(this); Content.RootDirectory = "Content"; } protected override void Initialize() { base.Initialize(); } protected override void LoadContent() { spriteBatch = new SpriteBatch(GraphicsDevice); } protected override void UnloadContent() { } protected override void Update(GameTime gameTime) { if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed) this.Exit(); base.Update(gameTime); } protected override void Draw(GameTime gameTime) { GraphicsDevice.Clear(Color.CornflowerBlue); base.Draw(gameTime); } } </pre> <br /> 재미있게도 강좌를 진행하는 분의 C++ 소스 코드 구조가 위의 XNA 응용 프로그램 구조와 크게 다르지 않습니다. ^^<br /> <br /> 자, 그럼 첫 작업으로 XNA 응용 프로그램의 윈도우 크기 조절부터 어떻게 하는지 살펴볼까요? 기본적으로 XNA는 순수하게 contents 윈도우 영역만 800 * 600으로 생성합니다. Visual C++로 만든 코드에서는 윈도우 영역을 조절하기 위해 다시 GetClientRect 등의 Win32 API를 사용해서 복잡하게 다음과 같이 크기 조정을 해주고 있는데요.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > // Client Rect 크기가 WIN_WIDTH, WIN_HEIGHT와 같도록 크기를 조정한다. POINT ptDiff; RECT rcClient, rcWindow; GetClientRect(hWnd, &rcClient); GetWindowRect(hWnd, &rcWindow); ptDiff.x = (rcWindow.right - rcWindow.left) - rcClient.right; ptDiff.y = (rcWindow.bottom - rcWindow.top) - rcClient.bottom; MoveWindow(hWnd,rcWindow.left, rcWindow.top, WIN_WIDTH + ptDiff.x, WIN_HEIGHT + ptDiff.y, TRUE); </pre> <br /> XNA 응용 프로그램에서는 graphics 개체에서 제공되는 속성을 통해서 간단하게 설정하는 것이 가능합니다. (역시 Managed 코드가 좋습니다. ^^)<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > public Game1() { graphics = new GraphicsDeviceManager(this); Content.RootDirectory = "Content"; <span style='color: blue; font-weight: bold'> this.graphics.PreferredBackBufferHeight = 600; this.graphics.PreferredBackBufferWidth = 800;</span> } </pre> <br /> 크기 조절은 이것으로 해결되었고, 그다음 ESC 키를 누르면 종료하는 조건을 추가하는 작업으로 넘어갑니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > protected override void Update(GameTime gameTime) { if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed) this.Exit(); <span style='color: blue; font-weight: bold'> if (Keyboard.GetState().IsKeyDown(Keys.Escape) == true) { this.Exit(); }</span> base.Update(gameTime); } </pre> <br /> 와~~~ 직관적이죠. ^^ 계속해서, 이번엔 폰트 부분으로 넘어가겠습니다. 원문에서는 D3DXCreateFont로 아래와 같이 생성을 해주는데요.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > D3DXCreateFont( gpD3DDevice, 20, 10, FW_BOLD, 1, FALSE, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, DEFAULT_QUALITY, (DEFAULT_PITCH | FF_DONTCARE), "Arial", &gpFont ); </pre> <br /> XNA에서는 이런 폰트 자원을 별도의 "Content"로 생성해서 관리를 하는 것 같습니다. 이에 대해서는 저도 단번에 알 수 없기 때문에 ^^ 다음의 글을 참고했습니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > Loading Fonts in XNA ; <a target='tab' href='http://www.stromcode.com/2008/03/02/loading-fonts-in-xna/'>http://www.stromcode.com/2008/03/02/loading-fonts-in-xna/</a> </pre> <br /> 이 글에 따라, 다음과 같이 XNA 프로젝트 생성 시에 부가적으로 함께 생성된 Content 프로젝트에서 "Sprite Font" 파일을 추가했습니다.<br /> <br /> <img onclick='toggle_img(this)' class='imgView' alt='basic_xna_1.png' src='/SysWebRes/bbs/basic_xna_1.png' /><br /> <br /> 추가된 SpriteFont1.spritefont 파일을 보면 XML 파일 형식으로 폰트에 대해 서술된 것임을 쉽게 알 수 있습니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > <?xml version="1.0" encoding="utf-8"?> <XnaContent xmlns:Graphics="Microsoft.Xna.Framework.Content.Pipeline.Graphics"> <Asset Type="Graphics:FontDescription"> <FontName>Segoe UI Mono</FontName> <Size>14</Size> <Spacing>0</Spacing> <UseKerning>true</UseKerning> <Style>Regular</Style> <CharacterRegions> <CharacterRegion> <Start>&#32;</Start> <End>&#126;</End> </CharacterRegion> </CharacterRegions> </Asset> </XnaContent> </pre> <br /> 이렇게 정의된 폰트 자원을 코드에서 사용하기 위해 다음과 같이 SpriteFont 개체를 생성해서 로드하고,<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > <span style='color: blue; font-weight: bold'>SpriteFont _spriteFont;</span> protected override void LoadContent() { spriteBatch = new SpriteBatch(GraphicsDevice); <span style='color: blue; font-weight: bold'>_spriteFont = Content.Load<SpriteFont>("SpriteFont1");</span> } </pre> <br /> Draw 메서드에서 사용해 보았습니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > protected override void Draw(GameTime gameTime) { GraphicsDevice.Clear(Color.CornflowerBlue); spriteBatch.Begin(); Vector2 vect2; vect2.X = 5; vect2.Y = 5; <span style='color: blue; font-weight: bold'>spriteBatch.DrawString(_spriteFont, "데모 프레임워크\n\nESC: 데모종료", vect2, Color.White);</span> spriteBatch.End(); base.Draw(gameTime); } </pre> <br /> 잘 될줄 알았는데 ^^ 왠 걸... DrawString에서 다음과 같은 오류가 발생했습니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > System.ArgumentException was unhandled Message=<span style='color: blue; font-weight: bold'>The character '데' (0xb370) is not available in this SpriteFont. If applicable, adjust the font's start and end CharacterRegions to include this character.</span> Parameter name: character Source=Microsoft.Xna.Framework.Graphics ParamName=character StackTrace: at Microsoft.Xna.Framework.Graphics.SpriteFont.GetIndexForCharacter(Char character) at Microsoft.Xna.Framework.Graphics.SpriteFont.InternalDraw(StringProxy& text, SpriteBatch spriteBatch, Vector2 textblockPosition, Color color, Single rotation, Vector2 origin, Vector2& scale, SpriteEffects spriteEffects, Single depth) at Microsoft.Xna.Framework.Graphics.SpriteBatch.DrawString(SpriteFont spriteFont, String text, Vector2 position, Color color) ...[생략]... at Microsoft.Xna.Framework.Game.Run() at WindowsGame1.Program.Main(String[] args) in D:\Settings\desktop\dxf\WindowsGame1\WindowsGame1\Program.cs:line 15 InnerException: </pre> <br /> 대강 CharacterRegions에 지정된 Start/End 값의 범위를 넘었다는 것은 알겠는데... 그렇다면 구체적으로 무슨 값을 넣어주어야 할까요?<br /> <br /> 검색하다 보니, 황당하더군요. ^^;<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > [XNA 3.0 ~ 3.1] Localization Sample을 이용한 초간단 예제 입니다. ; <a target='tab' href='http://blog.naver.com/fly33499/120094588332'>http://blog.naver.com/fly33499/120094588332</a> </pre> <br /> DirectX C++ 소스 코드에서는 그냥 DrawText에 유니코드 문자열을 지정해 주면 되었는데, XNA에서는 관련 문자를 모두 자원으로 포함하고 있어야 한다는 이야기입니다.<br /> <br /> 어쨌든, 한글 출력을 위해서는 위의 글을 읽고 따라해 보시면 됩니다. 간단하게 설명하면 <a target='tab' href='http://create.msdn.com/en-US/education/catalog/sample/localization'>LocalizationSample_4_0 프로젝트</a>를 내려받아서 빌드하면 생성되는 LocalizationPipeline.dll 파일과 LocalizationContent 프로젝트에 포함되어 있던 Font.spritefont를 제가 만든 게임 솔루션의 WindowsGame1Content 프로젝트 폴더에 복사하고 참조 및 추가를 해줍니다. (이전에 추가해 두었던 SpriteFont1.spritefont 파일은 그냥 삭제합니다.) Font.spriteFont의 속성창에서 "Content Processor"를 "LocalizedFontProcessor"로 바꿔줍니다.<br /> <br /> "WindowsGame1" 프로젝트에서 리소스 파일을 하나 추가하고 거기에 프로그램에서 사용될 문자를 포함하는 한글을 입력해 둔 후, Font.spritefont에 포함된 "<ResourceFiles/>" 하위에 <Resx /> 노드로 그 리소스 파일의 상대 경로를 입력해 두었습니다. 아래는 이 과정을 하나의 그림으로 표현한 것입니다.<br /> <br /> <img onclick='toggle_img(this)' class='imgView' alt='basic_xna_2.png' src='/SysWebRes/bbs/basic_xna_2.png' /><br /> <br /> 이렇게 구성한 후, 바뀐 Sprite 폰트 파일을 코드에 반영해 주고,<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > protected override void LoadContent() { spriteBatch = new SpriteBatch(GraphicsDevice); _spriteFont = <span style='color: blue; font-weight: bold'>Content.Load<SpriteFont>("Font");</span> } </pre> <br /> 빌드하면, 최초의 ^^ XNA 프로그램이 완성됩니다.<br /> <br /> 참고로, 2개의 프로젝트 파일을 첨부했는데 <a target='tab' href='http://www.sysnet.pe.kr/bbs/DownloadAttachment.aspx?fid=659&boardid=331301885'>하나는 여기서 사용된 XNA 프로젝트</a>이고, 다른 하나는 "<a target='tab' href='http://vsts2010.net/640? Part 2'>쉐이더란 무엇이죠? Part 2</a>" <a target='tab' href='http://www.sysnet.pe.kr/bbs/DownloadAttachment.aspx?fid=658&boardid=331301885'>글에서 제공된 예제 코드를 Unicode 지원으로 바꾼 것</a>입니다.<br /> <br /> 만약, 위의 예제에서 모든(?) 한글을 표현하고 싶도록 리소스 파일을 변경하고 싶다면 "<a target='tab' href='http://blog.naver.com/fly33499/120094743997'>[XNA] K-Zune에서 사용한 한글, 한자, 일본어, 로마자 및 기타부호 파일입니다.</a>" 글에 첨부된 "한글.TXT" 파일의 내용을 "Resources.resx" 파일에 담아주면 됩니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > === 아래의 리소스는 '데', '모', '프', '레', '임', '워', '크', '종', '료' 글자가 들어간 경우에만 한글이 정상적으로 출력됨. <data name="Hangul" xml:space="preserve"> <value>데모프레임워크종료</value> </data> === 아래의 리소스는 대부분의 한글을 담고 있으므로 웬만한 한글들은 모두 정상적으로 출력됨. <data name="Hangul" xml:space="preserve"> <value>가각간갇갈갉갊감갑값갓갔강갖갗 같갚갛개객갠갤갬갭갯갰갱갸갹갼걀 걋걍걔걘걜거걱건걷걸걺검겁것겄겅 겆겉겊겋게겐겔겜겝겟겠겡겨격겪견 ...[생략]... 활홧황홰홱홴횃횅회획횐횔횝횟횡효 횬횰횹횻후훅훈훌훑훔훗훙훠훤훨훰 훵훼훽휀휄휑휘휙휜휠휨휩휫휭휴휵 휸휼흄흉흐흑흔흖흗흘흙흠흡흣흥 흩희흰흴흼흽힁히힉힌힐힘힙힛힝</value> </data> </pre> <br /> <hr style='width: 50%' /><br /> <br /> 풀리지 않는 숙제 하나!<br /> <br /> 윈도우 타이틀을 다음과 같이 변경해 보았는데,<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > public Game1() { graphics = new GraphicsDeviceManager(this); Content.RootDirectory = "Content"; this.graphics.PreferredBackBufferHeight = 600; this.graphics.PreferredBackBufferWidth = 800; Window.Title = "초간단 쉐이더 데모 프레임워크"; } </pre> <br /> 문자열이 '?'로 깨져나오는데 해결책을 모르겠습니다. (물론, Resource.resx에도 해당 '문자'들을 넣어주었습니다.)<br /> <br /> 어쨌든... 이번엔 여기까지만! ^^ (이 글을 읽으시는 분들 중에 제목이 깨지는 문제에 대해서 아시는 분은 덧글 부탁드립니다.)<br /> </p><br /> <br /> <br /><hr /><span style='color: Maroon'>[이 글에 대해서 여러분들과 의견을 공유하고 싶습니다. 틀리거나 미흡한 부분 또는 의문 사항이 있으시면 언제든 댓글 남겨주십시오.]</span> </div>
첨부파일
스팸 방지용 인증 번호
3929
(왼쪽의 숫자를 입력해야 합니다.)