Creating A Window

Date:     Updated:

카테고리:

태그:

Main Reference
- Learn OpenGL
- Rinthel Kwon - OpenGL Lecture


Build Setting

OpenGL을 사용하기 위해 가장 먼저 해야하는 일은 우리가 사용할 window를 만드는 것과 추상화된 context를 정의하는 것이다. 일반적으로 운영체제, 하드웨어(그래픽카드 종류, 버전)에 따라 그에 맞는 함수들을 연결해줘야 하는데 이를 편하게 해주는 라이브러리들이 존재한다. 해당 라이브러리들은 cmake를 이용해 빌드해주면 된다.

# ExternalProject 관련 명령어 셋 추가
include(ExternalProject)

# Dependency 관련 변수 설정
set(DEP_INSTALL_DIR ${PROJECT_BINARY_DIR}/install)
set(DEP_INCLUDE_DIR ${DEP_INSTALL_DIR}/include)
set(DEP_LIB_DIR ${DEP_INSTALL_DIR}/lib)

# spdlog: fast logger library
ExternalProject_Add(
    dep_spdlog
    GIT_REPOSITORY "https://github.com/gabime/spdlog.git"
    GIT_TAG "v1.x"
    GIT_SHALLOW 1
    UPDATE_COMMAND ""
    PATCH_COMMAND ""
    CMAKE_ARGS -DCMAKE_INSTALL_PREFIX=${DEP_INSTALL_DIR}
    TEST_COMMAND ""
)
# Dependency 리스트 및 라이브러리 파일 리스트 추가
set(DEP_LIST ${DEP_LIST} dep_spdlog)
set(DEP_LIBS ${DEP_LIBS} spdlog$<$<CONFIG:Debug>:d>)


# glfw
ExternalProject_Add(
dep_glfw
GIT_REPOSITORY "https://github.com/glfw/glfw.git"
GIT_TAG "3.3.2"
GIT_SHALLOW 1
UPDATE_COMMAND "" PATCH_COMMAND "" TEST_COMMAND ""
CMAKE_ARGS
    -DCMAKE_INSTALL_PREFIX=${DEP_INSTALL_DIR}
    -DGLFW_BUILD_EXAMPLES=OFF
    -DGLFW_BUILD_TESTS=OFF
    -DGLFW_BUILD_DOCS=OFF
)

set(DEP_LIST ${DEP_LIST} dep_glfw)
set(DEP_LIBS ${DEP_LIBS} glfw3)

# glad
ExternalProject_Add(
dep_glad
GIT_REPOSITORY "https://github.com/Dav1dde/glad"
GIT_TAG "v0.1.34"
GIT_SHALLOW 1
UPDATE_COMMAND ""
PATCH_COMMAND ""
CMAKE_ARGS
    -DCMAKE_INSTALL_PREFIX=${DEP_INSTALL_DIR}
    -DGLAD_INSTALL=ON
TEST_COMMAND ""
)

set(DEP_LIST ${DEP_LIST} dep_glad)
set(DEP_LIBS ${DEP_LIBS} glad)
  • spdlog : cout보다 가볍고 빠른 로깅 라이브러리. (보기도 편함)
  • glfw : openGL context 정의, 사용자 입력 처리
  • glad : openGL은 스펙과 구현체(dll)가 별도로 존재. 런타임에 드라이버에 맞는 구현체 로딩


OpenGL Initialization

int main(int argc, const char** argv)
{
   SPDLOG_INFO("Start Program");

   SPDLOG_INFO("Initialize glfw");
   if (!glfwInit()) {
      const char* description = nullptr;
      glfwGetError(&description);
      SPDLOG_ERROR("failed to initialize glfw: {}", description);
      return -1;
   }

   glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
   glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
   glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);

   SPDLOG_INFO("Create glfw window");
   auto window = glfwCreateWindow(WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_NAME, nullptr, nullptr);
   if (!window) {
      SPDLOG_ERROR("failed to create glfw window");
      glfwTerminate();
      return -1;
   }
   glfwMakeContextCurrent(window);

   // glad를 활용한 OpenGL 함수 로딩
   if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress)) {
      SPDLOG_ERROR("failed to initialize glad");
      glfwTerminate();
      return -1;
   }
   auto glVersion = glGetString(GL_VERSION);
   SPDLOG_INFO("OpenGL context version: {}", (const char*)glVersion);

   OnFramebufferSizeChange(window, WINDOW_WIDTH, WINDOW_HEIGHT);
   glfwSetFramebufferSizeCallback(window, OnFramebufferSizeChange);
   glfwSetKeyCallback(window, OnKeyEvent);

   SPDLOG_INFO("Start main loop");
      while (!glfwWindowShouldClose(window)) {
         glfwPollEvents();
         glClearColor(0.0f, 0.1f, 0.2f, 0.0f);
         glClear(GL_COLOR_BUFFER_BIT);
         glfwSwapBuffers(window);
      }

      glfwTerminate();
      return 0;
}       
  • glfwInit이후 glfwWindowHHint 함수를 통해 OpenGL 버전, profile 명시
    • CORE_PROFILE은 더 이상 사용되지 않는(deprecated) 기능은 포함하지 않음
  • glfwCreateWindow함수로 window 생성
  • glfwMakeContextCurrent 로 context와 window 바인딩
  • gladLoadGLLoader: glad를 이용해 드라이버에 맞는 openGL 함수 로딩
    • 참고) context 생성 이후에 해야 함 (헤더파일 include할 때는 glfw보다 먼저 해야 함)


Callback 함수 추가

glfwXXXXCallback()

void OnFramebufferSizeChange(GLFWwindow* window, int width, int height) {
    SPDLOG_INFO("framebuffer size changed: ({} x {})", width, height);
    glViewport(0, 0, width, height);
}
 
void OnKeyEvent(GLFWwindow* window,
    int key, int scancode, int action, int mods) {
    SPDLOG_INFO("key: {}, scancode: {}, action: {}, mods: {}{}{}",
        key, scancode,
        action == GLFW_PRESS ? "Pressed" :
        action == GLFW_RELEASE ? "Released" :
        action == GLFW_REPEAT ? "Repeat" : "Unknown",
        mods & GLFW_MOD_CONTROL ? "C" : "-",
        mods & GLFW_MOD_SHIFT ? "S" : "-",
        mods & GLFW_MOD_ALT ? "A" : "-");
    if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS) {
        glfwSetWindowShouldClose(window, true);
    }
}


int main() {
    // ...
    glfwSetFramebufferSizeCallback(window, OnFramebufferSizeChange);
    glfwSetKeyCallback(window, OnKeyEvent);
}

image

  • glfw로 생성한 window에서 특정 이벤트가 발생했을 때 호출되는 콜백함수 추가
  • glfw 함수를 통해 다양한 Input 다룰 수 있음


Create Winodw

   while (!glfwWindowShouldClose(window)) {
      glfwPollEvents();
      glClearColor(0.0f, 0.1f, 0.2f, 0.0f);
      glClear(GL_COLOR_BUFFER_BIT);
      glfwSwapBuffers(window);
   }
  • glfwPollEvents : 이벤트 큐에 들어있는 이벤트들을 처리하면서 해당되는 콜백함수 호출
  • glClearColor : clear 컬러 지정 (Render함수 작성할 때에는 while문 밖에서 설정)
  • glfwSwapBuffers : back buffer와 스왑

image-1



맨 위로 이동하기

OpenGL 카테고리 내 다른 글 보러가기

댓글 남기기