일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 |
- 머신러닝
- 혼공스
- tutorial
- vulkan
- 혼공S
- 혼공머신
- 혼공C
- 혼공
- 컴퓨터그래픽스
- 불칸
- OpenGL
- 혼자공부하는C언어
- 네트워크
- 딥러닝
- 혼공학습단
- 한빛미디어
- 혼공컴운
- 자바스크립트
- 책리뷰
- 나는리뷰어다
- 혼공네트
- C++
- 혼자공부하는네트워크
- 데이터분석
- 혼공단
- 혼공단5기
- 제이펍
- 파이썬
- 벌칸
- 리뷰리뷰
- Today
- Total
Scientia Conditorium
[Vulkan004][번역] Vulkan Tutorial - 삼각형 그리기 기본 코드(Drawing a triangle - Base code) 본문
[Vulkan004][번역] Vulkan Tutorial - 삼각형 그리기 기본 코드(Drawing a triangle - Base code)
크썸 2023. 11. 18. 18:34원문 : https://vulkan-tutorial.com/Drawing_a_triangle/Setup/Base_code
[Vulkan004][번역] Vulkan Tutorial - 삼각형 그리기 기본 코드(Drawing a triangle - Base code)
전체 구조
이전 장에서는 모든 적절한 구성이 포함된 Vulkan 프로젝트를 생성하고 예시 코드로 테스트했습니다. 이 장에서는 다음 코드로 처음부터 다시 시작하겠습니다.
#include <vulkan/vulkan.h>
#include <iostream>
#include <stdexcept>
#include <cstdlib>
class HelloTriangleApplication {
public:
void run() {
initVulkan();
mainLoop();
cleanup();
}
private:
void initVulkan() {
}
void mainLoop() {
}
void cleanup() {
}
};
int main() {
HelloTriangleApplication app;
try {
app.run();
} catch (const std::exception& e) {
std::cerr << e.what() << std::endl;
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}
먼저 함수, 구조체와 열거형을 제공하는 LunarG SDK의 Vulkan 헤더를 포함합니다. stdexcept 와 iostream 헤더는 입출력과 예외 처리를 위해 사용됩니다. cstdlib 헤더는 EXIT_SUCCESS 와 EXIT_FAIURE 매크로를 제공합니다.
프로그램 자체는 클래스로 래핑되어 Vulkan 개체들을 private 멤버와 함수로 저장하고 각 개체를 시작하는 함수를 추가할 것입니다. 이 함수는 initVulkan 함수에서 호출될 것입니다. 일단 모든 준비가 완료되면, 메인 루프에 들어가 프레임 렌더링을 시작합니다. 잠시 후 창이 닫힐 때까지 반복하는 루프를 포함하도록 mainLoop 함수를 채우겠습니다. 창이 닫히고 mainLoop 가 반환되면 cleanup 함수에서 사용한 리소스를 할당 해제합니다.
실행 중에 치명적인 에러가 발생하면 설명 메시지와 함께 std::runtime_error 예외가 발생하고, 이 예외는 다시 메인 함수로 전파되어 명령 프롬프트에 출력됩니다. 다양한 표준 예외 유형도 처리하기 위해 보다 일반적인 std::exception 을 포착합니다. 곧 처리하게 될 오류의 한 가지 예는 특정 필수 확장이 지원되지 않는다는 것을 발견하는 것입니다.
이 장 이후에 이어지는 거의 모든 장에서는 initVulkan 에서 호출되는 새 함수를 하나씩 추가하고, 마지막에 cleanup 함수에서 해제해야 하는 private 클래스 멤버에 하나 이상의 새 Vulkan 개체를 추가할 것입니다.
리소스 관리(Resource management)
malloc 함수로 할당된 각 메모리들 중 못 쓰는 것들(chunk)은 free 함수 호출이 필요한 것처럼, 우리가 생성하는 모든 Vulkan 개체는 더 이상 필요하지 않을 때 명시적으로 소멸해야 합니다. C++에는 <memory> 헤더에 제공된 RAII 또는 스마트 포인터를 사용하여 자동 리소스 관리를 수행할 수 있습니다. 하지만 이 튜토리얼에서는 Vulkan 개체의 할당 및 해제를 명시하기로 했습니다. 결국 Vulkan의 역할은 실수를 피하기 위해 모든 작업에 대해 명시적인 것이므로 API 작동 방식을 배우려면 개체의 수명에 대해 명시적으로 기술하는 것이 좋습니다.
이 튜토리얼을 따라한 후에는 생성자에서 Vulkan 개체를 획득하고, 소멸자에서 해제하는 C++ 클래스를 작성하거나 소유권 요구 사항에 따라 std::unique_ptr 또는 std::shared_ptr 에 사용자 정의 삭제자를 제공함으로써 자동 리소스 관리를 구현할 수 있습니다. RAII는 대규모 Vulkan 프로그램에 권장되는 모델이지만, 학습 목적으로는 백그라운드에서 어떤 일이 일어나는지 알아두는 것이 좋습니다.
Vulkan 개체는 vkCreateXXX 와 같은 함수를 사용하여 직접 생성하거나 vkAllocateXXX 와 같은 함수를 사용하여 다른 개체를 통해 할당합니다. 개체가 더 이상 사용되지 않는지 확인한 후에는 해당 함수에 대응하는 vkDestoryXXX 및 vkFreeXXX 를 사용하여 개체를 소멸해야 합니다. 이러한 함수의 매개 변수는 일반적으로 개체 유형에 따라 다르지만 모두 공유하는 매개 변수가 하나 있습니다: pAllocator . 이 매개 변수는 사용자 정의 메모리 할당자에 대한 콜백을 지정할 수 있는 선택적 매개변수입니다. 튜토리얼에서는 이 매개 변수를 무시하고 항상 nullptr 을 인수로 전달하겠습니다.
GLFW 연동(Integrating GLFW)
Vulkan은 오프스크린 렌더링에 사용하려는 경우 창을 만들지 않고도 완벽하게 작동하지만, 실제로 무언가를 표시하는 것이 훨씬 더 흥미롭습니다! 먼저 #include <vulkan/vulkan.h> 줄을 다음과 같이 바꿉니다.
#define GLFW_INCLUDE_VULKAN
#include <GLFW/glfw3.h>
이렇게 하면 GLFW에 자체 정의가 포함되고 Vulkan 헤더가 자동으로 로드됩니다. initWindow 함수를 추가하고 다른 호출 전에 run 함수에서 이 함수에 대한 호출을 추가합니다. 이 함수를 사용하여 GLFW를 초기화하고 창을 생성합니다.
void run() {
initWindow();
initVulkan();
mainLoop();
cleanup();
}
private:
void initWindow() {
}
initWindow 의 첫 번째 호출은 GLFW 라이브러리를 초기화하는 glfwInit() 이어야 합니다. GLFW는 원래 OpenGL 컨텍스트를 생성하도록 설계되었으므로 후속 호출에서 OpenGL 컨텍스트를 생성하지 않도록 지시해야 합니다.
(일반저으로 OpenGL의 상태를 OpenGL context라고 합니다.)
glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);
크기가 조정된 창을 처리하는 데는 특별한 주의가 필요하여 나중에 살펴볼테니, 지금은 다른 창 힌트 호출을 사용하여 비활성화하세요:
glfwWindowHint(GLFW_RESIZABLE, GLFW_FALSE);
이제 남은 것은 실제 창을 만드는 것입니다. 이에 대한 참조를 저장하고 창을 초기화할 private 클래스 멤버로 GLFWwindow* window 를 추가합니다.
window = glfwCreateWindow(800, 600, "Vulkan", nullptr, nullptr);
처음 세 개의 매개변수는 창의 너비, 높이 및 제목을 지정합니다. 네 번째 매개변수는 창을 열 모니터를 선택적으로 지정할 수 있으며, 마지막 매개변수는 OpenGL에만 해당됩니다.
앞으로 이 값을 몇 번 참조할 것이므로 하드코딩된 너비 및 높이 숫자 대신 상수를 사용하는 것이 좋습니다. HelloTriangleApplication 클래스 정의 위에 다음 줄을 추가합니다.
const uint32_t WIDTH = 800;
const uint32_t HEIGHT = 600;
그리고 다음과 같이 창 생성 호출을 수정합니다.
window = glfwCreateWindow(WIDTH, HEIGHT, "Vulkan", nullptr, nullptr);
이제 다음과 같은 initWindow 함수가 생겼을 것입니다.
void initWindow() {
glfwInit();
glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);
glfwWindowHint(GLFW_RESIZABLE, GLFW_FALSE);
window = glfwCreateWindow(WIDTH, HEIGHT, "Vulkan", nullptr, nullptr);
}
오류가 발생하거나 창이 닫힐 때까지 응용프로그램을 계속 실행하려면 다음과 같이 mainLoop 함수에 이벤트 루프를 추가해야 합니다.
void mainLoop() {
while (!glfwWindowShouldClose(window)) {
glfwPollEvents();
}
}
이 코드는 설명이 필요 없을 정도로 간단합니다. 이 코드는 사용자가 창을 닫을 때까지 X 버튼을 누르는 등의 이벤트를 반복해서 확인합니다. 이 루프는 나중에 단일 프레임을 렌더링하는 함수를 호출할 떄도 사용됩니다.
창이 닫히면 창을 삭제하고 GLFW 자체를 종료하여 리소스를 정리해야 합니다. 이것이 첫 번째 cleanup 코드가 될 것입니다.
void cleanup() {
glfwDestroyWindow(window);
glfwTerminate();
}
이제 프로그램을 실행하면 창을 닫아 응용프로그램을 종료할 때까지 Vulkan 이라는 제목의 창이 표시될 것입니다. 이제 Vulkan 응용프로그램의 골격이 완성되었으니 첫 번째 Vulkan 개체를 생성해보겠습니다.
별도 코드
개인적으로 try-catch를 사용하는 것을 선호하지 않습니다. 그런데 이 Vulkan 예제 코드는 시작부터 try-catch를 사용합니다. 따라서 개인적인 공부도 할겸 다른 방식으로 코드를 구현하여 공유드립니다.
https://github.com/twoo0220/vulkanTW
'프로그래밍 > 컴퓨터 그래픽스' 카테고리의 다른 글
[Vulkan][오류] Validation Error : VUIT-vkDestroyInstance 오류 (0) | 2023.11.29 |
---|---|
[Vulkan005][번역] Vulkan Tutorial - 삼각형 그리기 인스턴스(Drawing a triangle - Instance) (0) | 2023.11.19 |
[Vulkan003][번역] Vulkan Tutorial - 개발 환경(Development environment) (0) | 2023.11.14 |
[Vulkan002][번역] Vulkan Tutorial - 개요(Overview) (0) | 2023.11.12 |
[Vulkan001][번역] Vulkan Tutorial - 소개(Introduction) (0) | 2023.11.12 |