'프로그래밍 > C' 카테고리의 다른 글
C Language Constructors and Destructors with GCC (0) | 2015.02.12 |
---|---|
C Standard Library (0) | 2010.09.25 |
싱글 스레드에서 멀티 스레드로... 왜 /MD 인가? (0) | 2010.03.11 |
C Language Constructors and Destructors with GCC (0) | 2015.02.12 |
---|---|
C Standard Library (0) | 2010.09.25 |
싱글 스레드에서 멀티 스레드로... 왜 /MD 인가? (0) | 2010.03.11 |
char *FProgram=
"uniform sampler2DRect Ytex;\n"
"uniform sampler2DRect Utex,Vtex;\n"
"void main(void) {\n"
" float nx,ny,r,g,b,y,u,v;\n"
" vec4 txl,ux,vx;"
" nx=gl_TexCoord[0].x;\n"
" ny=576.0-gl_TexCoord[0].y;\n"
" y=texture2DRect(Ytex,vec2(nx,ny)).r;\n"
" u=texture2DRect(Utex,vec2(nx/2.0,ny/2.0)).r;\n"
" v=texture2DRect(Vtex,vec2(nx/2.0,ny/2.0)).r;\n"
" y=1.1643*(y-0.0625);\n"
" u=u-0.5;\n"
" v=v-0.5;\n"
" r=y+1.5958*v;\n"
" g=y-0.39173*u-0.81290*v;\n"
" b=y+2.017*u;\n"
" gl_FragColor=vec4(r,g,b,1.0);\n"
"}\n";
위 코드에서 주의 해야 할 부분은 빨간색으로 표시된 576.0 부분이다. 바로 저 값은 일종의 Magic Number인데 바로 입력으로 들어가는 YUV 그림의 높이 값이다.
문제는 이 높이 값은 입력으로 들어오는 신호가 고정된 값이면 상관없지만 사용자가 임의로 결정하는 경우에는 반드시 바뀌어야 한다. 나의 경우에는 입력으로 들어오는 비디오 신호가 실시간 인데다가 NTSC와 PAL 모두를 고려해야 했으므로 높이값이 일정하지 않았다.
그래서 추가로 shader 내부에 변수값을 하나 추가하여 shader 외부에서 값을 입력 신호의 비디오 높이에 따라서 적당히 변경하였다.
김형준님의 홈페이지에 가면 참 좋은 정보를 많이 얻을수 있다.. 특히 요즘 쉐이더에 대한 강의가 많이 올라와 있어 도움이 많이 되었다. http://www.gisdeveloper.co.kr/category/Programming/OpenGL?page=3
나머지 코드를 살펴보면, 우선 쉐이더 프로그램을 초기화하고 불러들여 컴파일 하는 과정이 있다.
/* 쉐이더 프로그램 핸들 생성 */
PHandle=glCreateProgramObjectARB();
FSHandle=glCreateShaderObjectARB(GL_FRAGMENT_SHADER_ARB);
/* 쉐이터 컴파일 */
glShaderSourceARB(FSHandle,1,&FProgram,NULL);
glCompileShaderARB(FSHandle);
/* 에러가 있으면 출력해서 보여주기 */
glGetObjectParameterivARB(FSHandle,GL_OBJECT_COMPILE_STATUS_ARB,&i);
s=malloc(32768);
glGetInfoLogARB(FSHandle,32768,NULL,s);
printf("Compile Log: %s\n", s);
free(s);
/* 프로그램 오브젝트 생성 */
glAttachObjectARB(PHandle,FSHandle);
glLinkProgramARB(PHandle);
/* 링크시 에러있으면 보여주기 */
s=malloc(32768);
glGetInfoLogARB(PHandle,32768,NULL,s);
printf("Link Log: %s\n", s);
free(s);
/* 이제 쉐이더 사용하기 */
glUseProgramObjectARB(PHandle);
.... (렌더링 하기 by 쉐이더)
/* 쉐이더 분리하기 */
glUseProgramObjectARB(0);
사실 중요한 부분이 생략되어 있는데 이런 모든 확장 기능을 사용하기 전에 OpenGL 버전 체크 및 확장 버전 체크 부분이 생략되어 있다. 이것은 여러 사이트에서 쉽게 찾을 수 있으니 일단은 넘어가지만 나도 추가로 나중에 이와 관련해 문서를 하나 만들어 두는 것이 좋을 듯 하다.
아무튼, 위 내용은 초기화 및 컴파일 그리고 사용 그리고 마지막으로 연결 해제 순서로 되어 있어 이해하기 쉽다. 결국 쉐이더도 객체 지향성을 띄기 때문에 참 사용이 간편하고 용이하다.
이제 마지막으로 렌더링을 어떻게 하느냐 파트만 남았다. 이부분이 어쩌면 제일 중요한것 같다.. ^^
/* This might not be required, but should not hurt. */
glEnable(GL_TEXTURE_2D);
/* Select texture unit 1 as the active unit and bind the U texture. */
glActiveTexture(GL_TEXTURE1);
i=glGetUniformLocationARB(PHandle,"Utex");
glUniform1iARB(i,1); /* Bind Utex to texture unit 1 */
glBindTexture(GL_TEXTURE_RECTANGLE_NV,1);
glTexParameteri(GL_TEXTURE_RECTANGLE_NV,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
glTexParameteri(GL_TEXTURE_RECTANGLE_NV,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
glTexEnvf(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_DECAL);
glTexImage2D(GL_TEXTURE_RECTANGLE_NV,0,GL_LUMINANCE,376,288,0,GL_LUMINANCE,GL_UNSIGNED_BYTE,Utex);
/* Select texture unit 2 as the active unit and bind the V texture. */
glActiveTexture(GL_TEXTURE2);
i=glGetUniformLocationARB(PHandle,"Vtex");
glBindTexture(GL_TEXTURE_RECTANGLE_NV,2);
glUniform1iARB(i,2); /* Bind Vtext to texture unit 2 */
glTexParameteri(GL_TEXTURE_RECTANGLE_NV,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
glTexParameteri(GL_TEXTURE_RECTANGLE_NV,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
glTexEnvf(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_DECAL);
glTexImage2D(GL_TEXTURE_RECTANGLE_NV,0,GL_LUMINANCE,376,288,0,GL_LUMINANCE,GL_UNSIGNED_BYTE,Vtex);
/* Select texture unit 0 as the active unit and bind the Y texture. */
glActiveTexture(GL_TEXTURE0);
i=glGetUniformLocationARB(PHandle,"Ytex");
glUniform1iARB(i,0); /* Bind Ytex to texture unit 0 */
glBindTexture(GL_TEXTURE_RECTANGLE_NV,3);
glTexParameteri(GL_TEXTURE_RECTANGLE_NV,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
glTexParameteri(GL_TEXTURE_RECTANGLE_NV,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
glTexEnvf(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_DECAL);
glTexImage2D(GL_TEXTURE_RECTANGLE_NV,0,GL_LUMINANCE,752,576,0,GL_LUMINANCE,GL_UNSIGNED_BYTE,Ytex);
i=glGetUniformLocationARB(PHandle,"Utex"); 는 PHandle이 가리키는 쉐이더 프로그램에서 Utex라는 변수를 찾아서 그 고유 값을 i로 돌려준다. i는 일종의 포인터인 셈이다.
멀티 텍스쳐링을 이용하여 YUV를 RGB로 바꾸기 때문에 3개의 텍스쳐가 필요한데 바로 Y, U, V 세가지 텍스쳐가 필요하다. 이 각각의 쉐이더 내부의 텍스쳐와 쉐이더 외부의 YUV 이미지의 링크 과정이 필요한데 바로 위의 과정이 그것을 보여주고 있다.
참고로 나의 경우에는 실시간 입력이기 때문에 위와 같이 텍스쳐를 생성하여 연결하지 않았고 미리 만들어둔 텍스쳐를 바인딩만 하였다. 물론 이 텍스쳐는 실시간으로 데이터가 갱신되므로 함부로 데이터를 건드리면 안된다. (Lock과 Unlock이 필요)
마지막으로 이상했던 점은 쉐이더 자체가 텍스쳐 좌표를 integer 범위 (576과 같은) 를 사용하였기 때문에 위와 같이 쉐이더를 통과한 후 3차원 공간에서 맵핑을 하고자 한다면 glTexCoord2i() 함수를 사용해야 한다는 점인것 같다.
나는 늘 사용하던 glTexCoord3f()를 생각없이 사용했었는데 그것을 사용하면 제대로 계산된 텍스쳐 좌표가 나오질 않는다는 점을 꼭 알아두자...
부족한 설명이 많았지만 일단 여기까지만 적어두고 까먹을만 하면 읽어봐야지.. ㅎㅎ
glPolygonMode()와 glCullFace() (0) | 2010.02.19 |
---|---|
OpenGL Rendering Pipeline (0) | 2010.02.18 |
OpenGL Rendering Context v.s. Windows Device Context (0) | 2009.03.12 |
Oh my god... 이게 사진이 아니라고? (0) | 2008.01.18 |
glRasterPos와 glWindowPos (1) | 2007.12.01 |
기도 (2) | 2010.02.03 |
---|---|
'무한도전' 논란에 대한 내 생각 (1) | 2009.11.24 |
공간 이동 (0) | 2009.03.12 |
친구 이야기 (2) | 2008.12.12 |
죽기전에 "한번" 가볼만한 곳 - 알래스카 (0) | 2008.10.16 |
윈도우 - 차일드, 팝업 (0) | 2009.11.17 |
---|---|
윈도우 - SetClassLongPtr(), SetWindowLongPtr() (0) | 2009.11.17 |
윈도우 - WNDCLASS 구조체 (0) | 2009.11.17 |
윈도우 - CreateWindow() (0) | 2009.11.17 |
Device Context의 개념 + GetDC / ReleaseDC (0) | 2009.03.11 |
필터 렌더링 (1) - 자동 & 수동 소스 필터 렌더링 (0) | 2009.03.17 |
---|---|
필터 추가후 렌더링 하기 (0) | 2009.03.16 |
Null Rendering (0) | 2009.03.16 |
COM (Component Object Model) 과 DirectShow (2) | 2009.03.14 |
DirectShow 제일 중요한 필터 그래프 관리자 생성 및 해제 (0) | 2008.01.26 |
DirectShow 필터로 동영상 추출하여 OpenGL로 렌더링 하기 (0) | 2009.05.16 |
---|---|
필터 추가후 렌더링 하기 (0) | 2009.03.16 |
Null Rendering (0) | 2009.03.16 |
COM (Component Object Model) 과 DirectShow (2) | 2009.03.14 |
DirectShow 제일 중요한 필터 그래프 관리자 생성 및 해제 (0) | 2008.01.26 |
DirectShow 필터로 동영상 추출하여 OpenGL로 렌더링 하기 (0) | 2009.05.16 |
---|---|
필터 렌더링 (1) - 자동 & 수동 소스 필터 렌더링 (0) | 2009.03.17 |
Null Rendering (0) | 2009.03.16 |
COM (Component Object Model) 과 DirectShow (2) | 2009.03.14 |
DirectShow 제일 중요한 필터 그래프 관리자 생성 및 해제 (0) | 2008.01.26 |
필터 렌더링 (1) - 자동 & 수동 소스 필터 렌더링 (0) | 2009.03.17 |
---|---|
필터 추가후 렌더링 하기 (0) | 2009.03.16 |
COM (Component Object Model) 과 DirectShow (2) | 2009.03.14 |
DirectShow 제일 중요한 필터 그래프 관리자 생성 및 해제 (0) | 2008.01.26 |
DS에서 알아야 할 각종 멀티미디어 관련 단어들... (0) | 2008.01.24 |
필터 렌더링 (1) - 자동 & 수동 소스 필터 렌더링 (0) | 2009.03.17 |
---|---|
필터 추가후 렌더링 하기 (0) | 2009.03.16 |
Null Rendering (0) | 2009.03.16 |
DirectShow 제일 중요한 필터 그래프 관리자 생성 및 해제 (0) | 2008.01.26 |
DS에서 알아야 할 각종 멀티미디어 관련 단어들... (0) | 2008.01.24 |
x86_Microsoft.VC80.CRT_1fc8b3b9a1e18e3b_8.0.50727.4053_x-ww_e6967989 (6) | 2009.09.10 |
---|---|
C/C++ 메모리 오류에 대하여 (1) | 2009.07.30 |
프로그램, 프로세스, 스레드 (2) | 2008.10.22 |
객체 지향 언어(C++) V.S. 비 객체 지향 언어(C) (2) | 2008.10.18 |
왜 객체 지향인가? (0) | 2008.01.11 |
The Ten Man Experience! (0) | 2010.02.26 |
---|
OpenGL Rendering Pipeline (0) | 2010.02.18 |
---|---|
OpenGL Shader를 이용해 YUV 420 포맷 색상을 RGB로 변경하기 (4) | 2009.07.25 |
Oh my god... 이게 사진이 아니라고? (0) | 2008.01.18 |
glRasterPos와 glWindowPos (1) | 2007.12.01 |
OpenGL 에서 조명 설정에 관하여... (0) | 2007.11.16 |
'무한도전' 논란에 대한 내 생각 (1) | 2009.11.24 |
---|---|
노무현 대통령 타살 의혹 (0) | 2009.05.27 |
친구 이야기 (2) | 2008.12.12 |
죽기전에 "한번" 가볼만한 곳 - 알래스카 (0) | 2008.10.16 |
털어버리기 (0) | 2008.10.14 |
윈도우 - 차일드, 팝업 (0) | 2009.11.17 |
---|---|
윈도우 - SetClassLongPtr(), SetWindowLongPtr() (0) | 2009.11.17 |
윈도우 - WNDCLASS 구조체 (0) | 2009.11.17 |
윈도우 - CreateWindow() (0) | 2009.11.17 |
메모리, Win32 vs. Win16 (2) | 2009.05.22 |
나는 좁고 깊은 인관 관계를 가지는 편이다. 주위에 친구가 잘 없다. 미국에 있어서 그런것도 있지만 원래부터 사람을 넓게 만나지 않는다.
그런 와중에도 절친이 2~3명 있는데 이중 한놈이 결혼을 했다. 므허헐.. 참 축하할 일이다. 내 일처럼 기쁘다. :)
미국에 와있으면서 아쉬운게 있다면 부모님을 찾아뵙기 힘들다는 거랑 이 친구 녀석들을 못본다는 건데 이 두 가지 빼면 아무것도 아쉬울게 없다.
내 영혼이 심하게 방황하던 대학교 1, 2 학년 시절 이 친구와는 하루종일 같이 있었다. 하루 24시간중에 10시간 이상은 내내 얼굴을 맞대고 있었다.
수업, 공부, 땡땡이, 겜방... 모든 일들이 그 친구들과 함께 였다. 아, 중요한걸 빠뜨렸네. 밥 먹을때도 항상 함께.
재미있는 것은 우리는 서로에게 한번도 '넌 내 절친이야' 라든가 '넌 내가 제일 친한 친구야' 라는 이야기를 주고 받아 본적이 없다.
그런 이야기를 주고 받지 않았던 이유는 아마도 우리 셋 모두가 '친구'라는 의미에 대해서 같은 생각을 가지고 있었기 때문이고 인생관이 모두 같았기 때문이라고 본다.
강요에 의해서 움직이는 것, 주변의 눈치 때문에 어쩔수 없이 하는것, 명령에 복종해야 하는 것. 이 모든 것을 우리는 싫어했다.
물 흐르듯 자연스레 행동하는 것을 좋아했고 알게 모르게 반항적인 기운도 많았다. 우리들은 모두가 그런 공통적인 인생관을 가지고 있었기 때문에 더더욱 친했던 것 같다.
가만히 생각해 보니 우리는 또다른 공통점이 있었다. 집안 환경은 다 제각각 이었지만 서로에게 돈을 쓸때에는 누가 더 많이 내고 적게 내는 것을 따지지 않았다.
돈이 있는 사람이 내면 그만이고 내가 어제 크게 한번 샀다면 네가 사면되고, 만약 돈이 없다면 내가 또 사면 되는 거고... ㅋㅋㅋ
물론 내가 그때는 집안이 여유가 좀 있던 관계로 내가 많이 돈을 내기는 했지만 그 돈은 1원도 아깝지가 않았다. 지금도 그렇게 생각한다.
인간관계가 틀어지는 가장 큰 이유 2가지는 말 실수와 돈 문제인데 우리들에게는 발생할 일이 없는 것들이었다.
고등학교를 다닐때 집에 계신 아픈 어머니를 생각하면 늘 가슴이 먹먹해 지는 느낌이 들었는데 멀리 떨어진 이곳에서 이 친구들과 즐거웠던 시절을 생각하면 비슷한 느낌이 든다.
내년에 한국에 가게되면 이놈들과 꼭 하루 죙일 뭔가를 하고 싶다. 그 무엇인가가 아무리 재미 없는 것이라 하더라도 같이 있다는 것 만으로도 우리는 즐거울 것이다.
친구가 없다고 그래서 외롭다고 노래를 부르는 사람을 많이 보았다. 그런 사람들은 진정한 의미의 친구를 만나지 못했기 때문에, 또한 자신 역시 얕은 친구만을 사귀었기 때문에 그런 말을 하는 것이다.
진정한 친구는 비록 멀리 떨어져 있다고 하더라도 같이 했던 추억을 떠올리는 것만으로도 미소짓게 만드는 사람들이다.
우리가 같이 재미있는 것을 했기때문에 즐거웠던 것이 아니라 우리가 함께 였기 때문에 즐거웠다는 것을 시간이 지나보니 알겠다.
이 녀석들 잘지내는지... :) 궁금허다. ^^
노무현 대통령 타살 의혹 (0) | 2009.05.27 |
---|---|
공간 이동 (0) | 2009.03.12 |
죽기전에 "한번" 가볼만한 곳 - 알래스카 (0) | 2008.10.16 |
털어버리기 (0) | 2008.10.14 |
방관자 효과 (0) | 2008.01.15 |
참고 자료: http://msdn.microsoft.com/en-us/library/abx4dbyh(VS.80).aspx
관련글: http://diehard98.tistory.com/entry/MSDN-Manifest-파일 (manifest 파일에 대한 설명 및 재배포 방법)
Visual Studio 2005의 C++를 이용해서 프로그램을 작성하다 보면 프로젝트의 Properties 에서 Code Generation 속성에 보면 /MT, /MTd, /MD, /MDd 와 같은 다양한 형태의 옵션 설정이 가능하다.
이것을 어떻게 설정하는가에 따라서 내가 만드는 프로그램이 어떤 DLL과 연결이 되는지와 정적(Static)으로 라이브러리를 링크 할 것인지 아니면 동적(Dynamic)으로 라이브러리를 링크 할 것인지를 결정할 수 있다.
이 속성을 우습게 보았다가 나는 큰 코 다쳤다. =_+ 헐
Standard C++ Library |
Characteristics |
Option |
Preprocessor directives |
LIBCPMT.LIB |
Multithreaded, static link |
/MT |
_MT |
MSVCPRT.LIB |
Multithreaded, dynamic link (import library for MSVCP80.dll) |
/MD |
_MT, _DLL |
LIBCPMTD.LIB |
Multithreaded, static link |
/MTd |
_DEBUG, _MT |
MSVCPRTD.LIB |
Multithreaded, dynamic link (import library for MSVCP80D.DLL) |
/MDd |
_DEBUG, _MT, _DLL |
Best Practices For Managed And Native Code Interoperability - Jesse Kaplan (0) | 2013.04.13 |
---|---|
Visual C++ 2010에서 작성한 프로그램의 배포 방법 세 가지 (0) | 2012.12.14 |
[MSDN] COM (Component Object Model) (2) | 2008.10.17 |
[MSDN] End of DLL War! (0) | 2008.10.16 |
[MSDN] DLL HELL!!!! (1) (0) | 2008.10.15 |
프로그램, 프로세스, 스레드의 차이를 알아보자.
일반적으로 프로그램(Program)은 메모장과 같은 하나의 실행 가능한 단위를 의미한다.
그러나 아시다시피 메모장은 여러개를 동시에 실행할 수 있다. 이때 각각의 메모장은 서로 다른 프로세스(Process)에 의해서 실행이 된다.
즉, 프로세스는 프로그램을 객체화 시킨 것.
각 프로세스는 4GB의 개별 주소 공간과 파일, 메모리, 스레드를 소유하게 된다. 이 말에서도 나온것 처럼 스레드는 다시 프로세스에 속한다.
하나의 프로세스는 여러개의 스레드(Thread)를 소유할 수 있으며 프로세스 자체는 껍데기일 뿐이고 사실은 스레드가 모든 명령을 수행한다.
프로세스가 최초로 생성될때 각종 관련 변수와 메모리 등을 생성하면서 메인 스레드를 생성하게 되는데 이 메인 스레드가 사실 모든 명령들을 처리한다.
그러나 사용자가 원하면 멀티 스레드 (Multi-Thread)가 가능한데 즉, 하나의 프로세스가 여러개의 스레드를 가지고서 다양한 작업을 분산 시켜 처리하도록 하는 것이다.
사용자가 임의로 타이머를 만들어서 규칙적인 시간에 일정한 작업을 처리하는 것보다 (또는 PeekMessage를 이용한 방법보다) 운영체제가 알아서 시간을 쪼개에 스레드에게 작업을 나누어 주는 것이 훠어어얼씬 효율적이고 빠르단다.
다만, 멀티 스레드가 가지는 문제점은 하나의 프로세스안에 존재하는 스레드들은 같은 코드와 주소공간, 그리고 전역 변수를 '공유'하게 됨으로써 생기는 '자원 경쟁' 혹은 '비동기 문제'이다.
하나의 프로세스 안에 있는 1번 스레드가 전역 변수를 변경하고 있는 동안 다른 2번 스레드가 그 값을 참조하거나 다시 변경하게되면 사용자가 예상치 못한 이상한 값들로 바뀌어 버리는 문제가 생기게 된다.
그래서 이것을 해결하기 위해서는 가장 좋은 것이 스레드들이 공유하는 전역 변수 자체를 안만들거나, 혹은 스레드 지역 기억장소 (Thread Local Storage) 공간을 사용해야 한다.
TLS는 다른 말로 쓰자면 '하나의 스레드에 대해서만 전역 변수인 공간'이다.
이렇게 복잡하게 설정을 해야 하는 이유는, C의 런타임 라이브러리가 애당초 Multi-Thread개념이 생기기 전에 만들어 졌기 때문이다.
기존 C 런타임 라이브러리는 함수들이 주로 Static 을 많이 사용하고 있는데 (특정 함수에서) 이 Static 변수들이 스레드 간에 '자원 경쟁' 혹은 '비동기' 때문에 엉뚱한 결과를 내는 현상을 가져왔다.
그래서 이걸 뜯어고치기되 기존 C 런타임 라이브러리를 동시에 유지하기 위해서 MLS가 도입된 것이다.
C/C++ 메모리 오류에 대하여 (1) | 2009.07.30 |
---|---|
객체 / 클래스 / 객체화 / 추상 클래스 (0) | 2009.03.13 |
객체 지향 언어(C++) V.S. 비 객체 지향 언어(C) (2) | 2008.10.18 |
왜 객체 지향인가? (0) | 2008.01.11 |
젠장할 Direct Show (0) | 2008.01.10 |
내가 대학 다닐 시절에 처음으로 듣는 컴퓨터 관련 교양 과목은 아마도 '컴퓨터의 역사'나 '컴퓨터 개론' 뭐 이런거 였지 않나 싶다.
중요한 점은 그 과목들은 '어떻게' 컴퓨터가 발전해 왔는가에 대한 대답은 해주지만 '왜' 그렇게 발전해 왔는가에 대한 대답은 주지 않는다.
프로그래밍 언어에 대한 첫 수업을 들었을 때에도 마찬가지였다. C가 무엇인지는 가르쳐 주었지만 프로그래밍 언어의 큰 '흐름' 이나 '관계'에 대해서는 전혀 듣지 못했다.
이런 '개념'에 대한 부족은 사실 큰 그림으로 보면 한 가족인 COM, MFC, .NET Framework, JAVA 에 대한 '이해'를 매우 어렵게 만들었다. 이해가 힘들다 보니 배우기도 어렵고 '공포'스런 존재로 다가왔다.
이런 문제는 나에게도 어김없이 나타났다. 하지만 이것을 이겨내기 위한 나의 첫 단계는 C와 C++의 정복이었다. 나에게는 격하게 아끼는 책 두권이 있다. 바로 김상형님이 지은 혼자 연구하는 C/C++이라는 책인데 이책들이 나에게는 프로그램으로 향하는 길을 열어주었다.
이 책을 읽기 전에는 그저 C++은 C를 모태로한 발전된 형태의 언어라는 어렴풋한 개념을 가지고 있었는데 두 권을 읽으면서 확실한 개념적 차이를 알게 되었다. 이제부터 그책에서 얻은 지식과 잡다한 나의 지식을 모아 모아 최대한 쉽게 C와 C++에 대해서 이야기 하고자 한다. (수업에서는 얻을 수 없었던 그 이야기를)
사실 C와 C++는 '서로 틀리다'라고 말하는 것보다는 '프로그램을 구현(작성)하는 방식이 서로 틀리다' 라고 말해야 정확하다.
바로 '객체 지향 언어'와 '비 객체 지향 언어'의 차이에서 오는 '프로그램 작성 방식의 차이'가 C와 C++의 결정적 차이점이다.
비 객체 지향 언어라는 말은 객체 지향의 개념이 없으면 이해가 안되므로 다른 말로 바꿔서 '구조적 언어'라 할 수 있다.
과거 C로 작성된 언어들의 특징을 보면 '단일 프로그램'으로써 하나 혹은 몇개의 파일안에 하나의 프로그램을 돌리기 위한 함수들과 코드들이 모조리 들어가 있다.
이들의 연결 구조와 호출 관계는 프로그래머가 정의하는 것이 곧 '원칙'이요 '룰' 이기 때문에 서로 복잡하게 엉켜 있다. 즉, 프로그램을 구성하는 함수들이 '독립적'이지 못하고 서로가 서로에게 의존적이며 이곳 저곳에 난무 하는 전역 변수들이 전체 프로그램을 컨트롤 했다.
이런 방식의 프로그램 작성 기법을 '구조적' 이라 표현했는데 사실 적당히 어울리는 단어가 생각이 안난다. 아무튼... 그건 그렇고.. -_-
바로 이렇게 작성된 프로그램은 '재사용성'이 거의 없었다. 재사용성이라 함은 내가 짜놓은 코드를 다른 프로그램에서 가져다 사용하는 건데 '프로그래머 맘대로' 작성한 C 프로그램들은 필요한 일부의 코드만 가져다 쓸 수가 없었다. 왜? 전역 변수와 이곳 저곳에 흩어진 많은 다른 함수들이 서로 엉켜 있기 때문이다.
바로 이런 문제가 '소프트웨어의 위기'로 찾아온다. 80년 이후 하드웨어의 기술은 급격히 빨라져 자고나면 하드웨어 값이 떨어지고 하드디스크 용량이 2배로 뛰어 오를 그 시기에 소프트웨어의 발전은 더뎠다.
그 원인으로 지적된 것이 바로 C의 구조적 언어 작성법이었다. 지 맘대로 짜다보니 내가 짜 놓고도 몇 개월 지나서 보면 멍~ 때리게 되는 것이다.
그래서 이것을 해결하기 위해 C++, '객체 지향 언어'가 등장했다. 이 객체 지향 언어의 목표는 요약해서 말하자면,
이 두가지 룰을 지키게 되면 C++로 작성한 프로그램은 사용하는 모든 함수들이 클래스의 멤버 함수로 정의되고 전역변수를 전혀 사용할 필요가 없게 된다.
이 말을 쉽게 하면 프로그램을 블럭으로 나누어 작성하라는 말이다. 이 각각의 블럭이 바로 클래스 이고 이 클래스는 완전한 '독립체'로써 그냥 가져다 다른 프로그램에 쓸수가 있다. 바로 '재사용성'의 확보다.
그렇다면 왜 '재사용성'이 그리도 중요한가 궁금하지 않은가? :) 일단 '효율' 때문이다. 잘 만들어 놓은 클래스 하나는 어디서도 다시 사용이 가능하므로 개발자의 효율을 급격히 증가 시킨다.
이 효율의 장점은 곧바로 '돈'과 직결되므로 많은 개발자들이 이 방법을 따르기 시작했다.
이런 객체 지향 언어의 등장은 과거와는 다른 프로그래머와 사용자간의 계층을 만들게 되었다. 원래 과거에는 '개발자'와 '사용자' 딱 두개의 구분만 존재 했다. 개발자가 만들고 사용자가 사용하고. 간단하다.
지금은 '상위 개발자', '중급 개발자', '사용자' 이렇게 나뉜다. 상위 개발자는 중급 개발자에게 자신들이 공들여 안전하게 만든 수많은 클래스와 함수들을 라이브러리로 제공한다.
중급 개발자들은 바로 이 제공되는 아름답고 완벽한 클래스와 함수를 이용해서 자신이 원하는 프로그램을 작성해서, 사용자에게 유통하게 된다.
여기서 '표준적인 방식'이라 함이 바로 클래스와 클래스를 구성하는 멤버 함수 및 변수 작성법 그리고 생성자와 파괴자 규칙, 순수 가상 함수와 동적 연결, 추상 클래스와 상속 및 구현등 수많은 C++의 문법이다.
사실 이제는 C로도 객체 지향을 흉내 낼수 있지만 그래도 원조인 C++ 사용하는게 맞다.
두서 없이 쓴거 같아 잘 쓴건지 모르겠지만 글을 읽는 사람이 C와 C++의 차이를 이해할 수 있었으면 좋겠다. :)
객체 / 클래스 / 객체화 / 추상 클래스 (0) | 2009.03.13 |
---|---|
프로그램, 프로세스, 스레드 (2) | 2008.10.22 |
왜 객체 지향인가? (0) | 2008.01.11 |
젠장할 Direct Show (0) | 2008.01.10 |
RPCGEN (0) | 2007.11.09 |
COM 그 이름만 들어도 살짝 현기증이 날 듯한 이름... Microsoft의 작명 센스는 끝내준다. 몰라도 들어본 것 같고 알아도 헷갈리게 만드는 놀라운 작명 센스... /후아
내 블로그에 남기는 글들은 특정한 기술에 대한 'Teaching' 이 아닌 'Talking' 일 뿐이므로 머리를 쪼그라 들게 하는 깊이 있는 이야기보단 지나가는 이야기이지만 보다 쉽게 이해하기 위해 쓰는 것이므로 이해해 주길 바랍니다.
COM 에 대한 첫 만남은 DirectShow에서 시작되었다. 어찌하다 보니 DirectX를 사용해야 하는 상황이 생겼고 나중에는 DirectShow를 사용해야 하는 상황이 왔던 적이 있다.
물론 전혀 즐겁지 않았다.. -_- DirectShow의 자료를 뒤적거리다 첫 대면을 하게된 COM이란 놈은 DirectShow의 '근간' 이요 '근본' 이며 '바탕'이므로 꼬옥! 알아야 한다는 거였다. 줴엥장.
그때는 시간이 없던 관계로 COM에 대한 이해를 할 시간도 없이 '어떻게' 사용하는가만 집중적으로 판다음 완전히 잊어버리고 살았다.
하지만, 오늘 MSDN에서 COM에 대한 문서를 읽어보니 내가 참 무식했구나 하는 생각이 들었다. 물론 '방법'만 알면 오케이인 일도 많지만 '원리'와 함께 알면 절대 잊어버리지도 않을 뿐더러 연결되는 기술이나 개념에 대한 이해가 훨씬 더 쉽다. 그래서 많은 시간을 투자해가면서 MSDN의 미로를 헤메는 중이다.
이말 읽고 바로 이해되는 사람이 있다면 이글을 읽어볼 필요도 없는 사람이라고 생각한다.-_- 기본적인 프로그램만 짜본 사람의 입장으로써는 이글은 '김밥 옆구리 터지는' 소리다. 한마디로 뭔소린지 잘 모른다.
내가 생각하는 COM의 정의는 '뇌를 가진 C++ 클래스' 정도? 헐헐헐.. 이건 또 뭔소리? 라고 할수 있다. 이제 차근 차근 설명해 보겠다. 왜 COM이 뇌를 가진 C++ 클래스라 생각하는지.
우선 Interface와 Methods가 뭔지 알아야 하는데... 흠... 이걸 여기서 설명하게 되면 COM의 개념만 쉽게 풀고자 했던 내 의도가 딱딱한 MSDN 문서를 읽어주는 것과 다를게 없어지는 것 같아서 안쓰는게 좋을것 같다.
우선 COM의 단어적 의미를 집어내 보면 '요소 객체 모델'인데 모델은 어떤 체계를 말하므로 빼버리고 C가 의미하는 Component인 요소에 집중해 보자.
내가 앞서 말했듯이 DirectShow는 COM을 기반으로 하는데 DirectShow로 짜는 프로그램의 구성을 보게 되면 마치 전산시간에 배웠던 Flow Chart를 그리는 것과 똑같다.
전산 시간에 네모를 그러서 그 사이를 화살표로 연결하여 그렸던 흐름도 혹은 논리 흐름도를 기억하는가?
DirectShow의 시작은 입력과 출력을 가지는 Filter 라고 불리는 사각형들이 서로 물고 물리는 관계를 형성함으로써 시작된다. 하나의 Filter 출력이 다른 Filter의 입력으로 들어가게 되고 또 그 출력이 다른 입력으로 들어간다.
이런식으로 Data가 '물 흐르듯이' Stream을 가지게 되고 이처럼 쉽게 하나의 프로그램을 완성 할수 있다.
바로 여기서 보면 각각의 Filter가 하나의 COM이고 바로 '요소' 인 것이다. 프로그램을 구성하는 본질적인 요소임과 동시에 마치 레고 블록처럼 독립적이어서 가져다 붙여주고 서로 잘 이어주기만 하면 되는 것이다.
사실 이것은 JAVA의 상속과 크게 다르지 않다. C++의 상속과 재활용성과도 일맥 상통한다. 하지만 결정적인 차이가 있으니 바로 '뇌를 가진' 이라는 단어다.
COM으로 만들어진 객체는 이른바 QueryInterface라는 함수를 가지고 있다. 이건 무조건 모든 COM 객체가 가지는 함수로써 마치 C++의 생성자/파괴자와 같이 무조건 필요한 놈이다.
이 QueryInterface 함수의 특이점은, 프로그래머는 반드시 이 함수를 이용해서 COM객체의 다른 함수의 포인터 (진입점) 을 얻어와야 한다는 것이다.
Query의 단어 뜻 그 자체가 '질의한다'라는 의미로써 프로그래머가 COM객체에게 '야, 너 이런이런 함수 지원해주니?' 라고 물어보는 것이다.
더 놀라운 것은 이 COM 객체는 프로그래머가 저렇게 물어왔을때, 만약 지원이 가능하면 해당 기능으로 들어가는 문 (포인터)를 알려주고 만약 지원이 안되면 '안되요!' 라고 하면서 NULL 을 리턴한다는 것이다.
이게 뭐가 대단한가? 라고 의아해 한다면 당신은 아마도 잘못된 함수의 호출로 인해 공포의 퍼런 화면을 한번도 안띄워 본 사람! 우후훗!
뇌를 가졌다고 말하는 이유는 바로 이 기능 때문이다. COM 객체는 스스로가 할수 있는 일과 없는 일은 명확히 구분하여 프로그래머의 사용 미숙이나 강제 호출에도 스스로 'NO' 라고 말할 수 있기 때문에 나는 COM이 생각하는 클래스라고 말했다.
사실 여전히 COM 객체는 프로그래머에게 종속적이기는 하지만 스스로의 독립성과 안전성을 지키려고 하는 것은 예전에 C++의 클래스에서는 찾아보기 힘든 점이다.
MSDN에서 말하기를 'COM 객체는 프로그래머 (혹은 클라이언트) 와 Negotiate 한다.' 라고 했다. 즉, '협상'을 한다는 말인데 프로그래머와 대등한 입장에서 서로 대화를 주고 받는다는 의미라 하겠다. 세상 참 좋아졌다... 컴퓨터가 나랑 협상을 다하고... ㅋㅋ
많은 사람이 착각을 하는 것이 COM이 그 자체로 또다른 '언어'라고 생각하는 것인데 (C나 C++처럼) 사실 그렇지 않다고 생각한다.
다만 COM과 같은 '체계' 혹은 '모델'은 사용자에게 보다 나은 방법의 프로그램 설계 방식을 '제안'하고 있을 뿐이다.
그것을 이해한다면 COM이나 MFC에 대해 겁부터 덜컥 먹을 일이 전혀 없다. C와 C++부터 차근 차근 알아나가면 점점 탄력이 붙어 나중에는 자연스레 이해할 수 있게 된다.
이제 결론을 말하자면,
다만 이 COM을 제대로 사용하기 위해서 반드시 따라야 하는 조건들만 잘 지키면 무리없이 잘 사용할 수 있다는 점.
그리고 COM의 장점이라면,
Visual C++ 2010에서 작성한 프로그램의 배포 방법 세 가지 (0) | 2012.12.14 |
---|---|
[MSDN] /MT, /MTd, /MD, /MDd (C Runtime Library Option) (12) | 2008.10.22 |
[MSDN] End of DLL War! (0) | 2008.10.16 |
[MSDN] DLL HELL!!!! (1) (0) | 2008.10.15 |
[MSDN] Manifest 파일?!?! (0) | 2008.10.14 |
[MSDN] /MT, /MTd, /MD, /MDd (C Runtime Library Option) (12) | 2008.10.22 |
---|---|
[MSDN] COM (Component Object Model) (2) | 2008.10.17 |
[MSDN] DLL HELL!!!! (1) (0) | 2008.10.15 |
[MSDN] Manifest 파일?!?! (0) | 2008.10.14 |
[MSDN] Understanding Dependencies of a Visual C++ Application (0) | 2008.07.21 |
DLL HELL이라는 단어를 처음 접하고 '풋' 하고 웃었다면 당신은 이미 DLL로 인해 머리 한움큼 정도는 뽑아본 사람이 분명하다..
MSDN에서 머리에 쏙쏙 들어올만한 정보를 찾아 수없는 클릭질을 해댄지 어언 10분. 재미있는 재목의 글을 찾았다. 이름하여 THE END OF DLL HELL.
이름만 봐도 재미있을 것 같아서 차근 차근 읽어보았다.
DLL에 대해서 그 개념 정도는 충분히 이해하고 있었으나 정작 DLL이 일으켜온 문제와 어떤 방식으로 DLL의 문제를 종식시켜 나갔는지는 전혀 몰랐다. 이번을 계기로 확실히 알고 넘어가게 되었다.
DLL은 풀어서 쓰면 Dynamic Library Link인데 한국어로 하면 '동적 라이브러리 링크'이다.
C 프로그램을 작성하게 되면 우리는 생각없이 헤더 파일을 포함하는데 대표적인 헤더 파일이 바로 stdio.h파일이라던가 iostream 같은 파일들이다.
이 헤더 파일들은 실행 코드를 담고 있는, 즉 다시말해서, 실행에 필요한 모든 코드를 가지고 있는 것이 아니라 prototype만 담고 있는 글에 불과하다. 책의 '목차'에 불과한 것이다.
실제 '내용'은 바로 라이브러리가 담고 있는데 라이브러리는 참 많다... -_- 짜증나게 많고 다양하다.
대표적으로 Visual Studio 가 사용하는 라이브러리는 MSVCRT.DLL이다. 걍 이놈이란 놈이 자주 쓰인다고 알고 있자.
이 라이브러리는 수많은 윈도우 프로그램들에서 사용이된다. 프로그래머가 짜는 거의 대다수의 프로그램도 이 라이브러리를 사용하게 되는데 자 그렇다면 여기서 생각을 해보자.
만약에 저 라이브러리를 사용하는 모든 프로그램들이 저 MSVCRT.DLL을 하나씩 소유한다면 얼마나 비효율적일까?
우선 하드드라이브에 저 파일이 수십 수백개 만들어질꺼고, 게다가 내 피같은 RAM (메모리)에 저 파일이 수십 수백개가 생길것이다.
즉, 메모리 낭비요 게다가 하드디스크의 낭비다. 물론 요즘 메모리나 하드디스크가 똥값이긴 해도 그래도 낭비는 낭비다!
DLL을 개발해낸 사람의 최후의 카드는 바로 'Consistency' 즉 '일관성' 혹은 '통일성'에 있다. 바로 이것이 DLL의 가치를 드높여 주는 것인데, 이것이 무엇인가 하면...
많은 프로그램이 공유하게 되는 저 MSVCRT.DLL 파일 하나를 수정함으로써 혹은 업뎃함으로써 모든 프로그램의 동작을 수정할 수 있게된다. 즉, 사용되는 파일을 단 하나로 통일 시킴으로 얻게되는 장점이 바로 그것이다.
허나 반대로 말하면 저 파일 하나가 잘못됨으로써 저것을 사용해서 프로그램을 돌리는 모든 것이 한방에 동작을 안할 수도 있다는 말이다. 허걱. 이 얼마나 위험한 일인가...
바로 이런 문제들이 Windows 98이전에는 수도없이 빈번했으며 인증되지 않은 프로그램에 의해서 혹은 사용자의 실수에 의해서 중요한 DLL 파일이 바뀌어지는 바람에 수많은 프로그램이 갑자기 동작을 멈추게 되었고 이로인해 수많은 머리털이 뽑히거나 하드디스크의 쓸데없는 포멧으로 이어진것이다.... 헐헐헐..
이것을 어떻게 고쳤는가는... 다음 글에서 써야 겠다. 집에 가야 할 시간이 왔군요.. ^^
참조 http://msdn.microsoft.com/en-us/library/ms811694.aspx
[MSDN] /MT, /MTd, /MD, /MDd (C Runtime Library Option) (12) | 2008.10.22 |
---|---|
[MSDN] COM (Component Object Model) (2) | 2008.10.17 |
[MSDN] End of DLL War! (0) | 2008.10.16 |
[MSDN] Manifest 파일?!?! (0) | 2008.10.14 |
[MSDN] Understanding Dependencies of a Visual C++ Application (0) | 2008.07.21 |
사실 Visual Studio 2005 (VS 2005)를 사용해 오면서 신경쓰지 않았던 부분이 바로 이 manifest file의 존재다.
아마 이글을 본사람들 중에 상당수도 '저게 뭐임?' 이라고 생각하는 사람이 많을 것이라 생각된다.
이 manifest의 중요성은 내가 만든 프로그램을 다른 컴퓨터에서 돌려볼려고 할때 나타난다. 골 깨지는 소리와 함께... 두둥.
전반적인 설명을 위해 자세한 내용은 무시하고 개념만 적어보자. 내가 잘 까먹으므로 이렇게 적어놓는게 훨씬 도움이 됨...
일단 .NET Framework를 알아야 한다. 다 알거는 없고, 이 녀석은 간단히 말해서 컴퓨터의 spec에 관계 없이 VS 2005로 작성한 프로그램이 잘 돌아가도록 해주는 놈이라고 생각하자.
그니까 int가 4바이트인 컴퓨터건 8바이트인 컴퓨터건 (32 비트 컴퓨터냐 64 비트 컴퓨터냐) 관계없이 내가 짠 프로그램이 잘 돌아가도록 해준다.
상식적으로 .NET Framework가 컴퓨터에 관계없이 내 프로그램을 잘 돌아가게 만들어 준다는 것은 .NET Framework가 어떤 공통적인 무언가를 가지고 있거나 아니면 통일된 규정에 따라서 해당 컴퓨터에 맞게 Binary code (실행 코드)를 만들어 낸다는 것이다.
사실 많은 중요하지만 이해하기 쉽지 않은 단어들이 있다. CLR, CRL, CIL, MSIL, 등등등... 이런것들은 VS 2005 책이나 VS 2008 졸라 두꺼운 책 (빨강색) 에 보면 잘 나와있다. 아니면 MSDN 혹은 Wiki를 머리 뽑으면서 읽으면 이해할 수 있다.
이런거 모두 제끼고, .NET Framework Assemblies을 보자. 이놈들은 일부만 컴파일된 dll 파일들이다. 이놈들은 프로그램이 실행되는 시점 (CLR이 Just-in-time complier를 이용해 machine code를 생성해 내는 시점) 에 호출되어 사용된다.
한마디로 필요한 정보가 저장된 도서관(library)이다. 중요한 것은 이제부터인데, VS 2005를 이용해서 프로그램을 작성하게 되면 기본적으로 VS 2005는 manifest 파일이라는 것을 만들어낸다.
이 manifest 파일은 만들어진 프로그램이 어떤 .NET Framework Assemblies를 사용하는지 그리고 그 버젼은 무엇인지, 또 의존성은 어떻게 되는지 등등등을 설명하고 있다.
한번이라도 VS2005를 이용해서 프로그램을 만들어 본 사람이라면 Debug 혹은 Release 폴더에 manifest 라는 단어가 들어가 있는 파일이 생성된 것을 보았을 것이다.
그 파일을 열어서 보게 되면 안에 내용중에 이런 부분이 있다,
<assemblyIdentity type="win32" name="Microsoft.VC80.DebugCRT" version="8.0.50727.762" processorArchitecture="x86" publicKeyToken="1fc8b3b9a1e18e3b"></assemblyIdentity>
이것이 바로 .NET Assemblies 중에 어떤 버전을 사용하고 있는지 그리고 Debug인지 Release인지, 또 x86 인지 아닌지, 게다가 publickey 까지 자세히 보여주고 있다.
여기서 주목할 것은 name과 version이다. 윈도우 폴더 아래에 있는 WinSxS 라는 폴더를 열어보자. 여기를 열어보면 저 name과 비스무리한 폴더들이 보인다. 그리고 폴더 이름뒤에 version 번호도 보인다.
바로 WinSxS 폴더가 현재 컴퓨터에 설치되어 있는 Shared Side-by-Side Assemblies를 모두 보여준다. 한마디로 이 컴퓨터에서 제공되는 모든 .NET Framework Assemblies를 담고 있는 폴더인 셈이다.
만약 어떤 프로그램을 실행했는데 터무니 없게도 This system cannot execute from this program. 이라든가 위 그림처럼 어이없는 에러가 터진다면 가장 먼저 실행 파일과 함께 있는 manifest 파일을 열어보자. 그리고 그 컴퓨터의 WinSxS 폴더를 열어서 해당 어셈블리가 존재하는지 확인하자.
만약 manifest 파일에 나와있는 Version과 같은 폴더가 존재하지 않는다면 이 컴퓨터는 프로그램을 돌리기 위한 자료가 없기 때문에 실행할 수 없다는 '어이가 없는' 에러 메세지를 내 보낸다.
이것을 해결하기 위한 방법으로는, (확인해 본적은 없지만)
1) 만약 컴퓨터에 VS 2005나 VS 2008이 설치되어 있다면 업데이트를 해라. (업데이트를 하면 새로운 버젼의 어셈블리들이 자동으로 설치된다.)
2) Manifest를 열어서 해당되는 버젼의 DLL 파일을 찾아서 실행파일이 있는 폴더에 복사해 넣어라. 이것은 100% 된다고 장담할 수 없다. .NET Framework가 설치조차 안되어 있다면 아마도 작동 안될 것이다.
3) Microsoft Visual C++ Redistribution (재배포) Package 를 다운받아 설치하라.
3번이 가장 합리적인 방법인데 구글에서 Visual C++ Redistribution package를 검색하면 Visual Studio 2005 와 2008 버전에 대한 각각의 다운로드들이 뜬다. 이 파일을 다운로드 하여 설치하면 WinSxS 폴더에 해당 버전의 어셈블리들이 자동으로 설치되며 Visual Studio가 없는 사람들도 프로그램을 돌릴수 있게 된다.
재배포 파일의 설치가 가장 중요하다... 이 프로그램은 이 컴퓨터에서 돌아갈수 없다는 말도 안되는 문제를 거의 100% 해결해 준다.
[MSDN] /MT, /MTd, /MD, /MDd (C Runtime Library Option) (12) | 2008.10.22 |
---|---|
[MSDN] COM (Component Object Model) (2) | 2008.10.17 |
[MSDN] End of DLL War! (0) | 2008.10.16 |
[MSDN] DLL HELL!!!! (1) (0) | 2008.10.15 |
[MSDN] Understanding Dependencies of a Visual C++ Application (0) | 2008.07.21 |
1등을 해야한다는 강박관념...
뒤쳐지면 안된다는 두려움...
떠나간 사람에 대한 슬픔...
제한된 시간에 대한 미련...
죽음이 가져올 영원한 암흑에 대한 공포...
매 순간 어깨를 누르는 것들을 털어버리자..
등뒤에서 나를 떠밀던 것들을 털어버리자..
주어진 시간이 끝날땐, 저것들에 의해 이끌려온 내가 아닌,
후회없이 살아온 '나'이고 싶다.
친구 이야기 (2) | 2008.12.12 |
---|---|
죽기전에 "한번" 가볼만한 곳 - 알래스카 (0) | 2008.10.16 |
방관자 효과 (0) | 2008.01.15 |
그렇고 그런 이야기 (0) | 2007.11.15 |
오늘의 단편 뉴스 (1) | 2007.11.14 |
[MSDN] /MT, /MTd, /MD, /MDd (C Runtime Library Option) (12) | 2008.10.22 |
---|---|
[MSDN] COM (Component Object Model) (2) | 2008.10.17 |
[MSDN] End of DLL War! (0) | 2008.10.16 |
[MSDN] DLL HELL!!!! (1) (0) | 2008.10.15 |
[MSDN] Manifest 파일?!?! (0) | 2008.10.14 |
[DX Tutorial - Game Display] Lesson 4: Adding Text to the Display (0) | 2008.02.23 |
---|---|
[DX Tutorial - Game Display] Lesson 3: Animation (0) | 2008.02.23 |
[DX Tutorial - Game Display] Lesson 2: More about Sprites (0) | 2008.02.20 |
[DX Tutorial - Game Display] Lession 1: Using Sprites (0) | 2008.02.20 |
[DX Tutorial - Mesh] Lesson 3: Loading Textured Meshes (0) | 2008.02.20 |
이제 글자를 넣어보자.. 이거네
1. All About Fonts
font를 결정하는 세가지 요소가 있으니 바로 typeface, style 그리고 size다.
1-1. Typeface
타입페이스는 폰트의 모양, 길이 그리고 스트로크등을 결정하는 요소다. serif도 typeface를 결정하는 요소인데 이 serif라는 놈을 찾아보니 글자 모양 중에 끝부분에 각이진것을 serif라 하고 없는 것을 san serif라 한다. 다음 그림을 보면 그 예가 있는데
Times New Roman의 글자 중 M자를 보면 아래쪽에 꺽이는 짧은 라인이 들어간다. 위에도 들어간다. 하지만 San serif에는 그런게 없다. 그것이 차이점이란다... 흠... 그랬군..
1-2. Style
Style은 사실 typeface의 변형이다. 이것은 글자의 무게나 기울기등을 담당한다. 무게라함은 사실 blod냐 아니냐를 말하고 기울기라 함은 italics냐 아니냐를 말한다.
1-3. Size
이제는 크기다. 일반적으로 크기라 함은 글자의 제일 윗부분에서 제일 아랫부분의 크기인데 아래 그림에서 보다시피 의외로 낭비되는 공간이 있네.
이것들을 외우고 있을 필요는 없지만 나중에 사용할때는 반드시 이해하고 있는것이 좋다. 당삼하지요.
2. Creating Fonts and Displaying Text
글자를 그려내는것은 과정상으로 보면 되게 간단한데 다음과 같이 2단계만 거치면 된다.
2-1. Create the font
폰트를 만들어내야 하는데 만들기 위해선 D3DXCreateFont() 함수를 호출해야 한다.
LPDIRECT3DDEVICE9 pDevice : 이건뭐 d3ddev다
INT Height : g의 아래쪽 부터 M의 위쪽까지의 크기다. 일반적인 사이즈는 12이다.
UINT Width : 폰트의 폭인데 이것은 각각의 글자마다 다르므로 딱히 하나로 지정할 수는 없고 0으로 설정하면 알아서 적당한 크기의 글자로 찍어낸다. 이 인자는 초기값을 주는 것으로써 아마도 크게 주면 크게 줄수록 글자들 자체가 옆으로 늘어날것으로 예상. (테스트 해보자)
UINT Weight : 글자의 두께. 0에서 1000까지 된다는 군. 0으로 놓으면 기본값으로 표현하기. 이 인자에 대해서는 특별히 두께 플래깅이 존재하는데 다음 테이블과 같다.
Flag | Value |
---|---|
FW_DONTCARE | 0 |
FW_THIN | 100 |
FW_ULTRALIGHT | 200 |
FW_LIGHT | 300 |
FW_REGULAR | 400 |
FW_MEDIUM | 500 |
FW_DEMIBOLD | 600 |
FW_BOLD | 700 |
FW_ULTRABOLD | 800 |
FW_BLACK | 900 |
[Close Table] |
Value | Description |
---|---|
DEFAULT_QUALITY | This indicates that the quality of the font does not matter. |
NONANTIALIASED_QUALITY | This indicates that the edges of the font will not be smooth. It is faster and more efficient than quality types where smooth edges are used. |
ANTIALIASED_QUALITY | This indicates that the edges of the font are smooth. Note that if you don't use either this flag or the prior one, DirectX will use antialiased fonts only if the user has selected "Smooth Screen Fonts" in the Control Panel. |
PROOF_QUALITY | This indicates that the quality of the font is very high, and exactly matches the font image. However, because font images are not given in every size, this setting limits which sizes you can use, and using different fonts will cause DirectX to choose the closest font size supported. |
DRAFT_QUALITY | This indicates that the quality of the font is less important than in PROOF_QUALITY, but it allows you to select different sizes of fonts. Be warned, however, using various styles, such as bold and italic, can slow this one down if you have a lot of fonts. |
[Close Table] |
Value | Description |
---|---|
DT_SINGLELINE | Displays the text on a single line, regardless of line breaks or carraige returns. |
DT_CALCRECT | Calculates the height and width of the rectangle for you, regardless of the values stored specified in the pRect parameter. |
DT_CENTER | Centers the text in the rectangle. |
DT_LEFT | Aligns the text to the left side of the rectangle. |
DT_RIGHT | Aligns the text to the right side of the rectangle. |
DT_TOP | Justifies the text to the top of the rectangle you select. |
DT_BOTTOM | Justifies the text to the bottom of the rectangle you select. It only works when combined with DT_SINGLELINE |
DT_VCENTER | Justifies the text in the center of the rectangle. It only works on single lines. |
DT_WORDBREAK | Lines are automatically broken between words when text reaches the end of a rectangle, thus adding an additional line. |
[Close Table] |
[DX Tutorial - Game Display ] Lessong 5: Buildig a Game Display (2) | 2008.02.23 |
---|---|
[DX Tutorial - Game Display] Lesson 3: Animation (0) | 2008.02.23 |
[DX Tutorial - Game Display] Lesson 2: More about Sprites (0) | 2008.02.20 |
[DX Tutorial - Game Display] Lession 1: Using Sprites (0) | 2008.02.20 |
[DX Tutorial - Mesh] Lesson 3: Loading Textured Meshes (0) | 2008.02.20 |
[DX Tutorial - Game Display ] Lessong 5: Buildig a Game Display (2) | 2008.02.23 |
---|---|
[DX Tutorial - Game Display] Lesson 4: Adding Text to the Display (0) | 2008.02.23 |
[DX Tutorial - Game Display] Lesson 2: More about Sprites (0) | 2008.02.20 |
[DX Tutorial - Game Display] Lession 1: Using Sprites (0) | 2008.02.20 |
[DX Tutorial - Mesh] Lesson 3: Loading Textured Meshes (0) | 2008.02.20 |
스프라이트에 대해서 좀더 알아보자. 앞에서 실험해본 결과 특정 이미지를 특정 위치에 그리는건 좋은데 문제는 투명도 설정이나 그런게 안되서 배경색과 매치가 안되는 경우 심각한 문제를 발생시키더라. 허, 그러고 보니 생각나는게 color key 방법이네 :)
1. Color-Keys
알다시피 지난번에 컬러 키를 이용한 색 제거를 했었다. 이것은 텍스쳐를 사용하는 3차원 물체에 적용했던 것이었는데 스프라이트도 텍스쳐를 사용하므로 컬러 키를 그대로 사용가능하단다.
잘 기억이 나지 않으면 lesson 12에 D3DXCreateTextureFromFileEx() 함수를 참조하라.
Alpha Blending with Sprites
이전에 사용했던 스프라이트를 그리기 위한 함수가 생각나나?
BeginScene()과 EndScene() 사이에 썼던 바로 그 함수인데 컬러 키를 사용하기 위해서는 이 함수에 추가적인 플래그가 필요하다는데...
바로 알파 블랜딩 플래그이구나. 바로 이 플래그를 추가함으로써 우리는 스프라이트를 그릴때 컬러 키를 사용할수도 있고 반투명도를 사용할수도 있단다.
아마도 투패스 코드에도 이런 기본 셋팅 (DX용)이 들어가 있을것이다. 물론 스프라이트로 그리지는 않겠지만 말이다.
Using Color-Keyed Textures
내가 테스트 해본 바로 그 결과를 그림이 보여주는데, 만약 백그라운드 색상이 뻘건 색이면 이렇게 된다.
그리고자 하는 이미지는 사실 검은색 테두리 안에 있는 사각형일 뿐인데 배경색과 달라서 문제가 있다.
그래서 이런 걸 해결하기 위해서 드디어 컬러 키를 사용하는데,
헐, 여기서 잠깐 혼란에 빠졌는데 이 쓰뎅구리가 제대로 설명안해놨다. 바로 요 전에 사용했던 텍스쳐 파일은 배경이 검정색이지만 이 레슨에서 사용하는 새로운 텍스쳐 파일은 배경인 hot pink 색이다.
고것때문에 헷갈려서 한참을 뒤졌네. 젠장할쓴. 결론적으로 위에서 마지막에서 4번째 인자로 지정하는 색이 투명해 지는 것이고 주로 핫 핑크를 쓴단다.
고로 저렇게 하면 다음과 같은 결과가...
2. Semi-Transparency
이제는 좀더 발전된 단계로 진행해보자. 여기서 추가로 반투명도 까지 올리는 것인데, 흠.. 재미있겠는데?
바로 저런걸 해보자는 건데... 반투명한 패널뒤로 물체가 사알짝 비취는 거다.
이렇게 하는것은 매우 매우 간단하다는데 다음 명령만 바꿔주면 된단다.
이것은 그려지는 스프라이트를 50%의 alpha값을 가지도록 하여 반투명하게 만드는 역확을 한다... 너무 간단하다.
결과는 위와 같은 것이다. (물론 화면 왼쪽 상단 일부만 캡춰한거임)
3. The Finished Program
[DX Tutorial - Game Display] Lesson 4: Adding Text to the Display (0) | 2008.02.23 |
---|---|
[DX Tutorial - Game Display] Lesson 3: Animation (0) | 2008.02.23 |
[DX Tutorial - Game Display] Lession 1: Using Sprites (0) | 2008.02.20 |
[DX Tutorial - Mesh] Lesson 3: Loading Textured Meshes (0) | 2008.02.20 |
[DX Tutorial - Mesh] Lesson 2: Loading Meshes From X Files (0) | 2008.02.19 |
[DX Tutorial - Game Display] Lesson 3: Animation (0) | 2008.02.23 |
---|---|
[DX Tutorial - Game Display] Lesson 2: More about Sprites (0) | 2008.02.20 |
[DX Tutorial - Mesh] Lesson 3: Loading Textured Meshes (0) | 2008.02.20 |
[DX Tutorial - Mesh] Lesson 2: Loading Meshes From X Files (0) | 2008.02.19 |
[DX Tutorial - Mesh] Lesson 1: Using Basic Meshes (0) | 2008.02.16 |