Vulkan SDF Renderer + Video Recorder + Hot Reloader
VSDF is licensed under GPL-3.0
Quickstart: See QUICKSTART.md for installation and your first shader in minutes.
Shell Integration: (Experimental) See SHELL_INTEGRATION.md for instant shader development with one command.
Render an SDF like ShaderToy using Vulkan and hot reload based on frag shader changes. That way you can use your favourite editor / LSP and also utilise git.
Supports macOS, Linux, and Windows with native file watcher implementations for each platform.
| OS | Support |
|---|---|
| Windows | âś… Supported |
| Linux | âś… Supported |
| macOS | âś… Supported |
Easiest way to install vsdf:
This will install MoltenVK
brew install jamylak/vsdf/vsdfFor building from source or manual dependency management: Install Vulkan + deps with Homebrew:
brew install molten-vk vulkan-loader glslang glfw glm spdlog vulkan-tools googletest ffmpeg
# Note: FFmpeg is optional; set `-DDISABLE_FFMPEG=ON` (see `CMakeLists.txt`)https://vulkan.lunarg.com/sdk/home
Then follow the steps to do sudo ./install_vulkan.py in SDK System Paths section
VULKAN_SDK $HOME/VulkanSDK/1.4.328.1/macOS
Pre-built binaries for Linux are available in the GitHub Releases page.
Download the latest vsdf-linux binary, make it executable, and move it to a directory in your PATH.
The only dependency is Vulkan.
LATEST_RELEASE_TAG=$(curl -sL https://api.github.com/repos/jamylak/vsdf/releases/latest | grep '"tag_name":' | sed -E 's/.*"([^"]+)".*/\1/')
LINUX_ARCH=$( [ "$(uname -m)" = "aarch64" ] || [ "$(uname -m)" = "arm64" ] && echo arm64 || echo x86_64 )
LINUX_DIR="linux-${LINUX_ARCH}"
DOWNLOAD_URL="https://github.com/jamylak/vsdf/releases/download/${LATEST_RELEASE_TAG}/vsdf-linux-${LINUX_ARCH}.tar.gz"
echo "Downloading from: ${DOWNLOAD_URL}"
curl -LO "${DOWNLOAD_URL}"
tar -xzf vsdf-linux-${LINUX_ARCH}.tar.gz
chmod +x ${LINUX_DIR}/vsdf
sudo mv ${LINUX_DIR}/vsdf /usr/local/bin/vsdf
rm -rf vsdf-linux-${LINUX_ARCH}.tar.gz ${LINUX_DIR} # Clean up downloaded filesPre-built Windows binaries (built without ffmpeg) are available on the GitHub Releases page.
Download the latest release zip and run vsdf.exe from the extracted folder.
$tag = (Invoke-RestMethod https://api.github.com/repos/jamylak/vsdf/releases/latest).tag_name
$zip = "vsdf-windows-x86_64-disable_ffmpeg.zip"
$url = "https://github.com/jamylak/vsdf/releases/download/$tag/$zip"
Invoke-WebRequest -Uri $url -OutFile $zip
Expand-Archive $zip -DestinationPath vsdf
.\vsdf\vsdf.exe --versionInstall dependencies:
sudo apt-get update
sudo apt-get install -y \
build-essential cmake ninja-build \
libgtest-dev libspdlog-dev \
libglfw3 libglfw3-dev libvulkan-dev \
glslang-tools glslang-dev libglm-dev \
# (Optional) set -DDISABLE_FFMPEG=ON to skip \
libavcodec-dev libavformat-dev libavutil-dev libswscale-dev \- Install vcpkg (if not already installed):
git clone https://github.com/Microsoft/vcpkg.git cd vcpkg .\bootstrap-vcpkg.bat
- Install dependencies using vcpkg (includes Vulkan):
vcpkg install vulkan:x64-windows glfw3:x64-windows glslang:x64-windows spdlog:x64-windows glm:x64-windows gtest:x64-windows # Note: ffmpeg is optional; set `-DDISABLE_FFMPEG=ON` (see `CMakeLists.txt`) to build without it vcpkg install ffmpeg[avcodec,avformat,swscale]:x64-windows vcpkg integrate install
# ffmpeg is optional; set `-DDISABLE_FFMPEG=ON` (see `CMakeLists.txt`) to build without it.
git submodule update --init --recursive
cmake -B build .
cmake --build build
./build/vsdf {filepath}.frag# ffmpeg is optional; set `-DDISABLE_FFMPEG=ON` (see `CMakeLists.txt`) to build without it.
git submodule update --init --recursive
cmake -B build -DCMAKE_TOOLCHAIN_FILE="C:/vcpkg/scripts/buildsystems/vcpkg.cmake" .
cmake --build build --config Release
.\build\Release\vsdf.exe {filepath}.fragTo make vsdf available as a command in your shell, you can install it to a standard system directory like /usr/local.
Linux/macOS
# Pick somewhere in your PATH and install it there
cmake --install build --prefix /usr/local
vsdf {filepath}.fragOn Windows, you can also install to a custom location and add that location to your PATH environment variable to make it accessible from any command prompt.
vsdf --new-toy example.frag
vsdf --toy example.fragvsdf --toy example.frag --frames 100 --ffmpeg-output out.mp4vsdf --toy example.fragNote: That if you use --toy we will prepend a template
which links up the push constants
like iTime and we will also follow this logic.
if (useToyTemplate) {
Client = glslang::EShClientOpenGL;
ClientVersion = glslang::EShTargetOpenGL_450;
} else {
Client = glslang::EShClientVulkan;
ClientVersion = glslang::EShTargetVulkan_1_0;
}--helpShow this help message--versionShow version information--new-toy [name]Create a new shader file with starter template. Prints the filename and exits. Generates random name like my_new_toy_12345.frag if not provided.--template <name>Template to use with--new-toy(default, plot)--toyUse ShaderToy-style template wrapper--no-focusDon't steal window focus on startup and float--headlessHide the GLFW window (pair withxvfb-runin CI)--frames <N>Render N frames then exit--log-level <trace|debug|info|warn|error|critical|off>Setspdlogverbosity (default: info)--debug-dump-ppm <dir>Copy the swapchain image before present (adds a stall); mainly for smoke tests or debugging--ffmpeg-output <file>Enable offline encoding; output file path (requires--frames)--ffmpeg-fps <N>Output FPS (default: 30)--ffmpeg-crf <N>Quality for libx264 (default: 20; lower is higher quality)--ffmpeg-preset <name>libx264 preset (default: slow)--ffmpeg-codec <name>FFmpeg codec (default: libx264)--ffmpeg-width <N>Output width (default: 1280)--ffmpeg-height <N>Output height (default: 720)--ffmpeg-ring-buffer-size <N>Ring buffer size for offline render (default: 2)
git submodule update --init --recursive
cmake -B build -DBUILD_TESTS=ON -DDEBUG=ON
cmake --build build
./build/tests/vsdf_tests
./build/tests/filewatcher/filewatcher_testsgit submodule update --init --recursive
cmake -B build -DBUILD_TESTS=ON -DCMAKE_BUILD_TYPE=Debug -DCMAKE_TOOLCHAIN_FILE="C:/path/to/vcpkg/scripts/buildsystems/vcpkg.cmake" .
cmake --build build --config Debug
.\build\tests\vsdf_tests\Debug\vsdf_tests.exe
.\build\tests\filewatcher\Debug\filewatcher_tests.exenix developRun without installing (builds and runs):
nix run github:jamylak/vsdf -- --new-toy example.frag
nix run github:jamylak/vsdf -- --toy example.fragInstall into your profile (then vsdf is on PATH):
nix profile install github:jamylak/vsdfOpen a one-off shell with vsdf available:
nix shell github:jamylak/vsdf# flake.nix
{
inputs.vsdf.url = "github:jamylak/vsdf";
}# home.nix
{ inputs, pkgs, ... }:
{
home.packages = [
inputs.vsdf.packages.${pkgs.system}.default
];
}If you don't want any template prepended or you want
to use a Vulkan shader directly you can copy shaders/vulktemplate.frag
and adjust it to your liking
- See
shaders/vulktemplate.fragto see how push constants are passed in
# Then call it without the --toy flag
vsdf path/to/shader.fragThe binary uses volk to dynamically find Vulkan at runtime, so it works regardless of installation location.
- https://shadertoy.com
- https://iquilezles.org/
- https://www.youtube.com/playlist?list=PL0JVLUVCkk-l7CWCn3-cdftR0oajugYvd (zeux)
- https://github.com/SaschaWillems/Vulkan
(I should try follow this but haven't gotten through it all yet) https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines
