2018년 1월 13일 토요일

Hello World - OpenGL 기초 만들기

Hello World - 기초 만들기


윈도우를 만들고 운형하는 것은 여기서 설명하지는 않겠다.
이 글은 하나의 윈도우에 OpenGL을 적용하여 OpenGL Context 를 만들고 여기에 삼각형을 렌더링 하는 방법에 대하여 설명하고자 한다.

모든 언어의 처음은 대부분 “Hello World!!!” 일 것이다.

일반적으로 3D 그래픽 프로그램에서는 화면에 삼각형을 하나 그리는 것으로 Hello World 를 제시하게 된다.



이 글에서 우리는 OpenGL 과 Direct3D(다른페이지에서) 모두 설명할 것이다.

하나의 윈도우가 있고 이에 대한 HWND 가 있다고 하고 출발하도록 하자.


OpenGL

우리는 일차적으로 다음과 같은 내용에 대하여 프로그램 코딩을 할 것이다.

bool Init3D(HWND hwnd);
void SetBkColor(float r,float g,float b,float a);
void ClearBk();
void SwapBuffer();
void RenderScene();




Init3D
전달된 윈도우 핸들 hwnd 를 이용하여 HDC를 구하고 HDC에서 HGRC를 준비하여 OpenGL Context 를 만든다.

SetBkColor()
OpenGL Context의 배경색을 정한다.

RenderScene()
화면에 나타날 그림을 backbuffer에 준비한다.

ClearBk()
OpenGL Context를 정해진 배경색으로 지운다.

SwapBuffer()
화면을 갱신한다.
Color in OpenGL
Direct3D 와 OpenGL 에서 공통으로 사용하기 위하여 직접 class 를 만들어 사용하기로 한다.

OpenGL의 Color는 정하기 나름이지만 기본적으로 RGBA 를 사용한다고 보면 된다.
이는 OpenGL의 경우 PixelFormat을 준비할 때 설정한 값에 기인한다.
이에 대한 내용은 다음 링크 페이지에서 PixelFormat 부분을 살펴보기 바란다.

PIXELFORMATDESCRIPTOR 의 4번째 필드인 iPixelType 을 살펴보면 PFD_TYPE_RGBA 로 설정된 것을 알 수 있다.

Windows SDK의 내용을 보면

iPixelType
Specifies the type of pixel data. The following types are defined.
Value
Meaning
PFD_TYPE_RGBA
RGBA pixels. Each pixel has four components in this order: red, green, blue, and alpha.
PFD_TYPE_COLORINDEX
Color-index pixels. Each pixel uses a color-index value.

Pixel 데이터의 타입을 설정하는 값이며 위의 두가지 중 하나가 될 수 있다.
PFD_TYPE_RGBA 는 RGBA pixel 형식을 취하며 각 픽셀에 대하여 4개의 컴포넌트를 갖는다. 그 순서는 red, green, blue, alpha 이다.
만약 PFD_TYPE_COLORINDEX 로 설정 한다면 OpenGL 에서 color palette 를 만들어 적용해야 하는데 대부분 이 옵션을 사용하지 않는다. 만약 이 옵션을 사용하고 싶으면 다음 사이트를 참조하기 바라며 여기서는 설명하지 않겠다.




c_color4f.h


class c_color4f
{
public:
// Color components: red, green, blue, alpha
union
{
struct
{
float r; ///< Red component
float g; ///< Green component
float b; ///< Blue component
float a; ///< Alpha component

};
float f[4];

};

};



// 필요한 변수들... 초기화는 각자 적절하게 하기 바람...
int m_pixelformat=0;
HGLRC m_hrc=0;
HWND m_hwnd=0;
HDC m_hdc=0;
bool m_initialized=false;
c_color4f m_bkcolor;


// 초기화 함수
bool Init3D(HWND hwnd)
{
if(m_initialized) return false;

m_hwnd = hwnd;
m_hdc = GetDC(m_hwnd);


   // Set pixel format
PIXELFORMATDESCRIPTOR pfd = {
sizeof(PIXELFORMATDESCRIPTOR),
1,
PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL |  PFD_DOUBLEBUFFER,
PFD_TYPE_RGBA,
24,
0,0,0,0,0,0,
0,0,
0,0,0,0,0,
32,
0,
0,
PFD_MAIN_PLANE,
0,
0,0,0
};

m_pixelformat = ChoosePixelFormat(m_hdc, &pfd);
SetPixelFormat(m_hdc, m_pixelformat, &pfd);

          // Create GL Context
m_hrc = wglCreateContext(m_hdc);
wglMakeCurrent(m_hdc, m_hrc);

m_initialized = true;
return true;
}


배경 색상의 설정
void SetBkColor(float r,float g,float b,float a)
{
   m_bkcolor = c_color4f(r,g,b,a);
}


다음과 같이 호출하여 background color를 설정한다.
아래의 색상 값은 위의 그림과 같은 진한 청색이 될 것이다.

SetBkColor(0.0f, 0.2f, 0.4f, 1.0f);

배경을 지우는 함수
void ClearBk()
{
// Clear the screen to bkcolor
glClearColor(m_bkcolor.r,m_bkcolor.g,m_bkcolor.b,m_bkcolor.a);
glClear(GL_COLOR_BUFFER_BIT);
}


Swap Buffer 함수
void SwapBuffer()
{
::SwapBuffers(m_hdc);
}



화면 준비와 갱신
void RenderScene()
{
if(m_initialized==false) return;

// back buffer에 적용하게 된다.
ClearBk();  // 배경을 지운다

// 이부분에 실제 그림을 그리는 부분을 작성한다.

// back buffer 와 front buffer를 교환한다. 즉 그려진 그림을 실제 화면에 뿌리는 기능.
SwapBuffer();
}

SwapBuffer의 경우 함수를 따로 만들지 않고 직접 호출해도 되지만, 작성된 실제의 프로젝트 코드는 이런 함수 들이 virtual class로 작성 하여 virtual class에 의한 OpenGL 과 Direct3D를 같은 구조로 작동 시키기 위하여 만들게 된 것이다.

위의 코드들에서 보고 다음과 같은 규칙을 알아두어야 한다.

Windows API의 함수인 경우 대문자로 시작되었다.
예를 들면 GetDC,SetPixelFormat, SwapBuffers 와 같은…

또한 OpenGL API 함수들의 이름은 gl*** 형식으로 되어 있다는 것…
예를 들면 glClear, glClearColor 와 같은…

또한 wgl*** 로 된 함수도 있다.

이들 차이에서 gl*** 과 wgl*** 차이는

gl*** 은 OpenGL 표준 함수들이다.
wgl*** 은 OpenGL 함수 이지만 Microsoft Windows 에 적용되는 함수라는 것이다.

이에 대해서는 위키
를 참조하기 바란다.

이들 함수의 이름도 그렇지만 전달되는 인수를 살펴보기 바란다.

순수 Windows API는 그 인수가 일단 Windows 관련 인자들로 구성된다.
예를 들면 ChoosePixelFormat 함수

gl*** 은 역시 OpenGL 에서 사용할 수 있는 인자들로 구성된다.
예를 들면 glClear 함수

wgl*** 함수를 보면 두가지가 혼합되는 것을 볼 수 있다.
예를 들면 wglCreateContext 함수. 이 함수의 인수는 hdc 로 윈도우 관련이지만 그 return 값은 hrc 로 Rendering Context 값으로 OpenGL 과 관련된 인자이기 때문이다.

이렇게 함수의 네이밍 규칙을 알면 프로그램 코드를 이해하는데 많은 도움이 될 것이다.





위에 설명된 코드로 실제 프로그램에 적용을 하게 되면 적용된 윈도우가 다음과 같은 화면이 될 것이다.









댓글 없음:

댓글 쓰기

Vertex , 정점 정보의 확장

Vertex , 정점 정보의 확장 그동안의 설명에 있어서 우리는 VERTEX 정보에 대하여 3 차원의 위치 정보만 사용하였다. struct VERTEX {float x,y,z;}; 이제 이를 확장하여 색상을...