Breath

Breath is a shader node editor written in C++, generating HLSL code.

The Graph

Node inputs and outputs are connected in an acyclic graph, and the nodes can then be sorted and transpiled into HLSL code. The sorting is performed by calculating the maximum distance from the main output node to every other node. That way, I ensure that nodes always get a higher score than other nodes that depend on their output. This setup does mean that branching and looping code paths between nodes are not possible, but there is of course nothing stopping such things within the code of a single node.

The Nodes

Nodes can have multiple inputs and outputs. Each output gets a unique name based on its name and ID. This unique name can then be referenced in any subsequent node in order to access the output.

The {fmt} library is used to easily format each node's code based on its node template, using its variadic formatting functionality. An example of how to set up a vector combination node can be seen to the left. The library not only supports this manual way of setting up nodes, but it can also parse the function signatures of actual HLSL functions and create nodes based on those functions. Currently, this way of declaring node types is limited to a single output, since only primitve types are allowed as the output type. It could be extended to allow structs as return types in the future though. Being able to "export" functions into Breath gives users a very useful and simple way of extending their own toolset on the spot.

The Editor

The editor is written using Dear ImGui, with the imgui-node-editor extension library.

To the right is some HLSL code generated by the tool. As you can see, while the variable names are not the best (and there are a lot of them), the code is still fairly easy to read, allowing more code-oriented developers to use the generated code for debugging as well. You can also see how the tool deals with non-existant links. If there is no link to an input node, a constant, accessible to the user, will be tied to it instead.


Breath also supports named variables that can be set from the CPU, although this is currently a bit limiting in usefulness (this is expected to change within a few days).