Today, I will

[OpenGL] Learn Open GL 기본 코드 hello_window_clear 본문

Computer Science/그래픽스

[OpenGL] Learn Open GL 기본 코드 hello_window_clear

Lv.Forest 2023. 10. 10. 21:26

*컴퓨터 그래픽스 강의와 Learn Open GL Code를 참고하여 작성한 포스팅입니다.

 

LearnOpenGL - Creating a window

Creating a window Getting-started/Creating-a-window The first thing we need to do before we start creating stunning graphics is to create an OpenGL context and an application window to draw in. However, those operations are specific per operating system an

learnopengl.com

hello_window_clear.cpp

 

해당 코드는 별다르게 렌더링하는 것이 없으나 LearnOpenGL 기본 코드 구조가 잘 나타나 있다.

여타 LearnOpenGL 코드 베이스를 공유하고 있으므로 정리 겸 포스팅을 해두기로 하였다.

#include <glad/glad.h>
#include <GLFW/glfw3.h> 

GLFW와 GLAD 헤더(os 종속적인 작업을 처리해주는 라이브러리)

(1) GLFW : windowing과 Message handing을 처리

 - 유저인터페이스에서 발생하는 이벤트 메시지들을 핸들링해준다.

(2) GLAD : 하우스키핑 jobs들을 대신 처리해준다.


#include <iostream>

void framebuffer_size_callback(GLFWwindow* window, int width, int height);
void processInput(GLFWwindow *window);

const unsigned int SCR_WIDTH = 800;
const unsigned int SCR_HEIGHT = 600;

int main()
{


GLFW init

기계적인 코드 부분으로, 변경할 일이 거의 없다.



    // glfw: initialize and configure
    // ------------------------------
    glfwInit();
    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); // Open GL core 3.3을 쓰겠다
    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); // Open GL core 3.3을 쓰겠다
    glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);

#ifdef __APPLE__
    glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
#endif

    // glfw window creation
    // --------------------
    GLFWwindow* window = glfwCreateWindow(SCR_WIDTH, SCR_HEIGHT, "LearnOpenGL", NULL, NULL);

// 윈도우를 만든다. SCR_WIDTH(폭), SCR_HEIGHT(높이)는 위에서 const로 선언 정의


    if (window == NULL)
    {
        std::cout << "Failed to create GLFW window" << std::endl;
        glfwTerminate();
        return -1;
    }

// 잘 만들어졌는지 확인한다.


    glfwMakeContextCurrent(window); // 현재 윈도우에 open gl 컨텍스트가 만들어지도록 선언
    glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);


// 렌더링을 하려면, 프레임버퍼(픽셀들이 저장되는 곳)가 만들어져야 한다.

// 윈도우가 만들어지면서 프레임버퍼도 같이 만들어지게 된다. 일반적인 프레임버퍼 사이즈는 윈도우(녹색부분)에 해당하는 부분 만큼 만들어지게 된다.

// 렌더링을 할 스크린(뷰포트)을 같이 셋업하기 위해 callback을 쓴다. 윈도우 시스템은 기본적으로 메시지 콜백 매커니즘을 통해 메시지를 핸들링하게 된다.(추후 키보드 마우스 콜백 등 다양한 콜백을 추가하여 쓸 수 있다)

해당 코드에서는 프레임버퍼가 처음 만들어졌다는 이벤트가 발생하게 되고, 프레임버퍼 사이즈에 맞는 뷰포트를 만드는 조치를 framebuffer_size_callback 펑션이 수행한다. 이러한 콜백 펑션은 사용자가 정의해야 한다.

// glfw: whenever the window size changed (by OS or user resize) this callback function executes
// ---------------------------------------------------------------------------------------------
void framebuffer_size_callback(GLFWwindow* window, int width, int height)
{
    // make sure the viewport matches the new window dimensions; note that width and 
    // height will be significantly larger than specified on retina displays.
    glViewport(0, 0, width, height); // 오픈지엘 펑션이다.
}

 

프레임버퍼

2D array of pixels. 래스터라이제이션된 픽셀이 저장되는 곳으로 GPU 내에 있다.

엄밀히 따지면 RGBA와 Z-buffer(=depth buffer)이 저장되며 Double buffering 또한 일반적인 GPU 상에 전부 다 들어있다.

 - A : 투명도

 - Z-buffer : 각 픽셀마다 distance를 저장(픽셀마다 depth value가 있음)

 - Double buffering : 2개의 똑같은 full frame buffers을 front와 back으로 나누어 back에다 애니메이션이 다 그려지면 front에 보여주는 방식을 꾀하여 flicker-free real time animation을 구현하는데 쓰인다.

 

뷰포트

glViewport(0, 0, width, height);

width, height는 프레임 버퍼의 크기,

프레임 버퍼와 똑같은 뷰포트를 만든다

렌더링 마지막 결과는 뷰포트(프로젝션 범위)에 디스플레이되는 것이다. 이 뷰포트의 크기가 얼마인지는 프레임버퍼 콜백에서 정해주어야 한다. 뷰포트는 스크린 사이즈에 종속적이다.

 



    // glad: load all OpenGL function pointers 
    // GLAD init, 역시나 기계적인 코드
    if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress))
    {
        std::cout << "Failed to initialize GLAD" << std::endl;
        return -1;
    }    

   


render loop

제일 중요

 

윈도우가 닫히기 전까지 끊임없이 돌면서 렌더링을 한다.



    while (!glfwWindowShouldClose(window))
    {
        // input
        processInput(window); // (1) 유저인터페이스 처리

        // render                          (2) 렌더링파트이지만 이 코드에서는 사실상 렌더링하는 것이 없다.
        glClearColor(0.2f, 0.3f, 0.3f, 1.0f); // normalize되어 있다 (0~1 사이의 rgb)
        glClear(GL_COLOR_BUFFER_BIT); //<1> 프레임버퍼에서 컬러에 해당하는 비트를 다 클리어, 

             // rgb가 0.2f, 0.3f, 0.3f, 1.0f인 컬러로 프레임버퍼 컬러비트를 깨끗하게 지운다(결과 : 청록색)

        // glfw: swap buffers and poll IO events (keys pressed/released, mouse moved etc.) 위에서 언급한 더블버퍼링
        glfwSwapBuffers(window);
        glfwPollEvents(); // 그 다음 이벤트가 무엇이 있는지 확인차 기다림
    }




    // glfw: terminate, clearing all previously allocated GLFW resources.
    glfwTerminate();
    return 0;
}

// process all input: query GLFW whether relevant keys are pressed/released this frame and react accordingly
void processInput(GLFWwindow *window)
{
    if(glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS)
        glfwSetWindowShouldClose(window, true);
}