Skip to content
This repository was archived by the owner on Aug 2, 2025. It is now read-only.

Commit 5f9a8ba

Browse files
Merge pull request #1 from learndaxa/getting-started-v2
Improved the "Creating a window" section
2 parents d41f887 + 4e6b3b2 commit 5f9a8ba

File tree

2 files changed

+109
-84
lines changed

2 files changed

+109
-84
lines changed

docs/03_Getting_started/00_Creating_a_window.md

Lines changed: 108 additions & 83 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,21 @@
1-
## Disclaimer
1+
## Description
22

3-
In this tutorial, we will be using GLFW to create and manage our window. Since this is not part of the core tutorial, we will only provide a small rundown of the header file without going into further detail. If you are new to GLFW, we recommend you check out [this tutorial on learnopengl.com](https://learnopengl.com/Getting-started/Hello-Window)
3+
The first thing when developing a graphics application is to open a blank window.
44

5-
The code below will open a small window which we will use in the next sections.
5+
## Creating a header file
66

7-
## window.hpp
7+
In this tutorial, we will create a new header file `window.hpp` that is responsible for interfacing and abstracting the windowing library of our choice GLFW.
88

99
```cpp
1010
#pragma once
1111

12+
struct Window{
13+
};
14+
```
15+
16+
Next, we need to include the libraries. Since we need the native window handle later, we also need the native GLFW headers. Since those libraries are platform dependant though, we need some extra preprocessor magic.
17+
18+
```cpp
1219
#include <daxa/daxa.hpp>
1320
using namespace daxa::types;
1421

@@ -17,105 +24,123 @@ using namespace daxa::types;
1724
#define GLFW_EXPOSE_NATIVE_WIN32
1825
#define GLFW_NATIVE_INCLUDE_NONE
1926
using HWND = void *;
20-
#elif defined(__linux__)
27+
#elif defined(__linux__)/
2128
#define GLFW_EXPOSE_NATIVE_X11
2229
#define GLFW_EXPOSE_NATIVE_WAYLAND
2330
#endif
2431
#include <GLFW/glfw3native.h>
32+
```
2533
26-
struct Window{
27-
GLFWwindow * glfw_window_ptr;
28-
u32 width, height;
29-
bool minimized = false;
30-
bool swapchain_out_of_date = false;
31-
32-
explicit Window(char const * window_name, u32 sx = 800, u32 sy = 600) : width{sx}, height{sy} {
33-
// Initialize GLFW
34-
glfwInit();
35-
glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);
36-
37-
// Tell GLFW to make the window resizable
38-
glfwWindowHint(GLFW_RESIZABLE, GLFW_TRUE);
39-
40-
// Create the window
41-
glfw_window_ptr = glfwCreateWindow(static_cast<i32>(width), static_cast<i32>(height), window_name, nullptr, nullptr);
42-
43-
// Set the user pointer to this window
44-
glfwSetWindowUserPointer(glfw_window_ptr, this);
45-
46-
// Enable vsync (To limit the framerate to the refresh rate of the monitor)
47-
glfwSwapInterval(1);
48-
49-
// When the window is resized, update the width and height and mark the swapchain as out of date
50-
glfwSetWindowContentScaleCallback(glfw_window_ptr, [](GLFWwindow* window, float xscale, float yscale){
51-
auto* win = static_cast<Window*>(glfwGetWindowUserPointer(window));
52-
win->width = static_cast<u32>(xscale);
53-
win->height = static_cast<u32>(yscale);
54-
win->swapchain_out_of_date = true;
55-
});
56-
}
34+
We now need to add some properties to our window struct. This includes the GLFW window pointer, the current width and height, whether the window is minimized and whether the swapchain is out of date due to the resizing of the window.
5735
58-
~Window() {
59-
glfwDestroyWindow(glfw_window_ptr);
60-
glfwTerminate();
61-
}
36+
```cpp
37+
GLFWwindow * glfw_window_ptr;
38+
u32 width, height;
39+
bool minimized = false;
40+
bool swapchain_out_of_date = false;
41+
```
6242

63-
auto get_native_handle() const -> daxa::NativeWindowHandle
64-
{
43+
We can now create a constructor and a destructor for the window.
44+
45+
```cpp
46+
explicit Window(char const * window_name, u32 sx = 800, u32 sy = 600) : width{sx}, height{sy} {
47+
// Initialize GLFW
48+
glfwInit();
49+
50+
// Tell GLFW to not include any other API
51+
glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);
52+
53+
// Tell GLFW to make the window resizable
54+
glfwWindowHint(GLFW_RESIZABLE, GLFW_TRUE);
55+
56+
// Create the window
57+
glfw_window_ptr = glfwCreateWindow(static_cast<i32>(width), static_cast<i32>(height), window_name, nullptr, nullptr);
58+
59+
// Set the user pointer to this window
60+
glfwSetWindowUserPointer(glfw_window_ptr, this);
61+
62+
// Enable vsync (To limit the framerate to the refresh rate of the monitor)
63+
glfwSwapInterval(1);
64+
65+
// When the window is resized, update the width and height and mark the swapchain as out of date
66+
glfwSetWindowContentScaleCallback(glfw_window_ptr, [](GLFWwindow* window, float xscale, float yscale){
67+
auto* win = static_cast<Window*>(glfwGetWindowUserPointer(window));
68+
win->width = static_cast<u32>(xscale);
69+
win->height = static_cast<u32>(yscale);
70+
win->swapchain_out_of_date = true;
71+
});
72+
}
73+
74+
~Window() {
75+
glfwDestroyWindow(glfw_window_ptr);
76+
glfwTerminate();
77+
}
78+
```
79+
80+
Next, we need to create functions to obtain the native handle of the window and the platform identifier.
81+
82+
```cpp
83+
auto get_native_handle() const -> daxa::NativeWindowHandle
84+
{
6585
#if defined(_WIN32)
66-
return glfwGetWin32Window(glfw_window_ptr);
86+
return glfwGetWin32Window(glfw_window_ptr);
6787
#elif defined(__linux__)
68-
switch (get_native_platform())
69-
{
70-
case daxa::NativeWindowPlatform::WAYLAND_API:
71-
return reinterpret_cast<daxa::NativeWindowHandle>(glfwGetWaylandWindow(glfw_window_ptr));
72-
case daxa::NativeWindowPlatform::XLIB_API:
73-
default:
74-
return reinterpret_cast<daxa::NativeWindowHandle>(glfwGetX11Window(glfw_window_ptr));
75-
}
76-
#endif
77-
}
78-
79-
static auto get_native_platform() -> daxa::NativeWindowPlatform
88+
switch (get_native_platform())
8089
{
81-
switch(glfwGetPlatform())
82-
{
83-
case GLFW_PLATFORM_WIN32: return daxa::NativeWindowPlatform::WIN32_API;
84-
case GLFW_PLATFORM_X11: return daxa::NativeWindowPlatform::XLIB_API;
85-
case GLFW_PLATFORM_WAYLAND: return daxa::NativeWindowPlatform::WAYLAND_API;
86-
default: return daxa::NativeWindowPlatform::UNKNOWN;
87-
}
90+
case daxa::NativeWindowPlatform::WAYLAND_API:
91+
return reinterpret_cast<daxa::NativeWindowHandle>(glfwGetWaylandWindow(glfw_window_ptr));
92+
case daxa::NativeWindowPlatform::XLIB_API:
93+
default:
94+
return reinterpret_cast<daxa::NativeWindowHandle>(glfwGetX11Window(glfw_window_ptr));
8895
}
96+
#endif
97+
}
8998
90-
inline void set_mouse_capture(bool should_capture) const
99+
static auto get_native_platform() -> daxa::NativeWindowPlatform
100+
{
101+
switch(glfwGetPlatform())
91102
{
92-
glfwSetCursorPos(glfw_window_ptr, static_cast<f64>(width / 2.), static_cast<f64>(height / 2.));
93-
glfwSetInputMode(glfw_window_ptr, GLFW_CURSOR, should_capture ? GLFW_CURSOR_DISABLED : GLFW_CURSOR_NORMAL);
94-
glfwSetInputMode(glfw_window_ptr, GLFW_RAW_MOUSE_MOTION, should_capture);
103+
case GLFW_PLATFORM_WIN32: return daxa::NativeWindowPlatform::WIN32_API;
104+
case GLFW_PLATFORM_X11: return daxa::NativeWindowPlatform::XLIB_API;
105+
case GLFW_PLATFORM_WAYLAND: return daxa::NativeWindowPlatform::WAYLAND_API;
106+
default: return daxa::NativeWindowPlatform::UNKNOWN;
95107
}
108+
}
109+
```
96110

97-
inline bool should_close() const
98-
{
99-
return glfwWindowShouldClose(glfw_window_ptr);
100-
}
111+
While we are at it, we can also create some utility functions.
101112

102-
inline void update() const
103-
{
104-
glfwPollEvents();
105-
glfwSwapBuffers(glfw_window_ptr);
106-
}
113+
```cpp
114+
inline void set_mouse_capture(bool should_capture) const
115+
{
116+
glfwSetCursorPos(glfw_window_ptr, static_cast<f64>(width / 2.), static_cast<f64>(height / 2.));
117+
glfwSetInputMode(glfw_window_ptr, GLFW_CURSOR, should_capture ? GLFW_CURSOR_DISABLED : GLFW_CURSOR_NORMAL);
118+
glfwSetInputMode(glfw_window_ptr, GLFW_RAW_MOUSE_MOTION, should_capture);
119+
}
107120

108-
inline GLFWwindow* get_glfw_window() const{
109-
return glfw_window_ptr;
110-
}
121+
inline bool should_close() const
122+
{
123+
return glfwWindowShouldClose(glfw_window_ptr);
124+
}
111125

112-
inline bool should_close() {
113-
return glfwWindowShouldClose(glfw_window_ptr);
114-
}
115-
};
126+
inline void update() const
127+
{
128+
glfwPollEvents();
129+
glfwSwapBuffers(glfw_window_ptr);
130+
}
131+
132+
inline GLFWwindow* get_glfw_window() const{
133+
return glfw_window_ptr;
134+
}
135+
136+
inline bool should_close() {
137+
return glfwWindowShouldClose(glfw_window_ptr);
138+
}
116139
```
117140
118-
## main.cpp
141+
## Opening our window
142+
143+
We can now go ahead and open our window for the first time. We therefore need to extend our main.cpp file.
119144
120145
```cpp
121146
#include "window.hpp"

docs/03_Getting_started/03_Creating_a_swapchain.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ This defines the color space for the swapchain images. (`R8G8B8A8_UINT` is the d
5050

5151
You can now acquire a new swapchain image by running
5252

53-
```cp
53+
```cpp
5454
daxa::ImageId swapchain_image = swapchain.acquire_next_image();
5555
```
5656

0 commit comments

Comments
 (0)