MXVK Vulkan Framework 0.24.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 {
25 SDL_DestroySurface(surface);
26 }
27 };
28
29 using SurfacePtr = std::unique_ptr<SDL_Surface, SurfaceDeleter>;
30
31 SurfacePtr create_frame_surface(int width, int height) {
32 SurfacePtr surface(SDL_CreateSurface(width, height, SDL_PIXELFORMAT_RGBA32));
33 if (!surface) {
34 throw mxvk::Exception(std::format("Failed to create 3dmath frame surface: {}", SDL_GetError()));
35 }
36 return surface;
37 }
38
39} // namespace
40
41namespace example {
43 public:
44 Math3DWindow(const std::string &, const std::string &title, int width, int height, bool fullscreen, bool enable_vsync, const FramebufferDimensions &framebuffer)
45 : mxvk::VK_Window(title, width, height, fullscreen, MXVK_VALIDATION, enable_vsync),
46 frame_width(framebuffer.width),
47 frame_height(framebuffer.height),
48 fallback_width(width),
49 fallback_height(height) {
50 setClearColor(0.015f, 0.016f, 0.022f, 1.0f);
52 }
53
54 void event(SDL_Event &e) override {
55 if (e.type == SDL_EVENT_KEY_DOWN && e.key.key == SDLK_ESCAPE) {
56 exit();
57 }
58 }
59
60 void proc() override {
61 const int output_width = swapchain_extent.width > 0U ? static_cast<int>(swapchain_extent.width) : fallback_width;
62 const int output_height = swapchain_extent.height > 0U ? static_cast<int>(swapchain_extent.height) : fallback_height;
63
64 ensure_framebuffer();
65 if (frame_sprite == nullptr || frame_surface == nullptr || frame_format == nullptr) {
66 return;
67 }
68
69 clear_frame(mxvk::MXVK_RGB(4, 4, 6));
70 const float time = static_cast<float>(SDL_GetTicks()) * 0.001f;
71
72 mxvk::vec4D vertices[3] = {
73 {-0.75f, -0.45f, 2.6f, 1.0f},
74 {0.75f, -0.45f, 2.6f, 1.0f},
75 {0.0f, 0.75f, 2.6f, 1.0f},
76 };
77
78 mxvk::Mat4D rotation;
79 rotation.BuildXYZ(25.0f, time * 42.0f, time * 18.0f);
80
81 mxvk::RenderList render_list;
82 mxvk::Triangle triangle;
84 triangle.color = mxvk::MXVK_RGB(255, 255, 255);
85 for (int i = 0; i < 3; ++i) {
86 triangle.vlist[i] = vertices[i];
87 triangle.tlist[i] = rotation.MulVec(vertices[i]);
88 triangle.tlist[i].z += 3.0f;
89 }
90 render_list.BuildRenderList(triangle);
91
92 project_to_screen(render_list, frame_width, frame_height);
93
94 const int pixel_size = std::max(1, frame_width / 360);
95 mxvk::PipeLine pipeline;
96 pipeline.Begin(frame_width, frame_height, [this, pixel_size](int x, int y, mxvk::MXCOLOR color) {
97 put_block(x, y, pixel_size, color);
98 });
99 pipeline.DrawPolys(render_list);
100 pipeline.End();
101
102 frame_sprite->updateTexture(frame_surface.get());
103 frame_sprite->drawSpriteRect(0, 0, output_width, output_height);
104 }
105
106 private:
107 SurfacePtr frame_surface;
108 const SDL_PixelFormatDetails *frame_format = nullptr;
109 mxvk::VK_Sprite *frame_sprite = nullptr;
110 int frame_width = 1280;
111 int frame_height = 720;
112 int fallback_width = 1280;
113 int fallback_height = 720;
114
115 void ensure_framebuffer() {
116 if (frame_surface != nullptr) {
117 return;
118 }
119
120 frame_surface = create_frame_surface(frame_width, frame_height);
121 frame_format = SDL_GetPixelFormatDetails(frame_surface->format);
122 if (frame_format == nullptr) {
123 throw mxvk::Exception(std::format("Failed to query 3dmath frame format: {}", SDL_GetError()));
124 }
125
126 clear_frame(mxvk::MXVK_RGB(4, 4, 6));
127 frame_sprite = createSprite(frame_surface.get());
128 frame_sprite->setTextureFilter(VK_FILTER_NEAREST);
129 }
130
131 [[nodiscard]] std::uint32_t map_color(mxvk::MXCOLOR color) const {
132 return SDL_MapRGBA(frame_format, nullptr, mxvk::color_r(color), mxvk::color_g(color), mxvk::color_b(color), mxvk::color_a(color));
133 }
134
135 void clear_frame(mxvk::MXCOLOR color) {
136 SDL_FillSurfaceRect(frame_surface.get(), nullptr, map_color(color));
137 }
138
139 void put_pixel(int x, int y, mxvk::MXCOLOR color) {
140 if (x < 0 || y < 0 || x >= frame_width || y >= frame_height) {
141 return;
142 }
143
144 auto *row = static_cast<std::uint8_t *>(frame_surface->pixels) + (static_cast<std::size_t>(y) * static_cast<std::size_t>(frame_surface->pitch));
145 auto *pixel = reinterpret_cast<std::uint32_t *>(row) + x;
146 *pixel = map_color(color);
147 }
148
149 void put_block(int x, int y, int size, mxvk::MXCOLOR color) {
150 for (int block_y = 0; block_y < size; ++block_y) {
151 for (int block_x = 0; block_x < size; ++block_x) {
152 put_pixel(x + block_x, y + block_y, color);
153 }
154 }
155 }
156
157 static void project_to_screen(mxvk::RenderList &render_list, int width, int height) {
158 const float scale = static_cast<float>(std::min(width, height)) * 0.42f;
159 const float center_x = static_cast<float>(width) * 0.5f;
160 const float center_y = static_cast<float>(height) * 0.5f;
161
162 for (auto &poly : render_list.polys) {
163 for (auto &vertex : poly.tlist) {
164 const float z = std::max(vertex.z, 0.001f);
165 vertex.x = center_x + (vertex.x / z) * scale;
166 vertex.y = center_y - (vertex.y / z) * scale;
167 }
168 }
169 }
170 };
171} // namespace example
172
173int main(int argc, char **argv) {
174 try {
175 Arguments args = proc_args(argc, argv);
176 example::Math3DWindow window(args.path, "MXVK 3D Math", args.width, args.height, args.fullscreen, args.enable_vsync, args.framebuffer);
177 window.loop();
178 } catch (mxvk::Exception &e) {
179 std::cerr << std::format("mxvk: Exception: {}\n", e.text());
180 return EXIT_FAILURE;
181 } catch (ArgException<std::string> &e) {
182 std::cerr << std::format("mxvk: Argument Exception: {}\n", e.text());
183 return EXIT_FAILURE;
184 }
185 return EXIT_SUCCESS;
186}
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 operator()(SDL_Surface *surface) const
Definition main.cpp:24
void event(SDL_Event &e) override
Handle one SDL event.
Definition main.cpp:54
void proc() override
Execute one processing/update step.
Definition main.cpp:60
Math3DWindow(const std::string &, const std::string &title, int width, int height, bool fullscreen, bool enable_vsync, const FramebufferDimensions &framebuffer)
Definition main.cpp:44
std::string text() const
Four-by-four homogeneous transform matrix.
Definition mxvk_math.h:812
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:973
vec4D MulVec(const vec4D &in) const
Transform a homogeneous 4D vector by this matrix.
Definition mxvk_math.h:881
Clipped software rasterization pipeline for lines and filled triangles.
Definition mxvk_math.h:2273
void End()
End rendering and release the current plotting callbacks.
Definition mxvk_math.h:2671
void DrawPolys(const RenderList &list) const
Draw active render-list triangles as clipped wireframes.
Definition mxvk_math.h:2613
void Begin(int width, int height, std::function< void(int, int, MXCOLOR)> plotter)
Begin rendering with a custom pixel plotter.
Definition mxvk_math.h:2318
Flat list of triangles prepared for transformation and rasterization.
Definition mxvk_math.h:1371
std::vector< Triangle > polys
Triangle storage.
Definition mxvk_math.h:1374
void BuildRenderList(const Triangle &triangle)
Append one triangle to the render list.
Definition mxvk_math.h:1432
Main Vulkan window wrapper for MXVK.
Definition mxvk.hpp:37
void loop()
Run the main event/render loop.
Definition mxvk.cpp:600
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:3477
VkExtent2D swapchain_extent
Definition mxvk.hpp:495
void setClearColor(float r, float g, float b, float a=1.0f)
Set the per-frame color attachment clear color.
Definition mxvk.cpp:593
void exit()
Request loop termination.
Definition mxvk.cpp:1126
VK_Window()=default
Construct an empty window object.
Four-dimensional float vector used for homogeneous 3D coordinates.
Definition mxvk_math.h:416
float z
Z coordinate.
Definition mxvk_math.h:425
int main(void)
Definition main.cpp:7
#define MXVK_VALIDATION
Definition mxvk.hpp:27
Math, geometry, rasterization, and simple software 3D pipeline helpers for MXVK examples.
std::unique_ptr< SDL_Surface, SurfaceDeleter > SurfacePtr
Definition main.cpp:29
SurfacePtr create_frame_surface(int width, int height)
Definition main.cpp:31
Utilities for loading and saving PNG images.
Definition mxvk.hpp:30
constexpr std::uint8_t color_r(MXCOLOR color)
Extract the red component from a packed ARGB color.
Definition mxvk_math.h:54
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:113
constexpr std::uint8_t color_g(MXCOLOR color)
Extract the green component from a packed ARGB color.
Definition mxvk_math.h:59
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:69
@ MX_ACTIVE
Active object or polygon.
Definition mxvk_math.h:1358
@ MX_VISIBLE
Visible object or polygon.
Definition mxvk_math.h:1361
constexpr std::uint8_t color_b(MXCOLOR color)
Extract the blue component from a packed ARGB color.
Definition mxvk_math.h:64
Plain data structure returned by proc_args() with all common libmx2 CLI options.
Definition argz.hpp:730
FramebufferDimensions framebuffer
Software framebuffer size requested by --framebuffer.
Definition argz.hpp:758
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 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
Parsed software framebuffer dimensions.
Definition argz.hpp:721
Triangle primitive used by the simple software rendering pipeline.
Definition mxvk_math.h:1326
vec4D tlist[3]
Transformed vertex positions.
Definition mxvk_math.h:1331
MXCOLOR color
Triangle color.
Definition mxvk_math.h:1334
int state
Polygon state flags.
Definition mxvk_math.h:1340
vec4D vlist[3]
Working vertex positions.
Definition mxvk_math.h:1328