Skip to content

lostjared/MXVK

Repository files navigation

MXVK

mxvk_logo_640

MXVK is a C++20 Vulkan rendering framework with SDL3 integration, focused on practical 2D and 3D application development.

It provides a reusable window/render loop (mxvk::VK_Window), sprite and text rendering, model rendering, a small engine math library in mxvk/mxvk_math.h, optional OpenCV capture support, and a set of examples that demonstrate end-to-end usage. It is designed to be easy to use while still retaining the power that Vulkan provides.

Current development is on version 0.21.0. This release expands asteroids-net to four-player games, improves its host/join flow and bundled runtime assets, and adds automatic temporary UDP router mapping through optional UPnP/NAT-PMP support. It also adds model and texture-manifest loading to shader_viewer, expands the Mutatris background-effect pack, and extends Doxygen coverage for the multiplayer example. Recent framework work also added shared Vulkan context/resource helpers, a point-sprite batch renderer for particle/starfield effects, stronger post-processing and descriptor cleanup, and resize fixes for SDL surface upload examples.

The repository also includes MXWrite, a small FFmpeg-based video writer library for exporting RGBA frames to video files. It can be built alongside MXVK with -DWITH_MXWRITE=AUTO|ON|OFF.

Contents

What This Project Is

  • A static library (mxvk) for Vulkan-based rendering.
  • A small 2D/3D math and software-raster helper library used by the engine tests and examples.
  • A set of examples under examples/ that exercise key features:
    • dynamic rendering and custom pipelines
    • sprite rendering and shader effects
    • text rendering
    • engine math, projection, and software 3D raster tests
    • Matrix-style digital rain rendering
    • reusable Matrix rain texture generation
    • reusable point-sprite particle/starfield rendering
    • model rendering
    • game loops and input handling
    • controller input, console overlays, post-processing, and audio-enabled gameplay when optional features are present
    • simple gameplay examples and UI state flow
    • optional OpenCV camera/video workflows

Demo Video

View on YouTube: https://youtu.be/Y3PyGg3qBUA

Cloning the Repository

git clone https://github.com/lostjared/MXVK.git

Windows X64 Demo Builds:

Demos for Windows X64

Core Dependencies

The root CMake configuration checks for and uses:

  • C++20 compiler
  • SDL3
  • SDL3_ttf
  • optional: SDL3_mixer (use -DWITH_MIXER=AUTO|ON|OFF)
  • Vulkan 1.4+
  • PNG
  • ZLIB
  • optional: JPEG (use -DJPEG=ON)
  • glm
  • glslc (shader compiler)
  • Optional: OpenCV (when building with -DCV=ON)
  • Optional: FFmpeg for MXWrite (when building with -DWITH_MXWRITE=AUTO|ON)
  • Optional: miniupnpc and libnatpmp for automatic UDP router mapping in asteroids-net

Build

From repository root:

cmake -S . -B build
cmake --build build -j

If you clone/move the repo to a different machine or path, run a fresh configure first. CMake-generated build files contain absolute paths and can fail with errors like No rule to make target .../examples/.../*.frag when a previous build directory is reused.

cmake --fresh -S . -B build
cmake --build build -j

If your CMake version does not support --fresh, remove the build directory manually:

rm -rf build
cmake -S . -B build
cmake --build build -j

Useful CMake options:

  • -DVALIDATION=ON enables Vulkan validation layers.
  • -DDEBUG_MODE=ON enables debug compile flags.
  • -DWITH_CUDA=AUTO|ON|OFF controls CUDA acceleration/interop. The default is AUTO, which enables CUDA when the toolkit is detected; ON requires CUDA; OFF disables it.
  • -DWITH_MXWRITE=AUTO|ON|OFF controls the MXWrite FFmpeg video writer build. The default is AUTO, which builds MXWrite when FFmpeg is detected; ON requires FFmpeg; OFF skips MXWrite.
  • -DCV=ON enables OpenCV-based examples and capture support.
  • -DWITH_MIXER=AUTO|ON|OFF controls SDL3_mixer audio support (mxvk_sound.cpp, MXVK_WITH_MIXER). The default is AUTO, which enables audio when SDL3_mixer is detected; ON requires SDL3_mixer; OFF disables it.
  • -DJPEG=ON enables JPEG image support (mxvk_jpeg.cpp, MXVK_WITH_JPEG).
  • -DFRACTAL_ZOOM=ON enables the fractal_zoom example and its Boost dependency.
  • -DEXAMPLES=OFF builds/install only the mxvk library and skips all examples.

Example:

cmake -S . -B build -DVALIDATION=ON -DCV=ON
cmake --build build -j

Additional configure examples:

# Build library + examples with audio and JPEG support
cmake -S . -B build -DWITH_MIXER=ON -DJPEG=ON

# Build the fractal_zoom example and its Boost dependency
cmake -S . -B build -DFRACTAL_ZOOM=ON

# Library-only build (faster CI/package build)
cmake -S . -B build -DEXAMPLES=OFF

To install the configured build, run:

sudo cmake --install build

By default, CMake installs to /usr/local. Set -DCMAKE_INSTALL_PREFIX=<path> during configuration to use a different location.

Documentation

The repository includes a Doxygen configuration for the core framework. The generated output is written under docs/doxygen.

doxygen Doxyfile

The current Doxygen project version is 0.21.0. Recent public API comments cover VK_Window, the shared VulkanContext handle bundle in mxvk_context.hpp, the Vulkan resource helpers in mxvk_resource.hpp, the stencil helper in mxvk_stencil.hpp, the point-sprite batch renderer in mxvk_point_sprite_batch.hpp, and the asteroids-net multiplayer, ship, starfield, and port-mapping components.

Command Line Arguments

Most examples use the shared parser in mxvk/argz.hpp via proc_args(...).

Supported options:

  • -h
    • Show help and exit.
  • -p <path>, --path <path>
    • Asset root path (defaults to . when omitted).
  • -r <WxH>, --resolution <WxH>
    • Window resolution, e.g. -r 1280x720.
    • For compute_shader, this also sets the compute canvas and recorded video size; source frames are scaled into that canvas before shader processing. When omitted for file playback, the window and compute canvas use the video frame size unless fullscreen is enabled.
  • -f, --fullscreen
    • Launch in fullscreen mode.
  • --filename <file>
    • Optional input/model/video filename used by examples that support external assets.
    • For model_example, this overrides the default data/pyramid.obj mesh. You can point it at a custom .obj, .mxmod, or .mxmod.z file.
    • When you provide a custom model, the loader no longer assumes the built-in pyramid asset set. If the model references external textures, use --resource <file> for a texture manifest and --resource_path <dir> for the texture directory.
    • run.pl already passes the example asset root with -p, so --filename can usually be a relative path inside the repo or a full absolute path.
  • -o <file>, --output <file>
    • Optional output filename for examples that export video.
  • -c <value>, --crf <value>
    • Optional Constant Rate Factor for video export.
  • --encode-preset <preset>
    • Optional MXWrite encoder preset. For software x264 use values such as ultrafast, superfast, veryfast, fast, medium, slow, or veryslow; for NVENC these map to NVENC preset levels.
  • --encode-tune <tune>
    • Optional MXWrite encoder tune, such as film, animation, grain, stillimage, fastdecode, or zerolatency.
  • --encode-codec <auto|software|nvenc|h264_nvenc|hevc_nvenc>
    • Optional MXWrite encoder selection. auto prefers NVENC when available, software forces the software encoder, nvenc requests the resolution-selected NVENC codec, and h264_nvenc or hevc_nvenc request that concrete NVENC encoder with fallback handled by MXWrite.
  • --encode-realtime
    • Enable MXWrite low-latency/realtime encoder settings.
  • --mxwrite-block
    • Make MXWrite block when its internal queue is full instead of dropping frames.
  • --enable-crt
    • Start examples that support CRT post-processing with the effect enabled.
  • --enable-vsync
    • Request FIFO swapchain present mode instead of the default low-latency MAILBOX preference.
    • Example: ./run.pl hello_world --enable-vsync.
  • --enable-screenshot
    • Enable framework screenshot capture for examples based on mxvk::VK_Window.
    • Press F10 after the first frame has presented to save a PNG under ~/Pictures.
    • Filenames use the executable basename from argv[0], a dotted local date/time stamp, the current swapchain resolution, and a per-run index: breakout.screenshot.2026.07.02.08.30.37.1280x720-0.png.
    • A trailing .exe or .EXE suffix is stripped from the executable name before it is used.
  • --texture <file>
    • Optional texture filename.
  • -S <path>, --shader-path <path>
    • Shader SPIR-V folder path.
    • For shader_viewer, this path must contain index.txt. The index may list compiled .spv fragment shaders directly, or .glsl source names when matching compiled files exist under a spv/ subdirectory. Download a precompiled SPIR-V shader pack from https://lostsidedead.biz/packs/vk.shaders.2026.02.17.zip.
  • --shader-index <index>
    • Initial shader entry for examples that browse shader lists, such as shader_viewer.
  • --camera <index>
    • Camera index for OpenCV capture examples.

General run pattern:

./<example> [options]

To run a compiled example from the repository root, use run.pl:

./run.pl <example> [extra args...]

run.pl looks up the built executable under build/examples/<example>/ and passes the example's asset directory with -p automatically.

All examples based on mxvk::VK_Window also support F12 to toggle the framework FPS counter. The overlay is disabled by default and uses the copied data/default.ttf font from the example's build output directory.

When --enable-screenshot is provided, those same window-based examples also support F10 screenshots. The capture path uses the most recently presented swapchain image and writes a PNG to ~/Pictures.

For the full core demo sweep, use ./run.pl --all. It runs the example list sequentially by delegating to testapps.pl, forwards any extra arguments to each run.pl invocation, and stops on the first failure or Ctrl-C.

For automated smoke testing of windowed examples, add --timeout. This launches each example, lets it run for 5 seconds, closes it, and continues through the whole list. Unlike the default --all mode, timeout mode collects failures and prints a summary after every example has been attempted. You can override the timeout with --timeout=<seconds>.

Timeout mode is also supported for a single example. run.pl accepts --timeout before or after the example name, and closes the child process group when the deadline is reached. In non-interactive CODEX_CI runs, single-example launches default to timeout mode unless MXVK_RUN_DEFAULT_TIMEOUT overrides the duration.

./run.pl --all --timeout
./run.pl --all --timeout=3
./run.pl surface --timeout=2
./run.pl --timeout=2 stencil_surface

Examples:

./run.pl sprite_example -r 1920x1080 -f
./run.pl 3dmath
./run.pl 3dmath_cube
./run.pl 3dmath_texture --filename ./examples/sprite_example/data/intro.png
./run.pl model_example
./run.pl viewer --filename ./models/moon.mxmod.z
./run.pl planet
./run.pl surface
./run.pl stencil_surface
./run.pl stencil
./run.pl bluesky
./run.pl fire
./run.pl pointsprite
./run.pl fireworks
./run.pl starfield
./run.pl pong
./run.pl breakout
./run.pl tictactoe
./run.pl pool_demo
./run.pl puzzle_drop
./run.pl mutatris
./run.pl fractal_zoom
./run.pl console_demo -r 1280x720
./run.pl matrix
./run.pl glitch_cube -r 1280x720
./run.pl postprocess
./run.pl starship
./run.pl defender
./run.pl walk
./run.pl walk_post --shader-path /path/to/post_fx --shader-index 0
./run.pl 3dmath_masterpiece
./run.pl compute_shader --camera 0
./run.pl opencv_example --camera 0 -r 1280x720
./run.pl shader_viewer --camera 0 --shader-path /path/to/shaders --shader-index 0
./run.pl opencv_model --filename ./models/torus.mxmod.z --camera 0

VK_Window Post-Processing

mxvk::VK_Window can render the normal scene into an offscreen color target and then draw that image through one or more full-screen fragment shaders before presenting. Attach one shader with attachPostProcessingShader(...) or attach a chain with attachPostProcessingShaders(...). Each effect can use its own parameter vector and optional elapsed-time update, and the full chain can be toggled at runtime with setPostProcessingEnabled(...).

The multi-effect path uses intermediate render targets between passes, so post-processing no longer has to sample directly from the swapchain image. This allows effects such as invert, scanline, blur, CRT, color grading, or other sprite-compatible full-screen shaders to be composed in sequence.

The postprocess example demonstrates this flow. It reads examples/postprocess/data/shaders.txt, loads each listed SPIR-V fragment shader, and attaches the resulting list as a post-processing chain. The example currently ships with invert.frag and scanline.frag.

walk_post is an interactive post-processing browser built from the walk first-person sample. Pass --shader-path <dir> to a directory containing index.txt, optionally select the starting shader with --shader-index <index>, then press R and T while running to switch to the previous or next full-screen effect. Its post-processing sprite uses extended uniforms for elapsed time, frame timing, frame count, resolution, and mouse state.

defender and asteroids3d use this path for the CRT shader. In both examples, press F8 to toggle the CRT post-processing effect on or off.

Debugging Examples

Use debug.pl from the repository root to launch a built example under GDB:

./debug.pl <example> [extra args...]

The script resolves the executable name from examples/<example>/CMakeLists.txt, then looks for it under build/examples/<example>/. It changes into the executable directory before launching GDB so relative runtime files behave like a normal run.pl launch.

debug.pl also passes the example asset path automatically with -p. Most examples receive -p examples/<example>, while examples whose CMake file sets ASSET_DIR to the target output directory receive -p build/examples/<example>. Any extra arguments after the example name are forwarded to the program.

Internally, the script executes GDB in quiet mode and immediately starts the program:

gdb -q -ex "set confirm off" -ex "run" --args ./<executable> -p <asset_path> [extra args...]

When the program crashes or hits a breakpoint, you are left at the GDB prompt. Useful commands include bt for a backtrace, frame <n> to inspect a stack frame, print <expr> to inspect values, continue to resume, and quit to exit.

Examples:

./debug.pl sprite_example -r 1920x1080
./debug.pl model_example --filename ./models/torus.mxmod.z
./debug.pl opencv_example --camera 0 -r 1280x720

Model Viewer Tools

MXVK includes two related model inspection tools:

  • examples/viewer builds the viewer executable. It is the direct Vulkan renderer for loading and inspecting .obj, .mxmod, and .mxmod.z model files from the command line. It uses VKAbstractModel, the viewer-specific model shaders, and the shared MXVK window/input path. Use this when you want a lightweight renderer, a quick model smoke test, or a backend that can be launched by another tool.
  • model_viewer is a Qt6 desktop front end for the viewer executable. It provides file pickers, drag-and-drop, recent files, resolution presets, persistent settings, and a live process console. It does not replace the renderer; it launches viewer with the selected model, texture manifest, texture directory, and resolution.

Build viewer through the normal root build:

cmake -S . -B build
cmake --build build -j
./run.pl viewer --filename ./models/moon.mxmod.z

Build the Qt front end from its own directory after the root viewer target is available:

cmake -S model_viewer -B model_viewer/build
cmake --build model_viewer/build -j

If model_viewer cannot find viewer automatically, set the renderer path from its settings dialog.

Examples

The examples are grouped below by what they demonstrate. Most accept the shared arguments documented above, and the per-example README.md files carry the full control maps for the larger demos.

Starter Samples

  • cfg_example - config persistence smoke test. Inputs: none. Controls: none; it runs once, prints the incremented counter, and exits.
  • hello_world - minimal mxvk::VK_Window example with a custom graphics pipeline and animated triangle. Inputs: common -p, -r, -f. Controls: Escape quits.
  • skeleton - smallest practical subclass of mxvk::VK_Window, intended as a copyable starting point for new examples. Inputs: common -p, -r, -f. Controls: Escape quits.
  • static_example - fullscreen triangle sample that pushes window size and frame count into the shader. Inputs: common -p, -r, -f. Controls: Escape quits.
  • surface - SDL surface upload smoke test that fills a CPU-side surface with random pixels, uploads it to an MXVK sprite each frame, and redraws it after resize. The canvas is sized from the active swapchain extent so high-DPI and MoltenVK/macOS resize behavior matches the presented image. Inputs: common -r, -f, optional --filename as the sprite shader path. Controls: Escape quits.
  • stencil_surface - SDL surface upload demo that fills a CPU-side star mask with randomized color, uploads it to an MXVK sprite, and redraws it after resize. The canvas is sized from the active swapchain extent so high-DPI and MoltenVK/macOS resize behavior matches the presented image. Inputs: common -r, -f, optional --filename as the sprite shader path. Controls: Escape quits.
  • sprite_example - loads a PNG sprite, renders it full-screen, and overlays text with a custom sprite shader. Inputs: common -p, -r, -f; optional texture and shader path arguments. Controls: Escape quits.
  • text_example - compact text-rendering sample built around setFont(...) and printText(...). Inputs: common -p, -r, -f. Controls: Escape quits.
  • rain - static helper library used by Matrix-style examples to render configurable glyph rain into an SDL surface and MXVK sprite texture. It is not launched directly through run.pl.

Engine Math Tests

These programs are not intended as standalone applications. They are small visual tests for the engine's mxvk/mxvk_math.h math helpers, projection code, triangle drawing, filled polygons, lighting, and software texture sampling inside the MXVK render loop.

  • 3dmath - minimal rotating triangle test using vec4D, Mat4D, RenderList, and PipeLine projection/drawing helpers. Inputs: common -p, -r, -f. Controls: Escape quits.
  • 3dmath_cube - rotating cube test for matrix transforms, backface culling, depth sorting, diffuse face shading, filled triangle rasterization, and line clipping. Inputs: common -p, -r, -f. Controls: Escape quits.
  • 3dmath_texture - textured rotating cube test for the same software 3D path plus PNG loading and software UV sampling. Inputs: common -p, -r, -f, plus --filename <file.png> or --texture <file.png>. Controls: Escape quits.
  • 3dmath_masterpiece - MasterPiece variant that renders the board and falling blocks as CPU-rasterized spinning 3D cubes before uploading the frame through an MXVK sprite. Inputs: common -p, -r, -f. Controls: arrow keys move, Up rotates forward, Q rotates backward, hold W / A / S / D to rotate the grid, hold Page Up / Page Down to zoom, P pauses, Escape returns to the menu.

Shader And Effect Demos

  • matrix - Matrix-style digital rain rendered from SDL_ttf glyphs and a sprite-backed framebuffer. Inputs: common -p, -r, -f. Controls: Space randomizes the streams, Escape quits.
  • binary_matrix - 3D variant of matrix that turns 0 and 1 glyphs into a depth-aware scene. Inputs: common -p, -r, -f. Controls: Space randomizes the rain, arrow keys orbit the camera, Page Up / Page Down zoom, Escape quits.
  • fractal_zoom - fullscreen Mandelbrot-style renderer with runtime zoom, pan, palette switching, and shader-driven color output. Inputs: common -p, -r, -f. Controls: mouse wheel zoom, drag pan, W / A / S / D or arrow keys pan, Z / X continuous zoom, 1 / 2 / 3 presets, + / = and - iteration count, [ / ] palette, R reset, Escape quit.
  • fire - full-screen procedural fire shader driven through the VK_Window post-processing path. Inputs: common -p, -r, -f. Controls: mouse wheel adjusts shader zoom, Escape quits.
  • postprocess - full-screen post-processing chain demo. It reads data/shaders.txt, creates one effect per listed fragment shader, and runs the chain through VK_Window::attachPostProcessingShaders(...). Post-process sprites cache external texture descriptors per offscreen image and clear those descriptors when the swapchain targets are rebuilt. Inputs: common -p, -r, -f. Controls: Escape quits.
  • stencil - VK_Stencil demo that writes a shader-generated mask into a stencil attachment, then fills only the masked region with a second shader pass. Inputs: common -p, -r, -f. Controls: Escape quits.
  • console_demo - in-window console layered over a moving shader background. Inputs: common -p, -r, -f. Controls: F3 opens or closes the console, Escape quits when the console is hidden, console commands include help, echo, about, quit, and exit.
  • glitch_cube - stylized cube viewer with time-based transforms, shader-driven presentation, and runtime scale/orbit controls. Inputs: common -p, -r, -f. Controls: left mouse drag orbits, mouse wheel zooms, Space toggles the rotation axis, Page Up / Page Down scales the cube, Escape quits.
  • pointsprite - direct mxvk::VK_PointSpriteBatch sample that renders many Tux sprites as point primitives and grows the active point count at runtime. Inputs: common -p, -r, -f. Controls: hold Space to add sprites, Enter resets to the default count and size, Page Up / Page Down adjust sprite size, Escape quits.
  • fireworks - point-sprite particle burst demo using VK_PointSpriteBatch, additive blending, and a star texture. Inputs: common -p, -r, -f. Controls: Space triggers a new explosion, Escape quits.
  • starfield - dedicated point-sprite stress/demo scene using mxvk::VK_PointSpriteBatch to render 50,000 layered, twinkling stars with additive blending. Inputs: common -p, -r, -f, --enable-vsync. Controls: hold Space for a warp-speed boost, Escape quits.

3D Viewers

  • viewer - general-purpose model inspection renderer for OBJ, MXMOD, and compressed MXMOD assets. It defaults to cube.mxmod.z, accepts --filename, --texture, --resource_path, --shader-path, and common window arguments, and is the backend launched by the Qt model_viewer app. Controls: left mouse drag or arrow keys rotate, mouse wheel / + / - / A / S zoom, W toggles wireframe, R or P toggles auto-rotate, H or Space toggles help, Home resets the view, Escape quits.
  • model_example - basic VKAbstractModel viewer for textured OBJ or MXMOD assets. By default it loads data/pyramid.obj from the example asset directory. --filename overrides the model file, --resource can point at a texture manifest, --resource_path can override the texture lookup directory, and --binary replaces the model's texture with animated Matrix-style green rain while also enabling the skybox toggle. Inputs: common -p, -r, -f, --filename, --fragment, --resource, --resource_path, and --binary. Controls: left mouse drag rotates, mouse wheel zooms, Space toggles auto-spin, Enter toggles skybox mode when --binary is enabled, W/A/S/D look around inside the skybox view, Escape quits.
  • planet - textured Saturn scene with a ring, orbital camera, and runtime asset staging. Inputs: common -p, -r, -f, --filename. Controls: left mouse drag orbits, mouse wheel zooms, Escape quits.
  • bluesky - procedural water and sky scene that renders a large indexed water grid with custom Vulkan buffers and shaders. The shader push constants include viewport aspect data so the sky/cloud presentation remains stable across non-16:9 window sizes. Inputs: common -p, -r, -f. Controls: Left / Right orbit, Up / Page Up zoom in, Down / Page Down zoom out, Escape quits.
  • tux_example - layered scene that combines a textured model, an animated background sprite, and text overlays. Inputs: common -p, -r, -f. Controls: Escape quits.
  • sprite3d_example - 3D sprite scene with a starfield, a flying saucer, and mouse-driven camera orbiting. Inputs: common -p, -r, -f. Controls: left mouse drag orbits, mouse wheel zooms, Escape quits.
  • starship - ship viewer with Phong shading, a moving starfield, and exhaust effects. Inputs: common -p, -r, -f, plus the example asset set. Controls: mouse drag rotates the ship, Escape quits.
  • dark - Dark Crystal Pyramid viewer with a custom beam effect and layered model/sprite/text rendering. Inputs: common -p, -r, -f, optional --filename. Controls: left mouse drag orbits, mouse wheel zooms, Escape quits.
  • moon - moon model viewer with pyramids and a separate starfield layer. Inputs: common -p, -r, -f, optional --filename and --fragment. Controls: left mouse drag orbits, mouse wheel zooms, Space toggles auto-spin, Escape quits.

Games And Interactive Scenes

  • asteroids - 2D Asteroids-style arcade shooter with physics, scoring, particles, and a fixed playfield. Inputs: common -p, -r, -f. Controls: Left / Right rotate, Up thrust, Space fire, Escape quits.
  • asteroids3d - 3D Asteroids-style action game with ship, asteroids, projectiles, and console commands. Inputs: common -p, -r, -f, optional --enable-crt. Controls: Space or Enter starts from the intro, F1 toggles the debug HUD, F2 toggles inverted controls, F3 opens the console, F8 toggles CRT post-processing, Left / Right yaw, W / S pitch, A / D roll, Up / Down speed, Space fires, Escape returns to the intro or quits.
  • asteroids-net - network multiplayer variant of the 3D Asteroids game for up to four players over UDP. Hosts receive an eight-character join code and automatically request a temporary router mapping through UPnP or NAT-PMP when the optional libraries are installed. Inputs: common -p, -r, -f, optional --enable-crt; host/join address, UDP port, pilot name, and join code are entered in the lobby. Controls: the same flight, camera, firing, console, and CRT controls as asteroids3d.
  • breakout - 3D Breakout game with a model-rendered paddle, ball, block field, animated crystal backgrounds, touch/gamepad support, and optional SDL3_mixer sound effects. Inputs: common -p, -r, -f. Controls: Enter, Space, click, tap, or gamepad start begins play; Left / Right or H / L move the paddle; Space, Enter, click, double tap, or gamepad south launches the ball; W / A / S / D rotate the board, Page Up / Page Down zoom, Q resets the view, R restarts, Backspace returns to intro, and Escape quits.
  • defender - side-scrolling 3D starfield shooter with model-based ship and asteroids, animated UFO sprites, radar/HUD, controller support, console commands, Matrix-rain intro, CRT post-processing, and optional SDL3_mixer audio. Inputs: common -p, -r, -f. Controls: Enter or Space starts, Z thrusts, D boosts, X reverses, W / Up and Down move vertically, A / S roll, Space fires, F3 toggles the console, F4 toggles FPS, F8 toggles CRT, Escape quits.
  • pong - 3D-styled Pong demo with paddle/ball gameplay and real-time state updates. Inputs: common -p, -r, -f plus the example data directory. Controls: arrow keys move the paddle, W / A / S / D rotate the view, Q resets rotation, R resets the game, Space toggles wireframe, Enter resets the camera, Escape quits.
  • tictactoe - mouse-driven tic-tac-toe against a simple computer opponent. Inputs: common -p, -r, -f. Controls: mouse click places a mark, R resets, Escape quits.
  • walk - first-person maze and exploration sample with procedural generation, collision, collectibles, and combat. Inputs: common -p, -r, -f. Controls: W / A / S / D move, mouse or right stick look, Left Shift sprint, Left Ctrl crouch, Space jump, left click or right shoulder fire, F toggles the FPS overlay, Escape releases the mouse or quits.
  • walk_post - walk-style first-person maze that adds selectable full-screen post-processing through --shader-path and --shader-index, plus hot-swappable scene shaders from the console. Inputs: common -p, -r, -f, --shader-path, --shader-index. Controls: same movement/combat controls as walk, plus R / T select previous/next post-processing shader and F3 toggles the console.
  • pool_demo (Pool3D) - 3D billiards game with menus, high scores, cue-ball placement, and shot logic. Inputs: common -p, -r, -f. Controls: menus use Enter, Space, Escape, and Back; in-game controls include arrow keys, Space to charge a shot, Enter to confirm cue-ball placement, mouse drag for aiming, right mouse drag to rotate the camera, and wheel or pinch to zoom.
  • puzzle - Acid Drop, a falling-block puzzle with menus, scores, options, credits, and name entry. Inputs: common -p, -r, -f. Controls: Up / Down navigate menus, Left / Right move blocks, Space rotates, P pauses, Escape backs out or quits, and text entry uses Backspace / Enter.
  • puzzle_drop - 3D Acid Drop-style block puzzle with an intro, Matrix-rain backdrop, textured cube pieces, selectable difficulty, keyboard controls, and gamepad support. Inputs: common -p, -r, -f. Controls: Enter / Space skips the intro, 1 / 2 / 3 starts difficulty levels, Left / Right move, Down soft drops, Up cycles piece blocks, Z / X rotate, W / A / S / D rotate the board, Page Up / Page Down zoom, Escape quits.
  • mutatris - four-sided falling-block puzzle game with rotating board focus, selectable difficulty, animated backgrounds, randomized shader effects that change by level, startup/title/game-over screens, optional SDL3_mixer music and sound effects, and keyboard, mouse/touch, gamepad, and console input. Inputs: common -p, -r, -f. Controls: Enter, Space, click, tap, or gamepad start advances menus; Left / Right select difficulty; in game, arrows move relative to the active side, W or the active side's color-cycle arrow shifts piece colors, A / Space rotates, S hard drops, F3 toggles the console, and Escape quits.
  • masterpiece (MasterPiece) - port of the original MasterPiece.SDL block puzzle game with updated assets. Inputs: common -p, -r, -f. Controls: menu navigation uses Up / Down / Enter / Escape; in game use Left / Right move, Down soft drop, A or Up rotate forward, S rotate backward, P pause, Escape return to menu, with typed input for high-score entry.
  • tetris - 3D Tetris with a title flow, high scores, credits, and optional network multiplayer. Inputs: common -p, -r, -f. Controls: menus use Up / Down / Enter / Escape; in game use Left / Right move, Down soft drop, Up rotate, Z hard drop, R restart, Escape menu, camera controls use W / A / S / D, Q / E, Page Up / Page Down, and multiplayer uses H to host and J / Enter to join.

Camera And Video Workflows

  • compute_shader - OpenCV capture or video-file playback through selectable Vulkan compute shaders. Inputs: requires -DCV=ON; accepts --camera, --filename, --output, --crf, --shader-path, and compute-related options. Controls: Up / Down switch shaders, Left / Right change the acidcam_filters selector, Escape quits.
  • shader_viewer - OpenCV camera viewer that applies sprite-compatible fragment shaders from a shader index. Inputs: requires -DCV=ON; accepts --camera, --shader-path, and --shader-index. --shader-path should point at a folder containing index.txt; entries may be .spv files or .glsl source names with matching compiled files in spv/. A precompiled SPIR-V pack is available at https://lostsidedead.biz/packs/vk.shaders.2026.02.17.zip. Controls: Up / Down switch shaders, mouse position and left-button state are passed to shader uniforms, Escape quits.
  • opencv_example - displays camera or video frames on a sprite in real time. Inputs: requires -DCV=ON; accepts --camera and --filename. Controls: Escape quits.
  • opencv_model - maps a live camera feed onto a textured 3D model. Inputs: requires -DCV=ON; accepts --camera, --filename, and standard example arguments. Controls: left mouse drag orbits, mouse wheel zooms, arrow keys rotate the model, Escape quits.

If you want a quick tour of the core demos, ./run.pl --all executes the default example sweep used by testapps.pl.

Asteroids Net Multiplayer

asteroids-net hosts an authoritative UDP session on port 48120 by default and supports up to four players. When hosting, it tries UPnP first and NAT-PMP second to create a temporary public UDP mapping. The lobby reports the selected method and, when the router supplies it, the public endpoint. The mapping is removed when the host leaves the lobby or exits the application.

Router mapping support is optional. On Arch Linux, install both client libraries and run a fresh CMake configure so they are detected:

sudo pacman -S miniupnpc libnatpmp
cmake --fresh -S . -B build
cmake --build build -j --target asteroids-net
./run.pl asteroids-net

The package-to-feature mapping is:

  • miniupnpc provides the miniupnpc library and upnpc diagnostic program used for UPnP IGD discovery and mappings.
  • libnatpmp provides the libnatpmp library and natpmpc diagnostic program used for NAT-PMP mappings.

CMake gates the features independently. UPnP is compiled only when both miniupnpc/miniupnpc.h and the miniupnpc library are found; NAT-PMP is compiled only when both natpmp.h and the natpmp library are found. Neither package is required for a successful MXVK build.

If neither library is present, the example still builds and local/LAN multiplayer still works. If automatic mapping is unavailable, disabled on the router, or blocked by carrier-grade NAT, the lobby asks the host to forward the selected UDP port manually. Carrier-grade NAT generally requires a VPN/overlay network or a relay service; UPnP and NAT-PMP cannot bypass it.

See examples/asteroids-net/README.md for the complete lobby flow, controls, security notes, and troubleshooting steps.

Recent Optimizations

  • July 11, 2026: version 0.21.0 adds the four-player asteroids-net mode, including richer host/join screens, player-state and projectile synchronization improvements, runtime asset-path handling, and an application icon. The release also adds model/texture-manifest support to shader_viewer, enlarges the Mutatris background-effect pack, and documents the asteroids-net public types and networking helpers with Doxygen.
  • July 11, 2026: asteroids-net added automatic temporary UDP router mapping for hosted games. It tries UPnP through miniupnpc, falls back to NAT-PMP through libnatpmp, reports mapping results in the lobby, and removes active mappings when hosting stops. Both dependencies remain optional, preserving LAN play and builds on systems without them.
  • July 11, 2026: asteroids-net documentation now covers multiplayer hosting/joining, Arch Linux dependency installation, compile-time feature gating, router capability diagnostics, manual forwarding, IPv6/overlay alternatives, CGNAT limitations, and mapping cleanup behavior.
  • July 9, 2026: the project version moved to 0.20.0, and Doxyfile now reports 0.20.0 for generated API documentation. This release also includes descriptor cleanup hardening in VK_Sprite, updated Pong assets and sound effects, and refreshed Mutatris menu/game-over presentation.
  • July 8, 2026: the project version moved through 0.18.0 to 0.19.0, and Doxyfile now reports 0.19.0 for generated API documentation.
  • July 8, 2026: mxvk_context.hpp now owns the shared mxvk::VulkanContext handle bundle, and VK_Window::context() exposes the current logical device, physical device, graphics queue, and command pool to helper renderers.
  • July 8, 2026: Vulkan allocation and upload paths were hardened so replacement resources are only committed after successful creation, partial post-processing target creation is cleaned up on failure, and several examples explicitly release pending uploads before command-pool teardown.
  • July 8, 2026: VK_Sprite now clears cached external texture descriptors before post-processing targets are destroyed, which avoids stale descriptor references after swapchain recreation.
  • July 8, 2026: VK_Window handles VK_SUBOPTIMAL_KHR presentation results more conservatively by recreating the swapchain only when the actual window pixel extent changed, reducing unnecessary rebuilds on platforms such as macOS/MoltenVK.
  • July 8, 2026: surface and stencil_surface now initialize and resize their SDL canvases from the active swapchain extent, fixing redraw and sizing behavior after resize on macOS.
  • July 8, 2026: bluesky now passes viewport aspect data into its shaders so clouds, sun, and water presentation keep a stable composition across wider or narrower windows.
  • July 8, 2026: run.pl supports timeout smoke testing for single examples as well as --all, and testapps.pl / timeout child launches suppress repeated missing-validation-layer warnings with MXVK_QUIET_MISSING_VALIDATION=1.
  • July 5, 2026: the project version moved to 0.16.0, and Doxyfile now reports the same version for generated API documentation.
  • July 5, 2026: walk_post was added as a first-person post-processing browser. It loads a shader index from --shader-path, supports --shader-index, cycles effects with R / T, updates extended sprite uniforms for shader-style effects, and keeps the walk debug console shader-reload commands.
  • July 5, 2026: pointsprite and fireworks examples were added to exercise mxvk::VK_PointSpriteBatch outside the starfield stress scene.
  • July 4, 2026: testapps.pl now supports timeout smoke testing. Pass --timeout or --timeout=<seconds> to run each example briefly, terminate it, continue through the list, and print a collected success/failure summary.
  • July 4, 2026: mutatris now compiles a shader effect pack from examples/mutatris/shaders/effects, chooses a new background/effect combination as levels advance, and exposes a console switch_shader command for manually selecting another random effect.
  • July 4, 2026: mutatris gained optional SDL3_mixer playback for music.ogg, line.wav, and open.wav when built with -DWITH_MIXER=ON.
  • July 4, 2026: mutatris clearing now uses fixed-duration block-clear animation frames and visual matching across the top/bottom board layout, including seam matches that span the divider.
  • July 3, 2026: the project version moved to 0.15.0, and Doxyfile now reports the same version for generated API documentation.
  • July 2, 2026: the project version moved to 0.13.0, and Doxyfile now reports the same version for generated API documentation.
  • July 2, 2026: mxvk_resource.hpp / mxvk_resource.cpp provide reusable Vulkan buffer, image, texture upload, image-view, memory-type, layout-transition, and one-shot command helpers. These utilities centralize common allocation/upload code for new renderer components.
  • July 2, 2026: mxvk::VK_PointSpriteBatch was added as a reusable point-list renderer for particle effects. It owns a persistently mapped vertex buffer, sampled point texture, per-swapchain MVP uniform buffers, descriptors, dynamic-rendering pipeline, pipeline-cache integration, resize handling, additive or alpha blending, and optional depth testing/writes.
  • July 2, 2026: the new starfield example demonstrates VK_PointSpriteBatch with 50,000 layered stars, per-star color/twinkle/size variation, additive blending, and a hold-Space warp-speed boost.
  • July 2, 2026: proc_args(...) now exposes Arguments::enable_screenshot and Arguments::executable_name. Passing --enable-screenshot enables F10 screenshot capture in VK_Window, saving PNG files to ~/Pictures with names like puzzle_drop.screenshot.2026.07.02.08.24.45.1280x720-0.png.
  • July 2, 2026: example runtime shader-copy targets now wait for example-specific runtime-data targets when both write the same data directory. This fixes a parallel CMake build race seen in masterpiece and 3dmath_masterpiece.
  • Sprite and 3D sprite paths now keep more GPU state alive across frames, track dirty state, and support instanced sprite batches. This reduces repeated descriptor/pipeline work in sprite-heavy demos such as binary_matrix, defender, starship, and pong.
  • Sprite texture uploads use a resizable persistent staging buffer instead of a fixed-size staging allocation, so larger textures can grow the upload path without requiring a hardcoded staging limit.
  • Sprite descriptor pools grow on demand and track which pool owns each descriptor set. Model descriptor sets are reused and updated in place where possible, with pool recreation/retry only when capacity is actually exhausted.
  • VK_Window owns a persistent Vulkan pipeline cache. Framework sprite, text, 3D sprite, and model pipelines load cache data on startup and save updated cache data on shutdown, reducing repeated driver pipeline compilation work on later runs.
  • VK_Window post-processing now supports a vector of effects and uses intermediate render targets for multi-pass chains instead of sampling only from the swapchain image.
  • Text rendering caches uploaded glyph/text textures and evicts old entries instead of recreating Vulkan images for repeated strings every frame. HUD-heavy examples use this path for steadier frame times.
  • compute_shader now presents the Vulkan compute output through a full-screen sampled draw, avoiding a readback or sprite upload for display. When CUDA interop is available, GPU capture frames can be copied directly into the Vulkan compute input image; otherwise the CPU fallback path remains available.
  • fractal_zoom uses cached adaptive reference-orbit data, throttled rebuilds while the view is changing, and a direct shader path while coordinates are still safe for f32. Deep zooms switch to perturbation data only when needed.
  • Matrix rain is factored into the reusable rain library so matrix, binary_matrix, model_example, planet, and defender can share glyph loading, tinting, resize handling, and texture sync code.

MXWrite

MXWrite is the FFmpeg-based video writer library included in this repository. It is useful when you want to export RGBA frames to a video file from a C++20 application without building a separate project.

Build

MXWrite is included from the root CMake build and follows the same auto-detect pattern as other optional components:

cmake -S . -B build -DWITH_MXWRITE=AUTO
cmake --build build -j

Use -DWITH_MXWRITE=ON to require FFmpeg, or -DWITH_MXWRITE=OFF to skip MXWrite entirely.

Usage

Consumer code includes MXWrite/mxwrite.hpp and links against mxwrite. The public API provides Writer for frame-based or timestamp-based output, plus EncodeOptions for preset, codec, CRF, realtime, and HDR settings.

#include "mxwrite.hpp"

Writer writer;
EncodeOptions opts;
opts.codec = "auto";
opts.crf = 18;

if (writer.open("output.mp4", 1280, 720, 30.0f, opts)) {
    writer.write(rgba_frame_ptr);
    writer.close();
}

When built through MXVK, the library exports MXWRITE_ENABLED=1 on the mxwrite target so consumers can gate MXWrite-specific code consistently.

MXNetwork

MXNetwork is the small C++20 socket library included in this repository. It provides a C-compatible low-level socket API plus a move-only C++ RAII wrapper for IPv4/IPv6 TCP and UDP, plus Unix-domain socket workflows.

Build

MXNetwork is included from the root CMake build as the static mxnetwork library. The root build disables MXNetwork's standalone examples and uses the library where needed, such as the optional multiplayer path in tetris.

cmake -S . -B build
cmake --build build -j

To build MXNetwork directly with its own examples, configure the MXNetwork subdirectory:

cmake -S MXNetwork -B build-mxnetwork
cmake --build build-mxnetwork -j

MXNetwork's standalone build includes TCP, UDP, Unix-domain socket, relay, and file-download examples. TCP and UDP examples use the same wrapper methods that are available to IPv4 and IPv6 socket types. Use -DMXNETWORK_EXAMPLES=OFF when building that subdirectory if you only want the library.

Usage

Consumer code includes MXNetwork/include/mxnetwork/socket.hpp and links against libmxnetwork::mxnetwork when using this repository directly. Installed consumers can use find_package(mxnetwork REQUIRED) and link against mxnetwork::mxnetwork.

The C++ API provides mxnetwork::Socket for move-only socket ownership, plus mxnetwork::MXNetworkInit for platform socket initialization and cleanup.

#include "mxnetwork/socket.hpp"

#include <iostream>
#include <string>

int main() {
    mxnetwork::MXNetworkInit network_init;
    mx_socket_ignore_pipe_signal();

    mxnetwork::Socket socket(mxnetwork::SocketType::TYPE_INET);
    if (!socket.connect("127.0.0.1", "8080")) {
        std::cerr << "connect failed\n";
        return 1;
    }

    const std::string message = "hello";
    socket.write_all(message.data(), message.size());
}

The wrapper supports IPv4 TCP sockets, IPv6 TCP sockets, IPv4 UDP datagrams, IPv6 UDP datagrams, Unix-domain stream sockets, and Unix-domain datagrams where the platform supports them. Common helpers include connect, listen, accept, bind, setblocking, read, write, read_all, write_all, sendto, recvfrom, valid, and close.

IPv6 uses dedicated socket types while keeping the same method names as IPv4:

  • mxnetwork::SocketType::TYPE_INET6 for IPv6 TCP sockets.
  • mxnetwork::SocketType::TYPE_INET6_DGRAM for IPv6 UDP sockets.

For example, an IPv6 TCP connection only changes the socket type and address:

mxnetwork::Socket socket(mxnetwork::SocketType::TYPE_INET6);
if (!socket.connect("::1", "8080")) {
    std::cerr << "IPv6 connect failed\n";
    return 1;
}

For IPv6 UDP, construct TYPE_INET6_DGRAM; bind(port), connect(host, port), sendto, and recvfrom dispatch through MXNetwork's IPv6 datagram helpers.

Project Layout

  • mxvk/
    • Engine source, headers, built-in shaders, and the mxvk/mxvk_math.h math helpers used by the 3D math tests.
  • examples/
    • Runnable examples and sample assets.
  • examples/viewer/
    • Command-line Vulkan model viewer backend for OBJ and MXMOD model inspection.
  • model_viewer/
    • Qt6 desktop launcher for the viewer renderer with file selection, recent files, and process output.
  • models/
    • Model assets used by model-based examples.
  • volk/
    • Vulkan function loader submodule/source.

Notes

  • The example CMake files copy required runtime assets into each example's output directory after build.

Early Screenshots

image image image image image image image image breakout720 image image
  • If you run an example from a custom working directory, prefer passing -p with the correct asset root.

    Model Viewer

    viewer

About

Vulkan Game Engine in C++

Topics

Resources

License

Stars

1 star

Watchers

0 watching

Forks

Packages

 
 
 

Contributors