OpenGL_02, Hello Window

김경주·2024년 2월 1일

OpenGL

목록 보기
3/10
#include <glad/glad.h>
#include <GLFW/glfw3.h>

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;
}

GLFW를 초기화하고 glfwWindowHint 함수를 가지고 환경 설정한다.

  • 이 함수의 첫번째 인자는 어떤 옵션을 환경 설정하고 싶은지
    • GLFW_로 시작하는 옵션들이 enum로 되어있으며 여기서 선택 가능
  • 두번째 인자는 옵션의 값을 설정
  • 모든 가능한 옵션들은 아래의 사이트에서 찾을 수 있다.

GLFW: Window guide

여기서 3.3 version을 사용하기에 GLFW에 사용하는 OpenGL version을 알려주어야 GLFW는 OpenGL context를 생성할 때 제대로된 방식으로 만들 수 있다. 이는 사용자가 올바른 버전을 가지지 않았을 때 GLFW가 실행을 못하게 한다.

여기서 major와 minor를 3으로 설정하고 core profile을 사용한다고 명시한다고 GLFW에 알려준다. core profile을 사용하는 것을 알려주는 것은 더 이상 필요없는 구버전에 호환이 가능한 기능들 없이 OpenGL 기능의 더 작은 부분까지 접근할 수 있다는 것이다.

Mac에서는 마지막 줄을 추가해야한다.

glxinfo 함수를 통해서 버전 확인 가능

다음은 윈도우 생성

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);

glfwMakeContextCurrent

창 생성 이후 이 창의 context를 현재 스레드에서 메인 context로 지정한다고 GLFW에 알려준다.

GLAD

GLAD는 OpenGL에 관한 함수 포인터들 관리, 그래서 OpenGL 함수를 사용하기 전에 초기화 함수 실행

if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress))
{
	std::cout << "Failed to initialize GLAD" << std::endl;
	return -1;
}

OS마다 다른 OpenGL 함수 포인터들의 주소를 불러오는 GLAD 함수를 통한다. GLFW는 OS에 맞는 정확한 함수 정의하는 glfwGetProcAddress 함수를 준다.

Viewport

렌더링하기전 마지막 단계. 렌더링할 윈도우의 사이즈를 OpenGL에 알려준다. OpenGL은 윈도우에 맞게 어떻게 데이터와 좌표계를 디스플레이할 지 안다.

glViewport(0, 0, 800, 600);

glViewport의 첫 두 개의 인자는 윈도우의 좌하단의 위치 세번째 네번째 인자는 width와 height의 렌더링할 픽셀, 이는 윈도우의 크기와 같게 설정함.(물론 다르게 가능)

윈도우 창 크기 조절할 때마다 viewport의 크기도 조절되어야한다.

void framebuffer_size_callback(GLFWwindow* window, int width, int height);
void framebuffer_size_callback(GLFWwindow* window, int width, int height)
{
glViewport(0, 0, width, height);
}

위와 같이 콜백 함수를 만들고 아래의 함수 호출에 사용하면 크기 조절에 맞춰 viewport도 수정

glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);

Ready your Engines

이미지를 바로 창에 띄우고 바로 종료되는 애플리케이션을 원하지 않고 명시적으로 종료하는 순간까지 이미지를 그리고 사용자입력을 받길 원하는 건 당연. 이러한 이유로 루프문 구현, 이 루프를 렌더 루프라 한다. 이 렌더 루프는 GLFW가 종료될 때까지 실행.

while(!glfwWindowShouldClose(window))
{
	glfwSwapBuffers(window);
	glfwPollEvents();
}

glfwWindowShouldClose 함수는 GLFW가 종료지시를 받았는지 루프 시작점에서 확인.

glfwPollEvents 함수는 어떤 이벤트가 작동, 윈도우 창 업데이트, 그 이벤트에 맞는 함수 호출 체크.

glfwSwapBuffers 함수는 렌더링 반복 중 렌더하기 위해 사용되는 색상 버퍼를 스왑한다. 그리고 스크린에 출력.

Double Buffer : front buffer는 마지막 출력물을 담고 스크린에 나타난다. 언제까지? back buffer에 다음 출력물이 그려질때까지 그리고 스왑한다. 이러한 식으로 렌더링 한다.

마무리

glfwTerminate();
return 0;

glfwTerminate 함수는 이제 종료되기 전에 GLFW의 자원을 정리하기 위해서 호출

Input

GLFW에서 입력 처리

void processInput(GLFWwindow *window)
{
	if(glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS)
		glfwSetWindowShouldClose(window, true);
}

GLFW의 glfwGetKey 함수를 사용. 이 함수의 인자는 window와 키값을 받는다.

키값이 입력되지 않으면 함수 리턴값으로 GLFW_RELEASE를 받는다. Escape 키를 누르면 분기문으로 들어가 glfwSetWindowshouldClose 함수 실행한다.

while (!glfwWindowShouldClose(window))
{
	processInput(window);
	glfwSwapBuffers(window);
	glfwPollEvents();
}

위의 코드처럼 렌더 루프문에 넣어서 처리

렌더링

// render loop
while(!glfwWindowShouldClose(window))
{
	// input
	processInput(window);
	// rendering commands here
	...
	// check and call events and swap the buffers
	glfwPollEvents();
	glfwSwapBuffers(window);
}

렌더링 명령어들을 모두 렌더 루프에 넣는다.

glClear 스크린 색상 버퍼를 지우는 함수

glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);

glClearColor 함수는 glClear 함수 호출 시 색상 버퍼를 정리할 때 마다 색상 버퍼 전체는 glClearColor로 설정된 색으로 채워진다.

여기서 glClearColor는 state-setting 함수, glClear는 state-using 함수이다.

profile
Hello everyone

0개의 댓글