Skip to content

Commit

Permalink
Add MaterialX Graph Editor (#1169)
Browse files Browse the repository at this point in the history
The MaterialX Graph Editor is an example application for visualizing, creating, and editing MaterialX graphs. It utilizes the ImGui framework as well as ImGui extensions such as the Node Editor and File Browser.
  • Loading branch information
lfl-eholthouser committed Jan 27, 2023
1 parent 132e24f commit a9fd85f
Show file tree
Hide file tree
Showing 85 changed files with 43,997 additions and 7 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/main.yml
Expand Up @@ -180,7 +180,7 @@ jobs:
run: |
mkdir build
cd build
cmake -DMATERIALX_BUILD_PYTHON=ON -DMATERIALX_BUILD_VIEWER=ON -DMATERIALX_TEST_RENDER=OFF -DMATERIALX_WARNINGS_AS_ERRORS=ON -DCMAKE_EXPORT_COMPILE_COMMANDS=ON ${{matrix.cmake_config}} ..
cmake -DMATERIALX_BUILD_PYTHON=ON -DMATERIALX_BUILD_VIEWER=ON -DMATERIALX_BUILD_GRAPH_EDITOR=ON -DMATERIALX_TEST_RENDER=OFF -DMATERIALX_WARNINGS_AS_ERRORS=ON -DCMAKE_EXPORT_COMPILE_COMMANDS=ON ${{matrix.cmake_config}} ..
- name: CMake Build
run: cmake --build . --target install --config Release --parallel 2
Expand Down
9 changes: 9 additions & 0 deletions .gitmodules
@@ -1,3 +1,12 @@
[submodule "source/MaterialXView/NanoGUI"]
path = source/MaterialXView/NanoGUI
url = https://github.com/mitsuba-renderer/nanogui
[submodule "source/MaterialXGraphEditor/External/ImGui"]
path = source/MaterialXGraphEditor/External/ImGui
url = https://github.com/ocornut/imgui
[submodule "source/MaterialXGraphEditor/External/ImGuiNodeEditor"]
path = source/MaterialXGraphEditor/External/ImGuiNodeEditor
url = https://github.com/thedmd/imgui-node-editor
[submodule "source/MaterialXGraphEditor/External/ImGuiFileBrowser"]
path = source/MaterialXGraphEditor/External/ImGuiFileBrowser
url = https://github.com/AirGuanZ/imgui-filebrowser
12 changes: 8 additions & 4 deletions CMakeLists.txt
Expand Up @@ -35,6 +35,7 @@ project(MaterialX)

option(MATERIALX_BUILD_PYTHON "Build the MaterialX Python package from C++ bindings. Requires Python 2.7 or greater." OFF)
option(MATERIALX_BUILD_VIEWER "Build the MaterialX Viewer." OFF)
option(MATERIALX_BUILD_GRAPH_EDITOR "Build the MaterialX Graph Editor." OFF)
option(MATERIALX_BUILD_DOCS "Create HTML documentation using Doxygen. Requires that Doxygen be installed." OFF)

option(MATERIALX_BUILD_GEN_GLSL "Build the GLSL shader generator back-end." ON)
Expand Down Expand Up @@ -249,6 +250,9 @@ if(MATERIALX_BUILD_RENDER)
if(MATERIALX_BUILD_VIEWER)
add_subdirectory(source/MaterialXView)
endif()
if(MATERIALX_BUILD_GRAPH_EDITOR)
add_subdirectory(source/MaterialXGraphEditor)
endif()
add_subdirectory(resources)
endif()

Expand All @@ -274,10 +278,10 @@ endif()
if(${CMAKE_VERSION} VERSION_GREATER "3.6.2")
if(MATERIALX_BUILD_VIEWER)
set_property(DIRECTORY PROPERTY VS_STARTUP_PROJECT MaterialXView)
else()
if(MATERIALX_BUILD_TESTS)
set_property(DIRECTORY PROPERTY VS_STARTUP_PROJECT MaterialXTest)
endif()
elseif(MATERIALX_BUILD_GRAPH_EDITOR)
set_property(DIRECTORY PROPERTY VS_STARTUP_PROJECT MaterialXGraphEditor)
elseif(MATERIALX_BUILD_TESTS)
set_property(DIRECTORY PROPERTY VS_STARTUP_PROJECT MaterialXTest)
endif()
endif()

Expand Down
78 changes: 78 additions & 0 deletions documents/DeveloperGuide/GraphEditor.md
@@ -0,0 +1,78 @@
# MaterialX Graph Editor

The MaterialX Graph Editor is an example application for visualizing, creating, and editing MaterialX graphs. It utilizes the ImGui framework as well as additional ImGui extensions such as the Node Editor and File Browser.

### Example Images

**Figure 1:** MaterialX Graph Editor with procedural marble example
<img src="/documents/Images/MaterialXGraphEditor_Marble.png" />

## Building The MaterialX Graph Editor
Select the `MATERIALX_BUILD_GRAPH_EDITOR` option in CMake to build the MaterialX Graph Editor. Installation will copy the **MaterialXGraphEditor** executable to a `/bin` directory within the selected install folder.

### Summary of Graph Editor Features

1. **Load Material**: Load a material document in the MTLX format.
2. **Save Material**: Save out a graph as a mterial document in MTLX format.
3. **New Material**: Clear all information to set up for the creation of a new material
4. **Node Property Editor**: View or edit properties of the selected node.
5. **Render View**: View the rendered material.

### Buttons

To display a new material and graph, click the `Load Material` button and and navigate to the [Example Materials](../../resources/Materials/Examples) folder, which contains a selection of materials in the MTLX format, and select a document to load. The Graph Editor will display the graph hierarchy of the selected document for visualization and editing.

To save out changes to the graphs as MTLX files click the `Save Material` button. This will save the position of the nodes in the graph for future use as well.

### Editor Window

The MaterialX document is displayed as nodes in the Editor window. When a file is intially loaded the material node, surface shader node, and any enclosing nodegraphs will be displayed. Double-clicking on a nodegraph, or any node defined as a subgraph, will display the contents of that graph.

The current graph hierarchy is displayed above the editor. To back up and out of a subgraph click the `<` button to the left of the graph names.

Each node and nodegraph displays its name and pins for all of its inputs and outputs. Nodes can be connected by clicking on the output pin of one node and connecting it to the input pin of another node, thus creating a link. Links can only be created if the input and output pins have the same type, as designated by the color of the pin. When a new link is created the material in the render view will automatically be updated.

Using the tab key on the editor allows the user to add a certain node by bringing up the `Add Node` pop-up. The nodes are organized in the pop-up window based on their node group but a specfic node can also be searched for by name. To create a nodegraph select `Node Graph` in the `Add Node` popup and dive into the node in order to add nodes inside of it and populate it.

In order to connect to the nodegraph to a shader add output nodes inside the nodegraph then travel back up outside the nodegraph and connect the corresponding output pin to the surface shader. By default, the nodegraph does not contain any output nodes or pins.

Another type of node present in the `Add Node` pop-up is the group, or background node. This background node can be used to group specific nodes and label by them by dragging them on to the background node.

To search the editor window for a specific node use `CTRL` + `F` to bring up the search bar.

### Node Property Editor
When a node is selected in the graph, its information is displayed on the left-hand column in the `Node Property Editor`. This editor displays the name of the node, its category, its inputs, the input name, types and values. Inputs that are connected to other nodes will not display a value.

This is where a node's properties such as its name and input values can be adjusted. When an input value is changed the material is automatically updated to reflect that change. The node info button displays the `doc` string for the selected node and its inputs if they exist. This `doc` string is currently read only.

The show All Inputs checkbox displays all possible inputs for a node. With the box unchecked only inputs that have a connection or have had a value set will be shown. Only these inputs will be saved out when the graph is saved.

### Render View
Above the `Node Property Editor`, the `Render View` displays the current material on the Arnold Shader Ball. If inside a subgraph it will display the material associated with that subgraph; otherwise it will display the output of the selected node. It automatically updates when any changes are made to the graph.

To adjust the relative sizes of the Node Property Editor and Render View windows, drag the separator between these windows in the application. The render view window camera can be changed using the left or right mouse buttons to manipulate the shader ball.

### Keyboard Shortcuts

- `TAB`: Add Node Popup
- `Right Click`: pan along the editor
- `Double Click on Node`: Dive into node's subgraph if it has one
- `U`: Go up and out of a subgraph
- `F`: Frame selected node(s)
- `Ctrl + F` to search for a node in the editor by name
- `Ctrl/Cmd + C` for Copying Nodes
- `Ctrl/Cmd+X` for Cutting Nodes
- `Ctrl/Cmd+V` for Pasting Nodes
- `+` : Zoom in with the camera when mouse is over the Render View Window.
- `-` : Zoom out with the camera when mouse is over the Render View Window.

### Command-Line Options

The following are common command-line options for MaterialXGraphEditor, and a complete list can be displayed with the `--help` option.
- `--path [FILEPATH]` : Specify an additional absolute search path location (e.g. '/projects/MaterialX'). This path will be queried when locating standard data libraries, XInclude references, and referenced images.
- `--library [FILEPATH]` : Specify an additional relative path to a custom data library folder (e.g. 'libraries/custom'). MaterialX files at the root of this folder will be included in all content documents.

### Known Limitations

- Creating new connections from multi-output nodes is not yet supported, though existing multi-output connections will be displayed in graphs.
- Creating new connections using the `channels` attribute of an input is not yet supported, though existing `channels` connections will be displayed in graphs.
Binary file added documents/Images/MaterialXGraphEditor_Marble.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
12 changes: 10 additions & 2 deletions source/MaterialXCore/Node.cpp
Expand Up @@ -411,9 +411,17 @@ vector<ElementPtr> GraphElement::topologicalSort() const
size_t connectionCount = 0;
for (size_t i = 0; i < child->getUpstreamEdgeCount(); ++i)
{
if (child->getUpstreamEdge(i))
Edge upstreamEdge = child->getUpstreamEdge(i);
if (upstreamEdge)
{
connectionCount++;
if (upstreamEdge.getUpstreamElement())
{
ElementPtr elem = upstreamEdge.getUpstreamElement()->getParent();
if (elem == child->getParent())
{
connectionCount++;
}
}
}
}

Expand Down
113 changes: 113 additions & 0 deletions source/MaterialXGraphEditor/CMakeLists.txt
@@ -0,0 +1,113 @@
set(CMAKE_CXX_STANDARD 17)

set(DEAR_IMGUI_PREFIX "${CMAKE_CURRENT_SOURCE_DIR}/External/ImGui" CACHE STRING "Path to Dear ImGui")

if (NOT IS_DIRECTORY "${DEAR_IMGUI_PREFIX}/backends")
message(FATAL_ERROR "Building the MaterialX graph editor requires the ImGui submodule "
"to be present. Update your repository by calling the following:\n"
"git submodule update --init --recursive")
endif()

if(MSVC)
add_compile_options(-wd4100)
elseif(CMAKE_CXX_COMPILER_ID MATCHES "Clang")
add_compile_options(-Wno-unused -Wno-deprecated -Wno-comment -Wno-unused-variable)
elseif(CMAKE_CXX_COMPILER_ID MATCHES "GNU")
add_compile_options(-Wno-format-truncation -Wno-use-after-free -Wno-comment -Wno-unused-but-set-variable)
endif()

file(GLOB materialx_source "${CMAKE_CURRENT_SOURCE_DIR}/*.cpp")
file(GLOB materialx_headers "${CMAKE_CURRENT_SOURCE_DIR}/*.h*")

file(GLOB imgui_source "${DEAR_IMGUI_PREFIX}/*.cpp")
file(GLOB imgui_headers "${DEAR_IMGUI_PREFIX}/*.h*")

set(imgui_source ${imgui_source}
"${DEAR_IMGUI_PREFIX}/backends/imgui_impl_glfw.cpp"
"${DEAR_IMGUI_PREFIX}/backends/imgui_impl_opengl3.cpp"
"${DEAR_IMGUI_PREFIX}/misc/cpp/imgui_stdlib.cpp")
set(imgui_headers ${imgui_headers}
"${DEAR_IMGUI_PREFIX}/backends/imgui_impl_glfw.h"
"${DEAR_IMGUI_PREFIX}/backends/imgui_impl_opengl3.h"
"${DEAR_IMGUI_PREFIX}/misc/cpp/imgui_stdlib.h")

file(GLOB imguinode_source "${CMAKE_CURRENT_SOURCE_DIR}/External/ImGuiNodeEditor/*.cpp")
file(GLOB imguinode_headers "${CMAKE_CURRENT_SOURCE_DIR}/External/ImGuiNodeEditor/*.h*")

set(imguinode_source ${imguinode_source}
"${CMAKE_CURRENT_SOURCE_DIR}/External/ImGuiNodeEditor/examples/blueprints-example/utilities/drawing.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/External/ImGuiNodeEditor/examples/blueprints-example/utilities/widgets.cpp")
set(imguinode_headers ${imguinode_headers}
"${CMAKE_CURRENT_SOURCE_DIR}/External/ImGuiNodeEditor/examples/blueprints-example/utilities/drawing.h"
"${CMAKE_CURRENT_SOURCE_DIR}/External/ImGuiNodeEditor/examples/blueprints-example/utilities/widgets.h")

assign_source_group("Source Files" ${materialx_source} ${imgui_source} ${imguinode_source})
assign_source_group("Header Files" ${materialx_headers} ${imgui_headers} ${imguinode_headers})

find_package(OpenGL REQUIRED)

if (UNIX AND NOT APPLE)
find_package(Threads REQUIRED)
find_package(X11 REQUIRED)
endif()

include_directories(${OPENGL_INCLUDE_DIRS})
include_directories("${DEAR_IMGUI_PREFIX}")
include_directories("${DEAR_IMGUI_PREFIX}/backends")
include_directories("${DEAR_IMGUI_PREFIX}/misc/cpp")
include_directories("${CMAKE_CURRENT_SOURCE_DIR}/External/ImGuiNodeEditor")
include_directories("${CMAKE_CURRENT_SOURCE_DIR}/External/ImGuiNodeEditor/examples/blueprints-example/utilities")
include_directories("${CMAKE_CURRENT_SOURCE_DIR}/External/ImGuiFileBrowser")

set(GLFW_BUILD_EXAMPLES OFF)
set(GLFW_BUILD_TESTS OFF)
set(GLFW_BUILD_DOCS OFF)
set(GLFW_INSTALL OFF)

add_subdirectory(External/Glfw)

if(MSVC)
SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /ENTRY:mainCRTStartup")
endif()

add_executable(MaterialXGraphEditor
${materialx_source}
${materialx_headers}
${imgui_source}
${imgui_headers}
${imguinode_source}
${imguinode_headers})

set(MATERIALX_LIBRARIES
MaterialXFormat
MaterialXGenGlsl
MaterialXRenderGlsl)

target_link_libraries(
MaterialXGraphEditor
PRIVATE
${MATERIALX_LIBRARIES}
${OPENGL_LIBRARIES}
glfw_minimal)

if (UNIX)
if (APPLE)
target_link_libraries(MaterialXGraphEditor
PRIVATE
"-framework Cocoa"
"-framework IOKit"
"-framework CoreVideo")
else()
target_link_libraries(MaterialXGraphEditor
PRIVATE
${CMAKE_THREAD_LIBS_INIT}
${X11_LIBRARIES}
${CMAKE_DL_LIBS})
endif()
endif()

install(TARGETS MaterialXGraphEditor
EXPORT MaterialX
RUNTIME DESTINATION bin)
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_BUILD_TYPE}/MaterialXGraphEditor.pdb"
DESTINATION "${CMAKE_INSTALL_PREFIX}/bin/" OPTIONAL)

0 comments on commit a9fd85f

Please sign in to comment.