* always thanks to https://learnopengl.com/
4. Hello Window
- .cpp파일을 만들고 아래 헤더파일을 추가해준다.
#include <glad/glad.h>
#include <GLFW/glfw3.h>
- glad에서 glfw의 일부분의 내용을 포함하고 있기때문에 glad.h를 glfw3.h보다 먼저 include 해줘야 한다.
int main() {
glfwInit();
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
return 0;
}
- initialize GLFW (with glfwInit)
- configure GLFW (using glfwWindowHint) : 첫번째 인자는 configure option을 두번째는 선택한 option의 integer value이다.
- major, minor 버전에 3.3을 사용할 것 이라고 GLFW에게 말해준다. 이때 올바른 버전의 OpenGL이 아니라면 fail이 발생한다.
- OpenGL 3.3 혹은 이상이 설치되어있어야 한다.
- core-profile을 사용할 것 이라고 GLFW에게 말해준다.
- Mac OS X 에서는 glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); 를 추가해야 한다.
- 그다음은 window object를 만들어야한다.
- 이 window object는 windowing data를 가지고 있다.
GLFWwindow* window = glfwCreateWindow(800, 600, "LearnOpenGL", NULL, NULL);
if (window == NULL) {
std::cout << "Failed to create GLFW window" << std::endl;
glfwTerminate();
return -1;
}
glfwMakeContextCurrent(window);
- The glfwCreateWindow function은 window width와 height, window name 그리고 마지막 두개의 parameters를 받는다.
- 이 함수는 GLFWwindow object를 반환하며 이곳에 context를 만듦으로써 그림을 그리게 될 것이다.
4.1 GLAD
- GLAD가 앞으로 호출할 OpenGL의 함수들의 함수포인터를 관리해준다 따라서 더 나아가 OpenGL functions를 호출하기 전에 GLAD를 먼저 initialize 해준다.
if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress)) {
std::cout << "Failed to initialize GLAD" << std::endl;
return -1;
}
- OpenGL의 함수 포인터 주소를 load해주는 함수를 GLAD에게 전달해줘야한다.
- GLFW는 glfwGetProcAddress을 제공한다. 이것은 OS에 specific한 함수를 정의하고 있다.
4.2 Viewport
- rendering을 시작하기 전에 OpenGL에게 rendering window의 사이즈를 알려줘야한다. 그러면 OpenGL이 데이터들을 어떻게 display하고 window에 대해 좌표를 설정할 것인지 알고있게된다.
glViewport(0, 0, 800, 600);
- 첫번째, 두번째 매개변수는 좌하단 corner 좌표 / 세번째, 네번째 좌표는 rendering window의 width 와 height이다. window크기와 동일하게 설정하였다.
- viewport크기를 GLFW window크기보다 작게 해서 여러 elements를 띄우게 할 수도있다.
- 화면뒤에서 OpenGL은 glViewport를 거쳐서 data를 2D로 변환한다. 예를들면 (-0.5,0.5)이라는 point는 최종적으로 (200,450)로 매핑되어 screen에 표시된다.
- OpenGL에서 process되는 좌표는 -1과 1사이이고 코드에서 정의한 바와 같이 (0, 800)와 (0, 600) 사이로 변환될 것이다.
- 이번 예제에는 callback함수를 window에게 전달하여 window가 resize될 때마다 viewport가 adjust되도록 할 것이다.
void framebuffer_size_callback(GLFWwindow* window, int width, int height) {
glViewport(0, 0, width, height);
}
- window의 resize된 width와 height을 받아서 viewport의 크기를 조정한다.
glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);
- GLFW window가 resize될 때마다 callback 함수를 호출하라고 알려준다.
- window를 create하고 render loop가 initiate되기 전에 callback함수를 register한다.
4.3 Ready your engines
- 그림을 그리고 바로 window를 종료하는 것 이상을 하기 위해서는 사용자의 input을 기다리거나 명시적으로 그만하기를 요청할 때까지 화면에 그림을 계속 그리도록해야한다. 그 방법으로 while loop를 사용할 것이고 이를 render loop라고 한다.
- GLFW에게 그만하라고 말하기 전까지 계속해서 그림을 그린다.
while(!glfwWindowShouldClose(window)){
glfwSwapBuffers(window);
glfwPollEvents();
}
- glfwWindowShouldClose function은 loop가 돌때마다 GLFW가 close명령을 받았는지를 확인한다. 그래서 true를 return하면 rendering을 종료하게 된다.
- The glfwPollEvents function은 keyboard input 혹은 mouse movement event가 발생했는지를 확인한다.
- The glfwSwapBuffers는 GLFW window 각각의 pixel에 대한 색정보를 가지고 있는 커다란 2D buffer를 swap하는 역할을 한다. 이 loop에서 swap을 반복하면서 나중에 rendering할때 screen에 output을 보여주게될 것이다.
- double buffer는 이미지 drawing을 fluently하게 수행할 수 있게 한다. front buffer가 최종 output image를 가지고 있고 back buffer는 rendering command를 수행한다. back 버퍼가 다 비면 두 버퍼를 스왑한다. 그럼다시 한 버퍼에서는 이미지를 저장하고 한 버퍼는 rendering을 계속한다. 이런식으로 이미지를 저장하고의 동작이 끊임없이 지속되도록 하기 때문이다.
4.4 One last thing
- rendering이 끝나면 GLFW가 사용하기 위해 할당했던 resources를 clean/delete해야한다.
glfwTerminate();
return 0;
- 이제 output을 확인해보자
4.5 Input
- 이번에는 사용자의 input을 받아서 GLFW를 control하기위해 callback함수를 구현해 본다.
void processInput(GLFWwindow *window) {
if(glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS)
glfwSetWindowShouldClose(window, true);
}
- glfwGetKey함수로 사용자가 escape key를 눌렀는지 검사한다. 만약 키가 눌렸다면 GLFW를 close하도록 하는 callback함수이다. 이 동작이 수행되면 다음 render loop를 탈출하게 될 것이다.
while (!glfwWindowShouldClose(window)) {
processInput(window);
glfwSwapBuffers(window);
glfwPollEvents();
}
- render loop를 보통 frame이라고 한다.
4.6 Rendering
- 이제 rendering loop에 rendering command를 내려보자. 여기서 내린 command는 loop에 frame마다 실행된다.
// render loop
while(!glfwWindowShouldClose(window)) {
// input
processInput(window);
// rendering commands here
glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
// check and call events and swap the buffers
glfwPollEvents();
glfwSwapBuffers(window);
}
- 화면의 색을 바꿔볼 것이다. 먼저 frame의 시작에 screen을 clear한다. 그러지 않으면 이전에 그렸던 내용이 남아있게 되기 때문이다.
- glClear로 screen의 color buffer를 clear할 수 있다.
- glClear는 어느 특정 버퍼를 선택해서 clear할 수 있는데, clear하고자 하는 버퍼를 bit로 선택하면된다.
- (GL_COLOR_BUFFER_BIT, GL_DEPTH_BUFFER_BIT, GL_STENCIL_BUFFER_BIT.)
- 우리는 color buffer만을 비울것 이기 때문에 위와 같이 선택하였다.
- glClearColor는 screen의 color buffer를 clear할때 다시 채울 color의 configuration을 setting한다. 즉 glCearColor로 state를 set하면 glClear가 호출될때 그 state로 color buffer를 clear한다.
- glClearColor는 state-setting함수이고 glClear는 current state을 가져오는 state-using함수이다.
'ComputerScience > Computer Graphics' 카테고리의 다른 글
OpenGL - 5 Hello Triangle (3) (0) | 2021.06.30 |
---|---|
OpenGL - 5 Hello Triangle (2) (0) | 2021.06.29 |
OpenGL - 5 Hello Triangle (1) (0) | 2021.06.29 |
OpenGL - 3 Creating a window (0) | 2021.06.22 |
OpenGL - 2 OpenGL (0) | 2021.06.22 |