기본 요구 사항
본 블로그는 C++ 언어, Windows 운영체제를 기반으로 OpenGL 을 공부한다.
What is OpenGL?
OpenGL은 주요 키워드는 cross-platform, state machine 이다. cross-platform은 Ios, Android, Windows, Linux 등 각종 운영 체제에서 사용 가능하다는 뜻이며, state machine은 어떤 상태를 저장하여 출력하는 기계라고 생각하자. 학습을 하면서 더 와닿게 된다.
기본적으로 OpenGL은 version 3.3에서 극적으로 바뀐다. version 3.3 이전에는 Immediate Mode를 통해 손쉬운 방법이 가능했지만, OpenGL 3.3을 기점으로 Core-Profile이라는 모드가 생겼다. Immediate Mode보다 상대적으로 어렵지만, 프로그래머가 그래픽을 조작할 수 있는 자유도가 높아졌다. 물론 지금은 version 4.6까지 나왔지만, 3.3 이상의 버전만 한 번 잘 익혀두면 4.6으로 가는 데에는 큰 어려움은 없다.
Why OpenGL?
OpenGL은 khronos 사에서 만든 그래픽 API로 다양한 운영체제에서 사용 가능하며, CPU가 아닌 GPU에서 그래픽 작업을 가능케 한다. 요즘 주목 받는 메타버스, VR/AR 등으로 인해 인기가 높아지고 있다. Windows의 DirectX, Apple의 Metal 등 다양한 그래픽 API와 Unity, Unreal 등 렌더링 엔진이 많이 나왔지만, 그 기저에는 OpenGL이 있다고 해도 과언이 아니다. 물론, 그래픽을 자세히 알고 싶지 않은 사람에게는 굳이? 라는 의문이 들지만, 그래픽 공부를 제대로 해보고 싶다는 사람에게는 추천한다. (그중에 하나..)
OpenGL이 cross platform이긴 하지만, 드라이버, 운영체제마다 취해야 하는 조치가 다르다. Nvidia, AMD 그래픽 카드 드라이버마다 지원되는 OpenGL extension이 다르며, 사실 3.3 이상에서는 사용하지 않아도 된다.
How to use OpenGL?
OpenGL은 그냥 그래픽 api이다. 즉, window가 없다! (Windows 운영체제는 대문자로 표기) window가 없다는 말이 무슨 말인지 헷갈릴 수 있지만, 우리가 보는 모든 웹 사이트, 메모장, 등은 window 위에 표시된다. 이 window는 자동으로 생기는 게 아니며, 각 운영체제마다 내부 메커니즘을 따라 생성되고, 저장된다. 그런데 OpenGL은 그저 GPU와 통신하는 그래픽 API 이지, 그걸 window에 표시하려면 다른 framework나 library를 사용해야 한다. 가장 대표적으로는 GLFW가 있으며, CMAKE를 이용해서 build, link 하면 이용 가능하다. (build, link를 아예 처음 들었다면 그래픽 공부는 무리일수도!)
http://www.glfw.org/download.html -> 를 통해 GLFW 다운로드가 가능하며, documentation을 보고 천천히 따라해라!
Window를 만들 수 있는 라이브러리, 프레임 워크가 준비되었다면, OpenGL context를 만들어야 한다. OpenGL context는 OpenGL을 화면에 표시할 때 필요한 Context이며, 필수이다. 차차 알아가도록 하자!
What about this Blog?
이 블로그는 OpenGL을 MFC라는 Microsoft 사가 제공하는 Library를 통해 진행하려고 한다. IDE는 Visual Studio를 사용하며, 이유는 Microsoft SDK에는 기본적으로 opengl32.lib이 지원되어 Visual Studio 설정에서 linker에 포함만 시키면 사용 가능하며, MFC는 OpenGL context를 쉽게 만들 수 있기 때문에, 너무나도 오래되었지만 그래도 사용하고자 한다! Microsoft SDK에서 제공하는 opengl32.lib은 version 1.1이기에, 더 높은 version을 사용하기 위해 GLAD를 다운 받자.
What is GLAD?
OpenGL은 그저, 그래픽 API이다. 통일된 기준, 규정이며, 디테일한 활용법과 적용은 그래픽 드라이버마다 다르다. OpenGL을 사용하는 그래픽 드라이버는 너무나도 많으며, OpenGL 함수를 사용하고자 할 때마다, 함수의 위치를 찾는 것은 compile-time에는 알 수 없으며, runtime에만 알 수 있다. 따라서, 함수의 위치 탐색은 개발자의 업무이며 심지어 운영체제마다 다르기에, 여간 피곤하지 않다. 그 때 필요한게 GLAD 같은 library이며, opengl의 높은 version을 다운로드 받을 수 있다.
Download GLAD
다른 version을 선택해도 무관하지만, 필자는 3.3을 선택했다. Extension은 그래픽 드라이버마다 별도로 지원하는 확장으로 무시하도록 한다.
Options는 그대로 유지한 체, GENERATE 버튼을 누르자.
모든 파일을 다운로드 받고, include안에는 glad.h 와 KHR.h가 있으며, src안에는 glad.c 가 있다. glad.c는 Visual Studio 프로젝트에 포함시키며, glad.h 와 KHR.h는 Visual Studio IDE에서 프로젝트 설정의 include directory에 포함시켜, #incldue 매크로 적용되게 하자. 구글링하면 충분히 나온다!
Setting MFC and OpenGL
MFC는 기본적으로 SDI 로 설정하고, 기본적인 세팅들은 유지한다. 가장 먼저 해야 하는게, OpenGL context를 만드는 것이다.
SetupGLAD() 로 GLAD를 세팅하고, SetupPixelFormat()을 통해 스크린에 나오게 될 pixel 형식을 지정한다. 그 후에, InitializeOpenGL() 함수에서 wglCreateContext(Windows 운영체제와 OpenGL을 연결하는) 를 통해 device context, rendering context를 만든다.
BOOL CstructureView::InitializeOpenGL() {
m_pDC = new CClientDC(this);
if (NULL == m_pDC) {
MessageBox(_T("m_pDC gone"));
return FALSE;
}
if (!SetupPixelFormat())
return FALSE;
if (0 == (m_hRC = ::wglCreateContext(m_pDC->GetSafeHdc()))) {
MessageBox(_T("m_hRC gone"));
return FALSE;
}
if (FALSE == ::wglMakeCurrent(m_pDC->GetSafeHdc(), m_hRC)) {
MessageBox(_T("m_hRC gone"));
return FALSE;
}
if (FALSE == SetupGLAD()) {
MessageBox(_T("glad gone"));
return FALSE;
}
glClearColor(0.9f, 0.9f, 0.9f, 1.0f);
glClearDepth(1.0f);
glEnable(GL_DEPTH_TEST);
glEnable(GL_ALPHA_TEST);
if (GL_VERSION_3_3 > GL_VERSION) {
MessageBox(_T("Graphic Driver doens't support OpenGL 3.3 or above"));
OnDestroy();
}
return TRUE;
}
BOOL CstructureView::SetupGLAD() {
if (NULL == gladLoadGL()) // don't know how this works exactly
return FALSE;
const GLubyte* version = glGetString(GL_VERSION);
}
BOOL CstructureView::SetupPixelFormat() {
static PIXELFORMATDESCRIPTOR pfd = {
sizeof(PIXELFORMATDESCRIPTOR),
1, // version number of data structure
PFD_DRAW_TO_WINDOW | // buffer can draw to a window or device surface
PFD_SUPPORT_OPENGL | // buffer supports Opengl
PFD_DOUBLEBUFFER, // buffer is double-buffered.
PFD_TYPE_RGBA, // RGBA type, or Color-index value
24, // 24 bit color depth
0, 0, 0, 0, 0, 0, // color bits ignored
0, // no alpha buffer
0, // no alpha shift bit
0, // no accumulation buffer
0, 0, 0, 0, // accum bits ignored
32, // 32-bit z buffer
0, // no stencil buffer
0, // no auxiliary buffer
PFD_MAIN_PLANE, // MAIN LAYER
0,
0, 0, 0 // layer masks ignored
};
int pixelFormat;
if (0 == (pixelFormat = ::ChoosePixelFormat(m_pDC->GetSafeHdc(), &pfd))) {
return FALSE;
}
if (FALSE == ::SetPixelFormat(m_pDC->GetSafeHdc(), pixelFormat, &pfd)) {
return FALSE;
}
return TRUE;
}
https://github.com/BaeSungHyun/selfCAD/commit/715b0c3a04ded206374e55fe5b391993afdc7873
추가적인 내용은 github을 참고하자.
'Computer Science > Graphics' 카테고리의 다른 글
OpenGL 2. Coordinates, 좌표 (2) | 2023.08.10 |
---|