본문으로 바로가기

Vulkan) 2. 윈도우 창 구성

category Graphics/Vulkan 2021. 5. 5. 03:02

모든 내용은 https://vulkan-tutorial.com/Development_environment 에서 발췌합니다.

Windows를 기본으로 합니다. 그 외 플랫폼의 개발 환경 구성은 튜토리얼 사이트를 확인해 주세요.

 

모든 완성된 코드는 github.com/kimduuukbae/VulkanTutorial에 업로드됩니다.


1장의 코드는 벌칸이 실제로 동작하는지 확인하기 위한 코드였습니다. 

다 지우고 Window를 생성할 수 있는 래핑 클래스를 만들어보겠습니다.

 

//Window.h

#pragma once

#define GLFW_INCLUDE_VULKAN
#include <GLFW/glfw3.h>

#include <string>
#include <string_view>

namespace Core {

	class Window {
	private:
		GLFWwindow* window{ nullptr };
		const int width;
		const int height;

		std::string windowName;

		void InitWindow();

	public:
		Window(int sizeWidth, int sizeHeight, const std::string_view& windowName);
		~Window();

		Window(const Window& other) = delete;
		Window& operator=(const Window& other) = delete;

		bool IsClosed();
	};
}

1장에서도 언급했듯, GLFW는 플랫폼에 구애받지 않는 창 도구입니다.

#define GLFW_INCLUDE_VULKANGLFWVulkan 헤더도 포함해야한다는 신호를 보내는 것입니다.

나중에라도 각 각 시스템의 이름 충돌을 방지하기 위해 Core 이름공간 안에 정의하였습니다.

이후엔 PCH를 통하여 의존되는 헤더들을 포함할 것 입니다. 미리 해두셔도 상관 없습니다.

 

또한 우리는 창의 복사가 이루어지지 않길 바라기 때문에, 복사에 관련된 함수를 delete 합니다.

 

//Window.cpp

#include "Window.h"

namespace Core {

	Window::Window(int sizeWidth, int sizeHeight, const std::string_view& windowName) :
		width{ sizeWidth },
		height{ sizeHeight },
		windowName{ windowName } {
		InitWindow();
		
	}

	Window::~Window(){
		glfwDestroyWindow(window);
		glfwTerminate();
	}

	void Window::InitWindow() {
		glfwInit();
		glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);
		glfwWindowHint(GLFW_RESIZABLE, GLFW_FALSE);

		window = glfwCreateWindow(width, height, windowName.c_str(), nullptr, nullptr);
	}
    
    bool Window::IsClosed() {
    	return glfwWindowShouldClose(window);
    }
}

다음은 매개변수를 받아 Window를 생성할 차례입니다.

생성자의 멤버 이니셜라이저 를 이용하여 초기화 합니다. -> 성능에도 영향을 미치지만 const 멤버 변수가 있어 필수적입니다.

InitWindow를 이용하여 GLFW를 초기화 하고 라이브러리 창을 생성합니다.

 

GLFW는 기본적으로 OpenGL을 사용하기 위해 만들어져 있습니다, 하지만 우리는 Vulkan을 사용하기 때문에 

GLFW에게 OpenGL Context를 만들지 않도록 지시하는 glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API)를 추가해야합니다.

또한 우리는 특별한 방법 (후에 나옴)을 통해 윈도우의 크기를 늘릴것이기 때문에 glfwWindowHint(GLFW_RESIZABLE, GLFW_FALSE)를 사용하여 창크기 변경을 비활성화 하여야 합니다.

 

glfwCreateWindow의 뒤 2개의 인자는 OpenGL 사용과 관련이 있으므로 nullptr를 사용하여 무시합니다.

 

glfwWindowShouldClose는 사용자가 창 닫기를 선택했는지에 대한 쿼리 입니다. ( IsClosed와는 맞지않으나.. 일단은..ㅎ )

 

좋습니다. 다음은 새로운 윈도우를 띄우기 위한 첫 번째 튜토리얼 클래스를 생성합니다.

 

//FirstApp.h

#pragma once

#include "Window.h"

namespace App {
	class FirstApp {
	private:
		static constexpr int width{ 800 };
		static constexpr int height{ 600 };

		Core::Window window{ width, height, "HELLO VULKAN!" };

	public:
		FirstApp() = default;
		~FirstApp() = default;

		void Run();
	};
}

 

// FirstApp.cpp

#include "FirstApp.h"

namespace App {
	void FirstApp::Run() {
		while (!window.IsClosed()) {
			glfwPollEvents();
		}
	}
}

glfwPollEvents 는 모든 Window 이벤트를 처리합니다. 

 

이제 main함수를 작성합니다.

 

#include "FirstApp.h"

#include <iostream>
#include <stdexcept>

int main() {
	App::FirstApp app{};

	try {
		app.Run();
	}
	catch (const std::exception& e){
		std::cerr << e.what() << std::endl;
		return EXIT_FAILURE;
	}
}

800 x 600 의 HELLO VULKAN! 창이 뜬다면 성공한 것 입니다.