19 constexpr float PI = 3.14159265358979323846f;
21 std::array<Point, 10>
create_star_points(
float center_x,
float center_y,
float outer_radius,
float inner_radius) {
22 std::array<Point, 10> points{};
23 constexpr float start_angle = -
PI * 0.5f;
24 constexpr float step =
PI / 5.0f;
26 for (std::size_t i = 0; i < points.size(); ++i) {
27 const float radius = (i % 2U == 0U) ? outer_radius : inner_radius;
28 const float angle = start_angle +
static_cast<float>(i) * step;
30 .x = center_x + std::cos(angle) * radius,
31 .y = center_y + std::sin(angle) * radius,
37 bool point_in_star(
float x,
float y,
const std::array<Point, 10> &points) {
39 for (std::size_t i = 0, j = points.size() - 1U; i < points.size(); j = i++) {
40 const Point &a = points[i];
41 const Point &b = points[j];
42 if (((a.
y > y) != (b.
y > y)) && (x < (b.
x - a.
x) * (y - a.
y) / (b.
y - a.
y) + a.
x)) {
61 std::cout <<
"stencil_surface: started example.\n";
62 if (!resize_canvas_to_swapchain()) {
63 throw mxvk::Exception(
"stencil_surface: failed to initialize canvas from swapchain extent");
67 void event(SDL_Event &e)
override {
69 case SDL_EVENT_KEY_DOWN:
70 if (e.key.key == SDLK_ESCAPE) {
81 SDL_Surface *canvas = bg.get();
82 if (canvas ==
nullptr || !SDL_LockSurface(canvas)) {
85 const float center_x =
static_cast<float>(canvas->w) * 0.5f;
86 const float center_y =
static_cast<float>(canvas->h) * 0.5f;
87 const float outer_radius =
static_cast<float>(std::min(canvas->w, canvas->h)) * 0.42f;
88 const std::array<Point, 10> star =
create_star_points(center_x, center_y, outer_radius, outer_radius * 0.42f);
90 auto *pixels =
static_cast<Uint8 *
>(canvas->pixels);
91 for (
int y = 0; y < canvas->h; ++y) {
92 Uint8 *row = pixels + y * canvas->pitch;
93 for (
int x = 0; x < canvas->w; ++x) {
94 Uint8 *p = row + x * 4;
95 if (
point_in_star(
static_cast<float>(x) + 0.5f,
static_cast<float>(y) + 0.5f, star)) {
96 const std::uint32_t color = random_color(random_engine);
97 p[0] =
static_cast<Uint8
>(color & 0xFFU);
98 p[1] =
static_cast<Uint8
>((color >> 8U) & 0xFFU);
99 p[2] =
static_cast<Uint8
>((color >> 16U) & 0xFFU);
105 p[3] =
static_cast<Uint8
>(255);
108 SDL_UnlockSurface(canvas);
109 surf->updateTexture(canvas);
110 surf->drawSpriteRect(0, 0, target_width, target_height);
114 resize_canvas_to_swapchain();
118 bool resize_canvas_to_swapchain() {
123 if (extent.width == 0U || extent.height == 0U) {
126 resize_canvas(
static_cast<int>(extent.width),
static_cast<int>(extent.height));
130 void resize_canvas(
int width,
int height) {
131 if (width <= 0 || height <= 0 || (bg !=
nullptr && bg->w == width && bg->h == height)) {
134 bg.reset(SDL_CreateSurface(width, height, SDL_PIXELFORMAT_RGBA32));
136 throw mxvk::Exception(
"Failed to create surface canvas: " + std::string(SDL_GetError()));
138 SDL_FillSurfaceRect(bg.get(),
nullptr, SDL_MapSurfaceRGBA(bg.get(), 0, 0, 0, 255));
139 target_width = width;
140 target_height = height;
143 mxvk::VK_Sprite *surf =
nullptr;
144 std::unique_ptr<SDL_Surface, surface::SurfaceDeleter> bg;
145 int target_width = 1280;
146 int target_height = 720;
147 std::mt19937 random_engine{std::random_device{}()};
148 std::uniform_int_distribution<std::uint32_t> random_color{0U, 0x00FFFFFFU};
152int main(
int argc,
char **argv) {
158 std::cerr << std::format(
"mxvk: Exception: {}\n", e.
text());
161 std::cerr << std::format(
"mxvk: Argument Exception: {}\n", e.
text());
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.
Exception thrown by Argz::proc() on unrecognised or malformed options.
Main Vulkan window wrapper for MXVK.
VkExtent2D getSwapchainExtent() const noexcept
Get the current swapchain extent.
void loop()
Run the main event/render loop.
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.
void exit()
Request loop termination.
bool ensureRenderResources()
Ensure deferred render resources are initialized.
VK_Window()=default
Construct an empty window object.
void onSwapchainRecreated() override
Called after swapchain and render resources are recreated.
SurfaceWindow(std::string shader_path, int width, int height, bool full, bool enable_vsync)
void proc() override
Execute one processing/update step.
void event(SDL_Event &e) override
Handle one SDL event.
Utilities for loading and saving PNG images.
bool point_in_star(float x, float y, const std::array< Point, 10 > &points)
std::array< Point, 10 > create_star_points(float center_x, float center_y, float outer_radius, float inner_radius)
Plain data structure returned by proc_args() with all common libmx2 CLI options.
bool fullscreen
Whether fullscreen mode was requested.
bool enable_vsync
Enable FIFO present mode / v-sync (--enable-vsync).
int height
Viewport height in pixels (default: 720).
std::string filename
Optional input filename (--filename).
int width
Viewport width in pixels (default: 1280).
void operator()(SDL_Surface *surface) const