MXVK Vulkan Framework 0.35.0
C++20 Vulkan rendering framework for practical 2D and 3D application development with SDL3.
Loading...
Searching...
No Matches
main.cpp
Go to the documentation of this file.
1#include "mxvk/argz.hpp"
2#include "mxvk/mxvk.hpp"
4#if defined(MXVK_USE_EIGEN_MATH)
6#else
7#include "mxvk/mxvk_math.h"
8#endif
9
10#include <SDL3/SDL.h>
11
12#include <algorithm>
13#include <cmath>
14#include <cstdint>
15#include <cstdlib>
16#include <format>
17#include <iostream>
18#include <memory>
19#include <string>
20
21namespace {
23 public:
24 void operator()(SDL_Surface *surface) const { SDL_DestroySurface(surface); }
25 };
26
27 using SurfacePtr = std::unique_ptr<SDL_Surface, SurfaceDeleter>;
28
29 SurfacePtr create_frame_surface(int width, int height) {
30 SurfacePtr surface(SDL_CreateSurface(width, height, SDL_PIXELFORMAT_RGBA32));
31 if (!surface) {
32 throw mxvk::Exception(std::format("Failed to create 3dmath frame surface: {}", SDL_GetError()));
33 }
34 return surface;
35 }
36
37} // namespace
38
39namespace example {
41 public:
42 Math3DWindow(const std::string &, const std::string &title, int width, int height, bool fullscreen, bool enable_vsync, const FramebufferDimensions &framebuffer) : mxvk::VK_Window(title, width, height, fullscreen, MXVK_VALIDATION, enable_vsync), frame_width(framebuffer.width), frame_height(framebuffer.height), fallback_width(width), fallback_height(height) {
43 setClearColor(0.015f, 0.016f, 0.022f, 1.0f);
45 }
46
47 void event(SDL_Event &e) override {
48 if (e.type == SDL_EVENT_KEY_DOWN && e.key.key == SDLK_ESCAPE) {
49 exit();
50 }
51 }
52
53 void proc() override {
54 const int output_width = swapchain_extent.width > 0U ? static_cast<int>(swapchain_extent.width) : fallback_width;
55 const int output_height = swapchain_extent.height > 0U ? static_cast<int>(swapchain_extent.height) : fallback_height;
56
57 ensure_framebuffer();
58 if (frame_sprite == nullptr || frame_surface == nullptr || frame_format == nullptr) {
59 return;
60 }
61
62 clear_frame(mxvk::MXVK_RGB(4, 4, 6));
63 const float time = static_cast<float>(SDL_GetTicks()) * 0.001f;
64
65 mxvk::vec4D vertices[3] = {
66 {-0.75f, -0.45f, 2.6f, 1.0f},
67 {0.75f, -0.45f, 2.6f, 1.0f},
68 {0.0f, 0.75f, 2.6f, 1.0f},
69 };
70
71 mxvk::Mat4D rotation;
72 rotation.BuildXYZ(25.0f, time * 42.0f, time * 18.0f);
73
74 mxvk::RenderList render_list;
75 mxvk::Triangle triangle;
77 triangle.color = mxvk::MXVK_RGB(255, 255, 255);
78 for (int i = 0; i < 3; ++i) {
79 triangle.vlist[i] = vertices[i];
80 triangle.tlist[i] = rotation.MulVec(vertices[i]);
81 triangle.tlist[i].z += 3.0f;
82 }
83 render_list.BuildRenderList(triangle);
84
85 project_to_screen(render_list, frame_width, frame_height);
86
87 const int pixel_size = std::max(1, frame_width / 360);
88 mxvk::PipeLine pipeline;
89 pipeline.Begin(frame_width, frame_height, [this, pixel_size](int x, int y, mxvk::MXCOLOR color) { put_block(x, y, pixel_size, color); });
90 pipeline.DrawPolys(render_list);
91 pipeline.End();
92
93 frame_sprite->updateTexture(frame_surface.get());
94 frame_sprite->drawSpriteRect(0, 0, output_width, output_height);
95 }
96
97 private:
98 SurfacePtr frame_surface;
99 const SDL_PixelFormatDetails *frame_format = nullptr;
100 mxvk::VK_Sprite *frame_sprite = nullptr;
101 int frame_width = 1280;
102 int frame_height = 720;
103 int fallback_width = 1280;
104 int fallback_height = 720;
105
106 void ensure_framebuffer() {
107 if (frame_surface != nullptr) {
108 return;
109 }
110
111 frame_surface = create_frame_surface(frame_width, frame_height);
112 frame_format = SDL_GetPixelFormatDetails(frame_surface->format);
113 if (frame_format == nullptr) {
114 throw mxvk::Exception(std::format("Failed to query 3dmath frame format: {}", SDL_GetError()));
115 }
116
117 clear_frame(mxvk::MXVK_RGB(4, 4, 6));
118 frame_sprite = createSprite(frame_surface.get());
119 frame_sprite->setTextureFilter(VK_FILTER_NEAREST);
120 }
121
122 [[nodiscard]] std::uint32_t map_color(mxvk::MXCOLOR color) const { return SDL_MapRGBA(frame_format, nullptr, mxvk::color_r(color), mxvk::color_g(color), mxvk::color_b(color), mxvk::color_a(color)); }
123
124 void clear_frame(mxvk::MXCOLOR color) { SDL_FillSurfaceRect(frame_surface.get(), nullptr, map_color(color)); }
125
126 void put_pixel(int x, int y, mxvk::MXCOLOR color) {
127 if (x < 0 || y < 0 || x >= frame_width || y >= frame_height) {
128 return;
129 }
130
131 auto *row = static_cast<std::uint8_t *>(frame_surface->pixels) + (static_cast<std::size_t>(y) * static_cast<std::size_t>(frame_surface->pitch));
132 auto *pixel = reinterpret_cast<std::uint32_t *>(row) + x;
133 *pixel = map_color(color);
134 }
135
136 void put_block(int x, int y, int size, mxvk::MXCOLOR color) {
137 for (int block_y = 0; block_y < size; ++block_y) {
138 for (int block_x = 0; block_x < size; ++block_x) {
139 put_pixel(x + block_x, y + block_y, color);
140 }
141 }
142 }
143
144 static void project_to_screen(mxvk::RenderList &render_list, int width, int height) {
145 const float scale = static_cast<float>(std::min(width, height)) * 0.42f;
146 const float center_x = static_cast<float>(width) * 0.5f;
147 const float center_y = static_cast<float>(height) * 0.5f;
148
149 for (auto &poly : render_list.polys) {
150 for (auto &vertex : poly.tlist) {
151 const float z = std::max(vertex.z, 0.001f);
152 vertex.x = center_x + (vertex.x / z) * scale;
153 vertex.y = center_y - (vertex.y / z) * scale;
154 }
155 }
156 }
157 };
158} // namespace example
159
160int main(int argc, char **argv) {
161 try {
162 Arguments args = proc_args(argc, argv);
163 example::Math3DWindow window(args.path, "MXVK 3D Math", args.width, args.height, args.fullscreen, args.enable_vsync, args.framebuffer);
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 return EXIT_SUCCESS;
173}
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 operator()(SDL_Surface *surface) const
Definition main.cpp:24
void event(SDL_Event &e) override
Handle one SDL event.
Definition main.cpp:47
void proc() override
Execute one processing/update step.
Definition main.cpp:53
Math3DWindow(const std::string &, const std::string &title, int width, int height, bool fullscreen, bool enable_vsync, const FramebufferDimensions &framebuffer)
Definition main.cpp:42
std::string text() const
Four-by-four homogeneous transform matrix.
Definition mxvk_math.h:706
void BuildXYZ(float theta_x, float theta_y, float theta_z)
Build an XYZ Euler rotation matrix from angles in degrees.
Definition mxvk_math.h:859
vec4D MulVec(const vec4D &in) const
Transform a homogeneous 4D vector by this matrix.
Definition mxvk_math.h:771
Clipped software rasterization pipeline for lines and filled triangles.
Definition mxvk_math.h:2104
void End()
End rendering and release the current plotting callbacks.
Definition mxvk_math.h:2463
void DrawPolys(const RenderList &list) const
Draw active render-list triangles as clipped wireframes.
Definition mxvk_math.h:2405
void Begin(int width, int height, std::function< void(int, int, MXCOLOR)> plotter)
Begin rendering with a custom pixel plotter.
Definition mxvk_math.h:2149
Flat list of triangles prepared for transformation and rasterization.
Definition mxvk_math.h:1232
std::vector< Triangle > polys
Triangle storage.
Definition mxvk_math.h:1235
void BuildRenderList(const Triangle &triangle)
Append one triangle to the render list.
Definition mxvk_math.h:1293
Main Vulkan window wrapper for MXVK.
Definition mxvk.hpp:39
void loop()
Run the main event/render loop.
Definition mxvk.cpp:651
VK_Sprite * createSprite(const std::string &pngPath, const std::string &vertexShaderPath="", const std::string &fragmentShaderPath="")
Create a sprite from a PNG file and register it with this window.
Definition mxvk.cpp:4455
VkExtent2D swapchain_extent
Definition mxvk.hpp:616
void setClearColor(float r, float g, float b, float a=1.0f)
Set the per-frame color attachment clear color.
Definition mxvk.cpp:637
void exit()
Request loop termination.
Definition mxvk.cpp:1378
VK_Window()=default
Construct an empty window object.
Four-dimensional float vector used for homogeneous 3D coordinates.
Definition mxvk_math.h:363
float z
Z coordinate.
Definition mxvk_math.h:372
#define MXVK_VALIDATION
Definition mxvk.hpp:28
Math, geometry, rasterization, and simple software 3D pipeline helpers for MXVK examples.
std::unique_ptr< SDL_Surface, SurfaceDeleter > SurfacePtr
Definition main.cpp:27
SurfacePtr create_frame_surface(int width, int height)
Definition main.cpp:29
int main()
Definition main.py:165
Utilities for loading and saving PNG images.
Definition mxvk.hpp:31
constexpr std::uint8_t color_r(MXCOLOR color)
Extract the red component from a packed ARGB color.
Definition mxvk_math.h:52
std::uint32_t MXCOLOR
Packed 32-bit color in ARGB byte order.
Definition mxvk_math.h:40
void BuildTables()
Rebuild the sine and cosine lookup tables.
Definition mxvk_math.h:98
constexpr std::uint8_t color_g(MXCOLOR color)
Extract the green component from a packed ARGB color.
Definition mxvk_math.h:55
constexpr MXCOLOR MXVK_RGB(int r, int g, int b)
Build an opaque ARGB color from red, green, and blue components.
Definition mxvk_math.h:49
constexpr std::uint8_t color_a(MXCOLOR color)
Extract the alpha component from a packed ARGB color.
Definition mxvk_math.h:61
@ MX_ACTIVE
Active object or polygon.
Definition mxvk_math.h:1219
@ MX_VISIBLE
Visible object or polygon.
Definition mxvk_math.h:1222
constexpr std::uint8_t color_b(MXCOLOR color)
Extract the blue component from a packed ARGB color.
Definition mxvk_math.h:58
Plain data structure returned by proc_args() with all common libmx2 CLI options.
Definition argz.hpp:718
FramebufferDimensions framebuffer
Software framebuffer size requested by --framebuffer.
Definition argz.hpp:746
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 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
Parsed software framebuffer dimensions.
Definition argz.hpp:709
Triangle primitive used by the simple software rendering pipeline.
Definition mxvk_math.h:1187
vec4D tlist[3]
Transformed vertex positions.
Definition mxvk_math.h:1192
MXCOLOR color
Triangle color.
Definition mxvk_math.h:1195
int state
Polygon state flags.
Definition mxvk_math.h:1201
vec4D vlist[3]
Working vertex positions.
Definition mxvk_math.h:1189