diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml
index d5ac9d3f79..1af8012ef0 100644
--- a/.github/workflows/main.yml
+++ b/.github/workflows/main.yml
@@ -25,19 +25,28 @@ jobs:
python: 3.7
cmake_config: -DMATERIALX_BUILD_SHARED_LIBS=ON
- - name: Linux_GCC_11_Python39
- os: ubuntu-20.04
- compiler: gcc
- compiler_version: "11"
- python: 3.9
- build_javascript: ON
-
- name: Linux_GCC_12_Python311
os: ubuntu-22.04
compiler: gcc
compiler_version: "12"
python: 3.11
- upload_shaders: ON
+ build_javascript: ON
+
+ - name: Linux_GCC_13_Python312
+ os: ubuntu-22.04
+ compiler: gcc
+ compiler_version: "13"
+ python: 3.12
+ static_analysis: ON
+ cmake_config: -DCMAKE_EXPORT_COMPILE_COMMANDS=ON
+
+ - name: Linux_GCC_CoverageAnalysis
+ os: ubuntu-22.04
+ compiler: gcc
+ compiler_version: "None"
+ python: None
+ coverage_analysis: ON
+ cmake_config: -DMATERIALX_COVERAGE_ANALYSIS=ON -DMATERIALX_BUILD_RENDER=OFF -DMATERIALX_BUILD_PYTHON=OFF
- name: Linux_Clang_10_Python37
os: ubuntu-20.04
@@ -45,20 +54,19 @@ jobs:
compiler_version: "10"
python: 3.7
cmake_config: -DMATERIALX_BUILD_SHARED_LIBS=ON
- static_analysis: ON
- - name: Linux_Clang_14_Python311
+ - name: Linux_Clang_15_Python312
os: ubuntu-22.04
compiler: clang
- compiler_version: "14"
- python: 3.11
+ compiler_version: "15"
+ python: 3.12
test_render: ON
clang_format: ON
- - name: Linux_Clang_14_DynamicAnalysis
+ - name: Linux_Clang_DynamicAnalysis
os: ubuntu-22.04
compiler: clang
- compiler_version: "14"
+ compiler_version: "15"
python: None
cmake_config: -DMATERIALX_DYNAMIC_ANALYSIS=ON
dynamic_analysis: ON
@@ -70,17 +78,17 @@ jobs:
cmake_config: -DMATERIALX_BUILD_SHARED_LIBS=ON
python: 3.7
- - name: MacOS_Xcode_13_Python39
- os: macos-12
- compiler: xcode
- compiler_version: "13.4"
- python: 3.9
-
- name: MacOS_Xcode_14_Python311
os: macos-13
compiler: xcode
compiler_version: "14.3"
python: 3.11
+
+ - name: MacOS_Xcode_15_Python312
+ os: macos-13
+ compiler: xcode
+ compiler_version: "15.0"
+ python: 3.12
test_shaders: ON
- name: iOS_Xcode_15
@@ -96,18 +104,19 @@ jobs:
python: 3.7
cmake_config: -G "Visual Studio 16 2019" -A "Win32" -DMATERIALX_BUILD_SHARED_LIBS=ON
- - name: Windows_VS2022_x64_Python39
+ - name: Windows_VS2022_x64_Python311
os: windows-2022
architecture: x64
- python: 3.9
+ python: 3.11
cmake_config: -G "Visual Studio 17 2022" -A "x64"
+ test_shaders: ON
- - name: Windows_VS2022_x64_Python311
+ - name: Windows_VS2022_x64_Python312
os: windows-2022
architecture: x64
- python: 3.11
+ python: 3.12
cmake_config: -G "Visual Studio 17 2022" -A "x64"
- test_shaders: ON
+ upload_shaders: ON
steps:
- name: Sync Repository
@@ -120,28 +129,32 @@ jobs:
run: |
sudo apt-get update
sudo apt-get install xorg-dev mesa-utils
- if [ "${{ matrix.compiler }}" = "gcc" ]; then
- sudo apt-get install -y g++-${{ matrix.compiler_version }} g++-${{ matrix.compiler_version }}-multilib
- echo "CC=gcc-${{ matrix.compiler_version }}" >> $GITHUB_ENV
- echo "CXX=g++-${{ matrix.compiler_version }}" >> $GITHUB_ENV
- else
- sudo apt-get install -y clang-${{ matrix.compiler_version }} libc++-${{ matrix.compiler_version }}-dev libc++abi-${{ matrix.compiler_version }}-dev
- echo "CC=clang-${{ matrix.compiler_version }}" >> $GITHUB_ENV
- echo "CXX=clang++-${{ matrix.compiler_version }}" >> $GITHUB_ENV
+ if [ "${{ matrix.compiler_version }}" != 'None' ]; then
+ if [ "${{ matrix.compiler }}" = "gcc" ]; then
+ sudo apt-get install -y g++-${{ matrix.compiler_version }} g++-${{ matrix.compiler_version }}-multilib
+ echo "CC=gcc-${{ matrix.compiler_version }}" >> $GITHUB_ENV
+ echo "CXX=g++-${{ matrix.compiler_version }}" >> $GITHUB_ENV
+ else
+ sudo apt-get install -y clang-${{ matrix.compiler_version }} libc++-${{ matrix.compiler_version }}-dev libc++abi-${{ matrix.compiler_version }}-dev
+ echo "CC=clang-${{ matrix.compiler_version }}" >> $GITHUB_ENV
+ echo "CXX=clang++-${{ matrix.compiler_version }}" >> $GITHUB_ENV
+ fi
fi
- name: Install Dependencies (MacOS)
if: runner.os == 'macOS'
run: |
- if [ "${{ matrix.compiler }}" = "gcc" ]; then
- brew install gcc@${{ matrix.compiler_version }}
- echo "CC=gcc-${{ matrix.compiler_version }}" >> $GITHUB_ENV
- echo "CXX=g++-${{ matrix.compiler_version }}" >> $GITHUB_ENV
- else
- ls -ls /Applications/
- sudo xcode-select -switch /Applications/Xcode_${{ matrix.compiler_version }}.app
- echo "CC=clang" >> $GITHUB_ENV
- echo "CXX=clang++" >> $GITHUB_ENV
+ if [ "${{ matrix.compiler_version }}" != 'None' ]; then
+ if [ "${{ matrix.compiler }}" = "gcc" ]; then
+ brew install gcc@${{ matrix.compiler_version }}
+ echo "CC=gcc-${{ matrix.compiler_version }}" >> $GITHUB_ENV
+ echo "CXX=g++-${{ matrix.compiler_version }}" >> $GITHUB_ENV
+ else
+ ls -ls /Applications/
+ sudo xcode-select -switch /Applications/Xcode_${{ matrix.compiler_version }}.app
+ echo "CC=clang" >> $GITHUB_ENV
+ echo "CXX=clang++" >> $GITHUB_ENV
+ fi
fi
- name: Install Dependencies (Windows)
@@ -160,6 +173,10 @@ jobs:
python-version: ${{ matrix.python }}
architecture: ${{ matrix.architecture }}
+ - name: Install Python Dependencies
+ if: matrix.python != 'None'
+ run: pip install setuptools
+
- name: Install Emscripten
if: matrix.build_javascript == 'ON'
run: |
@@ -178,17 +195,13 @@ jobs:
- name: Run Clang Format
if: matrix.clang_format == 'ON'
- run: find source \( -name *.h -o -name *.cpp -o -name *.mm \) ! -path "*/External/*" ! -path "*/NanoGUI/*" | xargs clang-format -i --verbose
+ run: find source \( -name *.h -o -name *.cpp -o -name *.mm -o -name *.inl \) ! -path "*/External/*" ! -path "*/NanoGUI/*" | xargs clang-format -i --verbose
- name: CMake Generate
- run: |
- mkdir build
- cd build
- 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}} ..
+ run: cmake -S . -B build -DMATERIALX_BUILD_PYTHON=ON -DMATERIALX_BUILD_VIEWER=ON -DMATERIALX_BUILD_GRAPH_EDITOR=ON -DMATERIALX_TEST_RENDER=OFF -DMATERIALX_WARNINGS_AS_ERRORS=ON ${{matrix.cmake_config}}
- name: CMake Build
- run: cmake --build . --target install --config Release --parallel 2
- working-directory: build
+ run: cmake --build build --target install --config Release --parallel 2
- name: CMake Unit Tests
run: ctest -VV --output-on-failure --build-config Release
@@ -222,6 +235,14 @@ jobs:
run: |
python python/Scripts/generateshader.py resources/Materials/Examples/StandardSurface --target msl --validator "xcrun metal --language=metal" --validatorArgs="-w"
+ - name: Coverage Analysis Tests
+ if: matrix.coverage_analysis == 'ON'
+ run: |
+ sudo apt-get install gcovr
+ mkdir coverage
+ gcovr --html --html-details --output coverage/index.html --exclude .*\/External\/.* --root .. .
+ working-directory: build
+
- name: Static Analysis Tests
if: matrix.static_analysis == 'ON' && runner.os == 'Linux'
run: |
@@ -279,17 +300,20 @@ jobs:
name: Renders_${{ matrix.name }}
path: build/render/*.png
+ - name: Upload Coverage Report
+ uses: actions/upload-artifact@v3
+ if: matrix.coverage_analysis == 'ON'
+ with:
+ name: MaterialX_Coverage
+ path: build/coverage
+
- name: JavaScript CMake Generate
if: matrix.build_javascript == 'ON'
- run: |
- mkdir javascript/build
- cd javascript/build
- cmake -DMATERIALX_BUILD_JS=ON -DMATERIALX_EMSDK_PATH=${{ env.EMSDK }} -DMATERIALX_BUILD_RENDER=OFF -DMATERIALX_BUILD_TESTS=OFF -DMATERIALX_BUILD_GEN_OSL=OFF -DMATERIALX_BUILD_GEN_MDL=OFF ../..
+ run: cmake -S . -B javascript/build -DMATERIALX_BUILD_JS=ON -DMATERIALX_EMSDK_PATH=${{ env.EMSDK }}
- name: JavaScript CMake Build
if: matrix.build_javascript == 'ON'
- run: cmake --build . --target install --config Release --parallel 2
- working-directory: javascript/build
+ run: cmake --build javascript/build --target install --config Release --parallel 2
- name: JavaScript Unit Tests
if: matrix.build_javascript == 'ON'
diff --git a/CMakeLists.txt b/CMakeLists.txt
index c255924fa4..c29565a7ed 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -5,7 +5,7 @@ set(MATERIALX_BUILD_VERSION 9)
set(MATERIALX_LIBRARY_VERSION ${MATERIALX_MAJOR_VERSION}.${MATERIALX_MINOR_VERSION}.${MATERIALX_BUILD_VERSION})
# Cmake setup
-cmake_minimum_required(VERSION 3.5)
+cmake_minimum_required(VERSION 3.16)
set(CMAKE_CXX_STANDARD 14)
set(CMAKE_POSITION_INDEPENDENT_CODE TRUE)
set(CMAKE_MACOSX_RPATH ON)
@@ -45,6 +45,7 @@ option(MATERIALX_BUILD_GEN_MSL "Build the MSL shader generator back-end." ON)
option(MATERIALX_BUILD_RENDER "Build the MaterialX Render modules." ON)
option(MATERIALX_BUILD_OIIO "Build OpenImageIO support for MaterialXRender." OFF)
option(MATERIALX_BUILD_TESTS "Build unit tests." ON)
+option(MATERIALX_BUILD_BENCHMARK_TESTS "Build benchmark tests." OFF)
option(MATERIALX_BUILD_SHARED_LIBS "Build MaterialX libraries as shared rather than static." OFF)
option(MATERIALX_PYTHON_LTO "Enable link-time optimizations for MaterialX Python." ON)
@@ -52,6 +53,7 @@ option(MATERIALX_INSTALL_PYTHON "Install the MaterialX Python package as a third
option(MATERIALX_INSTALL_RESOURCES "Install the resources folder when building render modules." ON)
option(MATERIALX_TEST_RENDER "Run rendering tests for MaterialX Render module. GPU required for graphics validation." ON)
option(MATERIALX_WARNINGS_AS_ERRORS "Interpret all compiler warnings as errors." OFF)
+option(MATERIALX_COVERAGE_ANALYSIS "Build MaterialX libraries with coverage analysis on supporting platforms." OFF)
option(MATERIALX_DYNAMIC_ANALYSIS "Build MaterialX libraries with dynamic analysis on supporting platforms." OFF)
option(MATERIALX_OSL_LEGACY_CLOSURES "Build OSL shader generation supporting the legacy OSL closures." ON)
@@ -59,13 +61,21 @@ option(MATERIALX_BUILD_IOS "Build MaterialX for iOS." OFF)
if (MATERIALX_BUILD_IOS)
set(CMAKE_SYSTEM_NAME iOS)
add_definitions(-DTARGET_OS_IOS=1)
- set(MATERIALX_BUILD_PYTHON OFF)
- set(MATERIALX_BUILD_VIEWER OFF)
- set(MATERIALX_BUILD_GRAPH_EDITOR OFF)
- set(MATERIALX_BUILD_GEN_GLSL OFF)
- set(MATERIALX_BUILD_GEN_OSL OFF)
- set(MATERIALX_BUILD_GEN_MDL OFF)
- set(MATERIALX_BUILD_TESTS OFF)
+ set(MATERIALX_BUILD_PYTHON OFF)
+ set(MATERIALX_BUILD_VIEWER OFF)
+ set(MATERIALX_BUILD_GRAPH_EDITOR OFF)
+ set(MATERIALX_BUILD_GEN_GLSL OFF)
+ set(MATERIALX_BUILD_GEN_OSL OFF)
+ set(MATERIALX_BUILD_GEN_MDL OFF)
+ set(MATERIALX_BUILD_TESTS OFF)
+endif()
+
+if (MATERIALX_BUILD_JS)
+ set(MATERIALX_BUILD_GEN_OSL OFF)
+ set(MATERIALX_BUILD_GEN_MSL OFF)
+ set(MATERIALX_BUILD_GEN_MDL OFF)
+ set(MATERIALX_BUILD_RENDER OFF)
+ set(MATERIALX_BUILD_TESTS OFF)
endif()
set(MATERIALX_PYTHON_VERSION "" CACHE STRING
@@ -79,10 +89,6 @@ set(MATERIALX_PYTHON_PYBIND11_DIR "" CACHE PATH
set(MATERIALX_OIIO_DIR "" CACHE PATH "Path to the root folder of the OpenImageIO installation.")
-if (MATERIALX_BUILD_JS)
- set(MATERIALX_BUILD_GEN_GLSL ON)
-endif()
-
# Settings to define installation layout
set(MATERIALX_INSTALL_INCLUDE_PATH "include" CACHE STRING "Install header include path (e.g. 'inc', 'include').")
set(MATERIALX_INSTALL_LIB_PATH "lib" CACHE STRING "Install lib path (e.g. 'libs', 'lib').")
@@ -130,6 +136,7 @@ mark_as_advanced(MATERIALX_BUILD_GEN_MSL)
mark_as_advanced(MATERIALX_BUILD_RENDER)
mark_as_advanced(MATERIALX_BUILD_OIIO)
mark_as_advanced(MATERIALX_BUILD_TESTS)
+mark_as_advanced(MATERIALX_BUILD_BENCHMARK_TESTS)
mark_as_advanced(MATERIALX_BUILD_SHARED_LIBS)
mark_as_advanced(MATERIALX_NAMESPACE_SUFFIX)
mark_as_advanced(MATERIALX_LIBNAME_SUFFIX)
@@ -138,6 +145,7 @@ mark_as_advanced(MATERIALX_INSTALL_PYTHON)
mark_as_advanced(MATERIALX_INSTALL_RESOURCES)
mark_as_advanced(MATERIALX_TEST_RENDER)
mark_as_advanced(MATERIALX_WARNINGS_AS_ERRORS)
+mark_as_advanced(MATERIALX_COVERAGE_ANALYSIS)
mark_as_advanced(MATERIALX_DYNAMIC_ANALYSIS)
mark_as_advanced(MATERIALX_PYTHON_VERSION)
mark_as_advanced(MATERIALX_PYTHON_EXECUTABLE)
@@ -175,6 +183,9 @@ endif()
if(MATERIALX_TEST_RENDER)
add_definitions(-DMATERIALX_TEST_RENDER)
endif()
+if (MATERIALX_BUILD_BENCHMARK_TESTS)
+ add_definitions(-DMATERIALX_BUILD_BENCHMARK_TESTS)
+endif()
if (MATERIALX_BUILD_GEN_MDL)
add_definitions(-DMATERIALX_MDLC_EXECUTABLE=\"${MATERIALX_MDLC_EXECUTABLE}\")
@@ -228,6 +239,10 @@ else()
if(MATERIALX_WARNINGS_AS_ERRORS)
add_compile_options(-Werror)
endif()
+ if(MATERIALX_COVERAGE_ANALYSIS)
+ add_compile_options(--coverage -O0)
+ add_link_options(--coverage)
+ endif()
if(MATERIALX_DYNAMIC_ANALYSIS)
set(DYNAMIC_ANALYSIS_OPTIONS -fsanitize=address -fsanitize=leak -fsanitize=undefined -fno-sanitize-recover=all)
add_compile_options(${DYNAMIC_ANALYSIS_OPTIONS})
@@ -328,14 +343,12 @@ if(MATERIALX_BUILD_JS)
add_subdirectory(source/JsMaterialX)
endif()
-if(${CMAKE_VERSION} VERSION_GREATER "3.6.2")
- if(MATERIALX_BUILD_VIEWER)
- set_property(DIRECTORY PROPERTY VS_STARTUP_PROJECT MaterialXView)
- 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()
+if(MATERIALX_BUILD_VIEWER)
+ set_property(DIRECTORY PROPERTY VS_STARTUP_PROJECT MaterialXView)
+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()
# Install root-level documents
diff --git a/documents/Specification/MaterialX.GeomExts.md b/documents/Specification/MaterialX.GeomExts.md
index fb0d581ed8..5ff300de01 100644
--- a/documents/Specification/MaterialX.GeomExts.md
+++ b/documents/Specification/MaterialX.GeomExts.md
@@ -113,7 +113,7 @@ Collections are recipes for building a list of geometries (which can be any path
A **<collection>** element contains lists of geometry expressions and/or collections to be included, and an optional list of geometry expressions to be excluded:
-```
+```xml
@@ -132,7 +132,7 @@ As a shorthand convenience, MaterialX allows the specification of a `geomprefix`
So the following MTLX file snippets are equivalent:
-```
+```xml
@@ -176,7 +176,7 @@ The most common use for geominfo elements is to define the filenames (or portion
A **<geominfo>** element contains one or more geometry property and/or token definitions, and associates them and their values with all geometries listed in the `geom` or `collection` attribute of the <geominfo>:
-```
+```xml
...geometry property and token value definitions...
@@ -200,7 +200,7 @@ The core MaterialX Specification defines a Geometric Property, or "geomprop", as
MaterialX Geometry Extensions expands upons this by allowing the use of <geomprop> elements to define specific uniform values of a geometric property with specific geometries, as opposed to relying on those values being defined externally. This could include application-specific metadata, attributes passed from a lighting package to a renderer, or other geometry-specific data. A geomprop may also specify a `unittype` and `unit` if appropriate to indicate that the geometric property's value is in that unit; see the [**Units** section of the main MaterialX Specification](./MaterialX.Specification.md#units), although typically the <geompropdef> would define the `unittype` and `unit`, and a geomprop would only provide an overriding `unit` if the unit for its value differed from the geompropdef's defined default unit.
-```
+```xml
```
@@ -216,7 +216,7 @@ Only float and vectorN geometric properties may specify a `unittype` an
For example, one could specify a unique surface ID value associated with a geometry:
-```
+```xml
@@ -225,13 +225,13 @@ For example, one could specify a unique surface ID value associated with a geome
GeomProp values can be accessed from a nodegraph using a `` node:
-```
+```xml
```
A <geomprop> can also be used to define a default value for an intrinsic varying geometric property such as "geomcolor" for the geometry specified by the enclosing <geominfo>, which would be returned by the corresponding Geometric node (e.g. <geomcolor>) if the current geometry did not itself define values for that property.
-```
+```xml
@@ -243,7 +243,7 @@ A <geomprop> can also be used to define a default value for an intrinsic vary
Token elements may be used within <geominfo> elements to define constant (typically string or integer) named values associated with specific geometries. These geometry token values can be substituted into filenames within image nodes; see the [**Additional Filename Substitutions**](#additional-filename-substitutions) section above for details:
-```
+```xml
```
@@ -257,7 +257,7 @@ Token elements have the following attributes:
For example, one could specify a texture identifier value associated with a geometry:
-```
+```xml
@@ -265,7 +265,7 @@ For example, one could specify a texture identifier value associated with a geom
and then reference that token's value in a filename:
-```
+```xml
@@ -279,7 +279,7 @@ The <txtid> in the file name would be replaced by whatever value the txtid to
TokenDefault elements define the default value for a specified geometry token name; this default value will be used in a filename string substitution if an explicit token value is not defined for the current geometry. Since TokenDefault does not apply to any geometry in particular, it must be used outside of a <geominfo> element.
-```
+```xml
```
@@ -288,7 +288,7 @@ TokenDefault elements define the default value for a specified geometry token na
Workflows involving textures with implicitly-computed filenames based on u,v coordinates (such as <UDIM> and <UVTILE>) can be made more efficient by explicitly listing the set of values that they resolve to for any given geometry. The MaterialX specification reserves two geomprop names for this purpose, `udimset` and `uvtileset`, each of which is a stringarray containing a comma-separated list of UDIM or UVTILE values:
-```
+```xml
@@ -313,7 +313,7 @@ A MaterialX document can contain multiple property and/or look elements.
A **<property>** element defines the name, type and value of a look-specific non-material property of geometry; <**propertyset**> elements are used to group a number of <property>s into a single named object. The connection between properties or propertysets and specific geometries or collections is done in a <look> element, so that these properties can be reused across different geometries, and enabled in some looks but not others. <Property> elements may only be used within <propertyset>s; they may not be used independently, although a dedicated <propertyassign> element may be used within a <look> to declare a property name, type, value and assignment all at once.
-```
+```xml
@@ -338,7 +338,7 @@ In the example above, the "trace_maxdiffusedepth" property is target-specific, h
A **<look>** element contains one or more material, variant, visibility and/or propertyset assignment declarations:
-```
+```xml
...materialassign, variantassign, visibilityassign, property/propertysetassign declarations...
@@ -348,7 +348,7 @@ Looks can inherit the assignments from another look by including an `inherit` at
A number of looks can be grouped together into a **LookGroup**, e.g. to indicate which looks are defined for a particular asset:
-```
+```xml
```
@@ -368,7 +368,7 @@ For elements which make assignments to geometries, the pathed names within `geom
MaterialAssign elements are used within a <look> to connect a specified material to one or more geometries or collections (either a `geom` or a `collection` may be specified, but not both).
-```
+```xml
@@ -383,7 +383,7 @@ Material assignments are generally assumed to be mutually-exclusive, that is, an
VariantAssign elements are used within a <materialassign> or a <look> to apply the values defined in one variant of a variantset to one assigned material, or to all applicable materials in a look.
-```
+```xml
@@ -407,7 +407,7 @@ In the above example, the input/token values defined within variant "var1" will
Visibility elements are used within a <look> to define various types of generalized visibility between a "viewer" object and other geometries. A "viewer object" is simply a geometry that has the ability to "see" other geometries in some rendering context and thus may need to have the list of geometries that it "sees" in different contexts be specified; the most common examples are light sources and a primary rendering camera.
-```
+```xml
@@ -442,7 +442,7 @@ If the <visibility> `geom` or `collection` refers to light geometry, then ass
For the "secondary" vistype, `viewergeom` should be renderable geometry rather than a light, to declare that certain other geometry is or is not visible to indirect bounce illumination or raytraced reflections in that `viewergeom`. In this example, "/b" would not be seen in reflections nor contribute indirect bounce illumination to "/a", while geometry "/c" would not be visible to _any_ secondary rays:
-```
+```xml
```
@@ -452,7 +452,7 @@ For the "secondary" vistype, `viewergeom` should be renderable geometry rather t
PropertyAssign and PropertySetAssign elements are used within a <look> to connect a specified property value or propertyset to one or more geometries or collections.
-```
+```xml
@@ -467,7 +467,7 @@ Either a `geom` or a `collection` may be specified, but not both. Multiple prop
This example defines four collections, a light shader and material, and a propertyset, which are then used by two looks:
-```
+```xml
diff --git a/documents/Specification/MaterialX.Specification.md b/documents/Specification/MaterialX.Specification.md
index 7e876bdb57..895b4756c5 100644
--- a/documents/Specification/MaterialX.Specification.md
+++ b/documents/Specification/MaterialX.Specification.md
@@ -267,7 +267,7 @@ Types not defined with a specific semantic are assumed to have semantic="default
Custom types are defined using the <typedef> element:
-```
+```xml
```
@@ -292,7 +292,7 @@ The standard MaterialX distribution includes definitions for four "shader"-seman
An MTLX file (with file extension ".mtlx") has the following general form:
-```
+```xml
@@ -303,7 +303,7 @@ That is, a standard XML declaration line followed by a root <materialx> eleme
Standard XML XIncludes are supported ([http://en/wikipedia.org/wiki/XInclude](http://en/wikipedia.org/wiki/Xinclude)), as well as standard XML comments and the XML character entities `"`, `&`, `'`, `<` and `>`:
-```
+```xml
@@ -345,7 +345,7 @@ The working color space of a MaterialX document is defined by the `colorspace` a
The color space of individual color image files and values may be defined via a `colorspace` attribute in an input which defines a filename or value. Color images and values in spaces other than the working color space are expected to be transformed by the application into the working space before computations are performed. In the example below, an image file has been defined in the “srgb_texture” color space, while its default value has been defined in “lin_rec709”; both should be transformed to the application’s working color space before being applied to any computations.
-```
+```xml
@@ -364,7 +364,7 @@ MaterialX allows floating-point and vector values to be defined in terms of a sp
Unit types are defined using a <unittypedef> element, and a set of units of that type is defined using a <unitdef> element with one or more child <unit> elements:
-```
+```xml
@@ -397,7 +397,7 @@ References to elements in a different namespace are qualified using the syntax "
Mtllib.mtlx contains the following (assuming that "..." contains any necessary material input connections and other element definitions):
-```
+```xml
...
@@ -412,7 +412,7 @@ Mtllib.mtlx contains the following (assuming that "..." contains any necessary m
Then another MaterialX file could reference these materials like this:
-```
+```xml
...
@@ -423,7 +423,7 @@ Then another MaterialX file could reference these materials like this:
Similarly, if a .mtlx file defining the "site_ops" namespace defined a custom color3-typed node "mynoise" with a single float input "f", it could be used in a node graph like this:
-```
+```xml
@@ -431,7 +431,7 @@ Similarly, if a .mtlx file defining the "site_ops" namespace defined a custom co
A `namespace` attribute may also be added to individual <nodedef>s or <nodegraph>s, in which case the `name` and `node` of a <nodedef>, or just the `name` of a <nodegraph> will be assigned to the specified `namespace`. In a <nodegraph>, the `nodedef` must include a namespace reference if the <nodedef> to which it refers is defined in a specific namespace, even if it's the same namespace as the <nodegraph>: this is because the `namespace` only applies to the content that is created by or contained within an element, not to anything external referenced by that element.
-```
+```xml
@@ -453,14 +453,14 @@ Geometric Properties, or "geomprops", are intrinsic or user-defined surface coor
One may also define custom geometric properties using a <geompropdef> element:
-```
+```xml
```
e.g.
-```
+```xml
```
@@ -469,13 +469,13 @@ The `type` of the geomprop may be any non-array MaterialX type, although `string
Once defined, a custom geomprop name may be used any place that a standard geomprop can:
-```
+```xml
```
A geompropdef may also specify a `unittype` and a `unit` to indicate that the geometric property is defined in terms of a specific unit. If a geomprop with a defined unit is accessed in a nodegraph using <geompropvalue>, the geometric property value will be converted from the unit specified by the geompropdef to the application-specified scene unit.
-```
+```xml
```
@@ -487,7 +487,7 @@ As a shorthand convenience, MaterialX allows the specification of a `fileprefix`
So the following snippets are equivalent:
-```
+```xml
@@ -538,7 +538,7 @@ Nodes are individual data generation or processing "blocks". Node functionality
Individual node elements have the form:
-```
+```xml
@@ -560,7 +560,7 @@ Node elements contain zero or more <input> elements defining the name, type,
A float/vectorN input of a node, or a "filename"-type input referring to an image file containing float or vectorN values, may specify a unit for its value by providing a `unit` attribute, and that unit must be one associated with the `unittype` for that input in the nodedef, if specified; please see the [Units](#units) section above for details on declaring units and unittypes. If the nodedef for a node (see the [Custom Nodes](#custom-nodes) section below) does not declare a `unittype` for an input, the node may do so; it is not permissible to provide a `unit` for a node input without a compatible `unittype` being defined on either the node or applicable nodedef.
-```
+```xml
@@ -570,7 +570,7 @@ Unless specified otherwise, all inputs default to a value of 0 in all channels f
A node input must generally be connected to outputs of the same type, but float inputs may also be connected to any single channel within a multi-channel data types by adding an integer "channel" attribute, indicating the channel number (0-3) to extract from the input:
-```
+```xml
@@ -593,7 +593,7 @@ Standard MaterialX nodes have exactly one output, while custom nodes may have an
A graph containing any number of nodes and output declarations forms a Node Graph, which may be enclosed within a <nodegraph> element to group them together into a single functional unit. Please see the [Custom Node Definition Using Node Graphs](#custom-node-definition-using-node-graphs) section below for details on how nodegraphs can be used to describe the functionality of new nodes.
-```
+```xml
...node element(s)...
...output element(s)...
@@ -606,7 +606,7 @@ A graph containing any number of nodes and output declarations forms a Node Grap
Output data streams are defined using **<output>** elements, and may be used to declare which output streams are connectable to other MaterialX elements. Within a node graph, an <output> element declares an output stream that may be connected to a shader input or to the input of a referencing node in another graph when the nodegraph is the implementation of a custom node. See the [Custom Node Definition Using Node Graphs](#custom-node-definition-using-node-graphs) section for details on the use of node graphs as node implementations.
-```
+```xml
@@ -640,7 +640,7 @@ This section defines the Source Nodes that all MaterialX implementations are exp
Texture nodes are used to read filtered image data from image or texture map files for processing within a node graph.
-```
+```xml
@@ -721,7 +721,7 @@ Arbitrary frame number expressions and speed changes are not supported.
Procedural nodes are used to generate value data programmatically.
-```
+```xml
@@ -900,7 +900,7 @@ To scale or offset the noise pattern generated by `noise3d`, `fractal3d` or `cel
Geometric nodes are used to reference local geometric properties from within a node graph:
-```
+```xml
@@ -982,7 +982,7 @@ Applications may also reference other renderer-specific named spaces, at the exp
Global nodes generate color data using non-local geometric context, requiring access to geometric features beyond the surface point being processed. This non-local context can be provided by tracing rays into the scene, rasterizing scene geometry, or any other appropriate method.
-```
+```xml
@@ -1002,7 +1002,7 @@ Standard Global nodes:
Application nodes are used to reference application-defined properties within a node graph, and have no inputs:
-```
+```xml
```
@@ -1028,7 +1028,7 @@ Standard Application nodes:
Operator nodes process one or more required input streams to form an output. Like other nodes, each operator must define its output type, which in most cases also determines the type(s) of the required input streams.
-```
+```xml
@@ -1496,7 +1496,7 @@ Blend nodes take two 1-4 channel inputs and apply the same operator to all chann
| **`burn`** | 1-(1-B)/F | float, colorN |
| **`dodge`** | B/(1-F) | float, colorN |
| **`screen`** | 1-(1-F)(1-B) | float, colorN |
-| **`overlay`** | 2FB if F<0.5;
1-(1-F)(1-B) if F>=0.5 | float, colorN |
+| **`overlay`** | 2FB if B<0.5;
1-2(1-F)(1-B) if B>=0.5 | float, colorN |
#### Merge Nodes
@@ -1786,7 +1786,7 @@ A simple merge of two single-layer images with a separate mask image, followed b
![Nodegraph Example 1](media/nodegraph1.png "Nodegraph Example 1")
-```
+```xml
@@ -1818,7 +1818,7 @@ A more complex nodegraph using geometry properties to define two diffuse albedo
![Nodegraph Example 2](media/nodegraph2.png "Nodegraph Example 2")
-```
+```xml
@@ -1885,7 +1885,7 @@ MaterialX supports the definition of nodes, attributes and inputs that are speci
Targets are declared using a <targetdef> element:
-```
+```xml
@@ -1893,7 +1893,7 @@ Targets are declared using a <targetdef> element:
A target may inherit from another target, so that any reference to a parent target will automatically include any definitions specific to the inherited child target that do not have a definition for the parent target itself:
-```
+```xml
@@ -1913,14 +1913,14 @@ While the MaterialX specification describes the attributes and elements that are
If an application requires additional information related to any MaterialX element, it may define and utilize additional attributes with non-standard names. Custom attributes are defined using <attributedef> elements:
-```
+```xml
```
where _name_ is a unique name for the attributedef, _attrname_ is the name of the custom attribute to define, _type_ is the type of the attribute (typically string, stringarray, integer or boolean, although any MaterialX type is allowed), _defaultvalue_ is the default value for the attribute, _target_ is an optional list of targets to which this attribute applies, and _elements_ is an optional list of element names or elementname/inputname in which the attribute may be used. It is also permissible to provide enum and enumvalues attributes for an attributedef, to define specific labels and values that the custom attribute is allowed to take, using the same syntax and limitations as enum/enumvalues on nodedef inputs and tokens (see below). By default, a custom attribute is not emitted as metadata in generated shaders, but can be exported if the `exportable` attribute is set to "true". Examples:
-```
+```xml
@@ -1948,7 +1948,7 @@ Once defined, custom attributes may be used in exactly the same manner as standa
If an application requires additional custom inputs within a standard MaterialX node, it may define a target application-specific <nodedef> for that node inheriting the base input definitions from the standard node's <nodedef>, then add inputs specific to that target application.
-```
+```xml
@@ -1958,7 +1958,7 @@ In the above example, a Maya-specific version of the color4-type <image> node
When using a node, the definition appropriate for the current target will automatically be used, and other targets will ignore any inputs that are not part of the nodedef for that target. However, one may specify a documentational `target` attribute on an input to hint what target it is intended for if desired. In this example, the "preFilter" input has indicated that it is specific to the "maya" target.
-```
+```xml
@@ -1998,7 +1998,7 @@ NodeDefs must define one or more child <output> elements within the <noded
The parameter interface of a custom node is specified via a set of child <input> and <token> elements of the <nodedef>, while documentation of the folder structure of a node may be defined using a number of <uifolder> elements, each of which may provide a doc attribute to provide documentation for that folder layer. A <uifolder> element may not contain any other elements; in particular, the <input>s and <token>s of the nodedef interface must be direct children of the <nodedef>. Nested folders may be indicated using a full path for the folder, with a "/" separator between folder levels.
-```
+```xml
@@ -2012,7 +2012,7 @@ The parameter interface of a custom node is specified via a set of child <inp
**Input** elements are used within a <nodedef> to declare the spatially-varying and uniform inputs for a node:
-```
+```xml
```
@@ -2047,7 +2047,7 @@ It is permissible to define a `value` or a `defaultgeomprop` for an input but no
**Token** elements are used within a <nodedef> to declare uniform "interface token" string-substitution values to be referenced and substituted within filenames used in a node's nodegraph implementation:
-```
+```xml
```
@@ -2068,7 +2068,7 @@ Please see the [Example Pre-Shader Compositing Material](#example-pre-shader-com
**Output** elements are used within a <nodedef> to declare an output for node definitions, including the output's name, type, and default value or "defaultinput" connection:
-```
+```xml
```
@@ -2103,7 +2103,7 @@ An <implementation> may define a `file` or `sourcecode` attribute, or neither
Because the names used for node inputs (such as "normal" or "default") may conflict with the reserved words in various shading languages, or may simply be different for specific targets, <implementation> elements may contain a number of <input> elements to remap the `name`s of <input>s as specified in the <nodedef> to different `implname`s to indicate what the input name is actually called in the implementation's code. Only the inputs that need to be remapped to new `implname`s need to be listed; for each, it is recommended that the `type` of that input be listed for clarity, but if specified, it must match the type specified in the <nodedef>: <implementation>s are not allowed to change the type or any other attribute defined in the <nodedef>. In this example, the <implementation> declares that the "default" input defined in the "ND_image_color3" nodedef is actually called "default_value" in the "mx_image_color" function:
-```
+```xml
@@ -2112,7 +2112,7 @@ Because the names used for node inputs (such as "normal" or "default") may confl
For uniform inputs and tokens whose nodedef description includes an enum list of allowable values, individual implementations may associate different target-specific resolved values for them potentially of a different type; these may be described by providing an `enumvalues` attribute on the uniform input or token within an <implementation> and if appropriate, an `impltype` to declare the target-specific type of these enumvalues. Note that if the type of an enum input in the nodedef is an array type, then the `impltype` (if specified) must also be an array type, while `enumvalues` is a list of values of the base (non-array) type. The following <implementation> states that for the "mystudio" target, the uaddressmode and vaddressmode inputs of the "image" node are actually called "extrapolate_u" and "extrapolate_v", are integers rather than strings, and take different values (e.g. "clamp" is 2):
-```
+```xml
element with a file attribute defining an external compiled implementation of a surface shader may contain one or more <aov> elements to declare the names and types of arbitrary output variables ("AOVs") which the shader can output to the renderer. AOVs must be of type float, color3, vector3, BSDF or EDF. Note that in MaterialX, AOVs for pre-shading "pattern" colors are normally of type color3, while post-shaded color-like values are normally of type BSDF and emissive color-like values are normally of type EDF. An <implementation> with a `nodegraph` attribute may not contain <aov> elements; instead, <aovoutput> elements within the nodegraph should be used.
-```
+```xml
@@ -2139,7 +2139,7 @@ An <implementation> element with a file attribute defining an external compil
#### Example Custom Nodes Defined by External File Implementations
-```
+```xml
@@ -2179,7 +2179,7 @@ This example defines two templates for a custom operator node called "mariBlend"
Here is an example of a two-output node definition and external implementation declaration.
-```
+```xml
@@ -2203,7 +2203,7 @@ A **<nodegraph>** element consists of at least one node element and at least
A **functional nodegraph** is a nodegraph-based implementation for a specified <nodedef>, with the <nodedef> declaring the set of inputs that the nodegraph accepts: a functional nodegraph may not itself specify any direct child input elements.
-```
+```xml
...node element(s)...
...output element(s)...
@@ -2212,7 +2212,7 @@ A **functional nodegraph** is a nodegraph-based implementation for a specified &
or
-```
+```xml
...node element(s)...
...output element(s)...
@@ -2223,7 +2223,7 @@ or
The type(s) of the <output>(s) of the <nodedef> and the type(s) of the nodegraph <output>(s) must agree, and if there are multiple outputs, then the `name`s of the <output>s in the <nodegraph> and <nodedef> must also agree. The inputs and tokens of the <nodedef> can be referenced within <input> and <token> elements of nodes within the nodegraph implementation using `interfacename` attributes in place of `value` or `nodename` attributes, e.g. a nodedef input "i2" and interface token "diffmap" could be referenced as follows:
-```
+```xml
```
@@ -2235,7 +2235,7 @@ Note that a uniform <input> of a node within the nodegraph may use `interface
A **compound <nodegraph>** element may specify one or more child <input> and/or <token> elements. In this case, the <nodegraph> functions as a collapsible "wrapper" for the contained nodes.
-```
+```xml
[...input and/or token element(s)...]
...node and/or (compound) nodegraph element(s)...
@@ -2250,7 +2250,7 @@ It is permissible to define multiple nodegraph- and/or file-based implementation
#### Example Custom Node Defined by a Nodegraph
-```
+```xml
@@ -2277,7 +2277,7 @@ The inputs of the nodegraph are declared by the <nodedef>, and the nodes with
Once defined with a <nodedef>, using a custom node within a node graph follows the same syntax as any other standard node: the name of the element is the name of the custom node, and the MaterialX type of the node's output is required; the custom node's child elements define connections of inputs to other node outputs as well as any input values for the custom node.
-```
+```xml
@@ -2292,7 +2292,7 @@ Once defined with a <nodedef>, using a custom node within a node graph follow
When invoking nodes with multiple outputs, the `type` of the node should be declared as "multioutput", and other node inputs connecting to an output of the node must include an `output` attribute to specify which output of the node to connect to:
-```
+```xml
@@ -2313,7 +2313,7 @@ When invoking nodes with multiple outputs, the `type` of the node should be decl
Custom nodes that output data types with a "shader" semantic are referred to in MaterialX as "Shader Nodes". Shaders, along with their inputs, are declared using the same <nodedef>, <implementation> and <nodegraph> elements described above:
-```
+```xml
...input declarations...
@@ -2331,7 +2331,7 @@ NodeDef elements defining shader nodes do not typically include `default` or `de
As mentioned in the [Custom Data Types](#custom-data-types) section earlier, the standard MaterialX distribution includes the following standard data types for shaders:
-```
+```xml
@@ -2342,7 +2342,7 @@ These types all declare that they have "shader" semantic, but define different c
Instantiation of shader nodes to give them specific values is done the same way as instantiating any other node type:
-```
+```xml
@@ -2352,7 +2352,7 @@ Instantiation of shader nodes to give them specific values is done the same way
Instantiated shader nodes can also inherit from other shader nodes of the same class:
-```
+```xml
@@ -2398,7 +2398,7 @@ The Standard MaterialX Library defines the following nodes and node variants ope
A functional nodegraph with either a "shader" or "material"-semantic output type may contain a number of <aovoutput> elements to declare arbitrary output variables ("AOVs") which the renderer can see and output as additional streams of information. AOVoutputs must be of type float, color3 or vector3 for pre-shading "pattern" values, or BSDF or EDF for shader-node output values; the renderer is expected to extract the appropriate color-like information from BSDF and EDF types. AOVs defined within a shader-semantic node instantiated within this functional nodegraph may be "passed along" and potentially renamed (but may not be modified or operated on in any way) by providing a sourceaov attribute in the <aovoutput>.
-```
+```xml
```
@@ -2413,7 +2413,7 @@ The attributes for <aovoutput> elements are:
Examples:
-```
+```xml
@@ -2424,7 +2424,7 @@ Examples:
Example of using <aovoutput> with sourceaov to forward AOVs from within an instantiation of a shader-semantic node; this assumes that <standard_surface> has itself defined <aovoutput>s for "diffuse" and "specular" AOVs:
-```
+```xml
s for geometric
Custom nodes that output data types with a "material" semantic are referred to in MaterialX as "Material Nodes". Material nodes typically have one or more "shader" semantic inputs which establish what shaders the material references; previous versions of MaterialX used <shaderref> elements to establish these shader-to-material connections. Material Nodes are declared using the same <nodedef> elements as described above:
-```
+```xml
...additional shader or input declarations...
@@ -2476,7 +2476,7 @@ The attributes for <nodedef> elements as they pertain to the declaration of m
The standard MaterialX distribution includes a single material type definition used as the output type for all material nodes:
-```
+```xml
```
@@ -2501,7 +2501,7 @@ as well as definitions for three standard material nodes, all outputting type "m
Material nodes supporting multiple shaders of the same type for different rendering targets can be defined:
-```
+```xml
@@ -2514,7 +2514,7 @@ Material nodes supporting multiple shaders of the same type for different render
Creating materials with specific values bound to shader inputs involves instantiating a Shader Node for each desired shader type and setting values on those shader nodes, and connecting the shader node(s) to the inputs of a Material Node:
-```
+```xml
@@ -2535,7 +2535,7 @@ Alternatively, and perhaps more usefully, a complete network of multiple shader
Materials can inherit from other materials, to add or change shaders connected to different inputs; in this example, a displacement shader is added to the above "Mgold" material to create a new "Mgolddsp" material:
-```
+```xml
@@ -2555,7 +2555,7 @@ Inheritance of material-type custom nodes is also allowed, so that new or change
A material to blend between three different surface layers using mask textures. This example also demonstrates the use of the "target" attribute of a shader implementation element to define multiple renderer-specific shaders of the same type referenced within a single material, and the use of interface tokens to define texture filenames.
-```
+```xml
-
-
-
-
diff --git a/libraries/stdlib/genmdl/stdlib_genmdl_impl.mtlx b/libraries/stdlib/genmdl/stdlib_genmdl_impl.mtlx
index ab0d776936..022f0896f1 100644
--- a/libraries/stdlib/genmdl/stdlib_genmdl_impl.mtlx
+++ b/libraries/stdlib/genmdl/stdlib_genmdl_impl.mtlx
@@ -22,22 +22,22 @@
-
+
-
+
-
+
-
+
-
+
-
+
@@ -568,11 +568,6 @@
-
-
-
-
-
diff --git a/libraries/stdlib/genmsl/stdlib_genmsl_impl.mtlx b/libraries/stdlib/genmsl/stdlib_genmsl_impl.mtlx
index fcab8fd69d..dea1c49636 100644
--- a/libraries/stdlib/genmsl/stdlib_genmsl_impl.mtlx
+++ b/libraries/stdlib/genmsl/stdlib_genmsl_impl.mtlx
@@ -560,11 +560,6 @@
-
-
-
-
-
diff --git a/libraries/stdlib/genosl/mx_image_color3.osl b/libraries/stdlib/genosl/mx_image_color3.osl
index 15b594e885..89ba94f376 100644
--- a/libraries/stdlib/genosl/mx_image_color3.osl
+++ b/libraries/stdlib/genosl/mx_image_color3.osl
@@ -12,6 +12,5 @@ void mx_image_color3(textureresource file, string layer, color default_value, ve
color missingColor = default_value;
vector2 st = mx_transform_uv(texcoord);
- out = texture(file.filename, st.x, st.y, "subimage", layer, "missingcolor", missingColor, "swrap", uaddressmode, "twrap", vaddressmode $extraTextureLookupArguments);
+ out = texture(file.filename, st.x, st.y, "subimage", layer, "missingcolor", missingColor, "swrap", uaddressmode, "twrap", vaddressmode, "colorspace", file.colorspace);
}
-
diff --git a/libraries/stdlib/genosl/mx_image_color4.osl b/libraries/stdlib/genosl/mx_image_color4.osl
index 3bde1a5047..261108b5b4 100644
--- a/libraries/stdlib/genosl/mx_image_color4.osl
+++ b/libraries/stdlib/genosl/mx_image_color4.osl
@@ -15,7 +15,7 @@ void mx_image_color4(textureresource file, string layer, color4 default_value, v
vector2 st = mx_transform_uv(texcoord);
float alpha;
color rgb = texture(file.filename, st.x, st.y, "alpha", alpha, "subimage", layer,
- "missingcolor", missingColor, "missingalpha", missingAlpha, "swrap", uaddressmode, "twrap", vaddressmode $extraTextureLookupArguments );
+ "missingcolor", missingColor, "missingalpha", missingAlpha, "swrap", uaddressmode, "twrap", vaddressmode, "colorspace", file.colorspace);
out = color4(rgb, alpha);
}
diff --git a/libraries/stdlib/genosl/mx_overlay_color3.osl b/libraries/stdlib/genosl/mx_overlay_color3.osl
deleted file mode 100644
index 387653fe05..0000000000
--- a/libraries/stdlib/genosl/mx_overlay_color3.osl
+++ /dev/null
@@ -1,16 +0,0 @@
-float overlay(float fg, float bg)
-{
- return (fg < 0.5) ? (2 * fg * bg) : (1 - (1 - fg) * (1 - bg));
-}
-
-color overlay(color fg, color bg)
-{
- return color(overlay(fg[0], bg[0]),
- overlay(fg[1], bg[1]),
- overlay(fg[2], bg[2]));
-}
-
-void mx_overlay_color3(color fg, color bg, float mix, output color out)
-{
- out = mix * overlay(fg, bg) + (1-mix) * bg;
-}
diff --git a/libraries/stdlib/genosl/mx_overlay_color4.osl b/libraries/stdlib/genosl/mx_overlay_color4.osl
deleted file mode 100644
index 1ae6a72c15..0000000000
--- a/libraries/stdlib/genosl/mx_overlay_color4.osl
+++ /dev/null
@@ -1,22 +0,0 @@
-float overlay(float fg, float bg)
-{
- return (fg < 0.5) ? (2 * fg * bg) : (1 - (1 - fg) * (1 - bg));
-}
-
-color overlay(color fg, color bg)
-{
- return color(overlay(fg[0], bg[0]),
- overlay(fg[1], bg[1]),
- overlay(fg[2], bg[2]));
-}
-
-color4 overlay(color4 fg, color4 bg)
-{
- return color4(overlay(fg.rgb, bg.rgb),
- overlay(fg.a, bg.a));
-}
-
-void mx_overlay_color4(color4 fg, color4 bg, float mix, output color4 out)
-{
- out = mix * overlay(fg, bg) + (1-mix) * bg;
-}
diff --git a/libraries/stdlib/genosl/stdlib_genosl_impl.mtlx b/libraries/stdlib/genosl/stdlib_genosl_impl.mtlx
index 1ba22ef6a3..42828ce641 100644
--- a/libraries/stdlib/genosl/stdlib_genosl_impl.mtlx
+++ b/libraries/stdlib/genosl/stdlib_genosl_impl.mtlx
@@ -561,11 +561,6 @@
-
-
-
-
-
diff --git a/libraries/stdlib/stdlib_defs.mtlx b/libraries/stdlib/stdlib_defs.mtlx
index bb5e8edd1f..3f187e2be1 100644
--- a/libraries/stdlib/stdlib_defs.mtlx
+++ b/libraries/stdlib/stdlib_defs.mtlx
@@ -3343,8 +3343,8 @@
diff --git a/libraries/stdlib/stdlib_ng.mtlx b/libraries/stdlib/stdlib_ng.mtlx
index e031e72412..4983aaa477 100644
--- a/libraries/stdlib/stdlib_ng.mtlx
+++ b/libraries/stdlib/stdlib_ng.mtlx
@@ -3391,6 +3391,118 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/python/Scripts/baketextures.py b/python/Scripts/baketextures.py
index caf2aaed3e..ce132036a6 100644
--- a/python/Scripts/baketextures.py
+++ b/python/Scripts/baketextures.py
@@ -5,9 +5,8 @@
import sys, os, argparse
from sys import platform
+
import MaterialX as mx
-from MaterialX import PyMaterialXGenShader
-from MaterialX import PyMaterialXGenGlsl
from MaterialX import PyMaterialXRender as mx_render
from MaterialX import PyMaterialXRenderGlsl as mx_render_glsl
if platform == "darwin":
diff --git a/python/Scripts/generateshader.py b/python/Scripts/generateshader.py
index 8329f7231e..f6158d270a 100644
--- a/python/Scripts/generateshader.py
+++ b/python/Scripts/generateshader.py
@@ -5,12 +5,13 @@
'''
import sys, os, argparse, subprocess
+
import MaterialX as mx
-import MaterialX.PyMaterialXGenShader as mx_gen_shader
import MaterialX.PyMaterialXGenGlsl as mx_gen_glsl
-import MaterialX.PyMaterialXGenOsl as mx_gen_osl
import MaterialX.PyMaterialXGenMdl as mx_gen_mdl
import MaterialX.PyMaterialXGenMsl as mx_gen_msl
+import MaterialX.PyMaterialXGenOsl as mx_gen_osl
+import MaterialX.PyMaterialXGenShader as mx_gen_shader
def validateCode(sourceCodeFile, codevalidator, codevalidatorArgs):
if codevalidator:
@@ -24,7 +25,7 @@ def validateCode(sourceCodeFile, codevalidator, codevalidatorArgs):
print(cmd_flatten)
try:
output = subprocess.check_output(cmd, stderr=subprocess.STDOUT)
- result = output.decode(encoding='utf-8')
+ return output.decode(encoding='utf-8')
except subprocess.CalledProcessError as out:
return (out.output.decode(encoding='utf-8'))
return ""
@@ -82,7 +83,7 @@ def main():
try:
mx.loadLibraries(libraryFolders, searchPath, stdlib)
doc.importLibrary(stdlib)
- except err:
+ except Exception as err:
print('Generation failed: "', err, '"')
sys.exit(-1)
diff --git a/python/Scripts/genmdl.py b/python/Scripts/genmdl.py
index f42add0425..ded1021554 100644
--- a/python/Scripts/genmdl.py
+++ b/python/Scripts/genmdl.py
@@ -3,9 +3,11 @@
Generate MDL implementation directory based on MaterialX nodedefs
'''
-import sys
import os
-import string; os.environ['PYTHONIOENCODING'] = 'utf-8'
+import sys
+
+os.environ['PYTHONIOENCODING'] = 'utf-8'
+
import MaterialX as mx
def usage():
@@ -345,7 +347,7 @@ def main():
doc = mx.createDocument()
searchPath = os.path.join(_startPath, 'libraries')
- libraryPath = os.path.join(searchPath, 'stdlib')
+ libraryPath = os.path.join(searchPath, LIBRARY)
_loadLibraries(doc, searchPath, libraryPath)
DEFINITION_PREFIX = 'ND_'
@@ -522,7 +524,7 @@ def main():
if isinstance(elem, mx.Output):
outputValue = elem.getAttribute('default')
if outputValue == '[]':
- outputvalue = ''
+ outputValue = ''
if not outputValue:
outputValue = elem.getAttribute('defaultinput')
if outputValue:
diff --git a/python/Scripts/mxdoc.py b/python/Scripts/mxdoc.py
index 7ee21eb8e5..7c9ba09a07 100644
--- a/python/Scripts/mxdoc.py
+++ b/python/Scripts/mxdoc.py
@@ -3,7 +3,9 @@
Print markdown documentation for each nodedef in the given document.
'''
-import sys, os, argparse
+import argparse
+import sys
+
import MaterialX as mx
HEADERS = ('Name', 'Type', 'Default Value',
diff --git a/python/Scripts/mxformat.py b/python/Scripts/mxformat.py
index 8f6ad731e1..0b327883bd 100644
--- a/python/Scripts/mxformat.py
+++ b/python/Scripts/mxformat.py
@@ -4,7 +4,9 @@
the documents to the latest version of the standard.
'''
-import sys, os, argparse
+import argparse
+import os
+
import MaterialX as mx
def main():
diff --git a/python/Scripts/mxvalidate.py b/python/Scripts/mxvalidate.py
index e251b4599b..8b5271e9ed 100755
--- a/python/Scripts/mxvalidate.py
+++ b/python/Scripts/mxvalidate.py
@@ -3,7 +3,9 @@
Verify that the given file is a valid MaterialX document.
'''
-import sys, os, argparse
+import argparse
+import sys
+
import MaterialX as mx
def main():
@@ -25,7 +27,7 @@ def main():
stdlib = mx.createDocument()
try:
mx.loadLibraries(mx.getDefaultDataLibraryFolders(), mx.getDefaultDataSearchPath(), stdlib)
- except err:
+ except Exception as err:
print(err)
sys.exit(0)
doc.importLibrary(stdlib)
diff --git a/python/Scripts/translateshader.py b/python/Scripts/translateshader.py
index 71d7a480b5..f7c5686211 100644
--- a/python/Scripts/translateshader.py
+++ b/python/Scripts/translateshader.py
@@ -5,15 +5,13 @@
'''
import sys, os, argparse
-import MaterialX as mx
-
from sys import platform
+
+import MaterialX as mx
from MaterialX import PyMaterialXGenShader as mx_gen_shader
-from MaterialX import PyMaterialXGenGlsl as ms_gen_glsl
from MaterialX import PyMaterialXRender as mx_render
from MaterialX import PyMaterialXRenderGlsl as mx_render_glsl
if platform == "darwin":
- from MaterialX import PyMaterialXGenMsl as ms_gen_msl
from MaterialX import PyMaterialXRenderMsl as mx_render_msl
def main():
diff --git a/resources/Materials/TestSuite/_options.mtlx b/resources/Materials/TestSuite/_options.mtlx
index 8716cba5f0..bb29fbd7c1 100644
--- a/resources/Materials/TestSuite/_options.mtlx
+++ b/resources/Materials/TestSuite/_options.mtlx
@@ -87,9 +87,6 @@
-
-
-
diff --git a/resources/Materials/TestSuite/stdlib/compositing/compositing.mtlx b/resources/Materials/TestSuite/stdlib/compositing/compositing.mtlx
index e7a742c581..b125e70dca 100644
--- a/resources/Materials/TestSuite/stdlib/compositing/compositing.mtlx
+++ b/resources/Materials/TestSuite/stdlib/compositing/compositing.mtlx
@@ -183,24 +183,24 @@
-
-
+
+
-
-
+
+
-
-
+
+
diff --git a/resources/Materials/TestSuite/stdlib/texture/texcoord.mtlx b/resources/Materials/TestSuite/stdlib/texture/texcoord.mtlx
new file mode 100644
index 0000000000..4fbf6d12d9
--- /dev/null
+++ b/resources/Materials/TestSuite/stdlib/texture/texcoord.mtlx
@@ -0,0 +1,25 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/resources/Materials/TestSuite/stdlib/upgrade/1_37_to_1_38.mtlx b/resources/Materials/TestSuite/stdlib/upgrade/1_37_to_1_38.mtlx
deleted file mode 100644
index 28b9ae8ad2..0000000000
--- a/resources/Materials/TestSuite/stdlib/upgrade/1_37_to_1_38.mtlx
+++ /dev/null
@@ -1,40 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/resources/Materials/TestSuite/stdlib/upgrade/1_38_parameter_to_input.mtlx b/resources/Materials/TestSuite/stdlib/upgrade/1_38_parameter_to_input.mtlx
deleted file mode 100644
index 220836d354..0000000000
--- a/resources/Materials/TestSuite/stdlib/upgrade/1_38_parameter_to_input.mtlx
+++ /dev/null
@@ -1,71 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/resources/Materials/TestSuite/stdlib/upgrade/material_element_to_surface_material.mtlx b/resources/Materials/TestSuite/stdlib/upgrade/material_element_to_surface_material.mtlx
deleted file mode 100644
index 4979f7a6da..0000000000
--- a/resources/Materials/TestSuite/stdlib/upgrade/material_element_to_surface_material.mtlx
+++ /dev/null
@@ -1,22 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/resources/Materials/TestSuite/stdlib/upgrade/syntax_1_22.mtlx b/resources/Materials/TestSuite/stdlib/upgrade/syntax_1_22.mtlx
new file mode 100644
index 0000000000..a9eff392d3
--- /dev/null
+++ b/resources/Materials/TestSuite/stdlib/upgrade/syntax_1_22.mtlx
@@ -0,0 +1,70 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/resources/Materials/TestSuite/stdlib/upgrade/syntax_1_25.mtlx b/resources/Materials/TestSuite/stdlib/upgrade/syntax_1_25.mtlx
new file mode 100644
index 0000000000..df723e7054
--- /dev/null
+++ b/resources/Materials/TestSuite/stdlib/upgrade/syntax_1_25.mtlx
@@ -0,0 +1,28 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/resources/Materials/TestSuite/stdlib/upgrade/1_36_to_1_37.mtlx b/resources/Materials/TestSuite/stdlib/upgrade/syntax_1_36.mtlx
similarity index 99%
rename from resources/Materials/TestSuite/stdlib/upgrade/1_36_to_1_37.mtlx
rename to resources/Materials/TestSuite/stdlib/upgrade/syntax_1_36.mtlx
index 84db1c6101..08a049435f 100644
--- a/resources/Materials/TestSuite/stdlib/upgrade/1_36_to_1_37.mtlx
+++ b/resources/Materials/TestSuite/stdlib/upgrade/syntax_1_36.mtlx
@@ -1,9 +1,7 @@
diff --git a/resources/Materials/TestSuite/stdlib/upgrade/syntax_1_37.mtlx b/resources/Materials/TestSuite/stdlib/upgrade/syntax_1_37.mtlx
new file mode 100644
index 0000000000..66dc69f668
--- /dev/null
+++ b/resources/Materials/TestSuite/stdlib/upgrade/syntax_1_37.mtlx
@@ -0,0 +1,113 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/source/MaterialXCore/Definition.cpp b/source/MaterialXCore/Definition.cpp
index cf9587ecda..c3150e2a87 100644
--- a/source/MaterialXCore/Definition.cpp
+++ b/source/MaterialXCore/Definition.cpp
@@ -84,7 +84,7 @@ InterfaceElementPtr NodeDef::getImplementation(const string& target) const
}
}
}
-
+
// Then search for a generic match.
for (InterfaceElementPtr interface : interfaces)
{
diff --git a/source/MaterialXCore/Document.cpp b/source/MaterialXCore/Document.cpp
index 4ba48cc84b..80143bb9c8 100644
--- a/source/MaterialXCore/Document.cpp
+++ b/source/MaterialXCore/Document.cpp
@@ -492,12 +492,10 @@ void Document::upgradeVersion()
if (nodeDef->hasAttribute("shadertype"))
{
nodeDef->setType(SURFACE_SHADER_TYPE_STRING);
- nodeDef->removeAttribute("shadertype");
}
if (nodeDef->hasAttribute("shaderprogram"))
{
nodeDef->setNodeString(nodeDef->getAttribute("shaderprogram"));
- nodeDef->removeAttribute("shaderprogram");
}
}
else if (child->getCategory() == "shaderref")
@@ -751,8 +749,18 @@ void Document::upgradeVersion()
// Remove legacy shader nodedefs.
for (NodeDefPtr nodeDef : getNodeDefs())
{
- if (nodeDef->getType() == "surface")
+ if (nodeDef->hasAttribute("shadertype"))
{
+ for (ElementPtr mat : getChildrenOfType("material"))
+ {
+ for (ElementPtr shaderRef : mat->getChildrenOfType("shaderref"))
+ {
+ if (shaderRef->getAttribute(InterfaceElement::NODE_DEF_ATTRIBUTE) == nodeDef->getName())
+ {
+ shaderRef->removeAttribute(InterfaceElement::NODE_DEF_ATTRIBUTE);
+ }
+ }
+ }
removeNodeDef(nodeDef->getName());
}
}
@@ -1032,39 +1040,7 @@ void Document::upgradeVersion()
}
}
- // Update atan2 interface and rotate3d interface
- const string ATAN2 = "atan2";
- const string IN1 = "in1";
- const string IN2 = "in2";
- const string ROTATE3D = "rotate3d";
- const string AXIS = "axis";
- const string INPUT_ONE = "1.0";
-
- // Update nodedefs
- bool upgradeAtan2Instances = false;
- for (auto nodedef : getMatchingNodeDefs(ATAN2))
- {
- InputPtr input = nodedef->getInput(IN1);
- InputPtr input2 = nodedef->getInput(IN2);
- string inputValue = input->getValueString();
- // Only flip value if nodedef value is the previous versions.
- if (inputValue == INPUT_ONE)
- {
- input->setValueString(input2->getValueString());
- input2->setValueString(inputValue);
- upgradeAtan2Instances = true;
- }
- }
- for (auto nodedef : getMatchingNodeDefs(ROTATE3D))
- {
- ElementPtr axis = nodedef->getChild(AXIS);
- if (axis)
- {
- nodedef->changeChildCategory(axis, "input");
- }
- }
-
- // Update BSDF interfaces
+ // Define BSDF node pairs.
using StringPair = std::pair;
const StringPair DIELECTRIC_BRDF = { "dielectric_brdf", "dielectric_bsdf" };
const StringPair DIELECTRIC_BTDF = { "dielectric_btdf", "dielectric_bsdf" };
@@ -1077,57 +1053,11 @@ void Document::upgradeVersion()
const StringPair SUBSURFACE_BRDF = { "subsurface_brdf", "subsurface_bsdf" };
const StringPair THIN_FILM_BRDF = { "thin_film_brdf", "thin_film_bsdf" };
- const string SCATTER_MODE = "scatter_mode";
- const string BSDF = "BSDF";
- const string LAYER = "layer";
- const string TOP = "top";
- const string BASE = "base";
- const string INTERIOR = "interior";
- const string ARTISTIC_IOR = "artistic_ior";
- const string COMPLEX_IOR = "complex_ior";
- const string REFLECTIVITY = "reflectivity";
- const string EDGE_COLOR = "edge_color";
- const string IOR = "ior";
- const string EXTINCTION = "extinction";
- const string COLOR3 = "color3";
- const string VECTOR3 = "vector3";
- const string CONVERT = "convert";
- const string IN = "in";
-
- // Function for upgrading BSDF nodedef.
- auto upgradeBsdfNodeDef = [SCATTER_MODE](NodeDefPtr nodedef, const string& newCategory, bool addScatterMode = false)
- {
- if (nodedef)
- {
- nodedef->setName(newCategory);
- if (addScatterMode)
- {
- InputPtr mode = nodedef->addInput(SCATTER_MODE, STRING_TYPE_STRING);
- mode->setIsUniform(true);
- mode->setValueString("R");
- mode->setAttribute("enum", "R,T,RT");
- }
- }
- };
-
- // Update nodedefs.
- upgradeBsdfNodeDef(getNodeDef(DIELECTRIC_BRDF.first), DIELECTRIC_BRDF.second, true);
- upgradeBsdfNodeDef(getNodeDef(GENERALIZED_SCHLICK_BRDF.first), GENERALIZED_SCHLICK_BRDF.second, true);
- upgradeBsdfNodeDef(getNodeDef(CONDUCTOR_BRDF.first), CONDUCTOR_BRDF.second);
- upgradeBsdfNodeDef(getNodeDef(SHEEN_BRDF.first), SHEEN_BRDF.second);
- upgradeBsdfNodeDef(getNodeDef(DIFFUSE_BRDF.first), DIFFUSE_BRDF.second);
- upgradeBsdfNodeDef(getNodeDef(BURLEY_DIFFUSE_BRDF.first), BURLEY_DIFFUSE_BRDF.second);
- upgradeBsdfNodeDef(getNodeDef(DIFFUSE_BTDF.first), DIFFUSE_BTDF.second);
- upgradeBsdfNodeDef(getNodeDef(SUBSURFACE_BRDF.first), SUBSURFACE_BRDF.second);
- upgradeBsdfNodeDef(getNodeDef(THIN_FILM_BRDF.first), THIN_FILM_BRDF.second);
- removeNodeDef(DIELECTRIC_BTDF.first);
- removeNodeDef(COMPLEX_IOR);
-
// Function for upgrading old nested layering setup
// to new setup with layer operators.
- auto upgradeBsdfLayering = [TOP, BASE, LAYER, BSDF](NodePtr node)
+ auto upgradeBsdfLayering = [](NodePtr node)
{
- InputPtr base = node->getInput(BASE);
+ InputPtr base = node->getInput("base");
if (base)
{
NodePtr baseNode = base->getConnectedNode();
@@ -1138,13 +1068,13 @@ void Document::upgradeVersion()
// so we don't need to update any connection references.
const string oldName = node->getName();
node->setName(oldName + "__layer_top");
- NodePtr layer = parent->addNode(LAYER, oldName, BSDF);
- InputPtr layerTop = layer->addInput(TOP, BSDF);
- InputPtr layerBase = layer->addInput(BASE, BSDF);
+ NodePtr layer = parent->addNode("layer", oldName, "BSDF");
+ InputPtr layerTop = layer->addInput("top", "BSDF");
+ InputPtr layerBase = layer->addInput("base", "BSDF");
layerTop->setConnectedNode(node);
layerBase->setConnectedNode(baseNode);
}
- node->removeInput(BASE);
+ node->removeInput("base");
}
};
@@ -1169,31 +1099,31 @@ void Document::upgradeVersion()
continue;
}
const string& nodeCategory = node->getCategory();
- if (upgradeAtan2Instances && nodeCategory == ATAN2)
+ if (nodeCategory == "atan2")
{
- InputPtr input = node->getInput(IN1);
- InputPtr input2 = node->getInput(IN2);
+ InputPtr input = node->getInput("in1");
+ InputPtr input2 = node->getInput("in2");
if (input && input2)
{
input->setName(EMPTY_STRING);
- input2->setName(IN1);
- input->setName(IN2);
+ input2->setName("in1");
+ input->setName("in2");
}
else
{
if (input)
{
- input->setName(IN2);
+ input->setName("in2");
}
if (input2)
{
- input2->setName(IN1);
+ input2->setName("in1");
}
}
}
- else if (nodeCategory == ROTATE3D)
+ else if (nodeCategory == "rotate3d")
{
- ElementPtr axis = node->getChild(AXIS);
+ ElementPtr axis = node->getChild("axis");
if (axis)
{
node->changeChildCategory(axis, "input");
@@ -1207,8 +1137,8 @@ void Document::upgradeVersion()
else if (nodeCategory == DIELECTRIC_BTDF.first)
{
node->setCategory(DIELECTRIC_BTDF.second);
- node->removeInput(INTERIOR);
- InputPtr mode = node->addInput(SCATTER_MODE, STRING_TYPE_STRING);
+ node->removeInput("interior");
+ InputPtr mode = node->addInput("scatter_mode", STRING_TYPE_STRING);
mode->setValueString("T");
}
else if (nodeCategory == GENERALIZED_SCHLICK_BRDF.first)
@@ -1232,32 +1162,32 @@ void Document::upgradeVersion()
// Create an artistic_ior node to convert from artistic to physical parameterization.
GraphElementPtr parent = node->getParent()->asA();
- NodePtr artisticIor = parent->addNode(ARTISTIC_IOR, node->getName() + "__artistic_ior", "multioutput");
- OutputPtr artisticIor_ior = artisticIor->addOutput(IOR, COLOR3);
- OutputPtr artisticIor_extinction = artisticIor->addOutput(EXTINCTION, COLOR3);
+ NodePtr artisticIor = parent->addNode("artistic_ior", node->getName() + "__artistic_ior", "multioutput");
+ OutputPtr artisticIor_ior = artisticIor->addOutput("ior", "color3");
+ OutputPtr artisticIor_extinction = artisticIor->addOutput("extinction", "color3");
// Copy values and connections from conductor node to artistic_ior node.
- InputPtr reflectivity = node->getInput(REFLECTIVITY);
+ InputPtr reflectivity = node->getInput("reflectivity");
if (reflectivity)
{
- InputPtr artisticIor_reflectivity = artisticIor->addInput(REFLECTIVITY, COLOR3);
+ InputPtr artisticIor_reflectivity = artisticIor->addInput("reflectivity", "color3");
copyAttributes(reflectivity, artisticIor_reflectivity);
}
- InputPtr edge_color = node->getInput(EDGE_COLOR);
+ InputPtr edge_color = node->getInput("edge_color");
if (edge_color)
{
- InputPtr artisticIor_edge_color = artisticIor->addInput(EDGE_COLOR, COLOR3);
+ InputPtr artisticIor_edge_color = artisticIor->addInput("edge_color", "color3");
copyAttributes(edge_color, artisticIor_edge_color);
}
// Update the parameterization on the conductor node
// and connect it to the artistic_ior node.
- node->removeInput(REFLECTIVITY);
- node->removeInput(EDGE_COLOR);
- InputPtr ior = node->addInput(IOR, COLOR3);
+ node->removeInput("reflectivity");
+ node->removeInput("edge_color");
+ InputPtr ior = node->addInput("ior", "color3");
ior->setNodeName(artisticIor->getName());
ior->setOutputString(artisticIor_ior->getName());
- InputPtr extinction = node->addInput(EXTINCTION, COLOR3);
+ InputPtr extinction = node->addInput("extinction", "color3");
extinction->setNodeName(artisticIor->getName());
extinction->setOutputString(artisticIor_extinction->getName());
}
@@ -1277,17 +1207,17 @@ void Document::upgradeVersion()
{
node->setCategory(SUBSURFACE_BRDF.second);
}
- else if (nodeCategory == ARTISTIC_IOR)
+ else if (nodeCategory == "artistic_ior")
{
- OutputPtr ior = node->getOutput(IOR);
+ OutputPtr ior = node->getOutput("ior");
if (ior)
{
- ior->setType(COLOR3);
+ ior->setType("color3");
}
- OutputPtr extinction = node->getOutput(EXTINCTION);
+ OutputPtr extinction = node->getOutput("extinction");
if (extinction)
{
- extinction->setType(COLOR3);
+ extinction->setType("color3");
}
}
@@ -1298,18 +1228,18 @@ void Document::upgradeVersion()
// since we can't modify the graph while traversing it.
for (InputPtr input : node->getInputs())
{
- if (input->getOutputString() == IOR && input->getType() == VECTOR3)
+ if (input->getOutputString() == "ior" && input->getType() == "vector3")
{
NodePtr connectedNode = input->getConnectedNode();
- if (connectedNode && connectedNode->getCategory() == ARTISTIC_IOR)
+ if (connectedNode && connectedNode->getCategory() == "artistic_ior")
{
artisticIorConnections.push_back(input);
}
}
- else if (input->getOutputString() == EXTINCTION && input->getType() == VECTOR3)
+ else if (input->getOutputString() == "extinction" && input->getType() == "vector3")
{
NodePtr connectedNode = input->getConnectedNode();
- if (connectedNode && connectedNode->getCategory() == ARTISTIC_IOR)
+ if (connectedNode && connectedNode->getCategory() == "artistic_ior")
{
artisticExtConnections.push_back(input);
}
@@ -1323,10 +1253,10 @@ void Document::upgradeVersion()
NodePtr artisticIorNode = input->getConnectedNode();
ElementPtr node = input->getParent();
GraphElementPtr parent = node->getParent()->asA();
- NodePtr convert = parent->addNode(CONVERT, node->getName() + "__convert_ior", VECTOR3);
- InputPtr convertInput = convert->addInput(IN, COLOR3);
+ NodePtr convert = parent->addNode("convert", node->getName() + "__convert_ior", "vector3");
+ InputPtr convertInput = convert->addInput("in", "color3");
convertInput->setNodeName(artisticIorNode->getName());
- convertInput->setOutputString(IOR);
+ convertInput->setOutputString("ior");
input->setNodeName(convert->getName());
input->removeAttribute(PortElement::OUTPUT_ATTRIBUTE);
}
@@ -1335,10 +1265,10 @@ void Document::upgradeVersion()
NodePtr artisticIorNode = input->getConnectedNode();
ElementPtr node = input->getParent();
GraphElementPtr parent = node->getParent()->asA();
- NodePtr convert = parent->addNode(CONVERT, node->getName() + "__convert_extinction", VECTOR3);
- InputPtr convertInput = convert->addInput(IN, COLOR3);
+ NodePtr convert = parent->addNode("convert", node->getName() + "__convert_extinction", "vector3");
+ InputPtr convertInput = convert->addInput("in", "color3");
convertInput->setNodeName(artisticIorNode->getName());
- convertInput->setOutputString(EXTINCTION);
+ convertInput->setOutputString("extinction");
input->setNodeName(convert->getName());
input->removeAttribute(PortElement::OUTPUT_ATTRIBUTE);
}
diff --git a/source/MaterialXCore/Element.cpp b/source/MaterialXCore/Element.cpp
index 18d028efd3..5131dc8070 100644
--- a/source/MaterialXCore/Element.cpp
+++ b/source/MaterialXCore/Element.cpp
@@ -168,7 +168,7 @@ void Element::setChildIndex(const string& name, int index)
return;
}
- if (index < 0 || index > (int) _childOrder.size())
+ if (index < 0 || index >= (int) _childOrder.size())
{
throw Exception("Invalid child index");
}
diff --git a/source/MaterialXCore/Geom.h b/source/MaterialXCore/Geom.h
index c4d7f78060..f008a26419 100644
--- a/source/MaterialXCore/Geom.h
+++ b/source/MaterialXCore/Geom.h
@@ -90,16 +90,7 @@ class MX_CORE_API GeomPath
{
return _empty ? EMPTY_STRING : UNIVERSAL_GEOM_NAME;
}
- string geom;
- for (size_t i = 0; i < _vec.size(); i++)
- {
- geom += _vec[i];
- if (i + 1 < _vec.size())
- {
- geom += GEOM_PATH_SEPARATOR;
- }
- }
- return geom;
+ return GEOM_PATH_SEPARATOR + joinStrings(_vec, GEOM_PATH_SEPARATOR);
}
/// Return true if there is any geometry in common between the two paths.
diff --git a/source/MaterialXCore/Util.cpp b/source/MaterialXCore/Util.cpp
index d6001053c5..639b8f343c 100644
--- a/source/MaterialXCore/Util.cpp
+++ b/source/MaterialXCore/Util.cpp
@@ -24,7 +24,7 @@ const std::tuple LIBRARY_VERSION_TUPLE(MATERIALX_MAJOR_VERSION,
bool invalidNameChar(char c)
{
- return !isalnum(c) && c != '_' && c != ':';
+ return !isalnum((unsigned char) c) && c != '_' && c != ':';
}
} // anonymous namespace
@@ -93,10 +93,10 @@ StringVec splitString(const string& str, const string& sep)
string joinStrings(const StringVec& stringVec, const string& sep)
{
- string res;
- for (const string& name : stringVec)
+ string res = stringVec.empty() ? EMPTY_STRING : stringVec[0];
+ for (size_t i = 1; i < stringVec.size(); i++)
{
- res = res.empty() ? name : res + sep + name;
+ res += sep + stringVec[i];
}
return res;
}
diff --git a/source/MaterialXCore/Value.cpp b/source/MaterialXCore/Value.cpp
index 238473d5ad..3e8c1f4462 100644
--- a/source/MaterialXCore/Value.cpp
+++ b/source/MaterialXCore/Value.cpp
@@ -242,7 +242,10 @@ ScopedFloatFormatting::ScopedFloatFormatting(Value::FloatFormat format, int prec
_precision(Value::getFloatPrecision())
{
Value::setFloatFormat(format);
- Value::setFloatPrecision(precision);
+ if (precision >= 0)
+ {
+ Value::setFloatPrecision(precision);
+ }
}
ScopedFloatFormatting::~ScopedFloatFormatting()
diff --git a/source/MaterialXCore/Value.h b/source/MaterialXCore/Value.h
index 8e55a97acf..1bd29b1d2b 100644
--- a/source/MaterialXCore/Value.h
+++ b/source/MaterialXCore/Value.h
@@ -198,7 +198,7 @@ template class MX_CORE_API TypedValue : public Value
class MX_CORE_API ScopedFloatFormatting
{
public:
- explicit ScopedFloatFormatting(Value::FloatFormat format, int precision = 6);
+ explicit ScopedFloatFormatting(Value::FloatFormat format, int precision = -1);
~ScopedFloatFormatting();
private:
diff --git a/source/MaterialXFormat/File.cpp b/source/MaterialXFormat/File.cpp
index bb40ba54d1..62b7ec39a8 100644
--- a/source/MaterialXFormat/File.cpp
+++ b/source/MaterialXFormat/File.cpp
@@ -51,7 +51,7 @@ const string MATERIALX_SEARCH_PATH_ENV_VAR = "MATERIALX_SEARCH_PATH";
inline bool hasWindowsDriveSpecifier(const string& val)
{
- return (val.length() > 1 && std::isalpha(val[0]) && (val[1] == ':'));
+ return (val.length() > 1 && std::isalpha((unsigned char) val[0]) && (val[1] == ':'));
}
//
diff --git a/source/MaterialXFormat/Util.cpp b/source/MaterialXFormat/Util.cpp
index 32feda4d0d..48ded1d6b1 100644
--- a/source/MaterialXFormat/Util.cpp
+++ b/source/MaterialXFormat/Util.cpp
@@ -234,7 +234,7 @@ FileSearchPath getDefaultDataSearchPath()
}
currentPath = currentPath.getParentPath();
}
- return FileSearchPath();
+ return FileSearchPath();
}
MATERIALX_NAMESPACE_END
diff --git a/source/MaterialXFormat/Util.h b/source/MaterialXFormat/Util.h
index 46f55c41ee..c7ef0c6d38 100644
--- a/source/MaterialXFormat/Util.h
+++ b/source/MaterialXFormat/Util.h
@@ -62,7 +62,7 @@ MX_FORMAT_API FileSearchPath getSourceSearchPath(ConstDocumentPtr doc);
/// Return a file search path to the default data library folder.
/// The module path and all parent paths are examined to until either there is
-/// no parent or the library folder is found.
+/// no parent or the library folder is found.
MX_FORMAT_API FileSearchPath getDefaultDataSearchPath();
MATERIALX_NAMESPACE_END
diff --git a/source/MaterialXGenGlsl/GlslShaderGenerator.cpp b/source/MaterialXGenGlsl/GlslShaderGenerator.cpp
index 8396a259e6..1af30fd3fd 100644
--- a/source/MaterialXGenGlsl/GlslShaderGenerator.cpp
+++ b/source/MaterialXGenGlsl/GlslShaderGenerator.cpp
@@ -10,7 +10,6 @@
#include
#include
#include
-#include
#include
#include
#include
@@ -23,9 +22,6 @@
#include
#include
#include
-#include
-#include
-#include
#include
#include
@@ -34,6 +30,8 @@
#include
#include
#include
+#include
+#include
#include
#include
#include
@@ -58,17 +56,17 @@ GlslShaderGenerator::GlslShaderGenerator() :
//
StringVec elementNames;
-
+
//
elementNames = {
//
- "IM_switch_float_" + GlslShaderGenerator::TARGET,
- "IM_switch_color3_" + GlslShaderGenerator::TARGET,
- "IM_switch_color4_" + GlslShaderGenerator::TARGET,
+ "IM_switch_float_" + GlslShaderGenerator::TARGET,
+ "IM_switch_color3_" + GlslShaderGenerator::TARGET,
+ "IM_switch_color4_" + GlslShaderGenerator::TARGET,
"IM_switch_vector2_" + GlslShaderGenerator::TARGET,
"IM_switch_vector3_" + GlslShaderGenerator::TARGET,
"IM_switch_vector4_" + GlslShaderGenerator::TARGET,
-
+
//
"IM_switch_floatI_" + GlslShaderGenerator::TARGET,
"IM_switch_color3I_" + GlslShaderGenerator::TARGET,
@@ -87,7 +85,7 @@ GlslShaderGenerator::GlslShaderGenerator() :
"IM_swizzle_float_vector2_" + GlslShaderGenerator::TARGET,
"IM_swizzle_float_vector3_" + GlslShaderGenerator::TARGET,
"IM_swizzle_float_vector4_" + GlslShaderGenerator::TARGET,
-
+
//
"IM_swizzle_color3_float_" + GlslShaderGenerator::TARGET,
"IM_swizzle_color3_color3_" + GlslShaderGenerator::TARGET,
@@ -95,7 +93,7 @@ GlslShaderGenerator::GlslShaderGenerator() :
"IM_swizzle_color3_vector2_" + GlslShaderGenerator::TARGET,
"IM_swizzle_color3_vector3_" + GlslShaderGenerator::TARGET,
"IM_swizzle_color3_vector4_" + GlslShaderGenerator::TARGET,
-
+
//
"IM_swizzle_color4_float_" + GlslShaderGenerator::TARGET,
"IM_swizzle_color4_color3_" + GlslShaderGenerator::TARGET,
@@ -103,7 +101,7 @@ GlslShaderGenerator::GlslShaderGenerator() :
"IM_swizzle_color4_vector2_" + GlslShaderGenerator::TARGET,
"IM_swizzle_color4_vector3_" + GlslShaderGenerator::TARGET,
"IM_swizzle_color4_vector4_" + GlslShaderGenerator::TARGET,
-
+
//
"IM_swizzle_vector2_float_" + GlslShaderGenerator::TARGET,
"IM_swizzle_vector2_color3_" + GlslShaderGenerator::TARGET,
@@ -111,7 +109,7 @@ GlslShaderGenerator::GlslShaderGenerator() :
"IM_swizzle_vector2_vector2_" + GlslShaderGenerator::TARGET,
"IM_swizzle_vector2_vector3_" + GlslShaderGenerator::TARGET,
"IM_swizzle_vector2_vector4_" + GlslShaderGenerator::TARGET,
-
+
//
"IM_swizzle_vector3_float_" + GlslShaderGenerator::TARGET,
"IM_swizzle_vector3_color3_" + GlslShaderGenerator::TARGET,
@@ -119,7 +117,7 @@ GlslShaderGenerator::GlslShaderGenerator() :
"IM_swizzle_vector3_vector2_" + GlslShaderGenerator::TARGET,
"IM_swizzle_vector3_vector3_" + GlslShaderGenerator::TARGET,
"IM_swizzle_vector3_vector4_" + GlslShaderGenerator::TARGET,
-
+
//
"IM_swizzle_vector4_float_" + GlslShaderGenerator::TARGET,
"IM_swizzle_vector4_color3_" + GlslShaderGenerator::TARGET,
@@ -174,8 +172,8 @@ GlslShaderGenerator::GlslShaderGenerator() :
//
registerImplementation("IM_bitangent_vector3_" + GlslShaderGenerator::TARGET, BitangentNodeGlsl::create);
//
- registerImplementation("IM_texcoord_vector2_" + GlslShaderGenerator::TARGET, TexCoordNodeGlsl::create);
- registerImplementation("IM_texcoord_vector3_" + GlslShaderGenerator::TARGET, TexCoordNodeGlsl::create);
+ registerImplementation("IM_texcoord_vector2_" + GlslShaderGenerator::TARGET, HwTexCoordNode::create);
+ registerImplementation("IM_texcoord_vector3_" + GlslShaderGenerator::TARGET, HwTexCoordNode::create);
//
registerImplementation("IM_geomcolor_float_" + GlslShaderGenerator::TARGET, GeomColorNodeGlsl::create);
registerImplementation("IM_geomcolor_color3_" + GlslShaderGenerator::TARGET, GeomColorNodeGlsl::create);
@@ -228,13 +226,13 @@ GlslShaderGenerator::GlslShaderGenerator() :
registerImplementation(elementNames, BlurNodeGlsl::create);
//
elementNames = {
@@ -279,9 +277,7 @@ ShaderPtr GlslShaderGenerator::generate(const string& name, ElementPtr element,
{
ShaderPtr shader = createShader(name, element, context);
- // Turn on fixed float formatting to make sure float values are
- // emitted with a decimal point and not as integers, and to avoid
- // any scientific notation which isn't supported by all OpenGL targets.
+ // Request fixed floating-point notation for consistency across targets.
ScopedFloatFormatting fmt(Value::FloatFormatFixed);
// Make sure we initialize/reset the binding context before generation.
@@ -915,11 +911,6 @@ ShaderNodeImplPtr GlslShaderGenerator::getImplementation(const NodeDef& nodedef,
}
const string GlslImplementation::SPACE = "space";
-const string GlslImplementation::TO_SPACE = "tospace";
-const string GlslImplementation::FROM_SPACE = "fromspace";
-const string GlslImplementation::WORLD = "world";
-const string GlslImplementation::OBJECT = "object";
-const string GlslImplementation::MODEL = "model";
const string GlslImplementation::INDEX = "index";
const string GlslImplementation::GEOMPROP = "geomprop";
diff --git a/source/MaterialXGenGlsl/GlslShaderGenerator.h b/source/MaterialXGenGlsl/GlslShaderGenerator.h
index 1df2ace543..acc8b0d6ee 100644
--- a/source/MaterialXGenGlsl/GlslShaderGenerator.h
+++ b/source/MaterialXGenGlsl/GlslShaderGenerator.h
@@ -45,7 +45,7 @@ class MX_GENGLSL_API GlslShaderGenerator : public HwShaderGenerator
ShaderNodeImplPtr getImplementation(const NodeDef& nodedef, GenContext& context) const override;
/// Determine the prefix of vertex data variables.
- virtual string getVertexDataPrefix(const VariableBlock& vertexData) const;
+ string getVertexDataPrefix(const VariableBlock& vertexData) const override;
public:
/// Unique identifier for this generator target
@@ -110,11 +110,6 @@ class MX_GENGLSL_API GlslImplementation : public ShaderNodeImpl
/// Internal string constants
static const string SPACE;
- static const string TO_SPACE;
- static const string FROM_SPACE;
- static const string WORLD;
- static const string OBJECT;
- static const string MODEL;
static const string INDEX;
static const string GEOMPROP;
};
diff --git a/source/MaterialXGenGlsl/Nodes/HeightToNormalNodeGlsl.cpp b/source/MaterialXGenGlsl/Nodes/HeightToNormalNodeGlsl.cpp
index 157cd5be04..e98a4ab75c 100644
--- a/source/MaterialXGenGlsl/Nodes/HeightToNormalNodeGlsl.cpp
+++ b/source/MaterialXGenGlsl/Nodes/HeightToNormalNodeGlsl.cpp
@@ -33,6 +33,11 @@ ShaderNodeImplPtr HeightToNormalNodeGlsl::create()
return std::make_shared();
}
+void HeightToNormalNodeGlsl::createVariables(const ShaderNode&, GenContext&, Shader&) const
+{
+ // Default filter kernels from ConvolutionNode are not used by this derived class.
+}
+
void HeightToNormalNodeGlsl::computeSampleOffsetStrings(const string& sampleSizeName, const string& offsetTypeString,
unsigned int, StringVec& offsetStrings) const
{
diff --git a/source/MaterialXGenGlsl/Nodes/HeightToNormalNodeGlsl.h b/source/MaterialXGenGlsl/Nodes/HeightToNormalNodeGlsl.h
index 638623ea43..fc6e6b421f 100644
--- a/source/MaterialXGenGlsl/Nodes/HeightToNormalNodeGlsl.h
+++ b/source/MaterialXGenGlsl/Nodes/HeightToNormalNodeGlsl.h
@@ -18,6 +18,8 @@ class MX_GENGLSL_API HeightToNormalNodeGlsl : public ConvolutionNode
public:
static ShaderNodeImplPtr create();
+ void createVariables(const ShaderNode&, GenContext&, Shader& shader) const override;
+
void emitFunctionDefinition(const ShaderNode& node, GenContext& context, ShaderStage& stage) const override;
void emitFunctionCall(const ShaderNode& node, GenContext& context, ShaderStage& stage) const override;
diff --git a/source/MaterialXGenGlsl/Nodes/TexCoordNodeGlsl.cpp b/source/MaterialXGenGlsl/Nodes/TexCoordNodeGlsl.cpp
deleted file mode 100644
index 846c77f5b7..0000000000
--- a/source/MaterialXGenGlsl/Nodes/TexCoordNodeGlsl.cpp
+++ /dev/null
@@ -1,62 +0,0 @@
-//
-// Copyright Contributors to the MaterialX Project
-// SPDX-License-Identifier: Apache-2.0
-//
-
-#include
-
-#include
-
-MATERIALX_NAMESPACE_BEGIN
-
-ShaderNodeImplPtr TexCoordNodeGlsl::create()
-{
- return std::make_shared();
-}
-
-void TexCoordNodeGlsl::createVariables(const ShaderNode& node, GenContext&, Shader& shader) const
-{
- const ShaderOutput* output = node.getOutput();
- const ShaderInput* indexInput = node.getInput(INDEX);
- const string index = indexInput ? indexInput->getValue()->getValueString() : "0";
-
- ShaderStage& vs = shader.getStage(Stage::VERTEX);
- ShaderStage& ps = shader.getStage(Stage::PIXEL);
-
- addStageInput(HW::VERTEX_INPUTS, output->getType(), HW::T_IN_TEXCOORD + "_" + index, vs);
- addStageConnector(HW::VERTEX_DATA, output->getType(), HW::T_TEXCOORD + "_" + index, vs, ps);
-}
-
-void TexCoordNodeGlsl::emitFunctionCall(const ShaderNode& node, GenContext& context, ShaderStage& stage) const
-{
- const GlslShaderGenerator& shadergen = static_cast(context.getShaderGenerator());
-
- const ShaderInput* indexInput = node.getInput(INDEX);
- const string index = indexInput ? indexInput->getValue()->getValueString() : "0";
- const string variable = HW::T_TEXCOORD + "_" + index;
-
- DEFINE_SHADER_STAGE(stage, Stage::VERTEX)
- {
- VariableBlock& vertexData = stage.getOutputBlock(HW::VERTEX_DATA);
- const string prefix = shadergen.getVertexDataPrefix(vertexData);
- ShaderPort* texcoord = vertexData[variable];
- if (!texcoord->isEmitted())
- {
- shadergen.emitLine(prefix + texcoord->getVariable() + " = " + HW::T_IN_TEXCOORD + "_" + index, stage);
- texcoord->setEmitted();
- }
- }
-
- DEFINE_SHADER_STAGE(stage, Stage::PIXEL)
- {
- VariableBlock& vertexData = stage.getInputBlock(HW::VERTEX_DATA);
- const string prefix = shadergen.getVertexDataPrefix(vertexData);
- ShaderPort* texcoord = vertexData[variable];
- shadergen.emitLineBegin(stage);
- shadergen.emitOutput(node.getOutput(), true, false, context, stage);
- shadergen.emitString(" = " + prefix + texcoord->getVariable(), stage);
- shadergen.emitLineEnd(stage);
- }
-}
-
-MATERIALX_NAMESPACE_END
diff --git a/source/MaterialXGenGlsl/Nodes/TransformNormalNodeGlsl.cpp b/source/MaterialXGenGlsl/Nodes/TransformNormalNodeGlsl.cpp
deleted file mode 100644
index 0800fb4bf3..0000000000
--- a/source/MaterialXGenGlsl/Nodes/TransformNormalNodeGlsl.cpp
+++ /dev/null
@@ -1,43 +0,0 @@
-//
-// Copyright Contributors to the MaterialX Project
-// SPDX-License-Identifier: Apache-2.0
-//
-
-#include
-
-MATERIALX_NAMESPACE_BEGIN
-
-ShaderNodeImplPtr TransformNormalNodeGlsl::create()
-{
- return std::make_shared();
-}
-
-void TransformNormalNodeGlsl::emitFunctionCall(const ShaderNode& node, GenContext& context, ShaderStage& stage) const
-{
- TransformVectorNodeGlsl::emitFunctionCall(node, context, stage);
-
- DEFINE_SHADER_STAGE(stage, Stage::PIXEL)
- {
- const ShaderGenerator& shadergen = context.getShaderGenerator();
- const ShaderOutput* output = node.getOutput();
- shadergen.emitLineBegin(stage);
- shadergen.emitOutput(output, false, false, context, stage);
- shadergen.emitString(" = normalize(" + output->getVariable() + ")", stage);
- shadergen.emitLineEnd(stage);
- }
-}
-
-const string& TransformNormalNodeGlsl::getMatrix(const string& fromSpace, const string& toSpace) const
-{
- if ((fromSpace == MODEL || fromSpace == OBJECT) && toSpace == WORLD)
- {
- return HW::T_WORLD_INVERSE_TRANSPOSE_MATRIX;
- }
- else if (fromSpace == WORLD && (toSpace == MODEL || toSpace == OBJECT))
- {
- return HW::T_WORLD_TRANSPOSE_MATRIX;
- }
- return EMPTY_STRING;
-}
-
-MATERIALX_NAMESPACE_END
diff --git a/source/MaterialXGenGlsl/Nodes/TransformNormalNodeGlsl.h b/source/MaterialXGenGlsl/Nodes/TransformNormalNodeGlsl.h
deleted file mode 100644
index f08ec564d9..0000000000
--- a/source/MaterialXGenGlsl/Nodes/TransformNormalNodeGlsl.h
+++ /dev/null
@@ -1,27 +0,0 @@
-//
-// Copyright Contributors to the MaterialX Project
-// SPDX-License-Identifier: Apache-2.0
-//
-
-#ifndef MATERIALX_TRANSFORMNORMALNODEGLSL_H
-#define MATERIALX_TRANSFORMNORMALNODEGLSL_H
-
-#include
-
-MATERIALX_NAMESPACE_BEGIN
-
-/// TransformNormal node implementation for GLSL
-class MX_GENGLSL_API TransformNormalNodeGlsl : public TransformVectorNodeGlsl
-{
- public:
- static ShaderNodeImplPtr create();
-
- protected:
- void emitFunctionCall(const ShaderNode& node, GenContext& context, ShaderStage& stage) const override;
-
- const string& getMatrix(const string& fromSpace, const string& toSpace) const override;
-};
-
-MATERIALX_NAMESPACE_END
-
-#endif
diff --git a/source/MaterialXGenGlsl/Nodes/TransformPointNodeGlsl.cpp b/source/MaterialXGenGlsl/Nodes/TransformPointNodeGlsl.cpp
deleted file mode 100644
index 1570939bfe..0000000000
--- a/source/MaterialXGenGlsl/Nodes/TransformPointNodeGlsl.cpp
+++ /dev/null
@@ -1,23 +0,0 @@
-//
-// Copyright Contributors to the MaterialX Project
-// SPDX-License-Identifier: Apache-2.0
-//
-
-#include
-
-#include
-
-MATERIALX_NAMESPACE_BEGIN
-
-ShaderNodeImplPtr TransformPointNodeGlsl::create()
-{
- return std::make_shared();
-}
-
-string TransformPointNodeGlsl::getHomogeneousCoordinate(const ShaderInput* in, GenContext& context) const
-{
- const ShaderGenerator& shadergen = context.getShaderGenerator();
- return "vec4(" + shadergen.getUpstreamResult(in, context) + ", 1.0)";
-}
-
-MATERIALX_NAMESPACE_END
diff --git a/source/MaterialXGenGlsl/Nodes/TransformPointNodeGlsl.h b/source/MaterialXGenGlsl/Nodes/TransformPointNodeGlsl.h
deleted file mode 100644
index eb366d8190..0000000000
--- a/source/MaterialXGenGlsl/Nodes/TransformPointNodeGlsl.h
+++ /dev/null
@@ -1,25 +0,0 @@
-//
-// Copyright Contributors to the MaterialX Project
-// SPDX-License-Identifier: Apache-2.0
-//
-
-#ifndef MATERIALX_TRANSFORMPOINTNODEGLSL_H
-#define MATERIALX_TRANSFORMPOINTNODEGLSL_H
-
-#include
-
-MATERIALX_NAMESPACE_BEGIN
-
-/// TransformPoint node implementation for GLSL
-class MX_GENGLSL_API TransformPointNodeGlsl : public TransformVectorNodeGlsl
-{
- public:
- static ShaderNodeImplPtr create();
-
- protected:
- virtual string getHomogeneousCoordinate(const ShaderInput* in, GenContext& context) const override;
-};
-
-MATERIALX_NAMESPACE_END
-
-#endif
diff --git a/source/MaterialXGenGlsl/Nodes/TransformVectorNodeGlsl.cpp b/source/MaterialXGenGlsl/Nodes/TransformVectorNodeGlsl.cpp
deleted file mode 100644
index df1e921497..0000000000
--- a/source/MaterialXGenGlsl/Nodes/TransformVectorNodeGlsl.cpp
+++ /dev/null
@@ -1,84 +0,0 @@
-//
-// Copyright Contributors to the MaterialX Project
-// SPDX-License-Identifier: Apache-2.0
-//
-
-#include
-
-#include
-
-MATERIALX_NAMESPACE_BEGIN
-
-ShaderNodeImplPtr TransformVectorNodeGlsl::create()
-{
- return std::make_shared();
-}
-
-void TransformVectorNodeGlsl::createVariables(const ShaderNode& node, GenContext&, Shader& shader) const
-{
- const ShaderInput* toSpaceInput = node.getInput(TO_SPACE);
- string toSpace = toSpaceInput ? toSpaceInput->getValue()->getValueString() : EMPTY_STRING;
-
- const ShaderInput* fromSpaceInput = node.getInput(FROM_SPACE);
- string fromSpace = fromSpaceInput ? fromSpaceInput->getValue()->getValueString() : EMPTY_STRING;
-
- const string& matrix = getMatrix(fromSpace, toSpace);
- if (!matrix.empty())
- {
- ShaderStage& ps = shader.getStage(Stage::PIXEL);
- addStageUniform(HW::PRIVATE_UNIFORMS, Type::MATRIX44, matrix, ps);
- }
-}
-
-void TransformVectorNodeGlsl::emitFunctionCall(const ShaderNode& node, GenContext& context, ShaderStage& stage) const
-{
- DEFINE_SHADER_STAGE(stage, Stage::PIXEL)
- {
- const ShaderGenerator& shadergen = context.getShaderGenerator();
-
- const ShaderInput* inInput = node.getInput("in");
- if (inInput->getType() != Type::VECTOR3 && inInput->getType() != Type::VECTOR4)
- {
- throw ExceptionShaderGenError("Transform node must have 'in' type of vector3 or vector4.");
- }
-
- const ShaderInput* toSpaceInput = node.getInput(TO_SPACE);
- string toSpace = toSpaceInput ? toSpaceInput->getValue()->getValueString() : EMPTY_STRING;
-
- const ShaderInput* fromSpaceInput = node.getInput(FROM_SPACE);
- string fromSpace = fromSpaceInput ? fromSpaceInput->getValue()->getValueString() : EMPTY_STRING;
-
- shadergen.emitLineBegin(stage);
- shadergen.emitOutput(node.getOutput(), true, false, context, stage);
- shadergen.emitString(" = (", stage);
- const string& matrix = getMatrix(fromSpace, toSpace);
- if (!matrix.empty())
- {
- shadergen.emitString(matrix + " * ", stage);
- }
- shadergen.emitString(getHomogeneousCoordinate(inInput, context), stage);
- shadergen.emitString(").xyz", stage);
- shadergen.emitLineEnd(stage);
- }
-}
-
-const string& TransformVectorNodeGlsl::getMatrix(const string& fromSpace, const string& toSpace) const
-{
- if ((fromSpace == MODEL || fromSpace == OBJECT) && toSpace == WORLD)
- {
- return HW::T_WORLD_MATRIX;
- }
- else if (fromSpace == WORLD && (toSpace == MODEL || toSpace == OBJECT))
- {
- return HW::T_WORLD_INVERSE_MATRIX;
- }
- return EMPTY_STRING;
-}
-
-string TransformVectorNodeGlsl::getHomogeneousCoordinate(const ShaderInput* in, GenContext& context) const
-{
- const ShaderGenerator& shadergen = context.getShaderGenerator();
- return "vec4(" + shadergen.getUpstreamResult(in, context) + ", 0.0)";
-}
-
-MATERIALX_NAMESPACE_END
diff --git a/source/MaterialXGenGlsl/Nodes/TransformVectorNodeGlsl.h b/source/MaterialXGenGlsl/Nodes/TransformVectorNodeGlsl.h
deleted file mode 100644
index e9861650b3..0000000000
--- a/source/MaterialXGenGlsl/Nodes/TransformVectorNodeGlsl.h
+++ /dev/null
@@ -1,30 +0,0 @@
-//
-// Copyright Contributors to the MaterialX Project
-// SPDX-License-Identifier: Apache-2.0
-//
-
-#ifndef MATERIALX_TRANSFORMVECTORNODEGLSL_H
-#define MATERIALX_TRANSFORMVECTORNODEGLSL_H
-
-#include
-
-MATERIALX_NAMESPACE_BEGIN
-
-/// TransformVector node implementation for GLSL
-class MX_GENGLSL_API TransformVectorNodeGlsl : public GlslImplementation
-{
- public:
- static ShaderNodeImplPtr create();
-
- void createVariables(const ShaderNode& node, GenContext& context, Shader& shader) const override;
-
- void emitFunctionCall(const ShaderNode& node, GenContext& context, ShaderStage& stage) const override;
-
- protected:
- virtual const string& getMatrix(const string& fromSpace, const string& toSpace) const;
- virtual string getHomogeneousCoordinate(const ShaderInput* in, GenContext& context) const;
-};
-
-MATERIALX_NAMESPACE_END
-
-#endif
diff --git a/source/MaterialXGenMdl/MdlShaderGenerator.cpp b/source/MaterialXGenMdl/MdlShaderGenerator.cpp
index dddf1f2f13..af75a2cef4 100644
--- a/source/MaterialXGenMdl/MdlShaderGenerator.cpp
+++ b/source/MaterialXGenMdl/MdlShaderGenerator.cpp
@@ -17,6 +17,7 @@
#include
#include
#include
+#include
#include
#include
@@ -187,6 +188,14 @@ MdlShaderGenerator::MdlShaderGenerator() :
//
registerImplementation("IM_sheen_bsdf_" + MdlShaderGenerator::TARGET, LayerableNodeMdl::create);
+
+ //
+ registerImplementation("IM_image_float_" + MdlShaderGenerator::TARGET, ImageNodeMdl::create);
+ registerImplementation("IM_image_color3_" + MdlShaderGenerator::TARGET, ImageNodeMdl::create);
+ registerImplementation("IM_image_color4_" + MdlShaderGenerator::TARGET, ImageNodeMdl::create);
+ registerImplementation("IM_image_vector2_" + MdlShaderGenerator::TARGET, ImageNodeMdl::create);
+ registerImplementation("IM_image_vector3_" + MdlShaderGenerator::TARGET, ImageNodeMdl::create);
+ registerImplementation("IM_image_vector4_" + MdlShaderGenerator::TARGET, ImageNodeMdl::create);
}
ShaderPtr MdlShaderGenerator::generate(const string& name, ElementPtr element, GenContext& context) const
@@ -198,6 +207,9 @@ ShaderPtr MdlShaderGenerator::generate(const string& name, ElementPtr element, G
ShaderPtr shader = createShader(name, element, context);
+ // Request fixed floating-point notation for consistency across targets.
+ ScopedFloatFormatting fmt(Value::FloatFormatFixed);
+
ShaderGraph& graph = shader->getGraph();
ShaderStage& stage = shader->getStage(Stage::PIXEL);
@@ -279,9 +291,9 @@ ShaderPtr MdlShaderGenerator::generate(const string& name, ElementPtr element, G
{
emitLine("float3 displacement__ = " + result + ".geometry.displacement", stage);
emitLine("color finalOutput__ = mk_color3("
- "r: math::dot(displacement__, state::texture_tangent_u(0)),"
- "g: math::dot(displacement__, state::texture_tangent_v(0)),"
- "b: math::dot(displacement__, state::normal()))", stage);
+ "r: math::dot(displacement__, state::texture_tangent_u(0)),"
+ "g: math::dot(displacement__, state::texture_tangent_v(0)),"
+ "b: math::dot(displacement__, state::normal()))", stage);
}
else
{
diff --git a/source/MaterialXGenMdl/MdlSyntax.cpp b/source/MaterialXGenMdl/MdlSyntax.cpp
index 9d5483bcca..7560297ce4 100644
--- a/source/MaterialXGenMdl/MdlSyntax.cpp
+++ b/source/MaterialXGenMdl/MdlSyntax.cpp
@@ -48,7 +48,7 @@ class MdlFilenameTypeSyntax : public ScalarTypeSyntax
// assuming it ends with a slash ...
if (outputValue.back() == '/')
{
- return getDefaultValue(true);
+ return getDefaultValue(true);
}
// ... or the last segment does not have an extension suffix
size_t idx_s = outputValue.find_last_of('/');
diff --git a/source/MaterialXGenMdl/Nodes/ClosureCompoundNodeMdl.cpp b/source/MaterialXGenMdl/Nodes/ClosureCompoundNodeMdl.cpp
index e175696d55..0a2004cd71 100644
--- a/source/MaterialXGenMdl/Nodes/ClosureCompoundNodeMdl.cpp
+++ b/source/MaterialXGenMdl/Nodes/ClosureCompoundNodeMdl.cpp
@@ -41,7 +41,7 @@ void ClosureCompoundNodeMdl::emitFunctionDefinition(const ShaderNode& node, GenC
{
if (!outputSocket->getConnection())
continue;
-
+
const ShaderNode* upstream = outputSocket->getConnection()->getNode();
const bool isMaterialExpr = (upstream->hasClassification(ShaderNode::Classification::CLOSURE) ||
upstream->hasClassification(ShaderNode::Classification::SHADER));
diff --git a/source/MaterialXGenMdl/Nodes/ClosureLayerNodeMdl.cpp b/source/MaterialXGenMdl/Nodes/ClosureLayerNodeMdl.cpp
index fd27d5e547..bff1351142 100644
--- a/source/MaterialXGenMdl/Nodes/ClosureLayerNodeMdl.cpp
+++ b/source/MaterialXGenMdl/Nodes/ClosureLayerNodeMdl.cpp
@@ -368,12 +368,12 @@ const string& MixBsdfNodeMdl::getOperatorName(size_t index) const
{
switch (index)
{
- case 0:
- return StringConstantsMdl::FG;
- case 1:
- return StringConstantsMdl::BG;
- default:
- return StringConstantsMdl::EMPTY;
+ case 0:
+ return StringConstantsMdl::FG;
+ case 1:
+ return StringConstantsMdl::BG;
+ default:
+ return StringConstantsMdl::EMPTY;
}
}
@@ -386,12 +386,12 @@ const string& AddOrMultiplyBsdfNodeMdl::getOperatorName(size_t index) const
{
switch (index)
{
- case 0:
- return StringConstantsMdl::IN1;
- case 1:
- return StringConstantsMdl::IN2;
- default:
- return StringConstantsMdl::EMPTY;
+ case 0:
+ return StringConstantsMdl::IN1;
+ case 1:
+ return StringConstantsMdl::IN2;
+ default:
+ return StringConstantsMdl::EMPTY;
}
}
diff --git a/source/MaterialXGenMdl/Nodes/ClosureLayerNodeMdl.h b/source/MaterialXGenMdl/Nodes/ClosureLayerNodeMdl.h
index 75ea46046c..95c51198f8 100644
--- a/source/MaterialXGenMdl/Nodes/ClosureLayerNodeMdl.h
+++ b/source/MaterialXGenMdl/Nodes/ClosureLayerNodeMdl.h
@@ -21,18 +21,18 @@ class MX_GENMDL_API StringConstantsMdl
public:
/// String constants
- static const string TOP; ///< layer parameter name of the top component
+ static const string TOP; ///< layer parameter name of the top component
static const string BASE; ///< layer parameter name of the base component
- static const string FG; ///< parameter of the mix node
- static const string BG; ///< parameter of the mix node
- static const string IN1; ///< parameter of the add and multiply nodes
- static const string IN2; ///< parameter of the add and multiply nodes
+ static const string FG; ///< parameter of the mix node
+ static const string BG; ///< parameter of the mix node
+ static const string IN1; ///< parameter of the add and multiply nodes
+ static const string IN2; ///< parameter of the add and multiply nodes
static const string THICKNESS; ///< thickness parameter name of the thin_film_bsdf
- static const string IOR; ///< ior parameter name of the thin_film_bsdf
+ static const string IOR; ///< ior parameter name of the thin_film_bsdf
static const string THIN_FILM_THICKNESS; ///< helper parameter name for transporting thickness
- static const string THIN_FILM_IOR; ///< helper parameter name for transporting ior
+ static const string THIN_FILM_IOR; ///< helper parameter name for transporting ior
static const string EMPTY; ///< the empty string ""
};
@@ -41,7 +41,7 @@ class MX_GENMDL_API StringConstantsMdl
/// thin_film_bsdf through layers and mixers, etc., to the elemental bsdfs that support thin film.
/// Because thin-film can not be layered on any BSDF in MDL, we try to push down the parameters to
/// the nodes that support thin-film.
-template class CarryThinFilmParameters : public TBase
+template class CarryThinFilmParameters : public TBase
{
public:
/// Add the thin film inputs for transporting the parameter.
diff --git a/source/MaterialXGenMdl/Nodes/ImageNodeMdl.cpp b/source/MaterialXGenMdl/Nodes/ImageNodeMdl.cpp
new file mode 100644
index 0000000000..502711fe01
--- /dev/null
+++ b/source/MaterialXGenMdl/Nodes/ImageNodeMdl.cpp
@@ -0,0 +1,50 @@
+//
+// Copyright Contributors to the MaterialX Project
+// SPDX-License-Identifier: Apache-2.0
+//
+
+#include
+#include
+#include
+#include
+
+MATERIALX_NAMESPACE_BEGIN
+
+const string ImageNodeMdl::FLIP_V = "flip_v";
+
+ShaderNodeImplPtr ImageNodeMdl::create()
+{
+ return std::make_shared();
+}
+
+void ImageNodeMdl::addInputs(ShaderNode& node, GenContext& context) const
+{
+ BASE::addInputs(node, context);
+ node.addInput(ImageNodeMdl::FLIP_V, Type::BOOLEAN)->setUniform();
+}
+
+bool ImageNodeMdl::isEditable(const ShaderInput& input) const
+{
+ if (input.getName() == ImageNodeMdl::FLIP_V)
+ {
+ return false;
+ }
+ return BASE::isEditable(input);
+}
+
+void ImageNodeMdl::emitFunctionCall(const ShaderNode& _node, GenContext& context, ShaderStage& stage) const
+{
+ DEFINE_SHADER_STAGE(stage, Stage::PIXEL)
+ {
+ ShaderNode& node = const_cast(_node);
+ ShaderInput* flipUInput = node.getInput(ImageNodeMdl::FLIP_V);
+ ValuePtr value = TypedValue::createValue(context.getOptions().fileTextureVerticalFlip);
+ if (flipUInput)
+ {
+ flipUInput->setValue(value);
+ }
+ BASE::emitFunctionCall(_node, context, stage);
+ }
+}
+
+MATERIALX_NAMESPACE_END
diff --git a/source/MaterialXGenMdl/Nodes/ImageNodeMdl.h b/source/MaterialXGenMdl/Nodes/ImageNodeMdl.h
new file mode 100644
index 0000000000..fe88b2ce09
--- /dev/null
+++ b/source/MaterialXGenMdl/Nodes/ImageNodeMdl.h
@@ -0,0 +1,34 @@
+//
+// Copyright Contributors to the MaterialX Project
+// SPDX-License-Identifier: Apache-2.0
+//
+
+#ifndef MATERIALX_IMAGENODEMDL_H
+#define MATERIALX_IMAGENODEMDL_H
+
+#include
+
+#include "SourceCodeNodeMdl.h"
+
+MATERIALX_NAMESPACE_BEGIN
+
+/// Image node implementation for MDL
+class MX_GENMDL_API ImageNodeMdl : public SourceCodeNodeMdl
+{
+ using BASE = SourceCodeNodeMdl;
+
+ public:
+ static const string FLIP_V; ///< the empty string ""
+
+ static ShaderNodeImplPtr create();
+
+ void addInputs(ShaderNode& node, GenContext& context) const override;
+
+ bool isEditable(const ShaderInput& input) const override;
+
+ void emitFunctionCall(const ShaderNode& node, GenContext& context, ShaderStage& stage) const override;
+};
+
+MATERIALX_NAMESPACE_END
+
+#endif
diff --git a/source/MaterialXGenMdl/mdl/materialx/hsv.mdl b/source/MaterialXGenMdl/mdl/materialx/hsv.mdl
index 888d4ada86..9adb1505cb 100644
--- a/source/MaterialXGenMdl/mdl/materialx/hsv.mdl
+++ b/source/MaterialXGenMdl/mdl/materialx/hsv.mdl
@@ -25,16 +25,16 @@ import ::limits::*;
export float3 mx_hsvtorgb(float3 hsv) {
// from "Color Imaging, Fundamentals and Applications", Reinhard et al., p. 442
- // A hue of 1.0 is questionably valid, and needs to be interpreted as 0.0f
- float h_prime = (hsv.x < 1.0f) ? hsv.x * 6.0f : 0.0f; // H * 360.0/60.0
- float h_floor = math::floor(h_prime);
- float f = h_prime - h_floor;
+ float h = 6.0 * (hsv.x - math::floor(hsv.x));
+ int hi = int(h); // truncate
+ float f = h - float(hi);
+
float zy = hsv.z*hsv.y;
float a = hsv.z - zy;
float b = hsv.z - zy*f;
float c = a + zy*f;
- switch(int(h_floor)) {
+ switch(hi) {
default:
// hue out of [0,1] range...
// fall through...
diff --git a/source/MaterialXGenMdl/mdl/materialx/stdlib.mdl b/source/MaterialXGenMdl/mdl/materialx/stdlib.mdl
index bce4a44ea5..4ba4f0875a 100644
--- a/source/MaterialXGenMdl/mdl/materialx/stdlib.mdl
+++ b/source/MaterialXGenMdl/mdl/materialx/stdlib.mdl
@@ -139,6 +139,11 @@ export float mx_image_float(
anno::description("Enumeration {constant,clamp,periodic,mirror}."),
anno::display_name("Frame End Action"),
anno::unused()
+ ]],
+ uniform bool mxp_flip_v = false
+ [[
+ anno::usage("for applying the 'fileTextureVerticalFlip' shader generator option."),
+ anno::hidden()
]]
)
[[
@@ -153,7 +158,9 @@ export float mx_image_float(
return mxp_default;
float returnValue = ::tex::lookup_float(tex: mxp_file,
- coord: mxp_texcoord,
+ coord: mxp_flip_v
+ ? float2(mxp_texcoord.x, 1.0f - mxp_texcoord.y)
+ : mxp_texcoord,
wrap_u: map_addressmode(mxp_uaddressmode),
wrap_v: map_addressmode(mxp_vaddressmode));
return returnValue;
@@ -207,6 +214,11 @@ export color mx_image_color3(
anno::description("Enumeration {constant,clamp,periodic,mirror}."),
anno::display_name("Frame End Action"),
anno::unused()
+ ]],
+ uniform bool mxp_flip_v = false
+ [[
+ anno::usage("for applying the 'fileTextureVerticalFlip' shader generator option."),
+ anno::hidden()
]]
)
[[
@@ -221,7 +233,9 @@ export color mx_image_color3(
return mxp_default;
color returnValue = ::tex::lookup_color(tex: mxp_file,
- coord: mxp_texcoord,
+ coord: mxp_flip_v
+ ? float2(mxp_texcoord.x, 1.0f - mxp_texcoord.y)
+ : mxp_texcoord,
wrap_u: map_addressmode(mxp_uaddressmode),
wrap_v: map_addressmode(mxp_vaddressmode));
return returnValue;
@@ -275,6 +289,11 @@ export color4 mx_image_color4(
anno::description("Enumeration {constant,clamp,periodic,mirror}."),
anno::display_name("Frame End Action"),
anno::unused()
+ ]],
+ uniform bool mxp_flip_v = false
+ [[
+ anno::usage("for applying the 'fileTextureVerticalFlip' shader generator option."),
+ anno::hidden()
]]
)
[[
@@ -289,7 +308,9 @@ export color4 mx_image_color4(
return mxp_default;
color4 returnValue = mk_color4( ::tex::lookup_float4(tex: mxp_file,
- coord: mxp_texcoord,
+ coord: mxp_flip_v
+ ? float2(mxp_texcoord.x, 1.0f - mxp_texcoord.y)
+ : mxp_texcoord,
wrap_u: map_addressmode(mxp_uaddressmode),
wrap_v: map_addressmode(mxp_vaddressmode)));
return returnValue;
@@ -343,6 +364,11 @@ export float2 mx_image_vector2(
anno::description("Enumeration {constant,clamp,periodic,mirror}."),
anno::display_name("Frame End Action"),
anno::unused()
+ ]],
+ uniform bool mxp_flip_v = false
+ [[
+ anno::usage("for applying the 'fileTextureVerticalFlip' shader generator option."),
+ anno::hidden()
]]
)
[[
@@ -357,7 +383,9 @@ export float2 mx_image_vector2(
return mxp_default;
float2 returnValue = ::tex::lookup_float2(tex: mxp_file,
- coord: mxp_texcoord,
+ coord: mxp_flip_v
+ ? float2(mxp_texcoord.x, 1.0f - mxp_texcoord.y)
+ : mxp_texcoord,
wrap_u: map_addressmode(mxp_uaddressmode),
wrap_v: map_addressmode(mxp_vaddressmode));
return returnValue;
@@ -411,6 +439,11 @@ export float3 mx_image_vector3(
anno::description("Enumeration {constant,clamp,periodic,mirror}."),
anno::display_name("Frame End Action"),
anno::unused()
+ ]],
+ uniform bool mxp_flip_v = false
+ [[
+ anno::usage("for applying the 'fileTextureVerticalFlip' shader generator option."),
+ anno::hidden()
]]
)
[[
@@ -425,7 +458,9 @@ export float3 mx_image_vector3(
return mxp_default;
float3 returnValue = ::tex::lookup_float3(tex: mxp_file,
- coord: mxp_texcoord,
+ coord: mxp_flip_v
+ ? float2(mxp_texcoord.x, 1.0f - mxp_texcoord.y)
+ : mxp_texcoord,
wrap_u: map_addressmode(mxp_uaddressmode),
wrap_v: map_addressmode(mxp_vaddressmode));
return returnValue;
@@ -479,6 +514,11 @@ export float4 mx_image_vector4(
anno::description("Enumeration {constant,clamp,periodic,mirror}."),
anno::display_name("Frame End Action"),
anno::unused()
+ ]],
+ uniform bool mxp_flip_v = false
+ [[
+ anno::usage("for applying the 'fileTextureVerticalFlip' shader generator option."),
+ anno::hidden()
]]
)
[[
@@ -493,7 +533,9 @@ export float4 mx_image_vector4(
return mxp_default;
float4 returnValue = ::tex::lookup_float4(tex: mxp_file,
- coord: mxp_texcoord,
+ coord: mxp_flip_v
+ ? float2(mxp_texcoord.x, 1.0f - mxp_texcoord.y)
+ : mxp_texcoord,
wrap_u: map_addressmode(mxp_uaddressmode),
wrap_v: map_addressmode(mxp_vaddressmode));
return returnValue;
@@ -2777,66 +2819,6 @@ export color4 mx_screen_color4(
return color4(rgb,a);
}
-float mx_overlay(float mxp_fg, float mxp_bg)
-{
- return (mxp_fg < 0.5) ? (2 * mxp_fg * mxp_bg) : (1 - (1 - mxp_fg) * (1 - mxp_bg));
-}
-float2 mx_overlay(float2 mxp_fg, float2 mxp_bg) [[ anno::unused() ]]
-{
- return float2(
- mx_overlay(mxp_fg.x, mxp_bg.x),
- mx_overlay(mxp_fg.y, mxp_bg.y)
- );
-}
-color mx_overlay(color mxp_fg, color mxp_bg)
-{
- float3 fg(mxp_fg);
- float3 bg(mxp_bg);
- return color(
- mx_overlay(fg.x, bg.x),
- mx_overlay(fg.y, bg.y),
- mx_overlay(fg.z, bg.z)
- );
-}
-
-export float mx_overlay_float(
- float mxp_fg = 0.0,
- float mxp_bg = 0.0,
- float mxp_mix = 1.0
-)
- [[
- anno::description("Node Group: compositing")
- ]]
-{
- return mxp_mix * mx_overlay(mxp_fg, mxp_bg) + (1-mxp_mix) * mxp_bg;
-}
-
-export color mx_overlay_color3(
- color mxp_fg = color(0.0),
- color mxp_bg = color(0.0),
- float mxp_mix = 1.0
-)
- [[
- anno::description("Node Group: compositing")
- ]]
-{
- return mxp_mix * mx_overlay(mxp_fg, mxp_bg) + (1-mxp_mix) * mxp_bg;
-}
-
-export color4 mx_overlay_color4(
- color4 mxp_fg = mk_color4(0.0, 0.0, 0.0, 0.0),
- color4 mxp_bg = mk_color4(0.0, 0.0, 0.0, 0.0),
- float mxp_mix = float(1.0)
-)
- [[
- anno::description("Node Group: compositing")
- ]]
-{
- color rgb = mxp_mix * mx_overlay(mxp_fg.rgb, mxp_bg.rgb) + (1-mxp_mix) * mxp_bg.rgb;
- float a = mxp_mix * mx_overlay(mxp_fg.a , mxp_bg.a ) + (1-mxp_mix) * mxp_bg.a;
- return color4(rgb,a);
-}
-
export color4 mx_disjointover_color4(
color4 mxp_fg = mk_color4(0.0, 0.0, 0.0, 0.0),
color4 mxp_bg = mk_color4(0.0, 0.0, 0.0, 0.0),
diff --git a/source/MaterialXGenMsl/MslShaderGenerator.cpp b/source/MaterialXGenMsl/MslShaderGenerator.cpp
index 29eac785eb..1939e2a6da 100644
--- a/source/MaterialXGenMsl/MslShaderGenerator.cpp
+++ b/source/MaterialXGenMsl/MslShaderGenerator.cpp
@@ -10,7 +10,6 @@
#include
#include
#include
-#include
#include
#include
#include
@@ -23,9 +22,6 @@
#include
#include
#include
-#include
-#include
-#include
#include
#include
@@ -34,6 +30,8 @@
#include
#include
#include
+#include
+#include
#include
#include
#include
@@ -178,8 +176,8 @@ MslShaderGenerator::MslShaderGenerator() :
//
registerImplementation("IM_bitangent_vector3_" + MslShaderGenerator::TARGET, BitangentNodeMsl::create);
//
- registerImplementation("IM_texcoord_vector2_" + MslShaderGenerator::TARGET, TexCoordNodeMsl::create);
- registerImplementation("IM_texcoord_vector3_" + MslShaderGenerator::TARGET, TexCoordNodeMsl::create);
+ registerImplementation("IM_texcoord_vector2_" + MslShaderGenerator::TARGET, HwTexCoordNode::create);
+ registerImplementation("IM_texcoord_vector3_" + MslShaderGenerator::TARGET, HwTexCoordNode::create);
//
registerImplementation("IM_geomcolor_float_" + MslShaderGenerator::TARGET, GeomColorNodeMsl::create);
registerImplementation("IM_geomcolor_color3_" + MslShaderGenerator::TARGET, GeomColorNodeMsl::create);
@@ -232,13 +230,13 @@ MslShaderGenerator::MslShaderGenerator() :
registerImplementation(elementNames, BlurNodeMsl::create);
//
elementNames = {
@@ -283,9 +281,7 @@ ShaderPtr MslShaderGenerator::generate(const string& name, ElementPtr element, G
{
ShaderPtr shader = createShader(name, element, context);
- // Turn on fixed float formatting to make sure float values are
- // emitted with a decimal point and not as integers, and to avoid
- // any scientific notation which isn't supported by all OpenGL targets.
+ // Request fixed floating-point notation for consistency across targets.
ScopedFloatFormatting fmt(Value::FloatFormatFixed);
// Make sure we initialize/reset the binding context before generation.
@@ -1022,7 +1018,7 @@ void MslShaderGenerator::emitPixelStage(const ShaderGraph& graph, GenContext& co
emitLightData(context, stage);
}
}
-
+
bool needsLightBuffer = lighting && context.getOptions().hwMaxActiveLightSources > 0;
emitMathMatrixScalarMathOperators(context, stage);
@@ -1417,11 +1413,6 @@ ShaderNodeImplPtr MslShaderGenerator::getImplementation(const NodeDef& nodedef,
}
const string MslImplementation::SPACE = "space";
-const string MslImplementation::TO_SPACE = "tospace";
-const string MslImplementation::FROM_SPACE = "fromspace";
-const string MslImplementation::WORLD = "world";
-const string MslImplementation::OBJECT = "object";
-const string MslImplementation::MODEL = "model";
const string MslImplementation::INDEX = "index";
const string MslImplementation::GEOMPROP = "geomprop";
diff --git a/source/MaterialXGenMsl/MslShaderGenerator.h b/source/MaterialXGenMsl/MslShaderGenerator.h
index ecbf37d7a6..21817db735 100644
--- a/source/MaterialXGenMsl/MslShaderGenerator.h
+++ b/source/MaterialXGenMsl/MslShaderGenerator.h
@@ -48,7 +48,7 @@ class MX_GENMSL_API MslShaderGenerator : public HwShaderGenerator
ShaderNodeImplPtr getImplementation(const NodeDef& nodedef, GenContext& context) const override;
/// Determine the prefix of vertex data variables.
- virtual string getVertexDataPrefix(const VariableBlock& vertexData) const;
+ string getVertexDataPrefix(const VariableBlock& vertexData) const override;
public:
/// Unique identifier for this generator target
@@ -137,11 +137,6 @@ class MX_GENMSL_API MslImplementation : public ShaderNodeImpl
/// Internal string constants
static const string SPACE;
- static const string TO_SPACE;
- static const string FROM_SPACE;
- static const string WORLD;
- static const string OBJECT;
- static const string MODEL;
static const string INDEX;
static const string GEOMPROP;
};
diff --git a/source/MaterialXGenMsl/Nodes/HeightToNormalNodeMsl.cpp b/source/MaterialXGenMsl/Nodes/HeightToNormalNodeMsl.cpp
index 12b1a9675c..7282e5e9df 100644
--- a/source/MaterialXGenMsl/Nodes/HeightToNormalNodeMsl.cpp
+++ b/source/MaterialXGenMsl/Nodes/HeightToNormalNodeMsl.cpp
@@ -33,6 +33,11 @@ ShaderNodeImplPtr HeightToNormalNodeMsl::create()
return std::make_shared();
}
+void HeightToNormalNodeMsl::createVariables(const ShaderNode&, GenContext&, Shader&) const
+{
+ // Default filter kernels from ConvolutionNode are not used by this derived class.
+}
+
void HeightToNormalNodeMsl::computeSampleOffsetStrings(const string& sampleSizeName, const string& offsetTypeString,
unsigned int, StringVec& offsetStrings) const
{
diff --git a/source/MaterialXGenMsl/Nodes/HeightToNormalNodeMsl.h b/source/MaterialXGenMsl/Nodes/HeightToNormalNodeMsl.h
index 752c411ed5..035ad300b4 100644
--- a/source/MaterialXGenMsl/Nodes/HeightToNormalNodeMsl.h
+++ b/source/MaterialXGenMsl/Nodes/HeightToNormalNodeMsl.h
@@ -18,6 +18,8 @@ class MX_GENMSL_API HeightToNormalNodeMsl : public ConvolutionNode
public:
static ShaderNodeImplPtr create();
+ void createVariables(const ShaderNode&, GenContext&, Shader& shader) const override;
+
void emitFunctionDefinition(const ShaderNode& node, GenContext& context, ShaderStage& stage) const override;
void emitFunctionCall(const ShaderNode& node, GenContext& context, ShaderStage& stage) const override;
diff --git a/source/MaterialXGenMsl/Nodes/TexCoordNodeMsl.cpp b/source/MaterialXGenMsl/Nodes/TexCoordNodeMsl.cpp
deleted file mode 100644
index a88152eb82..0000000000
--- a/source/MaterialXGenMsl/Nodes/TexCoordNodeMsl.cpp
+++ /dev/null
@@ -1,62 +0,0 @@
-//
-// Copyright Contributors to the MaterialX Project
-// SPDX-License-Identifier: Apache-2.0
-//
-
-#include
-
-#include
-
-MATERIALX_NAMESPACE_BEGIN
-
-ShaderNodeImplPtr TexCoordNodeMsl::create()
-{
- return std::make_shared();
-}
-
-void TexCoordNodeMsl::createVariables(const ShaderNode& node, GenContext&, Shader& shader) const
-{
- const ShaderOutput* output = node.getOutput();
- const ShaderInput* indexInput = node.getInput(INDEX);
- const string index = indexInput ? indexInput->getValue()->getValueString() : "0";
-
- ShaderStage& vs = shader.getStage(Stage::VERTEX);
- ShaderStage& ps = shader.getStage(Stage::PIXEL);
-
- addStageInput(HW::VERTEX_INPUTS, output->getType(), HW::T_IN_TEXCOORD + "_" + index, vs);
- addStageConnector(HW::VERTEX_DATA, output->getType(), HW::T_TEXCOORD + "_" + index, vs, ps);
-}
-
-void TexCoordNodeMsl::emitFunctionCall(const ShaderNode& node, GenContext& context, ShaderStage& stage) const
-{
- const MslShaderGenerator& shadergen = static_cast(context.getShaderGenerator());
-
- const ShaderInput* indexInput = node.getInput(INDEX);
- const string index = indexInput ? indexInput->getValue()->getValueString() : "0";
- const string variable = HW::T_TEXCOORD + "_" + index;
-
- DEFINE_SHADER_STAGE(stage, Stage::VERTEX)
- {
- VariableBlock& vertexData = stage.getOutputBlock(HW::VERTEX_DATA);
- const string prefix = shadergen.getVertexDataPrefix(vertexData);
- ShaderPort* texcoord = vertexData[variable];
- if (!texcoord->isEmitted())
- {
- shadergen.emitLine(prefix + texcoord->getVariable() + " = " + HW::T_IN_TEXCOORD + "_" + index, stage);
- texcoord->setEmitted();
- }
- }
-
- DEFINE_SHADER_STAGE(stage, Stage::PIXEL)
- {
- VariableBlock& vertexData = stage.getInputBlock(HW::VERTEX_DATA);
- const string prefix = shadergen.getVertexDataPrefix(vertexData);
- ShaderPort* texcoord = vertexData[variable];
- shadergen.emitLineBegin(stage);
- shadergen.emitOutput(node.getOutput(), true, false, context, stage);
- shadergen.emitString(" = " + prefix + texcoord->getVariable(), stage);
- shadergen.emitLineEnd(stage);
- }
-}
-
-MATERIALX_NAMESPACE_END
diff --git a/source/MaterialXGenMsl/Nodes/TexCoordNodeMsl.h b/source/MaterialXGenMsl/Nodes/TexCoordNodeMsl.h
deleted file mode 100644
index 6c227cc63b..0000000000
--- a/source/MaterialXGenMsl/Nodes/TexCoordNodeMsl.h
+++ /dev/null
@@ -1,26 +0,0 @@
-//
-// Copyright Contributors to the MaterialX Project
-// SPDX-License-Identifier: Apache-2.0
-//
-
-#ifndef MATERIALX_TEXCOORDNODEMSL_H
-#define MATERIALX_TEXCOORDNODEMSL_H
-
-#include
-
-MATERIALX_NAMESPACE_BEGIN
-
-/// TexCoord node implementation for MSL
-class MX_GENMSL_API TexCoordNodeMsl : public MslImplementation
-{
- public:
- static ShaderNodeImplPtr create();
-
- void createVariables(const ShaderNode& node, GenContext& context, Shader& shader) const override;
-
- void emitFunctionCall(const ShaderNode& node, GenContext& context, ShaderStage& stage) const override;
-};
-
-MATERIALX_NAMESPACE_END
-
-#endif
diff --git a/source/MaterialXGenMsl/Nodes/TransformNormalNodeMsl.cpp b/source/MaterialXGenMsl/Nodes/TransformNormalNodeMsl.cpp
deleted file mode 100644
index 98810c025b..0000000000
--- a/source/MaterialXGenMsl/Nodes/TransformNormalNodeMsl.cpp
+++ /dev/null
@@ -1,43 +0,0 @@
-//
-// Copyright Contributors to the MaterialX Project
-// SPDX-License-Identifier: Apache-2.0
-//
-
-#include
-
-MATERIALX_NAMESPACE_BEGIN
-
-ShaderNodeImplPtr TransformNormalNodeMsl::create()
-{
- return std::make_shared();
-}
-
-void TransformNormalNodeMsl::emitFunctionCall(const ShaderNode& node, GenContext& context, ShaderStage& stage) const
-{
- TransformVectorNodeMsl::emitFunctionCall(node, context, stage);
-
- DEFINE_SHADER_STAGE(stage, Stage::PIXEL)
- {
- const ShaderGenerator& shadergen = context.getShaderGenerator();
- const ShaderOutput* output = node.getOutput();
- shadergen.emitLineBegin(stage);
- shadergen.emitOutput(output, false, false, context, stage);
- shadergen.emitString(" = normalize(" + output->getVariable() + ")", stage);
- shadergen.emitLineEnd(stage);
- }
-}
-
-const string& TransformNormalNodeMsl::getMatrix(const string& fromSpace, const string& toSpace) const
-{
- if ((fromSpace == MODEL || fromSpace == OBJECT) && toSpace == WORLD)
- {
- return HW::T_WORLD_INVERSE_TRANSPOSE_MATRIX;
- }
- else if (fromSpace == WORLD && (toSpace == MODEL || toSpace == OBJECT))
- {
- return HW::T_WORLD_TRANSPOSE_MATRIX;
- }
- return EMPTY_STRING;
-}
-
-MATERIALX_NAMESPACE_END
diff --git a/source/MaterialXGenMsl/Nodes/TransformNormalNodeMsl.h b/source/MaterialXGenMsl/Nodes/TransformNormalNodeMsl.h
deleted file mode 100644
index 603ba3771c..0000000000
--- a/source/MaterialXGenMsl/Nodes/TransformNormalNodeMsl.h
+++ /dev/null
@@ -1,27 +0,0 @@
-//
-// Copyright Contributors to the MaterialX Project
-// SPDX-License-Identifier: Apache-2.0
-//
-
-#ifndef MATERIALX_TRANSFORMNORMALNODEMSL_H
-#define MATERIALX_TRANSFORMNORMALNODEMSL_H
-
-#include
-
-MATERIALX_NAMESPACE_BEGIN
-
-/// TransformNormal node implementation for MSL
-class MX_GENMSL_API TransformNormalNodeMsl : public TransformVectorNodeMsl
-{
- public:
- static ShaderNodeImplPtr create();
-
- protected:
- void emitFunctionCall(const ShaderNode& node, GenContext& context, ShaderStage& stage) const override;
-
- const string& getMatrix(const string& fromSpace, const string& toSpace) const override;
-};
-
-MATERIALX_NAMESPACE_END
-
-#endif
diff --git a/source/MaterialXGenMsl/Nodes/TransformPointNodeMsl.cpp b/source/MaterialXGenMsl/Nodes/TransformPointNodeMsl.cpp
deleted file mode 100644
index 38db776855..0000000000
--- a/source/MaterialXGenMsl/Nodes/TransformPointNodeMsl.cpp
+++ /dev/null
@@ -1,23 +0,0 @@
-//
-// Copyright Contributors to the MaterialX Project
-// SPDX-License-Identifier: Apache-2.0
-//
-
-#include
-
-#include
-
-MATERIALX_NAMESPACE_BEGIN
-
-ShaderNodeImplPtr TransformPointNodeMsl::create()
-{
- return std::make_shared();
-}
-
-string TransformPointNodeMsl::getHomogeneousCoordinate(const ShaderInput* in, GenContext& context) const
-{
- const ShaderGenerator& shadergen = context.getShaderGenerator();
- return "float4(" + shadergen.getUpstreamResult(in, context) + ", 1.0)";
-}
-
-MATERIALX_NAMESPACE_END
diff --git a/source/MaterialXGenMsl/Nodes/TransformPointNodeMsl.h b/source/MaterialXGenMsl/Nodes/TransformPointNodeMsl.h
deleted file mode 100644
index 9fc2361d7d..0000000000
--- a/source/MaterialXGenMsl/Nodes/TransformPointNodeMsl.h
+++ /dev/null
@@ -1,25 +0,0 @@
-//
-// Copyright Contributors to the MaterialX Project
-// SPDX-License-Identifier: Apache-2.0
-//
-
-#ifndef MATERIALX_TRANSFORMPOINTNODEMSL_H
-#define MATERIALX_TRANSFORMPOINTNODEMSL_H
-
-#include
-
-MATERIALX_NAMESPACE_BEGIN
-
-/// TransformPoint node implementation for MSL
-class MX_GENMSL_API TransformPointNodeMsl : public TransformVectorNodeMsl
-{
- public:
- static ShaderNodeImplPtr create();
-
- protected:
- virtual string getHomogeneousCoordinate(const ShaderInput* in, GenContext& context) const override;
-};
-
-MATERIALX_NAMESPACE_END
-
-#endif
diff --git a/source/MaterialXGenMsl/Nodes/TransformVectorNodeMsl.cpp b/source/MaterialXGenMsl/Nodes/TransformVectorNodeMsl.cpp
deleted file mode 100644
index c5d6ce242a..0000000000
--- a/source/MaterialXGenMsl/Nodes/TransformVectorNodeMsl.cpp
+++ /dev/null
@@ -1,84 +0,0 @@
-//
-// Copyright Contributors to the MaterialX Project
-// SPDX-License-Identifier: Apache-2.0
-//
-
-#include
-
-#include
-
-MATERIALX_NAMESPACE_BEGIN
-
-ShaderNodeImplPtr TransformVectorNodeMsl::create()
-{
- return std::make_shared();
-}
-
-void TransformVectorNodeMsl::createVariables(const ShaderNode& node, GenContext&, Shader& shader) const
-{
- const ShaderInput* toSpaceInput = node.getInput(TO_SPACE);
- string toSpace = toSpaceInput ? toSpaceInput->getValue()->getValueString() : EMPTY_STRING;
-
- const ShaderInput* fromSpaceInput = node.getInput(FROM_SPACE);
- string fromSpace = fromSpaceInput ? fromSpaceInput->getValue()->getValueString() : EMPTY_STRING;
-
- const string& matrix = getMatrix(fromSpace, toSpace);
- if (!matrix.empty())
- {
- ShaderStage& ps = shader.getStage(Stage::PIXEL);
- addStageUniform(HW::PRIVATE_UNIFORMS, Type::MATRIX44, matrix, ps);
- }
-}
-
-void TransformVectorNodeMsl::emitFunctionCall(const ShaderNode& node, GenContext& context, ShaderStage& stage) const
-{
- DEFINE_SHADER_STAGE(stage, Stage::PIXEL)
- {
- const ShaderGenerator& shadergen = context.getShaderGenerator();
-
- const ShaderInput* inInput = node.getInput("in");
- if (inInput->getType() != Type::VECTOR3 && inInput->getType() != Type::VECTOR4)
- {
- throw ExceptionShaderGenError("Transform node must have 'in' type of vector3 or vector4.");
- }
-
- const ShaderInput* toSpaceInput = node.getInput(TO_SPACE);
- string toSpace = toSpaceInput ? toSpaceInput->getValue()->getValueString() : EMPTY_STRING;
-
- const ShaderInput* fromSpaceInput = node.getInput(FROM_SPACE);
- string fromSpace = fromSpaceInput ? fromSpaceInput->getValue()->getValueString() : EMPTY_STRING;
-
- shadergen.emitLineBegin(stage);
- shadergen.emitOutput(node.getOutput(), true, false, context, stage);
- shadergen.emitString(" = (", stage);
- const string& matrix = getMatrix(fromSpace, toSpace);
- if (!matrix.empty())
- {
- shadergen.emitString(matrix + " * ", stage);
- }
- shadergen.emitString(getHomogeneousCoordinate(inInput, context), stage);
- shadergen.emitString(").xyz", stage);
- shadergen.emitLineEnd(stage);
- }
-}
-
-const string& TransformVectorNodeMsl::getMatrix(const string& fromSpace, const string& toSpace) const
-{
- if ((fromSpace == MODEL || fromSpace == OBJECT) && toSpace == WORLD)
- {
- return HW::T_WORLD_MATRIX;
- }
- else if (fromSpace == WORLD && (toSpace == MODEL || toSpace == OBJECT))
- {
- return HW::T_WORLD_INVERSE_MATRIX;
- }
- return EMPTY_STRING;
-}
-
-string TransformVectorNodeMsl::getHomogeneousCoordinate(const ShaderInput* in, GenContext& context) const
-{
- const ShaderGenerator& shadergen = context.getShaderGenerator();
- return "float4(" + shadergen.getUpstreamResult(in, context) + ", 0.0)";
-}
-
-MATERIALX_NAMESPACE_END
diff --git a/source/MaterialXGenMsl/Nodes/TransformVectorNodeMsl.h b/source/MaterialXGenMsl/Nodes/TransformVectorNodeMsl.h
deleted file mode 100644
index 013a3db29a..0000000000
--- a/source/MaterialXGenMsl/Nodes/TransformVectorNodeMsl.h
+++ /dev/null
@@ -1,30 +0,0 @@
-//
-// Copyright Contributors to the MaterialX Project
-// SPDX-License-Identifier: Apache-2.0
-//
-
-#ifndef MATERIALX_TRANSFORMVECTORNODEMSL_H
-#define MATERIALX_TRANSFORMVECTORNODEMSL_H
-
-#include
-
-MATERIALX_NAMESPACE_BEGIN
-
-/// TransformVector node implementation for MSL
-class MX_GENMSL_API TransformVectorNodeMsl : public MslImplementation
-{
- public:
- static ShaderNodeImplPtr create();
-
- void createVariables(const ShaderNode& node, GenContext& context, Shader& shader) const override;
-
- void emitFunctionCall(const ShaderNode& node, GenContext& context, ShaderStage& stage) const override;
-
- protected:
- virtual const string& getMatrix(const string& fromSpace, const string& toSpace) const;
- virtual string getHomogeneousCoordinate(const ShaderInput* in, GenContext& context) const;
-};
-
-MATERIALX_NAMESPACE_END
-
-#endif
diff --git a/source/MaterialXGenOsl/OslShaderGenerator.cpp b/source/MaterialXGenOsl/OslShaderGenerator.cpp
index b4edbee44b..f16770174b 100644
--- a/source/MaterialXGenOsl/OslShaderGenerator.cpp
+++ b/source/MaterialXGenOsl/OslShaderGenerator.cpp
@@ -26,7 +26,6 @@
MATERIALX_NAMESPACE_BEGIN
const string OslShaderGenerator::TARGET = "genosl";
-const string OslShaderGenerator::T_FILE_EXTRA_ARGUMENTS = "$extraTextureLookupArguments";
//
// OslShaderGenerator methods
@@ -161,15 +160,15 @@ OslShaderGenerator::OslShaderGenerator() :
//
registerImplementation("IM_surfacematerial_" + OslShaderGenerator::TARGET, MaterialNodeOsl::create);
-
- // Extra arguments for texture lookups.
- _tokenSubstitutions[T_FILE_EXTRA_ARGUMENTS] = EMPTY_STRING;
}
ShaderPtr OslShaderGenerator::generate(const string& name, ElementPtr element, GenContext& context) const
{
ShaderPtr shader = createShader(name, element, context);
+ // Request fixed floating-point notation for consistency across targets.
+ ScopedFloatFormatting fmt(Value::FloatFormatFixed);
+
ShaderGraph& graph = shader->getGraph();
ShaderStage& stage = shader->getStage(Stage::PIXEL);
@@ -295,6 +294,25 @@ ShaderPtr OslShaderGenerator::generate(const string& name, ElementPtr element, G
emitLineBreak(stage);
}
+ // Inputs of type 'filename' has been generated into two shader inputs.
+ // So here we construct a single 'textureresource' from these inputs,
+ // to be used further downstream. See emitShaderInputs() for details.
+ VariableBlock& inputs = stage.getUniformBlock(OSL::UNIFORMS);
+ for (size_t i = 0; i < inputs.size(); ++i)
+ {
+ ShaderPort* input = inputs[i];
+ if (input->getType() == Type::FILENAME)
+ {
+ // Construct the textureresource variable.
+ const string newVariableName = input->getVariable() + "_";
+ const string& type = _syntax->getTypeName(input->getType());
+ emitLine(type + newVariableName + " = {" + input->getVariable() + ", " + input->getVariable() + "_colorspace}", stage);
+
+ // Update the variable name to be used downstream.
+ input->setVariable(newVariableName);
+ }
+ }
+
// Emit all texturing nodes. These are inputs to any
// closure/shader nodes and need to be emitted first.
emitFunctionCalls(graph, context, stage, ShaderNode::Classification::TEXTURE);
@@ -490,111 +508,75 @@ void OslShaderGenerator::emitLibraryIncludes(ShaderStage& stage, GenContext& con
emitLineBreak(stage);
}
-namespace
-{
-
-std::unordered_map GEOMPROP_DEFINITIONS =
-{
- { "Pobject", "transform(\"object\", P)" },
- { "Pworld", "P" },
- { "Nobject", "transform(\"object\", N)" },
- { "Nworld", "N" },
- { "Tobject", "transform(\"object\", dPdu)" },
- { "Tworld", "dPdu" },
- { "Bobject", "transform(\"object\", dPdv)" },
- { "Bworld", "dPdv" },
- { "UV0", "{u,v}" },
- { "Vworld", "I" }
-};
-
-} // anonymous namespace
-
void OslShaderGenerator::emitShaderInputs(const VariableBlock& inputs, ShaderStage& stage) const
{
- const std::unordered_map UI_WIDGET_METADATA =
+ static const std::unordered_map GEOMPROP_DEFINITIONS =
{
- { Type::FLOAT, ShaderMetadata("widget", Type::STRING, Value::createValueFromStrings("number", Type::STRING->getName())) },
- { Type::INTEGER, ShaderMetadata("widget", Type::STRING, Value::createValueFromStrings("number", Type::STRING->getName())) },
- { Type::FILENAME, ShaderMetadata("widget", Type::STRING, Value::createValueFromStrings("filename", Type::STRING->getName())) },
- { Type::BOOLEAN, ShaderMetadata("widget", Type::STRING, Value::createValueFromStrings("checkBox", Type::STRING->getName())) }
- };
-
- const std::set METADATA_TYPE_BLACKLIST =
- {
- Type::VECTOR2, // Custom struct types doesn't support metadata declarations.
- Type::VECTOR4, //
- Type::COLOR4, //
- Type::FILENAME, //
- Type::BSDF //
+ { "Pobject", "transform(\"object\", P)" },
+ { "Pworld", "P" },
+ { "Nobject", "transform(\"object\", N)" },
+ { "Nworld", "N" },
+ { "Tobject", "transform(\"object\", dPdu)" },
+ { "Tworld", "dPdu" },
+ { "Bobject", "transform(\"object\", dPdv)" },
+ { "Bworld", "dPdv" },
+ { "UV0", "{u,v}" },
+ { "Vworld", "I" }
};
for (size_t i = 0; i < inputs.size(); ++i)
{
const ShaderPort* input = inputs[i];
-
const string& type = _syntax->getTypeName(input->getType());
- string value = _syntax->getValue(input, true);
- emitLineBegin(stage);
- emitString(type + " " + input->getVariable(), stage);
-
- const string& geomprop = input->getGeomProp();
- if (!geomprop.empty())
+ if (input->getType() == Type::FILENAME)
{
- auto it = GEOMPROP_DEFINITIONS.find(geomprop);
- if (it != GEOMPROP_DEFINITIONS.end())
- {
- value = it->second;
- }
+ // Shader inputs of type 'filename' (textures) need special handling.
+ // In OSL codegen a 'filename' is translated to the custom type 'textureresource',
+ // which is a struct containing a file string and a colorspace string.
+ // For the published shader interface we here split this into two separate inputs,
+ // which gives a nicer shader interface with widget metadata on each input.
+
+ ValuePtr value = input->getValue();
+ const string valueStr = value ? value->getValueString() : EMPTY_STRING;
+
+ // Add the file string input
+ emitLineBegin(stage);
+ emitString("string " + input->getVariable() + " = \"" + valueStr + "\"", stage);
+ emitMetadata(input, stage);
+ emitString(",", stage);
+ emitLineEnd(stage, false);
+
+ // Add the colorspace string input
+ emitLineBegin(stage);
+ emitString("string " + input->getVariable() + "_colorspace = \"" + input->getColorSpace() + "\"", stage);
+ emitLineEnd(stage, false);
+ emitScopeBegin(stage, Syntax::DOUBLE_SQUARE_BRACKETS);
+ emitLine("string widget = \"colorspace\"", stage, false);
+ emitScopeEnd(stage, false, false);
}
-
- if (value.empty())
+ else
{
- value = _syntax->getDefaultValue(input->getType());
- }
- emitString(" = " + value, stage);
-
- //
- // Add shader input metadata.
- //
+ emitLineBegin(stage);
+ emitString(type + " " + input->getVariable(), stage);
- auto widgetMetadataIt = UI_WIDGET_METADATA.find(input->getType());
- const ShaderMetadata* widgetMetadata = widgetMetadataIt != UI_WIDGET_METADATA.end() ? &widgetMetadataIt->second : nullptr;
- const ShaderMetadataVecPtr& metadata = input->getMetadata();
-
- if (widgetMetadata || (metadata && metadata->size()))
- {
- StringVec metadataLines;
- if (metadata)
+ string value = _syntax->getValue(input, true);
+ const string& geomprop = input->getGeomProp();
+ if (!geomprop.empty())
{
- for (size_t j = 0; j < metadata->size(); ++j)
+ auto it = GEOMPROP_DEFINITIONS.find(geomprop);
+ if (it != GEOMPROP_DEFINITIONS.end())
{
- const ShaderMetadata& data = metadata->at(j);
- if (METADATA_TYPE_BLACKLIST.count(data.type) == 0)
- {
- const string& delim = (widgetMetadata || j < metadata->size() - 1) ? Syntax::COMMA : EMPTY_STRING;
- const string& dataType = _syntax->getTypeName(data.type);
- const string dataValue = _syntax->getValue(data.type, *data.value, true);
- metadataLines.push_back(dataType + " " + data.name + " = " + dataValue + delim);
- }
+ value = it->second;
}
}
- if (widgetMetadata)
+ if (value.empty())
{
- const string& dataType = _syntax->getTypeName(widgetMetadata->type);
- const string dataValue = _syntax->getValue(widgetMetadata->type, *widgetMetadata->value, true);
- metadataLines.push_back(dataType + " " + widgetMetadata->name + " = " + dataValue);
- }
- if (metadataLines.size())
- {
- emitLineEnd(stage, false);
- emitScopeBegin(stage, Syntax::DOUBLE_SQUARE_BRACKETS);
- for (auto line : metadataLines)
- {
- emitLine(line, stage, false);
- }
- emitScopeEnd(stage, false, false);
+ value = _syntax->getDefaultValue(input->getType());
}
+
+ emitString(" = " + value, stage);
+ emitMetadata(input, stage);
}
if (i < inputs.size())
@@ -619,6 +601,65 @@ void OslShaderGenerator::emitShaderOutputs(const VariableBlock& outputs, ShaderS
}
}
+void OslShaderGenerator::emitMetadata(const ShaderPort* port, ShaderStage& stage) const
+{
+ static const std::unordered_map UI_WIDGET_METADATA =
+ {
+ { Type::FLOAT, ShaderMetadata("widget", Type::STRING, Value::createValueFromStrings("number", Type::STRING->getName())) },
+ { Type::INTEGER, ShaderMetadata("widget", Type::STRING, Value::createValueFromStrings("number", Type::STRING->getName())) },
+ { Type::FILENAME, ShaderMetadata("widget", Type::STRING, Value::createValueFromStrings("filename", Type::STRING->getName())) },
+ { Type::BOOLEAN, ShaderMetadata("widget", Type::STRING, Value::createValueFromStrings("checkBox", Type::STRING->getName())) }
+ };
+
+ static const std::set METADATA_TYPE_BLACKLIST =
+ {
+ Type::VECTOR2, // Custom struct types doesn't support metadata declarations.
+ Type::VECTOR4, //
+ Type::COLOR4, //
+ Type::FILENAME, //
+ Type::BSDF //
+ };
+
+ auto widgetMetadataIt = UI_WIDGET_METADATA.find(port->getType());
+ const ShaderMetadata* widgetMetadata = widgetMetadataIt != UI_WIDGET_METADATA.end() ? &widgetMetadataIt->second : nullptr;
+ const ShaderMetadataVecPtr& metadata = port->getMetadata();
+
+ if (widgetMetadata || (metadata && metadata->size()))
+ {
+ StringVec metadataLines;
+ if (metadata)
+ {
+ for (size_t j = 0; j < metadata->size(); ++j)
+ {
+ const ShaderMetadata& data = metadata->at(j);
+ if (METADATA_TYPE_BLACKLIST.count(data.type) == 0)
+ {
+ const string& delim = (widgetMetadata || j < metadata->size() - 1) ? Syntax::COMMA : EMPTY_STRING;
+ const string& dataType = _syntax->getTypeName(data.type);
+ const string dataValue = _syntax->getValue(data.type, *data.value, true);
+ metadataLines.push_back(dataType + " " + data.name + " = " + dataValue + delim);
+ }
+ }
+ }
+ if (widgetMetadata)
+ {
+ const string& dataType = _syntax->getTypeName(widgetMetadata->type);
+ const string dataValue = _syntax->getValue(widgetMetadata->type, *widgetMetadata->value, true);
+ metadataLines.push_back(dataType + " " + widgetMetadata->name + " = " + dataValue);
+ }
+ if (metadataLines.size())
+ {
+ emitLineEnd(stage, false);
+ emitScopeBegin(stage, Syntax::DOUBLE_SQUARE_BRACKETS);
+ for (auto line : metadataLines)
+ {
+ emitLine(line, stage, false);
+ }
+ emitScopeEnd(stage, false, false);
+ }
+ }
+}
+
namespace OSL
{
diff --git a/source/MaterialXGenOsl/OslShaderGenerator.h b/source/MaterialXGenOsl/OslShaderGenerator.h
index 91690adc1d..e5cf13977e 100644
--- a/source/MaterialXGenOsl/OslShaderGenerator.h
+++ b/source/MaterialXGenOsl/OslShaderGenerator.h
@@ -48,9 +48,6 @@ class MX_GENOSL_API OslShaderGenerator : public ShaderGenerator
void registerShaderMetadata(const DocumentPtr& doc, GenContext& context) const override;
protected:
- // Extra file arguments for texture lookup call
- static const string T_FILE_EXTRA_ARGUMENTS;
-
/// Create and initialize a new OSL shader for shader generation.
virtual ShaderPtr createShader(const string& name, ElementPtr element, GenContext& context) const;
@@ -62,6 +59,9 @@ class MX_GENOSL_API OslShaderGenerator : public ShaderGenerator
/// Emit a block of shader outputs.
virtual void emitShaderOutputs(const VariableBlock& inputs, ShaderStage& stage) const;
+
+ /// Emit metadata for a shader parameter.
+ virtual void emitMetadata(const ShaderPort* port, ShaderStage& stage) const;
};
namespace OSL
diff --git a/source/MaterialXGenOsl/OslSyntax.cpp b/source/MaterialXGenOsl/OslSyntax.cpp
index d421c5e3d9..5a6b45dd61 100644
--- a/source/MaterialXGenOsl/OslSyntax.cpp
+++ b/source/MaterialXGenOsl/OslSyntax.cpp
@@ -220,7 +220,6 @@ class OSLMatrix3TypeSyntax : public AggregateTypeSyntax
string getValue(const Value& value, bool uniform) const override
{
- ScopedFloatFormatting fmt(Value::FloatFormatFixed, 3);
StringVec values = splitString(value.getValueString(), ",");
return getValue(values, uniform);
}
diff --git a/source/MaterialXGenShader/HwShaderGenerator.cpp b/source/MaterialXGenShader/HwShaderGenerator.cpp
index bb87cdff46..229c528ce4 100644
--- a/source/MaterialXGenShader/HwShaderGenerator.cpp
+++ b/source/MaterialXGenShader/HwShaderGenerator.cpp
@@ -263,9 +263,9 @@ ShaderPtr HwShaderGenerator::createShader(const string& name, ElementPtr element
if (geomprop)
{
// A default geomprop was assigned to this graph input.
- // For all internal connections to this input, break the connection
+ // For all internal connections to this input, break the connection
// and assign a geomprop node that generates this data.
- // Note: If a geomprop node exists already it is reused,
+ // Note: If a geomprop node exists already it is reused,
// so only a single node per geometry type is created.
ShaderInputVec connections = socket->getConnections();
for (auto connection : connections)
diff --git a/source/MaterialXGenShader/HwShaderGenerator.h b/source/MaterialXGenShader/HwShaderGenerator.h
index 5ac05ad542..efe3781952 100644
--- a/source/MaterialXGenShader/HwShaderGenerator.h
+++ b/source/MaterialXGenShader/HwShaderGenerator.h
@@ -308,6 +308,9 @@ class MX_GENSHADER_API HwShaderGenerator : public ShaderGenerator
/// Unbind all light shaders previously bound.
static void unbindLightShaders(GenContext& context);
+ /// Determine the prefix of vertex data variables.
+ virtual string getVertexDataPrefix(const VariableBlock& vertexData) const = 0;
+
/// Types of closure contexts for HW.
enum ClosureContextType
{
diff --git a/source/MaterialXGenShader/Nodes/HwTexCoordNode.cpp b/source/MaterialXGenShader/Nodes/HwTexCoordNode.cpp
new file mode 100644
index 0000000000..3aa84400df
--- /dev/null
+++ b/source/MaterialXGenShader/Nodes/HwTexCoordNode.cpp
@@ -0,0 +1,83 @@
+//
+// Copyright Contributors to the MaterialX Project
+// SPDX-License-Identifier: Apache-2.0
+//
+
+#include
+#include
+#include
+
+MATERIALX_NAMESPACE_BEGIN
+
+string HwTexCoordNode::INDEX = "index";
+
+ShaderNodeImplPtr HwTexCoordNode::create()
+{
+ return std::make_shared();
+}
+
+void HwTexCoordNode::createVariables(const ShaderNode& node, GenContext&, Shader& shader) const
+{
+ const ShaderOutput* output = node.getOutput();
+ const string index = getIndex(node);
+
+ ShaderStage& vs = shader.getStage(Stage::VERTEX);
+ ShaderStage& ps = shader.getStage(Stage::PIXEL);
+
+ addStageInput(HW::VERTEX_INPUTS, output->getType(), HW::T_IN_TEXCOORD + "_" + index, vs, true);
+ addStageConnector(HW::VERTEX_DATA, output->getType(), HW::T_TEXCOORD + "_" + index, vs, ps, true);
+}
+
+void HwTexCoordNode::emitFunctionCall(const ShaderNode& node, GenContext& context, ShaderStage& stage) const
+{
+ const HwShaderGenerator& shadergen = static_cast(context.getShaderGenerator());
+
+ const string index = getIndex(node);
+ const string variable = HW::T_TEXCOORD + "_" + index;
+ const ShaderOutput* output = node.getOutput();
+
+ DEFINE_SHADER_STAGE(stage, Stage::VERTEX)
+ {
+ VariableBlock& vertexData = stage.getOutputBlock(HW::VERTEX_DATA);
+ const string prefix = shadergen.getVertexDataPrefix(vertexData);
+ ShaderPort* texcoord = vertexData[variable];
+ if (!texcoord->isEmitted())
+ {
+ shadergen.emitLine(prefix + texcoord->getVariable() + " = " + HW::T_IN_TEXCOORD + "_" + index, stage);
+ texcoord->setEmitted();
+ }
+ }
+
+ DEFINE_SHADER_STAGE(stage, Stage::PIXEL)
+ {
+ VariableBlock& vertexData = stage.getInputBlock(HW::VERTEX_DATA);
+ const string prefix = shadergen.getVertexDataPrefix(vertexData);
+ ShaderPort* texcoord = vertexData[variable];
+ shadergen.emitLineBegin(stage);
+ shadergen.emitOutput(output, true, false, context, stage);
+
+ // Extract the requested number of components from the texture coordinates (which may be a
+ // larger datatype than the requested number of texture coordinates, if several texture
+ // coordinate nodes with different width coexist).
+ string suffix = EMPTY_STRING;
+ if (output->getType() == Type::VECTOR2)
+ {
+ suffix = ".xy";
+ }
+ else if (output->getType() == Type::VECTOR3)
+ {
+ suffix = ".xyz";
+ }
+
+ shadergen.emitString(" = " + prefix + texcoord->getVariable() + suffix, stage);
+ shadergen.emitLineEnd(stage);
+ }
+}
+
+string HwTexCoordNode::getIndex(const ShaderNode& node) const
+{
+ const ShaderInput* input = node.getInput(INDEX);
+ return input ? input->getValue()->getValueString() : "0";
+}
+
+MATERIALX_NAMESPACE_END
diff --git a/source/MaterialXGenGlsl/Nodes/TexCoordNodeGlsl.h b/source/MaterialXGenShader/Nodes/HwTexCoordNode.h
similarity index 55%
rename from source/MaterialXGenGlsl/Nodes/TexCoordNodeGlsl.h
rename to source/MaterialXGenShader/Nodes/HwTexCoordNode.h
index c15a86fd9c..9aae3d18ce 100644
--- a/source/MaterialXGenGlsl/Nodes/TexCoordNodeGlsl.h
+++ b/source/MaterialXGenShader/Nodes/HwTexCoordNode.h
@@ -3,15 +3,15 @@
// SPDX-License-Identifier: Apache-2.0
//
-#ifndef MATERIALX_TEXCOORDNODEGLSL_H
-#define MATERIALX_TEXCOORDNODEGLSL_H
+#ifndef MATERIALX_HWTEXCOORDNODE_H
+#define MATERIALX_HWTEXCOORDNODE_H
-#include
+#include
MATERIALX_NAMESPACE_BEGIN
-/// TexCoord node implementation for GLSL
-class MX_GENGLSL_API TexCoordNodeGlsl : public GlslImplementation
+/// Generic texture coordinate node for hardware languages
+class MX_GENSHADER_API HwTexCoordNode : public ShaderNodeImpl
{
public:
static ShaderNodeImplPtr create();
@@ -19,6 +19,11 @@ class MX_GENGLSL_API TexCoordNodeGlsl : public GlslImplementation
void createVariables(const ShaderNode& node, GenContext& context, Shader& shader) const override;
void emitFunctionCall(const ShaderNode& node, GenContext& context, ShaderStage& stage) const override;
+
+ protected:
+ virtual string getIndex(const ShaderNode& node) const;
+
+ static string INDEX;
};
MATERIALX_NAMESPACE_END
diff --git a/source/MaterialXGenShader/Nodes/HwTransformNode.cpp b/source/MaterialXGenShader/Nodes/HwTransformNode.cpp
new file mode 100644
index 0000000000..76394309af
--- /dev/null
+++ b/source/MaterialXGenShader/Nodes/HwTransformNode.cpp
@@ -0,0 +1,110 @@
+//
+// Copyright Contributors to the MaterialX Project
+// SPDX-License-Identifier: Apache-2.0
+//
+
+#include
+#include
+#include
+
+MATERIALX_NAMESPACE_BEGIN
+
+const string HwTransformNode::FROM_SPACE = "fromspace";
+const string HwTransformNode::TO_SPACE = "tospace";
+const string HwTransformNode::MODEL = "model";
+const string HwTransformNode::OBJECT = "object";
+const string HwTransformNode::WORLD = "world";
+
+void HwTransformNode::createVariables(const ShaderNode& node, GenContext&, Shader& shader) const
+{
+ const string toSpace = getToSpace(node);
+ const string fromSpace = getFromSpace(node);
+ const string& matrix = getMatrix(fromSpace, toSpace);
+ if (!matrix.empty())
+ {
+ ShaderStage& ps = shader.getStage(Stage::PIXEL);
+ addStageUniform(HW::PRIVATE_UNIFORMS, Type::MATRIX44, matrix, ps);
+ }
+}
+
+void HwTransformNode::emitFunctionCall(const ShaderNode& node, GenContext& context, ShaderStage& stage) const
+{
+ DEFINE_SHADER_STAGE(stage, Stage::PIXEL)
+ {
+ const ShaderGenerator& shadergen = context.getShaderGenerator();
+
+ const ShaderOutput* output = node.getOutput();
+ const ShaderInput* inInput = node.getInput("in");
+ if (inInput->getType() != Type::VECTOR3 && inInput->getType() != Type::VECTOR4)
+ {
+ throw ExceptionShaderGenError("Transform node must have 'in' type of vector3 or vector4.");
+ }
+
+ shadergen.emitLineBegin(stage);
+ shadergen.emitOutput(output, true, false, context, stage);
+ shadergen.emitString(" = (", stage);
+
+ const string toSpace = getToSpace(node);
+ const string fromSpace = getFromSpace(node);
+ const string& matrix = getMatrix(fromSpace, toSpace);
+ if (!matrix.empty())
+ {
+ shadergen.emitString(matrix + " * ", stage);
+ }
+
+ const string type = shadergen.getSyntax().getTypeName(Type::VECTOR4);
+ const string input = shadergen.getUpstreamResult(inInput, context);
+ shadergen.emitString(type + "(" + input + ", " + getHomogeneousCoordinate() + ")).xyz", stage);
+ shadergen.emitLineEnd(stage);
+
+ if (shouldNormalize())
+ {
+ shadergen.emitLineBegin(stage);
+ shadergen.emitOutput(output, false, false, context, stage);
+ shadergen.emitString(" = normalize(" + output->getVariable() + ")", stage);
+ shadergen.emitLineEnd(stage);
+ }
+ }
+}
+
+string HwTransformNode::getFromSpace(const ShaderNode& node) const
+{
+ const ShaderInput* input = node.getInput(FROM_SPACE);
+ return input ? input->getValueString() : EMPTY_STRING;
+}
+
+string HwTransformNode::getToSpace(const ShaderNode& node) const
+{
+ const ShaderInput* input = node.getInput(TO_SPACE);
+ return input ? input->getValueString() : EMPTY_STRING;
+}
+
+const string& HwTransformNode::getMatrix(const string& fromSpace, const string& toSpace) const
+{
+ if ((fromSpace == MODEL || fromSpace == OBJECT) && toSpace == WORLD)
+ {
+ return getModelToWorldMatrix();
+ }
+ else if (fromSpace == WORLD && (toSpace == MODEL || toSpace == OBJECT))
+ {
+ return getWorldToModelMatrix();
+ }
+ return EMPTY_STRING;
+}
+
+ShaderNodeImplPtr HwTransformVectorNode::create()
+{
+ return std::make_shared();
+}
+
+ShaderNodeImplPtr HwTransformPointNode::create()
+{
+ return std::make_shared();
+}
+
+ShaderNodeImplPtr HwTransformNormalNode::create()
+{
+ return std::make_shared();
+}
+
+MATERIALX_NAMESPACE_END
diff --git a/source/MaterialXGenShader/Nodes/HwTransformNode.h b/source/MaterialXGenShader/Nodes/HwTransformNode.h
new file mode 100644
index 0000000000..a97e57405c
--- /dev/null
+++ b/source/MaterialXGenShader/Nodes/HwTransformNode.h
@@ -0,0 +1,71 @@
+//
+// Copyright Contributors to the MaterialX Project
+// SPDX-License-Identifier: Apache-2.0
+//
+
+#ifndef MATERIALX_HWTRANSFORMNODE_H
+#define MATERIALX_HWTRANSFORMNODE_H
+
+#include
+
+MATERIALX_NAMESPACE_BEGIN
+
+/// Generic transformation node for hardware languages
+class MX_GENSHADER_API HwTransformNode : public ShaderNodeImpl
+{
+ public:
+ void createVariables(const ShaderNode& node, GenContext& context, Shader& shader) const override;
+ void emitFunctionCall(const ShaderNode& node, GenContext& context, ShaderStage& stage) const override;
+
+ protected:
+ virtual const string& getMatrix(const string& fromSpace, const string& toSpace) const;
+ virtual const string& getModelToWorldMatrix() const = 0;
+ virtual const string& getWorldToModelMatrix() const = 0;
+ virtual string getHomogeneousCoordinate() const = 0;
+ virtual bool shouldNormalize() const { return false; }
+
+ virtual string getFromSpace(const ShaderNode&) const;
+ virtual string getToSpace(const ShaderNode&) const;
+
+ static const string FROM_SPACE;
+ static const string TO_SPACE;
+ static const string MODEL;
+ static const string OBJECT;
+ static const string WORLD;
+};
+
+class MX_GENSHADER_API HwTransformVectorNode : public HwTransformNode
+{
+ public:
+ static ShaderNodeImplPtr create();
+
+ protected:
+ const string& getModelToWorldMatrix() const override { return HW::T_WORLD_MATRIX; }
+ const string& getWorldToModelMatrix() const override { return HW::T_WORLD_INVERSE_MATRIX; }
+ string getHomogeneousCoordinate() const override { return "0.0"; }
+};
+
+class MX_GENSHADER_API HwTransformPointNode : public HwTransformVectorNode
+{
+ public:
+ static ShaderNodeImplPtr create();
+
+ protected:
+ string getHomogeneousCoordinate() const override { return "1.0"; }
+};
+
+class MX_GENSHADER_API HwTransformNormalNode : public HwTransformNode
+{
+ public:
+ static ShaderNodeImplPtr create();
+
+ protected:
+ const string& getModelToWorldMatrix() const override { return HW::T_WORLD_INVERSE_TRANSPOSE_MATRIX; }
+ const string& getWorldToModelMatrix() const override { return HW::T_WORLD_TRANSPOSE_MATRIX; }
+ string getHomogeneousCoordinate() const override { return "0.0"; }
+ bool shouldNormalize() const override { return true; }
+};
+
+MATERIALX_NAMESPACE_END
+
+#endif
diff --git a/source/MaterialXGenShader/ShaderGenerator.cpp b/source/MaterialXGenShader/ShaderGenerator.cpp
index 177201a9e3..d5f51aed1c 100644
--- a/source/MaterialXGenShader/ShaderGenerator.cpp
+++ b/source/MaterialXGenShader/ShaderGenerator.cpp
@@ -270,7 +270,7 @@ void ShaderGenerator::registerImplementation(const string& name, CreatorFunction
void ShaderGenerator::registerImplementation(const StringVec& nameVec, CreatorFunction creator)
{
- for(const string& name : nameVec)
+ for (const string& name : nameVec)
{
_implFactory.registerClass(name, creator);
}
diff --git a/source/MaterialXGenShader/ShaderGenerator.h b/source/MaterialXGenShader/ShaderGenerator.h
index 8e7f9855de..fa60a4d63e 100644
--- a/source/MaterialXGenShader/ShaderGenerator.h
+++ b/source/MaterialXGenShader/ShaderGenerator.h
@@ -151,7 +151,7 @@ class MX_GENSHADER_API ShaderGenerator
/// Register a shader node implementation for a given implementation element name
void registerImplementation(const string& name, CreatorFunction creator);
-
+
/// Register a shader node implementation for a given set of implementation element names
void registerImplementation(const StringVec& nameVec, CreatorFunction creator);
diff --git a/source/MaterialXGenShader/ShaderNode.cpp b/source/MaterialXGenShader/ShaderNode.cpp
index 04551cb6d2..9ef5b0789a 100644
--- a/source/MaterialXGenShader/ShaderNode.cpp
+++ b/source/MaterialXGenShader/ShaderNode.cpp
@@ -32,6 +32,11 @@ string ShaderPort::getFullName() const
return (_node->getName() + "_" + _name);
}
+string ShaderPort::getValueString() const
+{
+ return getValue() ? getValue()->getValueString() : EMPTY_STRING;
+}
+
//
// ShaderInput methods
//
@@ -285,7 +290,7 @@ ShaderNodePtr ShaderNode::create(const ShaderGraph* parent, const string& name,
else if (nodeDef.getNodeString() == CONSTANT)
{
newNode->_classification = Classification::TEXTURE | Classification::CONSTANT;
- }
+ }
else if (nodeDef.getNodeString() == DOT)
{
newNode->_classification = Classification::TEXTURE | Classification::DOT;
diff --git a/source/MaterialXGenShader/ShaderNode.h b/source/MaterialXGenShader/ShaderNode.h
index 536e0adc1e..dd74269764 100644
--- a/source/MaterialXGenShader/ShaderNode.h
+++ b/source/MaterialXGenShader/ShaderNode.h
@@ -170,6 +170,9 @@ class MX_GENSHADER_API ShaderPort : public std::enable_shared_from_thissecond->getType()->getSize() < type->getSize())
+ {
+ it->second->setType(type);
+ }
+ }
+ else if (type != it->second->getType())
+ {
+ throw ExceptionShaderGenError("Trying to add shader port '" + name + "' with type '" +
+ type->getName() + "', but existing shader port with type '" +
+ it->second->getType()->getName() + "' was found");
+ }
return it->second.get();
}
diff --git a/source/MaterialXGenShader/ShaderStage.h b/source/MaterialXGenShader/ShaderStage.h
index 71004f8e52..a6a5cec0b8 100644
--- a/source/MaterialXGenShader/ShaderStage.h
+++ b/source/MaterialXGenShader/ShaderStage.h
@@ -113,7 +113,14 @@ class MX_GENSHADER_API VariableBlock
ShaderPort* find(const ShaderPortPredicate& predicate);
/// Add a new shader port to this block.
- ShaderPort* add(const TypeDesc* type, const string& name, ValuePtr value = nullptr);
+ /// @param type The desired shader port type
+ /// @param name The shader port name
+ /// @param value The value to attach to the shader port
+ /// @param shouldWiden When false, an exception is thrown if the type of the existing port with
+ /// the same name does not match the requested type. When true, the types can mismatch, and the
+ /// type of any existing port is widened to match the requested type when necessary.
+ /// @return A new shader port, or a pre-existing shader port with the same name.
+ ShaderPort* add(const TypeDesc* type, const string& name, ValuePtr value = nullptr, bool shouldWiden = false);
/// Add an existing shader port to this block.
void add(ShaderPortPtr port);
@@ -339,20 +346,22 @@ inline ShaderPort* addStageUniform(const string& block,
inline ShaderPort* addStageInput(const string& block,
const TypeDesc* type,
const string& name,
- ShaderStage& stage)
+ ShaderStage& stage,
+ bool shouldWiden = false)
{
VariableBlock& inputs = stage.getInputBlock(block);
- return inputs.add(type, name);
+ return inputs.add(type, name, {}, shouldWiden);
}
/// Utility function for adding a new shader port to an output block.
inline ShaderPort* addStageOutput(const string& block,
const TypeDesc* type,
const string& name,
- ShaderStage& stage)
+ ShaderStage& stage,
+ bool shouldWiden = false)
{
VariableBlock& outputs = stage.getOutputBlock(block);
- return outputs.add(type, name);
+ return outputs.add(type, name, {}, shouldWiden);
}
/// Utility function for adding a connector block between stages.
@@ -370,10 +379,11 @@ inline void addStageConnector(const string& block,
const TypeDesc* type,
const string& name,
ShaderStage& from,
- ShaderStage& to)
+ ShaderStage& to,
+ bool shouldWiden = false)
{
- addStageOutput(block, type, name, from);
- addStageInput(block, type, name, to);
+ addStageOutput(block, type, name, from, shouldWiden);
+ addStageInput(block, type, name, to, shouldWiden);
}
MATERIALX_NAMESPACE_END
diff --git a/source/MaterialXGraphEditor/CMakeLists.txt b/source/MaterialXGraphEditor/CMakeLists.txt
index 1785540bd8..f5f22be2c5 100644
--- a/source/MaterialXGraphEditor/CMakeLists.txt
+++ b/source/MaterialXGraphEditor/CMakeLists.txt
@@ -9,7 +9,7 @@ if (NOT IS_DIRECTORY "${DEAR_IMGUI_PREFIX}/backends")
endif()
if(MSVC)
- add_compile_options(-wd4100)
+ add_compile_options(-wd4100 -wd4152 -wd4201 -wd4244 -wd4456)
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")
diff --git a/source/MaterialXGraphEditor/External/Glfw/CMakeLists.txt b/source/MaterialXGraphEditor/External/Glfw/CMakeLists.txt
index eaae85a825..2ec553856f 100644
--- a/source/MaterialXGraphEditor/External/Glfw/CMakeLists.txt
+++ b/source/MaterialXGraphEditor/External/Glfw/CMakeLists.txt
@@ -41,7 +41,7 @@ if (BUILD_SHARED_LIBS AND UNIX)
# On Unix-like systems, shared libraries can use the soname system.
set(GLFW_LIB_NAME glfw)
else()
- set(GLFW_LIB_NAME glfw3)
+ set(GLFW_LIB_NAME glfw3_minimal)
endif()
if (GLFW_VULKAN_STATIC)
diff --git a/source/MaterialXGraphEditor/FileDialog.h b/source/MaterialXGraphEditor/FileDialog.h
index 49b905f28c..4b6c042ef8 100644
--- a/source/MaterialXGraphEditor/FileDialog.h
+++ b/source/MaterialXGraphEditor/FileDialog.h
@@ -16,9 +16,9 @@ class FileDialog
public:
enum Flags
{
- SelectDirectory = 1 << 0, // select directory instead of regular file
- EnterNewFilename = 1 << 1, // allow user to enter new filename when selecting regular file
- NoTitleBar = 1 << 2, // hide window title bar
+ SelectDirectory = 1 << 0, // select directory instead of regular file
+ EnterNewFilename = 1 << 1, // allow user to enter new filename when selecting regular file
+ NoTitleBar = 1 << 2, // hide window title bar
};
public:
diff --git a/source/MaterialXGraphEditor/Graph.cpp b/source/MaterialXGraphEditor/Graph.cpp
index 2b28317ee2..fc682e8f05 100644
--- a/source/MaterialXGraphEditor/Graph.cpp
+++ b/source/MaterialXGraphEditor/Graph.cpp
@@ -23,6 +23,32 @@ const ImVec2 DEFAULT_NODE_SIZE = ImVec2(138, 116);
const int DEFAULT_ALPHA = 255;
const int FILTER_ALPHA = 50;
+const std::array NODE_GROUP_ORDER =
+{
+ "texture2d",
+ "texture3d",
+ "procedural",
+ "procedural2d",
+ "procedural3d",
+ "geometric",
+ "translation",
+ "convolution2d",
+ "math",
+ "adjustment",
+ "compositing",
+ "conditional",
+ "channel",
+ "organization",
+ "global",
+ "application",
+ "material",
+ "shader",
+ "pbr",
+ "light",
+ "colortransform",
+ "none"
+};
+
// Based on ImRect_Expanded function in ImGui Node Editor blueprints-example.cpp
ImRect expandImRect(const ImRect& rect, float x, float y)
{
@@ -214,7 +240,7 @@ mx::DocumentPtr Graph::loadDocument(mx::FilePath filename)
std::cerr << "*** Validation warnings for " << filename.asString() << " ***" << std::endl;
std::cerr << message << std::endl;
}
-
+
// Cache the currently loaded file
_materialFilename = filename;
}
@@ -236,9 +262,6 @@ void Graph::addExtraNodes()
return;
}
- // Clear any old nodes, if we previously used tab with another graph doc
- _extraNodes.clear();
-
// Get all types from the doc
std::vector types;
std::vector typeDefs = _graphDoc->getTypeDefs();
@@ -252,18 +275,16 @@ void Graph::addExtraNodes()
for (const std::string& type : types)
{
std::string nodeName = "ND_input_" + type;
- _extraNodes["Input Nodes"].push_back({ nodeName, type, "input" });
+ _nodesToAdd.emplace_back(nodeName, type, "input", "Input Nodes");
nodeName = "ND_output_" + type;
- _extraNodes["Output Nodes"].push_back({ nodeName, type, "output" });
+ _nodesToAdd.emplace_back(nodeName, type, "output", "Output Nodes");
}
// Add group node
- std::vector groupNode{ "ND_group", "", "group" };
- _extraNodes["Group Nodes"].push_back(groupNode);
+ _nodesToAdd.emplace_back("ND_group", "", "group", "Group Nodes");
// Add nodegraph node
- std::vector nodeGraph{ "ND_nodegraph", "", "nodegraph" };
- _extraNodes["Node Graph"].push_back(nodeGraph);
+ _nodesToAdd.emplace_back("ND_nodegraph", "", "nodegraph", "Node Graph");
}
ed::PinId Graph::getOutputPin(UiNodePtr node, UiNodePtr upNode, UiPinPtr input)
@@ -846,7 +867,7 @@ void Graph::setRenderMaterial(UiNodePtr node)
}
}
-void Graph::updateMaterials(mx::InputPtr input, mx::ValuePtr value)
+void Graph::updateMaterials(mx::InputPtr input /* = nullptr */, mx::ValuePtr value /* = nullptr */)
{
std::string renderablePath;
if (_currRenderNode)
@@ -1224,20 +1245,37 @@ void Graph::setUiNodeInfo(UiNodePtr node, const std::string& type, const std::st
void Graph::createNodeUIList(mx::DocumentPtr doc)
{
_nodesToAdd.clear();
- const std::string EXTRA_GROUP_NAME = "extra";
- for (mx::NodeDefPtr nodeDef : doc->getNodeDefs())
+
+ auto nodeDefs = doc->getNodeDefs();
+ std::unordered_map> groupToNodeDef;
+
+ for (const auto& nodeDef : nodeDefs)
{
- // NodeDef is the key for the map
std::string group = nodeDef->getNodeGroup();
if (group.empty())
{
- group = EXTRA_GROUP_NAME;
+ group = NODE_GROUP_ORDER.back();
}
- if (_nodesToAdd.find(group) == _nodesToAdd.end())
+
+ if (groupToNodeDef.find(group) == groupToNodeDef.end())
{
- _nodesToAdd[group] = std::vector();
+ groupToNodeDef[group] = std::vector();
+ }
+ groupToNodeDef[group].push_back(nodeDef);
+ }
+
+ for (const auto& group : NODE_GROUP_ORDER)
+ {
+ auto it = groupToNodeDef.find(group);
+ if (it != groupToNodeDef.end())
+ {
+ const auto& groupNodeDefs = it->second;
+
+ for (const auto& nodeDef : groupNodeDefs)
+ {
+ _nodesToAdd.emplace_back(nodeDef->getName(), nodeDef->getType(), nodeDef->getNodeString(), group);
+ }
}
- _nodesToAdd[group].push_back(nodeDef);
}
addExtraNodes();
@@ -2064,11 +2102,11 @@ mx::InputPtr Graph::findInput(mx::InputPtr nodeInput, const std::string& name)
{
if (_isNodeGraph)
{
- for (UiNodePtr node : _graphNodes)
+ for (UiNodePtr uiNode : _graphNodes)
{
- if (node->getNode())
+ if (uiNode->getNode())
{
- for (mx::InputPtr input : node->getNode()->getActiveInputs())
+ for (mx::InputPtr input : uiNode->getNode()->getActiveInputs())
{
if (input->getInterfaceInput())
{
@@ -2219,6 +2257,7 @@ std::vector Graph::createNodes(bool nodegraph)
}
upUiNode->outputPins[pinIndex]->addConnection(pin);
+ pin->addConnection(upUiNode->outputPins[pinIndex]);
}
pin->setConnected(true);
}
@@ -2284,6 +2323,7 @@ std::vector Graph::createNodes(bool nodegraph)
}
}
upUiNode->outputPins[pinIndex]->addConnection(pin);
+ pin->addConnection(upUiNode->outputPins[pinIndex]);
}
pin->setConnected(true);
}
@@ -2354,6 +2394,7 @@ std::vector Graph::createNodes(bool nodegraph)
}
}
upUiNode->outputPins[pinIndex]->addConnection(pin);
+ pin->addConnection(upUiNode->outputPins[pinIndex]);
}
}
@@ -2483,12 +2524,22 @@ void Graph::setDefaults(mx::InputPtr input)
}
}
-void Graph::addLink(ed::PinId inputPinId, ed::PinId outputPinId)
+void Graph::addLink(ed::PinId startPinId, ed::PinId endPinId)
{
- int end_attr = int(outputPinId.Get());
- int start_attr = int(inputPinId.Get());
- UiPinPtr inputPin = getPin(outputPinId);
- UiPinPtr outputPin = getPin(inputPinId);
+ // Prefer to assume left to right - start is an output, end is an input; swap if inaccurate
+ if (UiPinPtr inputPin = getPin(endPinId); inputPin && inputPin->_kind != ed::PinKind::Input)
+ {
+ auto tmp = startPinId;
+ startPinId = endPinId;
+ endPinId = tmp;
+ }
+
+ int end_attr = int(endPinId.Get());
+ int start_attr = int(startPinId.Get());
+ ed::PinId outputPinId = startPinId;
+ ed::PinId inputPinId = endPinId;
+ UiPinPtr outputPin = getPin(outputPinId);
+ UiPinPtr inputPin = getPin(inputPinId);
if (!inputPin || !outputPin)
{
@@ -2496,7 +2547,7 @@ void Graph::addLink(ed::PinId inputPinId, ed::PinId outputPinId)
return;
}
- // Perform type check
+ // Perform type check
bool typesMatch = (outputPin->_type == inputPin->_type);
if (!typesMatch)
{
@@ -2505,187 +2556,207 @@ void Graph::addLink(ed::PinId inputPinId, ed::PinId outputPinId)
return;
}
- if (inputPin->_connected == false)
+ // Perform kind check
+ bool kindsMatch = (outputPin->_kind == inputPin->_kind);
+ if (kindsMatch)
{
- int upNode = getNodeId(inputPinId);
- int downNode = getNodeId(outputPinId);
- UiNodePtr uiDownNode = _graphNodes[downNode];
- UiNodePtr uiUpNode = _graphNodes[upNode];
- if (!uiDownNode || !uiUpNode)
- {
- ed::RejectNewItem();
- return;
- }
+ ed::RejectNewItem();
+ showLabel("Invalid connection due to same input/output kind", ImColor(50, 50, 50, 255));
+ return;
+ }
- // make sure there is an implementation for node
- const mx::ShaderGenerator& shadergen = _renderer->getGenContext().getShaderGenerator();
+ int upNode = getNodeId(outputPinId);
+ int downNode = getNodeId(inputPinId);
+ UiNodePtr uiDownNode = _graphNodes[downNode];
+ UiNodePtr uiUpNode = _graphNodes[upNode];
+ if (!uiDownNode || !uiUpNode)
+ {
+ ed::RejectNewItem();
+ return;
+ }
- // Prevent direct connecting from input to output
- if (uiDownNode->getInput() && uiUpNode->getOutput())
- {
- ed::RejectNewItem();
- showLabel("Direct connections between inputs and outputs is invalid", ImColor(50, 50, 50, 255));
- return;
- }
+ // Make sure there is an implementation for node
+ const mx::ShaderGenerator& shadergen = _renderer->getGenContext().getShaderGenerator();
- // Find the implementation for this nodedef if not an input or output uinode
- if (uiDownNode->getInput() && _isNodeGraph)
+ // Prevent direct connecting from input to output
+ if (uiDownNode->getInput() && uiUpNode->getOutput())
+ {
+ ed::RejectNewItem();
+ showLabel("Direct connections between inputs and outputs is invalid", ImColor(50, 50, 50, 255));
+ return;
+ }
+
+ // Find the implementation for this nodedef if not an input or output uinode
+ if (uiDownNode->getInput() && _isNodeGraph)
+ {
+ ed::RejectNewItem();
+ showLabel("Cannot connect to inputs inside of graph", ImColor(50, 50, 50, 255));
+ return;
+ }
+ else if (uiUpNode->getNode())
+ {
+ mx::ShaderNodeImplPtr impl = shadergen.getImplementation(*_graphNodes[upNode]->getNode()->getNodeDef(), _renderer->getGenContext());
+ if (!impl)
{
ed::RejectNewItem();
- showLabel("Cannot connect to inputs inside of graph", ImColor(50, 50, 50, 255));
+ showLabel("Invalid Connection: Node does not have an implementation", ImColor(50, 50, 50, 255));
return;
}
- else if (uiUpNode->getNode())
+ }
+
+ if (ed::AcceptNewItem())
+ {
+ // If the accepting node already has a link, remove it
+ if (inputPin->_connected)
{
- mx::ShaderNodeImplPtr impl = shadergen.getImplementation(*_graphNodes[upNode]->getNode()->getNodeDef(), _renderer->getGenContext());
- if (!impl)
+ for (auto linksItr = _currLinks.begin(); linksItr != _currLinks.end(); linksItr++)
{
- ed::RejectNewItem();
- showLabel("Invalid Connection: Node does not have an implementation", ImColor(50, 50, 50, 255));
- return;
+ if (linksItr->_endAttr == end_attr)
+ {
+ // Found existing link - remove it; adapted from deleteLink
+ // note: ed::BreakLinks doesn't work as the order ends up inaccurate
+ deleteLinkInfo(linksItr->_startAttr, linksItr->_endAttr);
+ _currLinks.erase(linksItr);
+ break;
+ }
}
}
- if (ed::AcceptNewItem())
- {
- // Since we accepted new link, lets add one to our list of links.
- Link link;
- link._startAttr = start_attr;
- link._endAttr = end_attr;
- _currLinks.push_back(link);
- _frameCount = ImGui::GetFrameCount();
- _renderer->setMaterialCompilation(true);
+ // Since we accepted new link, lets add one to our list of links.
+ Link link;
+ link._startAttr = start_attr;
+ link._endAttr = end_attr;
+ _currLinks.push_back(link);
+ _frameCount = ImGui::GetFrameCount();
+ _renderer->setMaterialCompilation(true);
+
+ inputPin->addConnection(outputPin);
+ outputPin->addConnection(inputPin);
+ outputPin->setConnected(true);
+ inputPin->setConnected(true);
- if (uiDownNode->getNode() || uiDownNode->getNodeGraph())
+ if (uiDownNode->getNode() || uiDownNode->getNodeGraph())
+ {
+ mx::InputPtr connectingInput = nullptr;
+ for (UiPinPtr pin : uiDownNode->inputPins)
{
- mx::InputPtr connectingInput = nullptr;
- for (UiPinPtr pin : uiDownNode->inputPins)
+ if (pin->_pinId == inputPinId)
{
- if (pin->_pinId == outputPinId)
+ addNodeInput(uiDownNode, pin->_input);
+
+ // Update value to be empty
+ if (uiDownNode->getNode() && uiDownNode->getNode()->getType() == mx::SURFACE_SHADER_TYPE_STRING)
{
- addNodeInput(uiDownNode, pin->_input);
- // update value to be empty
- if (uiDownNode->getNode() && uiDownNode->getNode()->getType() == mx::SURFACE_SHADER_TYPE_STRING)
+ if (uiUpNode->getOutput() != nullptr)
{
- if (uiUpNode->getOutput() != nullptr)
- {
- pin->_input->setConnectedOutput(uiUpNode->getOutput());
- }
- else if (uiUpNode->getInput() != nullptr)
- {
- pin->_input->setInterfaceName(uiUpNode->getName());
- }
- else
+ pin->_input->setConnectedOutput(uiUpNode->getOutput());
+ }
+ else if (uiUpNode->getInput() != nullptr)
+ {
+ pin->_input->setInterfaceName(uiUpNode->getName());
+ }
+ else
+ {
+ if (uiUpNode->getNodeGraph() != nullptr)
{
- // node graph
- if (uiUpNode->getNodeGraph() != nullptr)
+ for (UiPinPtr outPin : uiUpNode->outputPins)
{
- for (UiPinPtr outPin : uiUpNode->outputPins)
+ // Set pin connection to correct output
+ if (outPin->_pinId == outputPinId)
{
- // set pin connection to correct output
- if (outPin->_pinId == inputPinId)
- {
- mx::OutputPtr outputs = uiUpNode->getNodeGraph()->getOutput(outPin->_name);
- pin->_input->setConnectedOutput(outputs);
- }
+ mx::OutputPtr outputs = uiUpNode->getNodeGraph()->getOutput(outPin->_name);
+ pin->_input->setConnectedOutput(outputs);
}
}
- else
- {
- pin->_input->setConnectedNode(uiUpNode->getNode());
- }
}
+ else
+ {
+ pin->_input->setConnectedNode(uiUpNode->getNode());
+ }
+ }
+ }
+ else
+ {
+ if (uiUpNode->getInput())
+ {
+ pin->_input->setInterfaceName(uiUpNode->getName());
}
else
{
- if (uiUpNode->getInput())
- {
- pin->_input->setInterfaceName(uiUpNode->getName());
- }
- else
+ if (uiUpNode->getNode())
{
- if (uiUpNode->getNode())
+ mx::NodePtr upstreamNode = _graphNodes[upNode]->getNode();
+ mx::NodeDefPtr upstreamNodeDef = upstreamNode->getNodeDef();
+ bool isMultiOutput = upstreamNodeDef ? upstreamNodeDef->getOutputs().size() > 1 : false;
+ if (!isMultiOutput)
{
- mx::NodePtr upstreamNode = _graphNodes[upNode]->getNode();
- mx::NodeDefPtr upstreamNodeDef = upstreamNode->getNodeDef();
- bool isMultiOutput = upstreamNodeDef ? upstreamNodeDef->getOutputs().size() > 1 : false;
-
- // This is purely to avoid adding a reference to an update node only 1 output,
- // as currently validation consides adding this an error. Otherwise
- // it will add an "output" attribute all the time.
- if (!isMultiOutput)
- {
- pin->_input->setConnectedNode(uiUpNode->getNode());
- }
- else
+ pin->_input->setConnectedNode(uiUpNode->getNode());
+ }
+ else
+ {
+ for (UiPinPtr outPin : _graphNodes[upNode]->outputPins)
{
- for (UiPinPtr outPin : _graphNodes[upNode]->outputPins)
+ // Set pin connection to correct output
+ if (outPin->_pinId == outputPinId)
{
- // set pin connection to correct output
- if (outPin->_pinId == inputPinId)
+ mx::OutputPtr outputs = uiUpNode->getNode()->getOutput(outPin->_name);
+ if (!outputs)
{
- mx::OutputPtr outputs = uiUpNode->getNode()->getOutput(outPin->_name);
- if (!outputs)
- {
- outputs = uiUpNode->getNode()->addOutput(outPin->_name, pin->_input->getType());
- }
- pin->_input->setConnectedOutput(outputs);
+ outputs = uiUpNode->getNode()->addOutput(outPin->_name, pin->_input->getType());
}
+ pin->_input->setConnectedOutput(outputs);
}
}
}
- else if (uiUpNode->getNodeGraph())
+ }
+ else if (uiUpNode->getNodeGraph())
+ {
+ for (UiPinPtr outPin : uiUpNode->outputPins)
{
- for (UiPinPtr outPin : uiUpNode->outputPins)
+ // Set pin connection to correct output
+ if (outPin->_pinId == outputPinId)
{
- // set pin connection to correct output
- if (outPin->_pinId == inputPinId)
- {
- mx::OutputPtr outputs = uiUpNode->getNodeGraph()->getOutput(outPin->_name);
- pin->_input->setConnectedOutput(outputs);
- }
+ mx::OutputPtr outputs = uiUpNode->getNodeGraph()->getOutput(outPin->_name);
+ pin->_input->setConnectedOutput(outputs);
}
}
}
}
-
- pin->setConnected(true);
- pin->_input->removeAttribute(mx::ValueElement::VALUE_ATTRIBUTE);
- connectingInput = pin->_input;
- break;
}
+
+ pin->setConnected(true);
+ pin->_input->removeAttribute(mx::ValueElement::VALUE_ATTRIBUTE);
+ connectingInput = pin->_input;
+ break;
}
- // create new edge and set edge information
- createEdge(_graphNodes[upNode], _graphNodes[downNode], connectingInput);
}
- else if (_graphNodes[downNode]->getOutput() != nullptr)
- {
- mx::InputPtr connectingInput = nullptr;
- _graphNodes[downNode]->getOutput()->setConnectedNode(_graphNodes[upNode]->getNode());
- // create new edge and set edge information
- createEdge(_graphNodes[upNode], _graphNodes[downNode], connectingInput);
- }
- else
+ // Create new edge and set edge information
+ createEdge(_graphNodes[upNode], _graphNodes[downNode], connectingInput);
+ }
+ else if (_graphNodes[downNode]->getOutput() != nullptr)
+ {
+ mx::InputPtr connectingInput = nullptr;
+ _graphNodes[downNode]->getOutput()->setConnectedNode(_graphNodes[upNode]->getNode());
+
+ // Create new edge and set edge information
+ createEdge(_graphNodes[upNode], _graphNodes[downNode], connectingInput);
+ }
+ else
+ {
+ // Create new edge and set edge info
+ UiEdge newEdge = UiEdge(_graphNodes[upNode], _graphNodes[downNode], nullptr);
+ if (!edgeExists(newEdge))
{
- // create new edge and set edge info
- UiEdge newEdge = UiEdge(_graphNodes[upNode], _graphNodes[downNode], nullptr);
- if (!edgeExists(newEdge))
- {
- _graphNodes[downNode]->edges.push_back(newEdge);
- _currEdge.push_back(newEdge);
+ _graphNodes[downNode]->edges.push_back(newEdge);
+ _currEdge.push_back(newEdge);
- // update input node num and output connections
- _graphNodes[downNode]->setInputNodeNum(1);
- _graphNodes[upNode]->setOutputConnection(_graphNodes[downNode]);
- }
+ // Update input node num and output connections
+ _graphNodes[downNode]->setInputNodeNum(1);
+ _graphNodes[upNode]->setOutputConnection(_graphNodes[downNode]);
}
}
}
- else
- {
- ed::RejectNewItem();
- }
}
void Graph::removeEdge(int downNode, int upNode, UiPinPtr pin)
@@ -2739,9 +2810,13 @@ void Graph::deleteLinkInfo(int startAttr, int endAttr)
setDefaults(_graphNodes[upNode]->getInput());
}
+ for (UiPinPtr connect : pin->_connections)
+ {
+ pin->deleteConnection(connect);
+ }
+
// Remove any output reference
pin->_input->removeAttribute(mx::PortElement::OUTPUT_ATTRIBUTE);
-
pin->setConnected(false);
// If a value exists update the input with it
@@ -2766,6 +2841,10 @@ void Graph::deleteLinkInfo(int startAttr, int endAttr)
_graphNodes[downNode]->getNodeGraph()->getInput(pin->_name)->removeAttribute(mx::ValueElement::INTERFACE_NAME_ATTRIBUTE);
setDefaults(_graphNodes[upNode]->getInput());
}
+ for (UiPinPtr connect : pin->_connections)
+ {
+ pin->deleteConnection(connect);
+ }
pin->_input->setConnectedNode(nullptr);
pin->setConnected(false);
setDefaults(pin->_input);
@@ -2780,6 +2859,10 @@ void Graph::deleteLinkInfo(int startAttr, int endAttr)
{
removeEdge(downNode, upNode, pin);
_graphNodes[downNode]->getOutput()->removeAttribute("nodename");
+ for (UiPinPtr connect : pin->_connections)
+ {
+ pin->deleteConnection(connect);
+ }
pin->setConnected(false);
}
}
@@ -3009,7 +3092,7 @@ void Graph::loadGraphFromFile(bool prompt)
_fileDialog.open();
}
else
- {
+ {
_graphDoc = loadDocument(_materialFilename);
// Rebuild the UI
@@ -3020,7 +3103,7 @@ void Graph::loadGraphFromFile(bool prompt)
_renderer->setDocument(_graphDoc);
_renderer->updateMaterials(nullptr);
- }
+ }
}
void Graph::saveGraphToFile()
@@ -3157,13 +3240,27 @@ void Graph::graphButtons()
// Create two windows using splitter
float paneWidth = (leftPaneWidth - 2.0f);
- ImGui::BeginChild("Selection", ImVec2(paneWidth, 0));
+
+ float aspectRatio = _renderer->getPixelRatio();
+ ImVec2 screenSize = ImVec2(paneWidth, paneWidth / aspectRatio);
+
+ ImVec2 mousePos = ImGui::GetMousePos();
+ ImVec2 tempWindowPos = ImGui::GetCursorPos();
+ bool cursorInRenderView = mousePos.x > tempWindowPos.x && mousePos.x < (tempWindowPos.x + screenSize.x) &&
+ mousePos.y > tempWindowPos.y && mousePos.y < (tempWindowPos.y + screenSize.y);
+
+ ImGuiWindowFlags windowFlags = 0;
+
+ if (cursorInRenderView)
+ {
+ windowFlags |= ImGuiWindowFlags_NoScrollWithMouse;
+ }
+
+ ImGui::BeginChild("Selection", ImVec2(paneWidth, 0), false, windowFlags);
ImVec2 windowPos = ImGui::GetWindowPos();
// RenderView window
ImVec2 wsize = ImVec2((float) _renderer->getViewWidth(), (float) _renderer->getViewHeight());
- float aspectRatio = _renderer->getPixelRatio();
- ImVec2 screenSize = ImVec2(paneWidth, paneWidth / aspectRatio);
_renderer->setViewWidth((int) screenSize[0]);
_renderer->setViewHeight((int) screenSize[1]);
@@ -3183,7 +3280,10 @@ void Graph::graphButtons()
ImGui::EndChild();
ImGui::SameLine(0.0f, 12.0f);
- handleRenderViewInputs(windowPos, screenSize[0], screenSize[1]);
+ if (cursorInRenderView)
+ {
+ handleRenderViewInputs();
+ }
}
void Graph::propertyEditor()
@@ -3205,16 +3305,16 @@ void Graph::propertyEditor()
std::string name = _currUiNode->getNode()->getParent()->createValidChildName(temp);
std::vector downstreamNodes = _currUiNode->getOutputConnections();
- for (UiNodePtr nodes : downstreamNodes)
+ for (UiNodePtr uiNode : downstreamNodes)
{
- if (nodes->getInput() == nullptr)
+ if (!uiNode->getInput() && uiNode->getNode())
{
- for (mx::InputPtr input : nodes->getNode()->getActiveInputs())
+ for (mx::InputPtr input : uiNode->getNode()->getActiveInputs())
{
if (input->getConnectedNode() == _currUiNode->getNode())
{
_currUiNode->getNode()->setName(name);
- nodes->getNode()->setConnectedNode(input->getName(), _currUiNode->getNode());
+ uiNode->getNode()->setConnectedNode(input->getName(), _currUiNode->getNode());
}
}
}
@@ -3229,13 +3329,13 @@ void Graph::propertyEditor()
{
std::string name = _currUiNode->getInput()->getParent()->createValidChildName(temp);
std::vector downstreamNodes = _currUiNode->getOutputConnections();
- for (UiNodePtr nodes : downstreamNodes)
+ for (UiNodePtr uiNode : downstreamNodes)
{
- if (nodes->getInput() == nullptr)
+ if (uiNode->getInput() == nullptr)
{
- if (nodes->getNode())
+ if (uiNode->getNode())
{
- for (mx::InputPtr input : nodes->getNode()->getActiveInputs())
+ for (mx::InputPtr input : uiNode->getNode()->getActiveInputs())
{
if (input->getInterfaceInput() == _currUiNode->getInput())
{
@@ -3248,7 +3348,7 @@ void Graph::propertyEditor()
}
else
{
- nodes->getOutput()->setConnectedNode(_currUiNode->getNode());
+ uiNode->getOutput()->setConnectedNode(_currUiNode->getNode());
}
}
}
@@ -3566,96 +3666,65 @@ void Graph::addNodePopup(bool cursor)
// Input string length
// Filter extra nodes - includes inputs, outputs, groups, and node graphs
const std::string NODEGRAPH_ENTRY = "Node Graph";
- for (std::unordered_map>>::iterator it = _extraNodes.begin(); it != _extraNodes.end(); ++it)
+
+ // Filter nodedefs and add to menu if matches filter
+ for (auto node : _nodesToAdd)
{
// Filter out list of nodes
if (subs.size() > 0)
{
ImGui::SetNextWindowSizeConstraints(ImVec2(250.0f, 300.0f), ImVec2(-1.0f, 500.0f));
- for (size_t i = 0; i < it->second.size(); i++)
- {
- std::string str(it->second[i][0]);
- std::string nodeName = it->second[i][0];
+ std::string str(node.getName());
+ std::string nodeName = node.getName();
- // Disallow creating nested nodegraphs
- if (_isNodeGraph && it->first == NODEGRAPH_ENTRY)
- {
- continue;
- }
+ // Disallow creating nested nodegraphs
+ if (_isNodeGraph && node.getGroup() == NODEGRAPH_ENTRY)
+ {
+ continue;
+ }
- // Allow spaces to be used to search for node names
- std::replace(subs.begin(), subs.end(), ' ', '_');
+ // Allow spaces to be used to search for node names
+ std::replace(subs.begin(), subs.end(), ' ', '_');
- if (str.find(subs) != std::string::npos)
+ if (str.find(subs) != std::string::npos)
+ {
+ if (ImGui::MenuItem(getUserNodeDefName(nodeName).c_str()) || (ImGui::IsItemFocused() && ImGui::IsKeyPressedMap(ImGuiKey_Enter)))
{
- if (ImGui::MenuItem(getUserNodeDefName(nodeName).c_str()) || (ImGui::IsItemFocused() && ImGui::IsKeyPressedMap(ImGuiKey_Enter)))
- {
- addNode(it->second[i][2], getUserNodeDefName(nodeName), it->second[i][1]);
- _addNewNode = true;
- memset(input, '\0', sizeof(input));
- }
+ addNode(node.getCategory(), getUserNodeDefName(nodeName), node.getType());
+ _addNewNode = true;
+ memset(input, '\0', sizeof(input));
}
}
}
else
{
ImGui::SetNextWindowSizeConstraints(ImVec2(100, 10), ImVec2(-1, 300));
- if (ImGui::BeginMenu(it->first.c_str()))
+ if (ImGui::BeginMenu(node.getGroup().c_str()))
{
ImGui::SetWindowFontScale(_fontScale);
- for (size_t j = 0; j < it->second.size(); j++)
+ std::string name = node.getName();
+ std::string prefix = "ND_";
+ if (name.compare(0, prefix.size(), prefix) == 0 && name.compare(prefix.size(), std::string::npos, node.getCategory()) == 0)
{
- std::string name = it->second[j][0];
if (ImGui::MenuItem(getUserNodeDefName(name).c_str()) || (ImGui::IsItemFocused() && ImGui::IsKeyPressedMap(ImGuiKey_Enter)))
{
- addNode(it->second[j][2], getUserNodeDefName(name), it->second[j][1]);
- _addNewNode = true;
- }
- }
- ImGui::EndMenu();
- }
- }
- }
-
- // Filter nodedefs and add to menu if matches filter
- for (std::unordered_map>::iterator it = _nodesToAdd.begin(); it != _nodesToAdd.end(); ++it)
- {
- // Filter out list of nodes
- if (subs.size() > 0)
- {
- ImGui::SetNextWindowSizeConstraints(ImVec2(250.0f, 300.0f), ImVec2(-1.0f, 500.0f));
- for (size_t i = 0; i < it->second.size(); i++)
- {
- std::string str(it->second[i]->getName());
- std::string nodeName = it->second[i]->getName();
- if (str.find(subs) != std::string::npos)
- {
- std::string val = getUserNodeDefName(nodeName);
- if (ImGui::MenuItem(val.c_str()) || (ImGui::IsItemFocused() && ImGui::IsKeyPressedMap(ImGuiKey_Enter)))
- {
- addNode(it->second[i]->getNodeString(), val, it->second[i]->getType());
+ addNode(node.getCategory(), getUserNodeDefName(name), node.getType());
_addNewNode = true;
- memset(input, '\0', sizeof(input));
}
}
- }
- }
- else
- {
- ImGui::SetNextWindowSizeConstraints(ImVec2(100, 10), ImVec2(-1, 300));
- if (ImGui::BeginMenu(it->first.c_str()))
- {
- ImGui::SetWindowFontScale(_fontScale);
- for (size_t i = 0; i < it->second.size(); i++)
+ else
{
- std::string name = it->second[i]->getName();
- std::string val = getUserNodeDefName(name);
- if (ImGui::MenuItem(val.c_str()) || (ImGui::IsItemFocused() && ImGui::IsKeyPressedMap(ImGuiKey_Enter)))
+ if (ImGui::BeginMenu(node.getCategory().c_str()))
{
- addNode(it->second[i]->getNodeString(), val, it->second[i]->getType());
- _addNewNode = true;
+ if (ImGui::MenuItem(getUserNodeDefName(name).c_str()) || (ImGui::IsItemFocused() && ImGui::IsKeyPressedMap(ImGuiKey_Enter)))
+ {
+ addNode(node.getCategory(), getUserNodeDefName(name), node.getType());
+ _addNewNode = true;
+ }
+ ImGui::EndMenu();
}
}
+
ImGui::EndMenu();
}
}
@@ -3707,6 +3776,41 @@ void Graph::searchNodePopup(bool cursor)
}
}
+bool Graph::isPinHovered()
+{
+ ed::PinId currentPin = ed::GetHoveredPin();
+ ed::PinId nullPin = 0;
+ return currentPin != nullPin;
+}
+
+void Graph::addPinPopup()
+{
+ // Add a floating popup to pin when hovered
+ if (isPinHovered())
+ {
+ ed::Suspend();
+ UiPinPtr pin = getPin(ed::GetHoveredPin());
+ std::string connected;
+ std::string value;
+ if (pin->_connected)
+ {
+ mx::StringVec connectedNames;
+ for (UiPinPtr connectedPin : pin->getConnections())
+ {
+ connectedNames.push_back(connectedPin->_name);
+ }
+ connected = "\nConnected to " + mx::joinStrings(connectedNames, ", ");
+ }
+ else if (pin->_input)
+ {
+ value = "\nValue: " + pin->_input->getValueString();
+ }
+ const std::string message("Name: " + pin->_name + "\nType: " + pin->_type + value + connected);
+ ImGui::SetTooltip("%s", message.c_str());
+ ed::Resume();
+ }
+}
+
void Graph::readOnlyPopup()
{
if (_popup)
@@ -3741,55 +3845,52 @@ void Graph::shaderPopup()
}
}
-void Graph::handleRenderViewInputs(ImVec2 minValue, float width, float height)
+void Graph::handleRenderViewInputs()
{
ImVec2 mousePos = ImGui::GetMousePos();
- if (mousePos.x > minValue.x && mousePos.x < (minValue.x + width) && mousePos.y > minValue.y && mousePos.y < (minValue.y + height))
+ mx::Vector2 mxMousePos = mx::Vector2(mousePos.x, mousePos.y);
+ float scrollAmt = ImGui::GetIO().MouseWheel;
+ int button = -1;
+ bool down = false;
+ if (ImGui::IsMouseDragging(0) || ImGui::IsMouseDragging(1))
{
- mx::Vector2 mxMousePos = mx::Vector2(mousePos.x, mousePos.y);
- float scrollAmt = ImGui::GetIO().MouseWheel;
- int button = -1;
- bool down = false;
- if (ImGui::IsMouseDragging(0) || ImGui::IsMouseDragging(1))
- {
- _renderer->setMouseMotionEvent(mxMousePos);
- }
- if (ImGui::IsMouseClicked(0))
- {
- button = 0;
- down = true;
- _renderer->setMouseButtonEvent(button, down, mxMousePos);
- }
- else if (ImGui::IsMouseClicked(1))
- {
- button = 1;
- down = true;
- _renderer->setMouseButtonEvent(button, down, mxMousePos);
- }
- else if (ImGui::IsMouseReleased(0))
- {
- button = 0;
- _renderer->setMouseButtonEvent(button, down, mxMousePos);
- }
- else if (ImGui::IsMouseReleased(1))
- {
- button = 1;
- _renderer->setMouseButtonEvent(button, down, mxMousePos);
- }
- else if (ImGui::IsKeyPressed(ImGuiKey_KeypadAdd))
- {
- _renderer->setKeyEvent(ImGuiKey_KeypadAdd);
- }
- else if (ImGui::IsKeyPressed(ImGuiKey_KeypadSubtract))
- {
- _renderer->setKeyEvent(ImGuiKey_KeypadSubtract);
- }
+ _renderer->setMouseMotionEvent(mxMousePos);
+ }
+ if (ImGui::IsMouseClicked(0))
+ {
+ button = 0;
+ down = true;
+ _renderer->setMouseButtonEvent(button, down, mxMousePos);
+ }
+ else if (ImGui::IsMouseClicked(1))
+ {
+ button = 1;
+ down = true;
+ _renderer->setMouseButtonEvent(button, down, mxMousePos);
+ }
+ else if (ImGui::IsMouseReleased(0))
+ {
+ button = 0;
+ _renderer->setMouseButtonEvent(button, down, mxMousePos);
+ }
+ else if (ImGui::IsMouseReleased(1))
+ {
+ button = 1;
+ _renderer->setMouseButtonEvent(button, down, mxMousePos);
+ }
+ else if (ImGui::IsKeyPressed(ImGuiKey_KeypadAdd))
+ {
+ _renderer->setKeyEvent(ImGuiKey_KeypadAdd);
+ }
+ else if (ImGui::IsKeyPressed(ImGuiKey_KeypadSubtract))
+ {
+ _renderer->setKeyEvent(ImGuiKey_KeypadSubtract);
+ }
- // Scrolling not possible if open or save file dialog is open
- if (scrollAmt != 0 && !_fileDialogSave.isOpened() && !_fileDialog.isOpened() && !_fileDialogGeom.isOpened())
- {
- _renderer->setScrollEvent(scrollAmt);
- }
+ // Scrolling not possible if open or save file dialog is open
+ if (scrollAmt != 0 && !_fileDialogSave.isOpened() && !_fileDialog.isOpened() && !_fileDialogGeom.isOpened())
+ {
+ _renderer->setScrollEvent(scrollAmt);
}
}
@@ -3823,6 +3924,7 @@ void Graph::drawGraph(ImVec2 mousePos)
ImGui::SetNextWindowSizeConstraints(ImVec2(250.0f, 300.0f), ImVec2(-1.0f, 500.0f));
addNodePopup(TextCursor);
searchNodePopup(TextCursor);
+ addPinPopup();
readOnlyPopup();
ImGui::PopStyleVar();
@@ -4045,12 +4147,12 @@ void Graph::drawGraph(ImVec2 mousePos)
// Add new link
if (ed::BeginCreate())
{
- ed::PinId inputPinId, outputPinId, filterPinId;
- if (ed::QueryNewLink(&inputPinId, &outputPinId))
+ ed::PinId startPinId, endPinId, filterPinId;
+ if (ed::QueryNewLink(&startPinId, &endPinId))
{
if (!readOnly())
{
- addLink(inputPinId, outputPinId);
+ addLink(startPinId, endPinId);
}
else
{
diff --git a/source/MaterialXGraphEditor/Graph.h b/source/MaterialXGraphEditor/Graph.h
index 8c76f0f68d..821ecf71fd 100644
--- a/source/MaterialXGraphEditor/Graph.h
+++ b/source/MaterialXGraphEditor/Graph.h
@@ -14,6 +14,30 @@
#include
+class MenuItem
+{
+ public:
+ MenuItem(const std::string& name, const std::string& type, const std::string& category, const std::string& group) :
+ name(name), type(type), category(category), group(group) { }
+
+ // getters
+ std::string getName() const { return name; }
+ std::string getType() const { return type; }
+ std::string getCategory() const { return category; }
+ std::string getGroup() const { return group; }
+
+ // setters
+ void setName(const std::string& newName) { this->name = newName; }
+ void setType(const std::string& newType) { this->type = newType; }
+ void setCategory(const std::string& newCategory) { this->category = newCategory; }
+ void setGroup(const std::string& newGroup) { this->group = newGroup; }
+
+ private:
+ std::string name;
+ std::string type;
+ std::string category;
+ std::string group;
+};
namespace ed = ax::NodeEditor;
namespace mx = MaterialX;
@@ -90,7 +114,9 @@ class Graph
// Add link to nodegraph and set up connections between UiNodes and
// MaterialX Nodes to update shader
- void addLink(ed::PinId inputPinId, ed::PinId outputPinId);
+ // startPinId - where the link was initiated
+ // endPinId - where the link was ended
+ void addLink(ed::PinId startPinId, ed::PinId endPinId);
// Delete link from current link vector and remove any connections in
// UiNode or MaterialX Nodes to update shader
@@ -187,6 +213,8 @@ class Graph
void addNodePopup(bool cursor);
void searchNodePopup(bool cursor);
+ bool isPinHovered();
+ void addPinPopup();
bool readOnly();
void readOnlyPopup();
@@ -197,7 +225,7 @@ class Graph
void selectMaterial(UiNodePtr node);
// Allow for camera manipulation of render view window
- void handleRenderViewInputs(ImVec2 minValue, float width, float height);
+ void handleRenderViewInputs();
// Set the node to display in render view based on selected node or nodegraph
void setRenderMaterial(UiNodePtr node);
@@ -246,8 +274,7 @@ class Graph
std::vector _currGraphName;
// for adding new nodes
- std::unordered_map> _nodesToAdd;
- std::unordered_map>> _extraNodes;
+ std::vector