본문 바로가기

ComputerScience/Computer Graphics

OpenGL - 4 Hello Window

728x90

* always thanks to https://learnopengl.com/

 

Learn OpenGL, extensive tutorial resource for learning Modern OpenGL

Welcome to OpenGL Welcome to the online book for learning OpenGL! Whether you are trying to learn OpenGL for academic purposes, to pursue a career or simply looking for a hobby, this book will teach you the basics, the intermediate, and all the advanced kn

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함수이다.

 

 

728x90
반응형

'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