MXVK Vulkan Framework 0.24.0
C++20 Vulkan rendering framework for practical 2D and 3D application development with SDL3.
Loading...
Searching...
No Matches
glitch.cpp
Go to the documentation of this file.
1#include "mxvk/argz.hpp"
2#include "mxvk/mxvk.hpp"
5#include <chrono>
6#include <cmath>
7#include <cstdlib>
8#include <format>
9#include <glm/ext/matrix_clip_space.hpp>
10#include <glm/ext/matrix_transform.hpp>
11#include <glm/glm.hpp>
12#include <iostream>
13#include <string>
14
15namespace example {
16
18 public:
19 GlitchCubeWindow(const std::string &filename, const std::string &path, const std::string &title, int width, int height, bool fullscreen, bool enable_vsync)
20 : mxvk::VK_Window(title, width, height, fullscreen, MXVK_VALIDATION, enable_vsync),
21 assetRoot((path.empty() || path == ".") ? std::string(GLITCH_CUBE_ASSET_DIR) : path) {
22 const std::string shaderRoot = assetRoot + "/data";
23 const std::string modelPath = filename.empty() ? (assetRoot + "/data/cube.mxmod.z") : filename;
24 const std::string textureManifestPath = assetRoot + "/data/cube.tex";
25 const std::string textureBasePath = assetRoot + "/data";
26 const std::string modelVertPath = shaderRoot + "/model.vert.spv";
27 const std::string modelFragPath = shaderRoot + "/model.frag.spv";
28 setFont(assetRoot + "/data/font.ttf", 22);
29 model.load(this, modelPath, textureManifestPath, textureBasePath, 1.0f);
30 model.setShaders(this, modelVertPath, modelFragPath);
31 }
32
33 ~GlitchCubeWindow() override {
34 if (device != VK_NULL_HANDLE) {
35 vkDeviceWaitIdle(device);
36 }
37 model.cleanup(this);
38 }
39
40 void event(SDL_Event &e) override {
41 if (e.type == SDL_EVENT_KEY_DOWN) {
42 switch (e.key.key) {
43 case SDLK_ESCAPE:
44 exit();
45 break;
46 case SDLK_SPACE:
47 rotXFactor = (rotXFactor > 0.0f) ? 0.0f : 1.0f;
48 break;
49 case SDLK_PAGEUP:
50 cubeScale += 0.1f;
51 if (cubeScale > 4.0f) {
52 cubeScale = 4.0f;
53 }
54 break;
55 case SDLK_PAGEDOWN:
56 cubeScale -= 0.1f;
57 if (cubeScale < 0.2f) {
58 cubeScale = 0.2f;
59 }
60 break;
61 default:
62 break;
63 }
64 return;
65 }
66
67 if (e.type == SDL_EVENT_MOUSE_BUTTON_DOWN && e.button.button == SDL_BUTTON_LEFT) {
68 mouseDragging = true;
69 lastMouseX = static_cast<int>(e.button.x);
70 lastMouseY = static_cast<int>(e.button.y);
71 return;
72 }
73
74 if (e.type == SDL_EVENT_MOUSE_BUTTON_UP && e.button.button == SDL_BUTTON_LEFT) {
75 mouseDragging = false;
76 return;
77 }
78
79 if (e.type == SDL_EVENT_MOUSE_MOTION && mouseDragging) {
80 const int x = static_cast<int>(e.motion.x);
81 const int y = static_cast<int>(e.motion.y);
82 const int deltaX = x - lastMouseX;
83 const int deltaY = y - lastMouseY;
84
85 yawDegrees += static_cast<float>(deltaX) * mouseSensitivity;
86 pitchDegrees += static_cast<float>(deltaY) * mouseSensitivity;
87 pitchDegrees = std::clamp(pitchDegrees, -80.0f, 80.0f);
88
89 lastMouseX = x;
90 lastMouseY = y;
91 return;
92 }
93
94 if (e.type == SDL_EVENT_MOUSE_WHEEL) {
95 const float delta = (e.wheel.y != 0.0f) ? e.wheel.y : static_cast<float>(e.wheel.integer_y);
96 cameraDistance -= delta * 0.45f;
97 cameraDistance = std::clamp(cameraDistance, 1.8f, 12.0f);
98 }
99 }
100
101 void proc() override {
102 printText("Drag left mouse to orbit the cube", 25, 25, {255, 255, 255, 255});
103 printText("Mouse wheel zooms the camera", 25, 60, {255, 255, 255, 255});
104 printText("Space toggles the rotation axis", 25, 95, {255, 255, 255, 255});
105 printText("Page Up / Page Down adjust cube scale", 25, 130, {255, 255, 255, 255});
106 printText(std::format("Current scale: {:.1f}", cubeScale), 25, 165, {230, 245, 255, 255});
107 }
108
109 void onSwapchainRecreated() override {
110 model.resize(this);
111 }
112
113 void onRecordCustomRendering(VkCommandBuffer cmd, uint32_t imageIndex) override {
114 const float elapsedSeconds = std::chrono::duration<float>(std::chrono::steady_clock::now() - start).count();
115 const VkExtent2D extent = getSwapchainExtent();
116
117 const float aspect = (extent.height > 0U)
118 ? static_cast<float>(extent.width) / static_cast<float>(extent.height)
119 : 1.0f;
120
121 const float rotationAngle = elapsedSeconds * glm::radians(50.0f);
122
124 ubo.model = glm::rotate(glm::mat4(1.0f), rotationAngle, glm::vec3(rotXFactor, 1.0f, 0.0f));
125 ubo.model = glm::scale(ubo.model, glm::vec3(model.modelRenderScale() * cubeScale));
126 ubo.model = glm::translate(ubo.model, model.modelCenterOffset());
127
128 const float yawRadians = glm::radians(yawDegrees);
129 const float pitchRadians = glm::radians(pitchDegrees);
130 const glm::vec3 cameraPos{
131 cameraDistance * std::cos(pitchRadians) * std::sin(yawRadians),
132 cameraDistance * std::sin(pitchRadians),
133 cameraDistance * std::cos(pitchRadians) * std::cos(yawRadians)};
134
135 ubo.view = glm::lookAt(cameraPos, glm::vec3(0.0f), glm::vec3(0.0f, 1.0f, 0.0f));
136 ubo.proj = glm::perspective(glm::radians(45.0f), aspect, 0.1f, 100.0f);
137 ubo.proj[1][1] *= -1.0f;
138
139 model.updateUBO(imageIndex, ubo);
140 model.render(cmd, imageIndex, false);
141 }
142
143 private:
144 std::string assetRoot;
145 mxvk::VKAbstractModel model{};
146 float rotXFactor = 1.0f;
147 float cubeScale = 1.0f;
148 std::chrono::steady_clock::time_point start{std::chrono::steady_clock::now()};
149 bool mouseDragging = false;
150 int lastMouseX = 0;
151 int lastMouseY = 0;
152 float yawDegrees = 0.0f;
153 float pitchDegrees = 12.0f;
154 float cameraDistance = 5.0f;
155 float mouseSensitivity = 0.35f;
156 };
157
158} // namespace example
159
160int main(int argc, char **argv) {
161 try {
162 const Arguments args = proc_args(argc, argv);
163 example::GlitchCubeWindow window(args.filename, args.path, "MXVK Glitch Cube", args.width, args.height, args.fullscreen, args.enable_vsync);
164 window.loop();
165 } catch (mxvk::Exception &e) {
166 std::cerr << std::format("mxvk: Exception: {}\n", e.text());
167 return EXIT_FAILURE;
168 } catch (ArgException<std::string> &e) {
169 std::cerr << std::format("mxvk: Argument Exception: {}\n", e.text());
170 return EXIT_FAILURE;
171 }
172
173 return EXIT_SUCCESS;
174}
Lightweight, header-only, template command-line argument parser.
Arguments proc_args(int &argc, char **argv)
Parse standard libmx2 command-line options from main()'s argv.
Definition argz.hpp:872
Exception thrown by Argz::proc() on unrecognised or malformed options.
Definition argz.hpp:178
void event(SDL_Event &e) override
Handle one SDL event.
Definition glitch.cpp:40
GlitchCubeWindow(const std::string &filename, const std::string &path, const std::string &title, int width, int height, bool fullscreen, bool enable_vsync)
Definition glitch.cpp:19
~GlitchCubeWindow() override
Definition glitch.cpp:33
void onSwapchainRecreated() override
Called after swapchain and render resources are recreated.
Definition glitch.cpp:109
void proc() override
Execute one processing/update step.
Definition glitch.cpp:101
void onRecordCustomRendering(VkCommandBuffer cmd, uint32_t imageIndex) override
Optional hook for derived classes to record extra draw commands.
Definition glitch.cpp:113
std::string text() const
Convenience wrapper that owns mesh, textures, descriptors, and pipeline state.
Main Vulkan window wrapper for MXVK.
Definition mxvk.hpp:37
VkExtent2D getSwapchainExtent() const noexcept
Get the current swapchain extent.
Definition mxvk.hpp:186
void loop()
Run the main event/render loop.
Definition mxvk.cpp:600
VkDevice device
Definition mxvk.hpp:485
void exit()
Request loop termination.
Definition mxvk.cpp:1126
VK_Window()=default
Construct an empty window object.
void setFont(const std::string &fontPath, int fontSize=24)
Set the active text-render font.
Definition mxvk.cpp:2991
void printText(const std::string &text, int x, int y, const SDL_Color &col)
Queue a text string for rendering during the current frame.
Definition mxvk.cpp:3018
int main(void)
Definition main.cpp:7
#define MXVK_VALIDATION
Definition mxvk.hpp:27
High-level model wrapper integrated with MXVK dynamic rendering.
Utilities for loading and saving PNG images.
Definition mxvk.hpp:30
Plain data structure returned by proc_args() with all common libmx2 CLI options.
Definition argz.hpp:730
bool fullscreen
Whether fullscreen mode was requested.
Definition argz.hpp:736
bool enable_vsync
Enable FIFO present mode / v-sync (--enable-vsync).
Definition argz.hpp:750
int height
Viewport height in pixels (default: 720).
Definition argz.hpp:733
std::string filename
Optional input filename (--filename).
Definition argz.hpp:738
std::string path
Asset root; proc_args() defaults it to the executable directory.
Definition argz.hpp:735
int width
Viewport width in pixels (default: 1280).
Definition argz.hpp:732
Default transform UBO payload for model shaders.