Mood

March 24, 2023 ยท View on GitHub

Explore a remote outpost somewhere in space and uncover the mysterious secrets of the alien lifeforms you encounter. You play as Moodguy, a space cadet, hell-bent on discovery and science.

This repository demonstrates various techniques which may be used to create a multi-platform video game using the screen-13 rendering engine.

Command Line Interface

An example 3D FPS game using the Screen 13 rendering engine.

Usage: mood [OPTIONS]

Options:
      --benchmark                Run in benchmarking mode (instead of game mode)
      --debug-vulkan             Enable Vulkan debug layers
      --disable-framerate-limit  Disable the framerate limit (has no effect when v-sync is enabled)
      --disable-ray-tracing      Disable ray tracing graphics
      --mute                     Disable audio
      --window                   Run in windowed mode
  -h, --help                     Print help
  -V, --version                  Print version

Prerequisites

Git LFS

This repository uses Git LFS for audio samples, videos, graphics and other binary files. Download and install the Git command line extension. On Ubuntu and most debian distributions you may simply run:

sudo apt install git-lfs

Once downloaded and installed, set up Git LFS for your user account by running:

git lfs install

You only need to run this once per user account.

If you have installed Git LFS after cloning this repository, you may need to run the following command to update the binary file pointers with actual data.

git lfs pull

Development Libraries

On Ubuntu and most debian distributions you will need:

sudo apt install libasound2-dev

External Programs

Requires Blender 3.4 in order to package assets for runtime use.

Features

  • Audio: sound effects and music using kira
  • Assets: pre-processed and compressed bitmaps, models, animtations, etc., using pak
  • Graphics: layered and composable UI and model rendering using screen-13

Hot Shaders

cargo run --features hot-shaders

Build and run using shaders compiled at runtime and re-compiled whenever edits are saved. Make changes within the res/shader directory. Supports GLSL and HLSL.

Project Structure

The build process uses a build.rs file to package art and resources, and to compile shaders. There are two interesting artifacts generated by this process, in the root directory:

  • build.log: Helpful for debugging what happened during the build process
  • .timestamps: Keeps track of when asset files last changed in order to reduce the amount of work during subsequent builds - delete this if you want a full rebuild

Shader Versions

Shaders compiled from the res/shader directory may have multiple versions each with different macro definitions. To enable, add a file next to the shader with the same filename and a .toml extension. The contents of the file should look something like this example:

[[shader.version]]
name = 'fast'
macros = ['DO_FAST_THING=1']

[[shader.version]]
name = 'extra-quality'
macros = ['ITERATION_COUNT=42']

Blender Export

Models and scenes are exported using Blender's Python API. This produces the both .glb files which are packed into game format and also the .toml scenes which reference models, materials, points of interest, cameras, geometry, etc.

Asset Types

Assets are roughly split between game-specific art and engine-specific res directories, and each is packed into a compressed .pak file for runtime use. The build process also generates string constants for each item in each package file, which the code uses to load data at runtime. This helpfully allows for compiler warnings when assets are not actually used in the game.

See art/pak.toml and res/pak.toml for asset manifest details, and the pak crate for details on supported data formats and available options.

Code Structure

Once running, the main event loop uses an XNA-style state machine where the active user interface is updated and drawn, using the update and draw functions of the Ui trait. Each UI is allowed to handle keyboard and mouse input, do things, and either return self (continue) or another UI. This modularity allows for easy transitions such as fades/wipes between two different UI instances using the Transition struct.

Platform Notes

When testing on the macOS platform using cargo test all tests which use the graphics device run in a serial fashion in order to avoid an error caused by multiple logical devices running at the same time. At this time I'm not certain if this is a known issue with MoltenVK or just a quirk.

Credits

Ray tracer and ReSTIR implementation derived largely from kajiya and vulkan-rt.

Assets by Kenney and Quaternius.