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