An openFrameworks addon for hot-reloading shader files on the fly. Utilizes Facebook’s Watchman service to monitor filesystem changes. Tested on macOS, but as long as you can build the dependencies, it should work on your platform.
- Using this addon will require you to build OpenFrameworks against a newer version of Boost. That shouldn’t screw up any existing projects (because it looks like the newer Boost headers are almost completely backwards compatible), but you’ve been warned. To make this change, open
OpenFrameworks -> libs -> openFrameworksCompiled -> project -> osx -> CoreOF.xcconfig
, and editHEADER_BOOST
to point to"/usr/local/include"
(as opposed to"$(OF_PATH)/libs/boost/include"
). - On macOS, it seems the Watchman dependency will only build for targets of macOS 10.13 and up. Any project wishing to use this addon will need to (in Xcode) navigate to
Project -> General -> Deployment Info
and changeDeployment Target
to at least10.13
.
Note: This currently assumes you’re using Xcode. If you got this built & running on another platform, and want to document it, reach out and I’ll update this guide.
- Install Watchman and its dependencies (namely, you’ll need Folly and its dependencies). On macOS with Homebrew, this should be something along the lines of
brew install folly watchman
- Simply include this as an addon when using the Project Generator, or, if adding manually, be sure to include each source file in
Project -> [select target] -> Build Phases -> Compile Sources
- Add
libfolly.dylib,
libevent.dylib
,libglog.dylib,
andlibssl.dylib
toProject -> [select target] -> General -> Linked Frameworks and Libraries
. NOTE: After clicking “+
” to add a framework, I had to manually select “Add Other
”, and navigate to/usr/local/opt
(usingcmd+shift+G
should help out) to get to these libraries. - Add
/usr/local/include
toProject -> [select target] -> Build Settings -> Header Search Paths
NOTE: This next step may not be necessary based on your project/dependency settings/how far into the future you’re doing this, but as of right now, Xcode defaults to c++11 so you absolutely must change it to build against c++14 at minimum (the -std=c++1z
flag below will build against c++17, for example).
- Add a few C++ compiler flags to your target under
Project -> [select target] -> Build Settings -> Other C++ Flags
:-I/usr/local/opt/openssl/include -std=c++1z
-
First, in
ofApp.h
, we need to add#include "ShaderFileWatcher.h"
to the list of includes, and create a public ShaderFileWatcher pointer member in theofApp
classclass ofApp : public ofBaseApp { public: ... ... ShaderFileWatcher* fileWatcher; // And obviously you'll be updating a shader: ofShader shader; }
-
Next, we must instantiate the
folly
library in our main. Theinit
function requiresargc
andargv
, so we’ll need to expose these parameters inmain.cpp
by changingint main() {…}
to
int main(int argc, char** argv) {…}
and immediately passing these to
folly::init()
. I'm going to only pass the first argument because of this.int main(int argc, char** argv) { argc = 1; folly::init(&argc, &argv); ... }
-
Awesome! With all of that out of the way, now we can instantiate a
fileWatcher
which will tell thewatchman
server to watch a directory of our choosing, and will automatically listen for changes to certain (or any) shader files within that directory. So navigate toofApp.cpp
, and insetup()
, initialize the ShaderFileWatcher pointervoid ofApp::setup() { fileWatcher = new ShaderFileWatcher( // 1. Folder containing shader files (default = project/bin/data) "/absolute/path/to/folder/of/shaders", // 2. Name of vertex shader to monitor for changes (default = "*.vert") "shader.vert", // 3. Name of fragment shader to monitor for changes (default = "*.frag") "shader.frag", // 4. Path to your Watchman executable (default = "/usr/local/bin") "/usr/local/bin" ); ... ... }
-
Lastly, all we have to do is call
checkForUpdate()
, which will returntrue
if we need to reload our shadersvoid ofApp::update() { if (fileWatcher->checkForUpdate()) { shader.load("shader.vert", "shader.frag"); } ... ... }
-
That’s it! You can now compile openFrameworks once, and write your shaders on the fly (even in a different editor!). Check the example project to see it all put together. Happy shading!