diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml
index c11603dd70..3f67667550 100644
--- a/.github/workflows/main.yml
+++ b/.github/workflows/main.yml
@@ -68,10 +68,10 @@ jobs:
cmake_config: -DMATERIALX_BUILD_SHARED_LIBS=ON
python: 3.9
- - name: MacOS_Xcode_14_Python311
+ - name: MacOS_Xcode_15_Python311
os: macos-14
compiler: xcode
- compiler_version: "14.3"
+ compiler_version: "15.1"
python: 3.11
static_analysis: ON
cmake_config: -DCMAKE_EXPORT_COMPILE_COMMANDS=ON
@@ -389,7 +389,7 @@ jobs:
fail-fast: false
matrix:
python-minor: ['7', '8', '9', '10', '11', '12']
- os: ['ubuntu-22.04', 'windows-2022', 'macos-13']
+ os: ['ubuntu-22.04', 'windows-2022', 'macos-14-large']
steps:
- name: Sync Repository
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 3fedc1ceaa..6fb0c98143 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -2,6 +2,32 @@
## [1.39.2] - Development
+### Added
+- Added support for the [Chiang Hair BSDF](https://github.com/AcademySoftwareFoundation/MaterialX/pull/1968), with initial implementations in hardware shading languages and MDL.
+- Added support for the [Disney Principled](https://github.com/AcademySoftwareFoundation/MaterialX/pull/2004) shading model, implemented as a language-independent graph.
+- Added support for [data library referencing](https://github.com/AcademySoftwareFoundation/MaterialX/pull/2054), enabling improved performance in shader generation.
+- Added support for [custom structure types](https://github.com/AcademySoftwareFoundation/MaterialX/pull/1831) in MaterialX.
+- Added support for [functional equivalence](https://github.com/AcademySoftwareFoundation/MaterialX/pull/2003) tests between MaterialX elements.
+- Added support for [transmission effects](https://github.com/AcademySoftwareFoundation/MaterialX/pull/2027) in the translation graph from Standard Surface to glTF PBR.
+- Added support for [coated emission](https://github.com/AcademySoftwareFoundation/MaterialX/pull/2087) in the translation graph from Standard Surface to UsdPreviewSurface.
+- Added support for [Apple framework builds](https://github.com/AcademySoftwareFoundation/MaterialX/pull/2020).
+- Added support for [MDL 1.9](https://github.com/AcademySoftwareFoundation/MaterialX/pull/2102) in shader generation.
+- Added support for [viewdirection space](https://github.com/AcademySoftwareFoundation/MaterialX/pull/2036) in hardware shading languages.
+- Added a [combined version define](https://github.com/AcademySoftwareFoundation/MaterialX/pull/2031) to MaterialX C++.
+- Added a [release signing workflow](https://github.com/AcademySoftwareFoundation/MaterialX/pull/2009) to GitHub Actions.
+- Added documentation for [keyboard shortcuts](https://github.com/AcademySoftwareFoundation/MaterialX/pull/2026) in the MaterialX Viewer.
+
+### Changed
+- Reduced duplication between the [MSL and GLSL implementations](https://github.com/AcademySoftwareFoundation/MaterialX/pull/2068) of nodes.
+
+### Fixed
+- Fixed [unintentional camera orbiting](https://github.com/AcademySoftwareFoundation/MaterialX/pull/2032) in the render view of the MaterialX Graph Editor.
+- Fixed [banding artifacts](https://github.com/AcademySoftwareFoundation/MaterialX/pull/1977) in the MaterialX Viewer on MacOS.
+- Fixed a call to the [anisotropic_vdf closure](https://github.com/AcademySoftwareFoundation/MaterialX/pull/2016) in OSL shader generation.
+
+### Removed
+- Removed support for the [legacy OSL closures](https://github.com/AcademySoftwareFoundation/MaterialX/pull/2121), focusing exclusively on the MaterialX-synchronized closures in OSL 1.12 and beyond.
+
## [1.39.1] - 2024-09-03
### Added
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 31db83e8fe..569cceeebd 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -57,7 +57,6 @@ option(MATERIALX_TEST_RENDER "Run rendering tests for MaterialX Render module. G
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." OFF)
option(MATERIALX_BUILD_IOS "Build MaterialX for iOS. (Deprecated. Set CMAKE_SYSTEM_NAME instead)" OFF)
option(MATERIALX_BUILD_APPLE_FRAMEWORK "Build MaterialX as an Apple Framework" ${__build_apple_framework})
@@ -180,7 +179,6 @@ mark_as_advanced(MATERIALX_PYTHON_EXECUTABLE)
mark_as_advanced(MATERIALX_PYTHON_OCIO_DIR)
mark_as_advanced(MATERIALX_PYTHON_PYBIND11_DIR)
mark_as_advanced(MATERIALX_OIIO_DIR)
-mark_as_advanced(MATERIALX_OSL_LEGACY_CLOSURES)
mark_as_advanced(MATERIALX_OSL_BINARY_OSLC)
mark_as_advanced(MATERIALX_OSL_BINARY_TESTRENDER)
mark_as_advanced(MATERIALX_OSL_INCLUDE_PATH)
@@ -227,9 +225,6 @@ if(MATERIALX_BUILD_RENDER AND MATERIALX_BUILD_GEN_OSL AND MATERIALX_BUILD_TESTS)
endif()
# Add global definitions
-if (MATERIALX_OSL_LEGACY_CLOSURES)
- add_definitions(-DMATERIALX_OSL_LEGACY_CLOSURES)
-endif()
if(MATERIALX_BUILD_OIIO)
add_definitions(-DMATERIALX_BUILD_OIIO)
endif()
diff --git a/documents/Specification/MaterialX.Proposals.md b/documents/Specification/MaterialX.Proposals.md
index 86c165128e..1aaa930923 100644
--- a/documents/Specification/MaterialX.Proposals.md
+++ b/documents/Specification/MaterialX.Proposals.md
@@ -188,7 +188,25 @@ We have a standard 3d fractal noise, but a 2d variant would be useful as well.
* `period` (float or vector3): the positive integer distance at which the noise function returns the same value for input coordinate repeated at that step. Default is 0, meaning the noise is not periodic.
* `in` (float): the 1D coordinate at which the noise is evaluated.
+
+Expanded 2D Worley noise to support different distance metrics and periodicity.
+
+* **`worleynoise2d`**: 2D Worley noise using centered jitter, outputting float (distance metric to closest feature), vector2 (distance metrics to closest 2 features) or vector3 (distance metrics to closest 3 features).
+ * `metric` (uniform string): the distance metric to return, one of "distance" (Euclidean distance to feature), "distance2" (Euclidean distance squared), "manhattan" or "chebyshev". Default is "distance".
+ * `period` (float or vector3): the positive integer distance at which the noise function returns the same value for texture coordinates repeated at that step. Default is 0, meaning the noise is not periodic.
+
+
+
+Expanded 3D Worley noise to support different distance metrics and periodicity.
+
+* **`worleynoise3d`**: 3D Worley noise using centered jitter, outputting float (distance metric to closest feature), vector2 (distance metrics to closest 2 features) or vector3 (distance metrics to closest 3 features).
+ * `metric` (uniform string): the distance metric to return, one of "distance" (Euclidean distance to feature), "distance2" (Euclidean distance squared), "manhattan" or "chebyshev". Default is "distance".
+ * `period` (float or vector3): the positive integer distance at which the noise function returns the same value for position coordinates repeated at that step. Default is 0, meaning the noise is not periodic.
+
+#### Periodic Noises
+
+In #1201 it was decided that separate periodic versions of all of the noises is preferred to adding it to the existing noises.
### Shape Nodes
diff --git a/documents/Specification/MaterialX.Specification.md b/documents/Specification/MaterialX.Specification.md
index df4f561978..4ad29dc963 100644
--- a/documents/Specification/MaterialX.Specification.md
+++ b/documents/Specification/MaterialX.Specification.md
@@ -887,16 +887,12 @@ Standard Noise nodes:
* **`worleynoise2d`**: 2D Worley noise using centered jitter, outputting float (distance metric to closest feature), vector2 (distance metrics to closest 2 features) or vector3 (distance metrics to closest 3 features).
- * `metric` (uniform string): the distance metric to return, one of "distance" (Euclidean distance to feature), "distance2" (Euclidean distance squared), "manhattan" or "chebyshev". Default is "distance".
- * `period` (float or vector3): the positive integer distance at which the noise function returns the same value for texture coordinates repeated at that step. Default is 0, meaning the noise is not periodic.
* `jitter` (float): amount to jitter the cell center position, with smaller values creating a more regular pattern. Default is 1.0.
* `texcoord` (vector2): the 2D position at which the noise is evaluated. Default is to use the first set of texture coordinates.
* **`worleynoise3d`**: 3D Worley noise using centered jitter, outputting float (distance metric to closest feature), vector2 (distance metrics to closest 2 features) or vector3 (distance metrics to closest 3 features).
- * `metric` (uniform string): the distance metric to return, one of "distance" (Euclidean distance to feature), "distance2" (Euclidean distance squared), "manhattan" or "chebyshev". Default is "distance".
- * `period` (float or vector3): the positive integer distance at which the noise function returns the same value for position coordinates repeated at that step. Default is 0, meaning the noise is not periodic.
* `jitter` (float): amount to jitter the cell center position, with smaller values creating a more regular pattern. Default is 1.0.
* `position` (vector3): the 3D position at which the noise is evaluated. Default is to use the current 3D object-space coordinate.
diff --git a/javascript/MaterialXView/source/viewer.js b/javascript/MaterialXView/source/viewer.js
index febe34c809..e558ad0bc9 100644
--- a/javascript/MaterialXView/source/viewer.js
+++ b/javascript/MaterialXView/source/viewer.js
@@ -90,14 +90,14 @@ export class Scene
}
this.#_rootNode = null;
- const model = gltfData.scene;
+ let model = gltfData.scene;
if (!model)
{
const geometry = new THREE.BoxGeometry(1, 1, 1);
const material = new THREE.MeshBasicMaterial({ color: 0xdddddd });
const cube = new THREE.Mesh(geometry, material);
- obj = new Group();
- obj.add(geometry);
+ model = new Group();
+ model.add(cube);
}
else
{
diff --git a/libraries/CMakeLists.txt b/libraries/CMakeLists.txt
index d60a54cf3b..6852090932 100644
--- a/libraries/CMakeLists.txt
+++ b/libraries/CMakeLists.txt
@@ -1,15 +1,9 @@
-if (MATERIALX_OSL_LEGACY_CLOSURES)
- set(PBRLIB_SUFFIX "legacy")
-else()
- set(PBRLIB_SUFFIX "mtlx")
-endif()
-
if(NOT SKBUILD)
install(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/
DESTINATION "${MATERIALX_INSTALL_STDLIB_PATH}"
PATTERN "CMakeLists.txt" EXCLUDE
PATTERN "pbrlib_genosl_impl.*" EXCLUDE)
- install(FILES "${CMAKE_CURRENT_SOURCE_DIR}/pbrlib/genosl/pbrlib_genosl_impl.${PBRLIB_SUFFIX}"
+ install(FILES "${CMAKE_CURRENT_SOURCE_DIR}/pbrlib/genosl/pbrlib_genosl_impl.mtlx"
DESTINATION "${MATERIALX_INSTALL_STDLIB_PATH}/pbrlib/genosl/" RENAME pbrlib_genosl_impl.mtlx)
endif()
@@ -23,6 +17,6 @@ if(MATERIALX_BUILD_PYTHON)
DESTINATION "${MATERIALX_PYTHON_LIBRARIES_PATH}"
PATTERN "CMakeLists.txt" EXCLUDE
PATTERN "pbrlib_genosl_impl.*" EXCLUDE)
- install(FILES "${CMAKE_CURRENT_SOURCE_DIR}/pbrlib/genosl/pbrlib_genosl_impl.${PBRLIB_SUFFIX}"
+ install(FILES "${CMAKE_CURRENT_SOURCE_DIR}/pbrlib/genosl/pbrlib_genosl_impl.mtlx"
DESTINATION "${MATERIALX_PYTHON_LIBRARIES_PATH}/pbrlib/genosl/" RENAME pbrlib_genosl_impl.mtlx)
endif()
diff --git a/libraries/README.md b/libraries/README.md
index 15916f76e2..0ace221bcc 100644
--- a/libraries/README.md
+++ b/libraries/README.md
@@ -74,7 +74,4 @@ This folder contains the standard data libraries for MaterialX, providing declar
- Basic GLSL and MSL `lightshader` node definitions and implementations are provided for the following light types:
- point, directional, spot
- Shader generation does not currently support:
- - `ambientocclusion` node.
- - `arrayappend` node.
- - `curveadjust` node.
- `displacementshader` and `volumeshader` nodes for hardware shading targets (GLSL, MSL).
diff --git a/libraries/bxdf/translation/standard_surface_to_usd.mtlx b/libraries/bxdf/translation/standard_surface_to_usd.mtlx
index 51c7d5fc6e..f1009e3a4c 100644
--- a/libraries/bxdf/translation/standard_surface_to_usd.mtlx
+++ b/libraries/bxdf/translation/standard_surface_to_usd.mtlx
@@ -12,6 +12,8 @@
+
+
@@ -47,13 +49,18 @@
+
+
+
+
+
-
+
diff --git a/libraries/bxdf/usd_preview_surface.mtlx b/libraries/bxdf/usd_preview_surface.mtlx
index 62600842cc..afc6954af9 100644
--- a/libraries/bxdf/usd_preview_surface.mtlx
+++ b/libraries/bxdf/usd_preview_surface.mtlx
@@ -6,21 +6,21 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/libraries/pbrlib/genmdl/pbrlib_genmdl_impl.mtlx b/libraries/pbrlib/genmdl/pbrlib_genmdl_impl.mtlx
index c8f23958ae..45f83f164a 100644
--- a/libraries/pbrlib/genmdl/pbrlib_genmdl_impl.mtlx
+++ b/libraries/pbrlib/genmdl/pbrlib_genmdl_impl.mtlx
@@ -2,7 +2,7 @@
-
+
@@ -11,13 +11,13 @@
-
+
-
+
diff --git a/libraries/pbrlib/genosl/legacy/mx_anisotropic_vdf.osl b/libraries/pbrlib/genosl/legacy/mx_anisotropic_vdf.osl
deleted file mode 100644
index 6d52e08509..0000000000
--- a/libraries/pbrlib/genosl/legacy/mx_anisotropic_vdf.osl
+++ /dev/null
@@ -1,5 +0,0 @@
-void mx_anisotropic_vdf(vector absorption, vector scattering, float anisotropy, output VDF vdf)
-{
- // Not implemented in vanilla OSL
- vdf = 0; // volume_henyey_greenstein(color(absorption), color(scattering), color(0.0), anisotropy);
-}
diff --git a/libraries/pbrlib/genosl/legacy/mx_burley_diffuse_bsdf.osl b/libraries/pbrlib/genosl/legacy/mx_burley_diffuse_bsdf.osl
deleted file mode 100644
index 5f7d397dce..0000000000
--- a/libraries/pbrlib/genosl/legacy/mx_burley_diffuse_bsdf.osl
+++ /dev/null
@@ -1,6 +0,0 @@
-void mx_burley_diffuse_bsdf(float weight, color reflectance, float roughness, normal N, output BSDF bsdf)
-{
- // TODO: Implement properly.
- bsdf.response = reflectance * weight * oren_nayar(N, roughness);
- bsdf.throughput = color(0.0);
-}
diff --git a/libraries/pbrlib/genosl/legacy/mx_conductor_bsdf.osl b/libraries/pbrlib/genosl/legacy/mx_conductor_bsdf.osl
deleted file mode 100644
index 82cb6f32be..0000000000
--- a/libraries/pbrlib/genosl/legacy/mx_conductor_bsdf.osl
+++ /dev/null
@@ -1,32 +0,0 @@
-#include "../lib/mx_microfacet_specular.osl"
-
-void mx_conductor_bsdf(float weight, color ior_n, color ior_k, vector2 roughness, float thinfilm_thickness, float thinfilm_ior, normal N, vector U, string distribution, output BSDF bsdf)
-{
- bsdf.throughput = color(0.0);
-
- if (weight < M_FLOAT_EPS)
- {
- bsdf.response = 0;
- return;
- }
-
- // Calculate conductor fresnel
- //
- // Fresnel should be based on microfacet normal
- // but we have no access to that from here, so just use
- // view direction and surface normal instead
- //
- float NdotV = fabs(dot(N,-I));
- color F = mx_fresnel_conductor(NdotV, ior_n, ior_k);
-
- // Calculate compensation for multiple scattering.
- // This should normally be done inside the closure
- // but since vanilla OSL doesen't support this we
- // add it here in shader code instead.
- vector2 safeAlpha = clamp(roughness, M_FLOAT_EPS, 1.0);
- float avgAlpha = mx_average_alpha(safeAlpha);
- color comp = mx_ggx_energy_compensation(NdotV, avgAlpha, F);
-
- // Set ior to 0.0 to disable the internal dielectric fresnel
- bsdf.response = F * comp * weight * microfacet(distribution, N, U, safeAlpha.x, safeAlpha.y, 0.0, false);
-}
diff --git a/libraries/pbrlib/genosl/legacy/mx_dielectric_bsdf.osl b/libraries/pbrlib/genosl/legacy/mx_dielectric_bsdf.osl
deleted file mode 100644
index 5e50834746..0000000000
--- a/libraries/pbrlib/genosl/legacy/mx_dielectric_bsdf.osl
+++ /dev/null
@@ -1,36 +0,0 @@
-#include "../lib/mx_microfacet_specular.osl"
-
-void mx_dielectric_bsdf(float weight, color tint, float ior, vector2 roughness, float thinfilm_thickness, float thinfilm_ior, normal N, vector U, string distribution, string scatter_mode, output BSDF bsdf)
-{
- if (scatter_mode == "T")
- {
- bsdf.response = tint * weight * microfacet(distribution, N, U, roughness.x, roughness.y, ior, 1);
- bsdf.throughput = tint * weight;
- return;
- }
-
- float NdotV = clamp(dot(N,-I), M_FLOAT_EPS, 1.0);
- float F0 = mx_ior_to_f0(ior);
- float F = mx_fresnel_schlick(NdotV, F0);
-
- // Calculate compensation for multiple scattering.
- // This should normally be done inside the closure
- // but since vanilla OSL doesen't support this we
- // add it here in shader code instead.
- vector2 safeAlpha = clamp(roughness, M_FLOAT_EPS, 1.0);
- float avgAlpha = mx_average_alpha(safeAlpha);
- float comp = mx_ggx_energy_compensation(NdotV, avgAlpha, F);
-
- // Calculate throughput from directional albedo.
- float dirAlbedo = mx_ggx_dir_albedo(NdotV, avgAlpha, ior) * comp;
- bsdf.throughput = 1.0 - dirAlbedo * weight;
-
- if (scatter_mode == "R")
- {
- bsdf.response = tint * weight * comp * microfacet(distribution, N, U, safeAlpha.x, safeAlpha.y, ior, 0);
- }
- else
- {
- bsdf.response = tint * weight * comp * microfacet(distribution, N, U, safeAlpha.x, safeAlpha.y, ior, 2);
- }
-}
diff --git a/libraries/pbrlib/genosl/legacy/mx_generalized_schlick_bsdf.osl b/libraries/pbrlib/genosl/legacy/mx_generalized_schlick_bsdf.osl
deleted file mode 100644
index cd022f8295..0000000000
--- a/libraries/pbrlib/genosl/legacy/mx_generalized_schlick_bsdf.osl
+++ /dev/null
@@ -1,38 +0,0 @@
-#include "../lib/mx_microfacet_specular.osl"
-
-void mx_generalized_schlick_bsdf(float weight, color color0, color color82, color color90, float exponent, vector2 roughness, float thinfilm_thickness, float thinfilm_ior, normal N, vector U, string distribution, string scatter_mode, output BSDF bsdf)
-{
- float avgF0 = dot(color0, color(1.0 / 3.0));
- float ior = mx_f0_to_ior(avgF0);
-
- if (scatter_mode == "T")
- {
- bsdf.response = weight * microfacet(distribution, N, U, roughness.x, roughness.y, ior, 1);
- bsdf.throughput = weight;
- return;
- }
-
- float NdotV = fabs(dot(N,-I));
- color F = mx_fresnel_schlick(NdotV, color0, color90, exponent);
-
- // Calculate compensation for multiple scattering.
- // This should normally be done inside the closure
- // but since vanilla OSL doesen't support this we
- // add it here in shader code instead.
- vector2 safeAlpha = clamp(roughness, M_FLOAT_EPS, 1.0);
- float avgAlpha = mx_average_alpha(safeAlpha);
- color comp = mx_ggx_energy_compensation(NdotV, avgAlpha, F);
-
- // Calculate throughput from directional albedo.
- color dirAlbedo = mx_ggx_dir_albedo(NdotV, avgAlpha, color0, color90) * comp;
- float avgDirAlbedo = dot(dirAlbedo, color(1.0 / 3.0));
- bsdf.throughput = 1.0 - avgDirAlbedo * weight;
-
- // Calculate the reflection response, setting IOR to zero to disable internal Fresnel.
- bsdf.response = F * comp * weight * microfacet(distribution, N, U, safeAlpha.x, safeAlpha.y, 0.0, 0);
-
- if (scatter_mode == "RT")
- {
- bsdf.response += bsdf.throughput * microfacet(distribution, N, U, safeAlpha.x, safeAlpha.y, ior, 1);
- }
-}
diff --git a/libraries/pbrlib/genosl/legacy/mx_oren_nayar_diffuse_bsdf.osl b/libraries/pbrlib/genosl/legacy/mx_oren_nayar_diffuse_bsdf.osl
deleted file mode 100644
index b9c5fba797..0000000000
--- a/libraries/pbrlib/genosl/legacy/mx_oren_nayar_diffuse_bsdf.osl
+++ /dev/null
@@ -1,5 +0,0 @@
-void mx_oren_nayar_diffuse_bsdf(float weight, color _color, float roughness, normal N, int energy_compensation, output BSDF bsdf)
-{
- bsdf.response = _color * weight * oren_nayar(N, roughness);
- bsdf.throughput = color(0.0);
-}
diff --git a/libraries/pbrlib/genosl/legacy/mx_sheen_bsdf.osl b/libraries/pbrlib/genosl/legacy/mx_sheen_bsdf.osl
deleted file mode 100644
index e94325fe99..0000000000
--- a/libraries/pbrlib/genosl/legacy/mx_sheen_bsdf.osl
+++ /dev/null
@@ -1,24 +0,0 @@
-#include "../lib/mx_microfacet_sheen.osl"
-
-// TODO: Vanilla OSL doesn't have a proper sheen closure,
-// so use 'diffuse' scaled by sheen directional albedo for now.
-void mx_sheen_bsdf(float weight, color Ks, float roughness, vector N, output BSDF bsdf)
-{
- if (weight < M_FLOAT_EPS)
- {
- bsdf.response = 0;
- bsdf.throughput = color(1.0);
- return;
- }
-
- // TODO: Normalization should not be needed. My suspicion is that
- // BSDF sampling of new outgoing direction in 'testrender' needs
- // to be fixed.
- vector V = normalize(-I);
-
- float NdotV = fabs(dot(N,V));
- float alpha = clamp(roughness, M_FLOAT_EPS, 1.0);
- float albedo = weight * mx_imageworks_sheen_dir_albedo(NdotV, alpha);
- bsdf.response = albedo * Ks * diffuse(N);
- bsdf.throughput = 1.0 - albedo;
-}
diff --git a/libraries/pbrlib/genosl/legacy/mx_subsurface_bsdf.osl b/libraries/pbrlib/genosl/legacy/mx_subsurface_bsdf.osl
deleted file mode 100644
index da0e3cc12a..0000000000
--- a/libraries/pbrlib/genosl/legacy/mx_subsurface_bsdf.osl
+++ /dev/null
@@ -1,6 +0,0 @@
-void mx_subsurface_bsdf(float weight, color _color, color radius, float anisotropy, normal N, output BSDF bsdf)
-{
- // TODO: Subsurface closure is not supported by vanilla OSL.
- bsdf.response = _color * weight * diffuse(N);
- bsdf.throughput = color(0.0);
-}
diff --git a/libraries/pbrlib/genosl/legacy/mx_surface.osl b/libraries/pbrlib/genosl/legacy/mx_surface.osl
deleted file mode 100644
index d48320411e..0000000000
--- a/libraries/pbrlib/genosl/legacy/mx_surface.osl
+++ /dev/null
@@ -1,6 +0,0 @@
-void mx_surface(BSDF bsdf, EDF edf, float opacity, int thin_walled, output surfaceshader result)
-{
- result.bsdf = bsdf.response;
- result.edf = edf;
- result.opacity = clamp(opacity, 0.0, 1.0);
-}
diff --git a/libraries/pbrlib/genosl/legacy/mx_translucent_bsdf.osl b/libraries/pbrlib/genosl/legacy/mx_translucent_bsdf.osl
deleted file mode 100644
index fd56a37db8..0000000000
--- a/libraries/pbrlib/genosl/legacy/mx_translucent_bsdf.osl
+++ /dev/null
@@ -1,5 +0,0 @@
-void mx_translucent_bsdf(float weight, color _color, normal N, output BSDF bsdf)
-{
- bsdf.response = _color * weight * translucent(N);
- bsdf.throughput = color(0.0);
-}
diff --git a/libraries/pbrlib/genosl/mx_chiang_hair_roughness.osl b/libraries/pbrlib/genosl/mx_chiang_hair_roughness.osl
new file mode 100644
index 0000000000..002bdc3044
--- /dev/null
+++ b/libraries/pbrlib/genosl/mx_chiang_hair_roughness.osl
@@ -0,0 +1,7 @@
+void mx_chiang_hair_roughness(float longitudinal, float azimuthal, float scale_TT, float scale_TRT, output vector2 roughness_R, output vector2 roughness_TT, output vector2 roughness_TRT)
+{
+ // TODO: Write OSL implementation of this node.
+ roughness_R = vector2(0.0, 0.0);
+ roughness_TT = vector2(0.0, 0.0);
+ roughness_TRT = vector2(0.0, 0.0);
+}
diff --git a/libraries/pbrlib/genosl/pbrlib_genosl_impl.legacy b/libraries/pbrlib/genosl/pbrlib_genosl_impl.legacy
deleted file mode 100644
index e4a424e1ac..0000000000
--- a/libraries/pbrlib/genosl/pbrlib_genosl_impl.legacy
+++ /dev/null
@@ -1,74 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/libraries/pbrlib/genosl/pbrlib_genosl_impl.mtlx b/libraries/pbrlib/genosl/pbrlib_genosl_impl.mtlx
index d3849a5ddb..beac984518 100644
--- a/libraries/pbrlib/genosl/pbrlib_genosl_impl.mtlx
+++ b/libraries/pbrlib/genosl/pbrlib_genosl_impl.mtlx
@@ -22,6 +22,9 @@
+
+
+
@@ -71,4 +74,13 @@
+
+
+
+
+
+
+
+
+
diff --git a/libraries/stdlib/genglsl/stdlib_genglsl_impl.mtlx b/libraries/stdlib/genglsl/stdlib_genglsl_impl.mtlx
index 34000f3933..0625d17a25 100644
--- a/libraries/stdlib/genglsl/stdlib_genglsl_impl.mtlx
+++ b/libraries/stdlib/genglsl/stdlib_genglsl_impl.mtlx
@@ -129,12 +129,6 @@
-
-
-
-
-
-
diff --git a/libraries/stdlib/genmdl/stdlib_genmdl_impl.mtlx b/libraries/stdlib/genmdl/stdlib_genmdl_impl.mtlx
index 1ba84b8083..05dbc995d6 100644
--- a/libraries/stdlib/genmdl/stdlib_genmdl_impl.mtlx
+++ b/libraries/stdlib/genmdl/stdlib_genmdl_impl.mtlx
@@ -131,13 +131,6 @@
-
-
-
-
-
-
-
@@ -698,7 +691,7 @@
-
+
diff --git a/libraries/stdlib/genmsl/lib/mx_texture.metal b/libraries/stdlib/genmsl/lib/mx_texture.metal
index 479a8836bf..7e90b60686 100644
--- a/libraries/stdlib/genmsl/lib/mx_texture.metal
+++ b/libraries/stdlib/genmsl/lib/mx_texture.metal
@@ -2,13 +2,8 @@ struct MetalTexture
{
texture2d tex;
sampler s;
- int get_width() { return tex.get_width(); }
- int get_height() { return tex.get_height(); }
- int get_num_mip_levels() { return tex.get_num_mip_levels(); }
};
-int get_width(MetalTexture mtlTex) { return mtlTex.get_width(); }
-
float4 texture(MetalTexture mtlTex, float2 uv)
{
return mtlTex.tex.sample(mtlTex.s, uv);
@@ -21,10 +16,5 @@ float4 textureLod(MetalTexture mtlTex, float2 uv, float lod)
int2 textureSize(MetalTexture mtlTex, int mipLevel)
{
- return int2(mtlTex.get_width(), mtlTex.get_height());
-}
-
-int texture_mips(MetalTexture mtlTex)
-{
- return mtlTex.tex.get_num_mip_levels();
+ return int2(mtlTex.tex.get_width(), mtlTex.tex.get_height());
}
diff --git a/libraries/stdlib/genmsl/stdlib_genmsl_impl.mtlx b/libraries/stdlib/genmsl/stdlib_genmsl_impl.mtlx
index ac4ea4e0b2..ea09880543 100644
--- a/libraries/stdlib/genmsl/stdlib_genmsl_impl.mtlx
+++ b/libraries/stdlib/genmsl/stdlib_genmsl_impl.mtlx
@@ -45,10 +45,6 @@
-
-
-
-
diff --git a/libraries/stdlib/genosl/mx_ambientocclusion_float.osl b/libraries/stdlib/genosl/mx_ambientocclusion_float.osl
deleted file mode 100644
index 10baf0b736..0000000000
--- a/libraries/stdlib/genosl/mx_ambientocclusion_float.osl
+++ /dev/null
@@ -1,5 +0,0 @@
-void mx_ambientocclusion_float(float coneangle, float maxdistance, output float result)
-{
- // This node is a stub and does not currently operate to specification
- result = 0;
-}
diff --git a/libraries/stdlib/genosl/stdlib_genosl_impl.mtlx b/libraries/stdlib/genosl/stdlib_genosl_impl.mtlx
index 3c4c5c4a6e..bd2e2540b5 100644
--- a/libraries/stdlib/genosl/stdlib_genosl_impl.mtlx
+++ b/libraries/stdlib/genosl/stdlib_genosl_impl.mtlx
@@ -131,13 +131,6 @@
-
-
-
-
-
-
-
diff --git a/libraries/stdlib/stdlib_defs.mtlx b/libraries/stdlib/stdlib_defs.mtlx
index 7d26d66639..7c24307f0e 100644
--- a/libraries/stdlib/stdlib_defs.mtlx
+++ b/libraries/stdlib/stdlib_defs.mtlx
@@ -1365,21 +1365,6 @@
-
-
-
-
-
-
-
-
-
-
-
@@ -2910,44 +2895,6 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- registerImplementation("IM_mix_bsdf_" + OslShaderGenerator::TARGET, ClosureMixNode::create);
- registerImplementation("IM_mix_edf_" + OslShaderGenerator::TARGET, ClosureMixNode::create);
- //
- registerImplementation("IM_add_bsdf_" + OslShaderGenerator::TARGET, ClosureAddNode::create);
- registerImplementation("IM_add_edf_" + OslShaderGenerator::TARGET, ClosureAddNode::create);
- //
- registerImplementation("IM_multiply_bsdfC_" + OslShaderGenerator::TARGET, ClosureMultiplyNode::create);
- registerImplementation("IM_multiply_bsdfF_" + OslShaderGenerator::TARGET, ClosureMultiplyNode::create);
- registerImplementation("IM_multiply_edfC_" + OslShaderGenerator::TARGET, ClosureMultiplyNode::create);
- registerImplementation("IM_multiply_edfF_" + OslShaderGenerator::TARGET, ClosureMultiplyNode::create);
-
-#endif // MATERIALX_OSL_LEGACY_CLOSURES
-
//
registerImplementation("IM_surface_" + OslShaderGenerator::TARGET, SurfaceNodeOsl::create);
@@ -157,10 +142,6 @@ ShaderPtr OslShaderGenerator::generate(const string& name, ElementPtr element, G
const bool isSurfaceShaderOutput = singleOutput && singleOutput->getType() == Type::SURFACESHADER;
-#ifdef MATERIALX_OSL_LEGACY_CLOSURES
- const bool isBsdfOutput = singleOutput && singleOutput->getType() == Type::BSDF;
-#endif
-
if (isSurfaceShaderOutput)
{
// Special case for having 'surfaceshader' as final output type.
@@ -169,16 +150,6 @@ ShaderPtr OslShaderGenerator::generate(const string& name, ElementPtr element, G
// to understand this output.
emitLine("output closure color " + singleOutput->getVariable() + " = 0", stage, false);
}
-#ifdef MATERIALX_OSL_LEGACY_CLOSURES
- else if (isBsdfOutput)
- {
- // Special case for having 'BSDF' as final output type.
- // For legacy closures this type is a struct internally (response, throughput, thickness, ior)
- // so we must declare this as a single closure color type in order for renderers
- // to understand this output.
- emitLine("output closure color " + singleOutput->getVariable() + " = 0", stage, false);
- }
-#endif
else
{
// Just emit all outputs the way they are declared.
@@ -252,18 +223,6 @@ ShaderPtr OslShaderGenerator::generate(const string& name, ElementPtr element, G
emitLine(singleOutput->getVariable() + " = (" + result + ".bsdf + " + result + ".edf) * opacity_weight + transparent() * (1.0 - opacity_weight)", stage);
emitScopeEnd(stage);
}
-#ifdef MATERIALX_OSL_LEGACY_CLOSURES
- else if (isBsdfOutput)
- {
- // Special case for having 'BSDF' as final output type.
- // For legacy closures this type is a struct internally (response, throughput, thickness, ior)
- // so we must declare this as a single closure color type in order for renderers
- // to understand this output.
- const ShaderGraphOutputSocket* socket = graph.getOutputSocket(0);
- const string result = getUpstreamResult(socket, context);
- emitLine(singleOutput->getVariable() + " = " + result + ".response", stage);
- }
-#endif
else
{
// Assign results to final outputs.
@@ -510,10 +469,10 @@ void OslShaderGenerator::emitMetadata(const ShaderPort* port, ShaderStage& stage
{
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())) }
+ { Type::FLOAT, ShaderMetadata("widget", Type::STRING, Type::STRING.createValueFromStrings("number")) },
+ { Type::INTEGER, ShaderMetadata("widget", Type::STRING, Type::STRING.createValueFromStrings("number")) },
+ { Type::FILENAME, ShaderMetadata("widget", Type::STRING, Type::STRING.createValueFromStrings("filename")) },
+ { Type::BOOLEAN, ShaderMetadata("widget", Type::STRING, Type::STRING.createValueFromStrings("checkBox")) }
};
static const std::set METADATA_TYPE_BLACKLIST =
diff --git a/source/MaterialXGenOsl/OslSyntax.cpp b/source/MaterialXGenOsl/OslSyntax.cpp
index 797a891ce6..a85821c4fd 100644
--- a/source/MaterialXGenOsl/OslSyntax.cpp
+++ b/source/MaterialXGenOsl/OslSyntax.cpp
@@ -371,19 +371,6 @@ OslSyntax::OslSyntax()
EMPTY_STRING,
"struct textureresource { string filename; string colorspace; };"));
-#ifdef MATERIALX_OSL_LEGACY_CLOSURES
-
- registerTypeSyntax(
- Type::BSDF,
- std::make_shared(
- "BSDF",
- "BSDF(null_closure, color(1.0))",
- "{ 0, color(1.0) }",
- "closure color",
- "struct BSDF { closure color response; color throughput; };"));
-
-#else
-
registerTypeSyntax(
Type::BSDF,
std::make_shared(
@@ -393,8 +380,6 @@ OslSyntax::OslSyntax()
"closure color",
"#define BSDF closure color"));
-#endif // MATERIALX_OSL_LEGACY_CLOSURES
-
registerTypeSyntax(
Type::EDF,
std::make_shared(
diff --git a/source/MaterialXGenShader/ShaderGenerator.cpp b/source/MaterialXGenShader/ShaderGenerator.cpp
index 6c23382f81..398232bf39 100644
--- a/source/MaterialXGenShader/ShaderGenerator.cpp
+++ b/source/MaterialXGenShader/ShaderGenerator.cpp
@@ -344,6 +344,47 @@ ShaderNodeImplPtr ShaderGenerator::getImplementation(const NodeDef& nodedef, Gen
return impl;
}
+/// Load any struct type definitions from the document in to the type cache.
+void ShaderGenerator::loadStructTypeDefs(const DocumentPtr& doc)
+{
+ for (const auto& mxTypeDef : doc->getTypeDefs())
+ {
+ const auto& typeDefName = mxTypeDef->getName();
+ const auto& members = mxTypeDef->getMembers();
+
+ // If we don't have any member children then we're not going to consider ourselves a struct.
+ if (members.empty())
+ continue;
+
+ StructTypeDesc newStructTypeDesc;
+ for (const auto& member : members)
+ {
+ auto memberName = member->getName();
+ auto memberTypeName = member->getType();
+ auto memberType = TypeDesc::get(memberTypeName);
+ auto memberDefaultValue = member->getValueString();
+
+ newStructTypeDesc.addMember(memberName, memberType, memberDefaultValue);
+ }
+
+ auto structIndex = StructTypeDesc::emplace_back(newStructTypeDesc);
+
+ TypeDesc structTypeDesc(typeDefName, TypeDesc::BASETYPE_STRUCT, TypeDesc::SEMANTIC_NONE, 1, structIndex);
+
+ TypeDescRegistry(structTypeDesc, typeDefName);
+
+ StructTypeDesc::get(structIndex).setTypeDesc(TypeDesc::get(typeDefName));
+ }
+
+ _syntax->registerStructTypeDescSyntax();
+}
+
+/// Clear any struct type definitions loaded
+void ShaderGenerator::clearStructTypeDefs()
+{
+ StructTypeDesc::clear();
+}
+
namespace
{
diff --git a/source/MaterialXGenShader/ShaderGenerator.h b/source/MaterialXGenShader/ShaderGenerator.h
index fa60a4d63e..a2f54fec2e 100644
--- a/source/MaterialXGenShader/ShaderGenerator.h
+++ b/source/MaterialXGenShader/ShaderGenerator.h
@@ -191,6 +191,12 @@ class MX_GENSHADER_API ShaderGenerator
return _tokenSubstitutions;
}
+ /// Load any struct type definitions from the document in to the type cache.
+ void loadStructTypeDefs(const DocumentPtr& doc);
+
+ /// Clear any struct type definitions loaded
+ void clearStructTypeDefs();
+
/// Register metadata that should be exported to the generated shaders.
/// Supported metadata includes standard UI attributes like "uiname", "uifolder",
/// "uimin", "uimax", etc.
diff --git a/source/MaterialXGenShader/ShaderNode.cpp b/source/MaterialXGenShader/ShaderNode.cpp
index 4e90fcbb2d..d52810ffc4 100644
--- a/source/MaterialXGenShader/ShaderNode.cpp
+++ b/source/MaterialXGenShader/ShaderNode.cpp
@@ -437,7 +437,7 @@ void ShaderNode::createMetadata(const NodeDef& nodeDef, GenContext& context)
const string& attrValue = nodeDef.getAttribute(nodedefAttr);
if (!attrValue.empty())
{
- ValuePtr value = Value::createValueFromStrings(attrValue, metadataEntry->type.getName());
+ ValuePtr value = metadataEntry->type.createValueFromStrings(attrValue);
if (!value)
{
value = metadataEntry->value;
@@ -472,7 +472,7 @@ void ShaderNode::createMetadata(const NodeDef& nodeDef, GenContext& context)
if (!attrValue.empty())
{
const TypeDesc type = metadataEntry->type != Type::NONE ? metadataEntry->type : input->getType();
- ValuePtr value = Value::createValueFromStrings(attrValue, type.getName());
+ ValuePtr value = type.createValueFromStrings(attrValue);
if (!value)
{
value = metadataEntry->value;
diff --git a/source/MaterialXGenShader/Syntax.cpp b/source/MaterialXGenShader/Syntax.cpp
index 661aa41660..81daa9e0a7 100644
--- a/source/MaterialXGenShader/Syntax.cpp
+++ b/source/MaterialXGenShader/Syntax.cpp
@@ -190,6 +190,36 @@ bool Syntax::remapEnumeration(const string&, TypeDesc, const string&, std::pair<
return false;
}
+void Syntax::registerStructTypeDescSyntax()
+{
+ for (const auto& typeName : StructTypeDesc::getStructTypeNames())
+ {
+ const auto& typeDesc = TypeDesc::get(typeName);
+ const auto& structTypeDesc = StructTypeDesc::get(typeDesc.getStructIndex());
+
+ string structTypeName = typeName;
+ string defaultValue = typeName + "( ";
+ string uniformDefaultValue = EMPTY_STRING;
+ string typeAlias = EMPTY_STRING;
+ string typeDefinition = "struct " + structTypeName + " { ";
+
+ for (const auto& x : structTypeDesc.getMembers())
+ {
+ string memberName = x._name;
+ string memberType = x._typeDesc.getName();
+ string memberDefaultValue = x._defaultValueStr;
+
+ defaultValue += memberDefaultValue + ", ";
+ typeDefinition += memberType + " " + memberName + "; ";
+ }
+
+ typeDefinition += " };";
+ defaultValue += " )";
+
+ registerTypeSyntax(typeDesc, createStructSyntax(structTypeName, defaultValue, uniformDefaultValue, typeAlias, typeDefinition));
+ }
+}
+
const StringVec TypeSyntax::EMPTY_MEMBERS;
TypeSyntax::TypeSyntax(const string& name, const string& defaultValue, const string& uniformDefaultValue,
@@ -246,4 +276,36 @@ string AggregateTypeSyntax::getValue(const Value& value, bool /*uniform*/) const
return valueString.empty() ? valueString : getName() + "(" + valueString + ")";
}
+StructTypeSyntax::StructTypeSyntax(const Syntax* parentSyntax, const string& name, const string& defaultValue, const string& uniformDefaultValue,
+ const string& typeAlias, const string& typeDefinition, const StringVec& members) :
+ TypeSyntax(name, defaultValue, uniformDefaultValue, typeAlias, typeDefinition, members), _parentSyntax(parentSyntax)
+{
+}
+
+string StructTypeSyntax::getValue(const Value& value, bool /*uniform*/) const
+{
+ const AggregateValue& aggValue = static_cast(value);
+
+ string result = "{";
+
+ string separator = "";
+ for (const auto& memberValue : aggValue.getMembers())
+ {
+ result += separator;
+ separator = ";";
+
+ const string& memberTypeName = memberValue->getTypeString();
+ TypeDesc memberTypeDesc = TypeDesc::get(memberTypeName);
+
+ // Recursively use the syntax to generate the output, so we can support nested structs.
+ const string valueStr = _parentSyntax->getValue(memberTypeDesc, *memberValue, true);
+
+ result += valueStr;
+ }
+
+ result += "}";
+
+ return result;
+}
+
MATERIALX_NAMESPACE_END
diff --git a/source/MaterialXGenShader/Syntax.h b/source/MaterialXGenShader/Syntax.h
index a4bb7e49b5..6f16633b59 100644
--- a/source/MaterialXGenShader/Syntax.h
+++ b/source/MaterialXGenShader/Syntax.h
@@ -20,6 +20,7 @@ MATERIALX_NAMESPACE_BEGIN
class Syntax;
class TypeSyntax;
+class StructTypeSyntax;
class TypeDesc;
class ShaderPort;
@@ -29,6 +30,8 @@ using SyntaxPtr = shared_ptr;
using ConstSyntaxPtr = shared_ptr;
/// Shared pointer to a TypeSyntax
using TypeSyntaxPtr = shared_ptr;
+/// Shared pointer to a StructTypeSyntax
+using StructTypeSyntaxPtr = shared_ptr;
/// Map holding identifier names and a counter for
/// creating unique names from them.
@@ -67,6 +70,8 @@ class MX_GENSHADER_API Syntax
/// Multiple calls will add to the internal set of tokens.
void registerInvalidTokens(const StringMap& tokens);
+ virtual void registerStructTypeDescSyntax();
+
/// Returns a set of names that are reserved words for this language syntax.
const StringSet& getReservedWords() const { return _reservedWords; }
@@ -199,6 +204,19 @@ class MX_GENSHADER_API Syntax
/// Protected constructor
Syntax();
+ virtual StructTypeSyntaxPtr createStructSyntax(const string& structTypeName, const string& defaultValue,
+ const string& uniformDefaultValue, const string& typeAlias,
+ const string& typeDefinition) const
+ {
+ return std::make_shared(
+ this,
+ structTypeName,
+ defaultValue,
+ uniformDefaultValue,
+ typeAlias,
+ typeDefinition);
+ }
+
vector _typeSyntaxes;
std::unordered_map _typeSyntaxIndexByType;
@@ -292,6 +310,20 @@ class MX_GENSHADER_API AggregateTypeSyntax : public TypeSyntax
string getValue(const Value& value, bool uniform) const override;
};
+/// Specialization of TypeSyntax for aggregate types.
+class MX_GENSHADER_API StructTypeSyntax : public TypeSyntax
+{
+ public:
+ StructTypeSyntax(const Syntax* parentSyntax, const string& name, const string& defaultValue, const string& uniformDefaultValue,
+ const string& typeAlias = EMPTY_STRING, const string& typeDefinition = EMPTY_STRING,
+ const StringVec& members = EMPTY_MEMBERS);
+
+ string getValue(const Value& value, bool uniform) const override;
+
+ protected:
+ const Syntax* _parentSyntax;
+};
+
MATERIALX_NAMESPACE_END
#endif
diff --git a/source/MaterialXGenShader/TypeDesc.cpp b/source/MaterialXGenShader/TypeDesc.cpp
index 1267caf14d..5d51680211 100644
--- a/source/MaterialXGenShader/TypeDesc.cpp
+++ b/source/MaterialXGenShader/TypeDesc.cpp
@@ -5,7 +5,7 @@
#include
-#include
+#include
MATERIALX_NAMESPACE_BEGIN
@@ -28,6 +28,16 @@ TypeDescNameMap& typeNameMap()
return map;
}
+using StructTypeDescStorage = vector;
+StructTypeDescStorage& structTypeStorage()
+{
+ // TODO: Our use of the singleton pattern for TypeDescMap and StructTypeDestStorage
+ // is not thread-safe, and we should consider replacing this with thread-local
+ // data in the GenContext object.
+ static StructTypeDescStorage storage;
+ return storage;
+}
+
} // anonymous namespace
const string TypeDesc::NONE_TYPE_NAME = "none";
@@ -46,7 +56,52 @@ TypeDesc TypeDesc::get(const string& name)
return it != types.end() ? it->second : Type::NONE;
}
-TypeDescRegistry::TypeDescRegistry(TypeDesc type, const std::string& name)
+void TypeDesc::remove(const string& name)
+{
+ TypeDescNameMap& typenames = typeNameMap();
+
+ TypeDescMap& types = typeMap();
+
+ auto it = types.find(name);
+ if (it == types.end())
+ return;
+
+ typenames.erase(it->second.typeId());
+ types.erase(it);
+}
+
+ValuePtr TypeDesc::createValueFromStrings(const string& value) const
+{
+ ValuePtr newValue = Value::createValueFromStrings(value, getName());
+ if (!isStruct())
+ return newValue;
+
+ // Value::createValueFromStrings() can only create a valid Value for a struct if it is passed
+ // the optional TypeDef argument, otherwise it just returns a "string" typed Value.
+ // So if this is a struct type we need to create a new AggregateValue.
+
+ StringVec subValues = parseStructValueString(value);
+
+ AggregateValuePtr result = AggregateValue::createAggregateValue(getName());
+ auto structTypeDesc = StructTypeDesc::get(getStructIndex());
+ const auto& members = structTypeDesc.getMembers();
+
+ if (subValues.size() != members.size())
+ {
+ std::stringstream ss;
+ ss << "Wrong number of initializers - expect " << members.size();
+ throw ExceptionShaderGenError(ss.str());
+ }
+
+ for (size_t i = 0; i < members.size(); ++i)
+ {
+ result->appendValue( members[i]._typeDesc.createValueFromStrings(subValues[i]));
+ }
+
+ return result;
+}
+
+TypeDescRegistry::TypeDescRegistry(TypeDesc type, const string& name)
{
TypeDescMap& types = typeMap();
TypeDescNameMap& typenames = typeNameMap();
@@ -86,4 +141,74 @@ TYPEDESC_REGISTER_TYPE(MATERIAL, "material")
} // namespace Type
+//
+// StructTypeDesc methods
+//
+
+void StructTypeDesc::addMember(const string& name, TypeDesc type, string defaultValueStr)
+{
+ _members.emplace_back(StructTypeDesc::StructMemberTypeDesc(name, type, defaultValueStr));
+}
+
+vector StructTypeDesc::getStructTypeNames()
+{
+ StructTypeDescStorage& structs = structTypeStorage();
+ vector structNames;
+ for (const auto& x : structs)
+ {
+ structNames.emplace_back(x.typeDesc().getName());
+ }
+ return structNames;
+}
+
+StructTypeDesc& StructTypeDesc::get(unsigned int index)
+{
+ StructTypeDescStorage& structs = structTypeStorage();
+ return structs[index];
+}
+
+uint16_t StructTypeDesc::emplace_back(StructTypeDesc structTypeDesc)
+{
+ StructTypeDescStorage& structs = structTypeStorage();
+ if (structs.size() >= std::numeric_limits::max())
+ {
+ throw ExceptionShaderGenError("Maximum number of custom struct types has been exceeded.");
+ }
+ uint16_t index = static_cast(structs.size());
+ structs.emplace_back(structTypeDesc);
+ return index;
+}
+
+void StructTypeDesc::clear()
+{
+ StructTypeDescStorage& structs = structTypeStorage();
+ for (const auto& structType: structs)
+ {
+ // Need to add typeID to structTypeDesc - and use it here to reference back to typeDesc obj and remove it.
+ TypeDesc::remove(structType.typeDesc().getName());
+ }
+ structs.clear();
+}
+
+const string& StructTypeDesc::getName() const
+{
+ return _typedesc.getName();
+}
+
+const vector& StructTypeDesc::getMembers() const
+{
+ return _members;
+}
+
+TypeDesc createStructTypeDesc(std::string_view name)
+{
+ return {name, TypeDesc::BASETYPE_STRUCT};
+}
+
+void registerStructTypeDesc(std::string_view name)
+{
+ auto structTypeDesc = createStructTypeDesc(name);
+ TypeDescRegistry register_struct(structTypeDesc, string(name));
+}
+
MATERIALX_NAMESPACE_END
diff --git a/source/MaterialXGenShader/TypeDesc.h b/source/MaterialXGenShader/TypeDesc.h
index 1a537b7e58..95d2851915 100644
--- a/source/MaterialXGenShader/TypeDesc.h
+++ b/source/MaterialXGenShader/TypeDesc.h
@@ -10,6 +10,7 @@
/// Type descriptor for a MaterialX data type.
#include
+#include
#include
@@ -61,14 +62,21 @@ class MX_GENSHADER_API TypeDesc
/// Empty constructor.
constexpr TypeDesc() noexcept :
- _id(0), _basetype(BASETYPE_NONE), _semantic(SEMANTIC_NONE), _size(0) { }
+ _id(0),
+ _basetype(BASETYPE_NONE),
+ _semantic(SEMANTIC_NONE),
+ _size(0),
+ _structIndex(0)
+ {
+ }
/// Constructor.
- constexpr TypeDesc(std::string_view name, uint8_t basetype, uint8_t semantic = SEMANTIC_NONE, uint16_t size = 1) noexcept :
+ constexpr TypeDesc(std::string_view name, uint8_t basetype, uint8_t semantic = SEMANTIC_NONE, uint16_t size = 1, uint16_t structIndex = 0) noexcept :
_id(constexpr_hash(name)), // Note: We only store the hash to keep the class size minimal.
_basetype(basetype),
_semantic(semantic),
- _size(size)
+ _size(size),
+ _structIndex(structIndex)
{
}
@@ -112,6 +120,12 @@ class MX_GENSHADER_API TypeDesc
/// Return true if the type represents a closure.
bool isClosure() const { return (_semantic == SEMANTIC_CLOSURE || _semantic == SEMANTIC_SHADER || _semantic == SEMANTIC_MATERIAL); }
+ /// Return true if the type represents a struct.
+ bool isStruct() const { return _basetype == BASETYPE_STRUCT; }
+
+ /// Return the index for the struct member information in StructTypeDesc, the result is invalid if `isStruct()` returns false.
+ uint16_t getStructIndex() const { return _structIndex; }
+
/// Equality operator
bool operator==(TypeDesc rhs) const
{
@@ -143,8 +157,14 @@ class MX_GENSHADER_API TypeDesc
/// If no type is found Type::NONE is returned.
static TypeDesc get(const string& name);
+ /// Remove a type description by name, if it exists.
+ static void remove(const string& name);
+
static const string NONE_TYPE_NAME;
+ /// Create a Value from a string for a given typeDesc
+ ValuePtr createValueFromStrings(const string& value) const;
+
private:
/// Simple constexpr hash function, good enough for the small set of short strings that
/// are used for our data type names.
@@ -157,6 +177,7 @@ class MX_GENSHADER_API TypeDesc
uint8_t _basetype;
uint8_t _semantic;
uint16_t _size;
+ uint16_t _structIndex;
};
/// @class TypeDescRegistry
@@ -208,6 +229,58 @@ TYPEDESC_DEFINE_TYPE(MATERIAL, "material", TypeDesc::BASETYPE_NONE, TypeDesc::SE
} // namespace Type
+
+/// @class StructTypeDesc
+/// A type descriptor for MaterialX struct types.
+///
+/// All types need to have a type descriptor registered in order for shader generators
+/// to know about the type. If the type represented is of basetype=BASETYPE_STRUCT then
+/// the type also needs to have an associated StructTypeDesc that describes the members
+/// of the struct.
+///
+class MX_GENSHADER_API StructTypeDesc
+{
+ public:
+ struct StructMemberTypeDesc
+ {
+ StructMemberTypeDesc(string name, TypeDesc typeDesc, string defaultValueStr) :
+ _name(name), _typeDesc(typeDesc), _defaultValueStr(defaultValueStr)
+ {
+ }
+ string _name;
+ TypeDesc _typeDesc;
+ string _defaultValueStr;
+ };
+
+ /// Empty constructor.
+ StructTypeDesc() noexcept{}
+
+ void addMember(const string& name, TypeDesc type, string defaultValueStr);
+ void setTypeDesc(TypeDesc typedesc) { _typedesc = typedesc; }
+
+ /// Return a type description by index.
+ static StructTypeDesc& get(unsigned int index);
+ static vector getStructTypeNames();
+ static uint16_t emplace_back(StructTypeDesc structTypeDesc);
+ static void clear();
+
+ TypeDesc typeDesc() const { return _typedesc; }
+
+ const string& getName() const;
+
+ const vector& getMembers() const;
+
+ private:
+ TypeDesc _typedesc;
+ vector _members;
+};
+
+class MX_GENSHADER_API StructTypeDescRegistry
+{
+ public:
+ StructTypeDescRegistry();
+};
+
MATERIALX_NAMESPACE_END
#endif
diff --git a/source/MaterialXGraphEditor/RenderView.cpp b/source/MaterialXGraphEditor/RenderView.cpp
index dbc9b4f980..92cd8f07c7 100644
--- a/source/MaterialXGraphEditor/RenderView.cpp
+++ b/source/MaterialXGraphEditor/RenderView.cpp
@@ -630,6 +630,9 @@ void RenderView::initContext(mx::GenContext& context)
unitSystem->setUnitConverterRegistry(_unitRegistry);
context.getShaderGenerator().setUnitSystem(unitSystem);
context.getOptions().targetDistanceUnit = "meter";
+
+ // Register struct type definitions
+ context.getShaderGenerator().loadStructTypeDefs(_document);
}
void RenderView::drawContents()
diff --git a/source/MaterialXRender/Util.cpp b/source/MaterialXRender/Util.cpp
index 881f1b7eea..c206514412 100644
--- a/source/MaterialXRender/Util.cpp
+++ b/source/MaterialXRender/Util.cpp
@@ -170,7 +170,7 @@ unsigned int getUIProperties(InputPtr input, const string& target, UIProperties&
else
{
valueString += val;
- uiProperties.enumerationValues.push_back(Value::createValueFromStrings(valueString, input->getType()));
+ uiProperties.enumerationValues.push_back(typeDesc.createValueFromStrings(valueString));
valueString.clear();
index = 0;
}
@@ -318,7 +318,7 @@ void createUIPropertyGroups(DocumentPtr doc, const VariableBlock& block, UIPrope
// Prepend a parent label for unlabeled node inputs.
ElementPtr parent = pair.first->getParent();
- if (item.ui.uiFolder.empty() && parent && parent->isA())
+ if (item.ui.uiName.empty() && parent && parent->isA())
{
item.label = parent->getName() + pathSeparator + item.label;
}
diff --git a/source/MaterialXRenderGlsl/GlslMaterial.cpp b/source/MaterialXRenderGlsl/GlslMaterial.cpp
index 788af713b2..064ab898ff 100644
--- a/source/MaterialXRenderGlsl/GlslMaterial.cpp
+++ b/source/MaterialXRenderGlsl/GlslMaterial.cpp
@@ -360,7 +360,7 @@ void GlslMaterial::modifyUniform(const std::string& path, ConstValuePtr value, s
{
valueString = value->getValueString();
}
- uniform->setValue(Value::createValueFromStrings(valueString, uniform->getType().getName()));
+ uniform->setValue(uniform->getType().createValueFromStrings(valueString));
if (_doc)
{
ElementPtr element = _doc->getDescendant(uniform->getPath());
diff --git a/source/MaterialXRenderGlsl/GlslProgram.cpp b/source/MaterialXRenderGlsl/GlslProgram.cpp
index b2ca0aa66e..b63e1faecc 100644
--- a/source/MaterialXRenderGlsl/GlslProgram.cpp
+++ b/source/MaterialXRenderGlsl/GlslProgram.cpp
@@ -508,7 +508,7 @@ ImagePtr GlslProgram::bindTexture(unsigned int uniformType, int uniformLocation,
return nullptr;
}
-MaterialX::ValuePtr GlslProgram::findUniformValue(const string& uniformName, const GlslProgram::InputMap& uniformList)
+MaterialX::ConstValuePtr GlslProgram::findUniformValue(const string& uniformName, const GlslProgram::InputMap& uniformList)
{
auto uniform = uniformList.find(uniformName);
if (uniform != uniformList.end())
@@ -946,47 +946,87 @@ const GlslProgram::InputMap& GlslProgram::updateUniformsList()
for (size_t i = 0; i < uniforms.size(); ++i)
{
const ShaderPort* v = uniforms[i];
- int glType = mapTypeToOpenGLType(v->getType());
- // There is no way to match with an unnamed variable
- if (v->getVariable().empty())
- {
- continue;
- }
-
- // Ignore types which are unsupported in GLSL.
- if (glType == Input::INVALID_OPENGL_TYPE)
- {
- continue;
- }
+ const auto& variablePath = v->getPath();
+ const auto& variableUnit = v->getUnit();
+ const auto& variableColorspace = v->getColorSpace();
+ const auto& variableSemantic = v->getSemantic();
- auto inputIt = _uniformList.find(v->getVariable());
- if (inputIt != _uniformList.end())
+ const auto populateUniformInput =
+ [this, variablePath, variableUnit, variableColorspace, variableSemantic, &errors, uniforms, &uniformTypeMismatchFound]
+ (TypeDesc typedesc, const string& variableName, ConstValuePtr variableValue) -> void
{
- Input* input = inputIt->second.get();
- input->path = v->getPath();
- input->unit = v->getUnit();
- input->colorspace = v->getColorSpace();
- input->value = v->getValue();
- if (input->gltype == glType)
- {
- input->typeString = v->getType().getName();
- }
- else
+ auto populateUniformInput_impl =
+ [this, variablePath, variableUnit, variableColorspace, variableSemantic, &errors, uniforms, &uniformTypeMismatchFound]
+ (TypeDesc typedesc, const string& variableName, ConstValuePtr variableValue, auto& populateUniformInput_ref) -> void
{
- errors.push_back(
- "Pixel shader uniform block type mismatch [" + uniforms.getName() + "]. "
- + "Name: \"" + v->getVariable()
- + "\". Type: \"" + v->getType().getName()
- + "\". Semantic: \"" + v->getSemantic()
- + "\". Value: \"" + (v->getValue() ? v->getValue()->getValueString() : "")
- + "\". Unit: \"" + (!v->getUnit().empty() ? v->getUnit() : "")
- + "\". Colorspace: \"" + (!v->getColorSpace().empty() ? v->getColorSpace() : "")
- + "\". GLType: " + std::to_string(mapTypeToOpenGLType(v->getType()))
- );
- uniformTypeMismatchFound = true;
- }
- }
+ if (!typedesc.isStruct())
+ {
+ // Handle non-struct types
+ int glType = mapTypeToOpenGLType(typedesc);
+
+ // There is no way to match with an unnamed variable
+ if (variableName.empty())
+ {
+ return;
+ }
+
+ // Ignore types which are unsupported in GLSL.
+ if (glType == Input::INVALID_OPENGL_TYPE)
+ {
+ return;
+ }
+
+ auto inputIt = _uniformList.find(variableName);
+ if (inputIt != _uniformList.end())
+ {
+ Input* input = inputIt->second.get();
+ input->path = variablePath;
+ input->unit = variableUnit;
+ input->colorspace = variableColorspace;
+ input->value = variableValue;
+ if (input->gltype == glType)
+ {
+ input->typeString = typedesc.getName();
+ }
+ else
+ {
+ errors.push_back(
+ "Pixel shader uniform block type mismatch [" + uniforms.getName() + "]. "
+ + "Name: \"" + variableName
+ + "\". Type: \"" + typedesc.getName()
+ + "\". Semantic: \"" + variableSemantic
+ + "\". Value: \"" + (variableValue ? variableValue->getValueString() : "")
+ + "\". Unit: \"" + (!variableUnit.empty() ? variableUnit : "")
+ + "\". Colorspace: \"" + (!variableColorspace.empty() ? variableColorspace : "")
+ + "\". GLType: " + std::to_string(glType));
+ uniformTypeMismatchFound = true;
+ }
+ }
+ }
+ else
+ {
+ // If we're a struct - we need to loop over each member
+ auto structTypeDesc = StructTypeDesc::get(typedesc.getStructIndex());
+ auto aggregateValue = std::static_pointer_cast(variableValue);
+
+ const auto& members = structTypeDesc.getMembers();
+ for (size_t i = 0, n = members.size(); i < n; ++i)
+ {
+ const auto& member = members[i];
+ auto memberTypeDesc = member._typeDesc;
+ auto memberVariableName = variableName + "." + member._name;
+ auto memberVariableValue = aggregateValue->getMemberValue(i);
+
+ populateUniformInput_ref(memberTypeDesc, memberVariableName, memberVariableValue, populateUniformInput_ref);
+ }
+ }
+ };
+
+ return populateUniformInput_impl(typedesc, variableName, variableValue, populateUniformInput_impl);
+ };
+
+ populateUniformInput(v->getType(), v->getVariable(), v->getValue());
}
}
@@ -1100,12 +1140,12 @@ const GlslProgram::InputMap& GlslProgram::updateAttributesList()
if (string::npos != sattributeName.find(colorSet))
{
string setNumber = sattributeName.substr(colorSet.size(), sattributeName.size());
- inputPtr->value = Value::createValueFromStrings(setNumber, getTypeString());
+ inputPtr->value = Type::INTEGER.createValueFromStrings(setNumber);
}
else if (string::npos != sattributeName.find(uvSet))
{
string setNumber = sattributeName.substr(uvSet.size(), sattributeName.size());
- inputPtr->value = Value::createValueFromStrings(setNumber, getTypeString());
+ inputPtr->value = Type::INTEGER.createValueFromStrings(setNumber);
}
_attributeList[sattributeName] = inputPtr;
diff --git a/source/MaterialXRenderGlsl/GlslProgram.h b/source/MaterialXRenderGlsl/GlslProgram.h
index 7d58dbaca7..4addd7d54b 100644
--- a/source/MaterialXRenderGlsl/GlslProgram.h
+++ b/source/MaterialXRenderGlsl/GlslProgram.h
@@ -102,7 +102,7 @@ class MX_RENDERGLSL_API GlslProgram
string typeString;
/// Input value. Will only be non-empty if initialized stages with a HwShader and a value was set during
/// shader generation.
- MaterialX::ValuePtr value;
+ MaterialX::ConstValuePtr value;
/// Is this a constant
bool isConstant;
/// Element path (if any)
@@ -223,7 +223,7 @@ class MX_RENDERGLSL_API GlslProgram
// Utility to find a uniform value in an uniform list.
// If uniform cannot be found a null pointer will be return.
- ValuePtr findUniformValue(const string& uniformName, const InputMap& uniformList);
+ ConstValuePtr findUniformValue(const string& uniformName, const InputMap& uniformList);
// Bind an individual texture to a program uniform location
ImagePtr bindTexture(unsigned int uniformType, int uniformLocation, const FilePath& filePath,
diff --git a/source/MaterialXRenderMsl/MslMaterial.mm b/source/MaterialXRenderMsl/MslMaterial.mm
index 311d84acee..eb13ea7900 100644
--- a/source/MaterialXRenderMsl/MslMaterial.mm
+++ b/source/MaterialXRenderMsl/MslMaterial.mm
@@ -318,7 +318,7 @@
{
valueString = value->getValueString();
}
- uniform->setValue(Value::createValueFromStrings(valueString, uniform->getType().getName()));
+ uniform->setValue(uniform->getType().createValueFromStrings(valueString));
if (_doc)
{
ElementPtr element = _doc->getDescendant(uniform->getPath());
diff --git a/source/MaterialXRenderMsl/MslPipelineStateObject.h b/source/MaterialXRenderMsl/MslPipelineStateObject.h
index b335e29af5..a823662f5f 100644
--- a/source/MaterialXRenderMsl/MslPipelineStateObject.h
+++ b/source/MaterialXRenderMsl/MslPipelineStateObject.h
@@ -99,7 +99,7 @@ class MX_RENDERMSL_API MslProgram
string typeString;
/// Input value. Will only be non-empty if initialized stages with a HwShader and a value was set during
/// shader generation.
- MaterialX::ValuePtr value;
+ MaterialX::ConstValuePtr value;
/// Is this a constant
bool isConstant;
/// Element path (if any)
@@ -256,7 +256,7 @@ class MX_RENDERMSL_API MslProgram
// Utility to find a uniform value in an uniform list.
// If uniform cannot be found a null pointer will be return.
- ValuePtr findUniformValue(const string& uniformName, const InputMap& uniformList);
+ ConstValuePtr findUniformValue(const string& uniformName, const InputMap& uniformList);
// Bind an individual texture to a program uniform location
ImagePtr bindTexture(id renderCmdEncoder,
diff --git a/source/MaterialXRenderMsl/MslPipelineStateObject.mm b/source/MaterialXRenderMsl/MslPipelineStateObject.mm
index 2d5685646f..470fa549b2 100644
--- a/source/MaterialXRenderMsl/MslPipelineStateObject.mm
+++ b/source/MaterialXRenderMsl/MslPipelineStateObject.mm
@@ -235,12 +235,12 @@ int GetStrideOfMetalType(MTLDataType type)
if (_shader->hasAttribute(HW::ATTR_TRANSPARENT))
{
- psoDesc.colorAttachments[0].blendingEnabled = YES;
- psoDesc.colorAttachments[0].rgbBlendOperation = MTLBlendOperationAdd;
- psoDesc.colorAttachments[0].alphaBlendOperation = MTLBlendOperationAdd;
- psoDesc.colorAttachments[0].sourceRGBBlendFactor = MTLBlendFactorSourceAlpha;
- psoDesc.colorAttachments[0].sourceAlphaBlendFactor = MTLBlendFactorSourceAlpha;
- psoDesc.colorAttachments[0].destinationRGBBlendFactor = MTLBlendFactorOneMinusSourceAlpha;
+ psoDesc.colorAttachments[0].blendingEnabled = YES;
+ psoDesc.colorAttachments[0].rgbBlendOperation = MTLBlendOperationAdd;
+ psoDesc.colorAttachments[0].alphaBlendOperation = MTLBlendOperationAdd;
+ psoDesc.colorAttachments[0].sourceRGBBlendFactor = MTLBlendFactorSourceAlpha;
+ psoDesc.colorAttachments[0].sourceAlphaBlendFactor = MTLBlendFactorSourceAlpha;
+ psoDesc.colorAttachments[0].destinationRGBBlendFactor = MTLBlendFactorOneMinusSourceAlpha;
psoDesc.colorAttachments[0].destinationAlphaBlendFactor = MTLBlendFactorOneMinusSourceAlpha;
_alphaBlendingEnabled = true;
@@ -265,12 +265,12 @@ int GetStrideOfMetalType(MTLDataType type)
if (string::npos != sattributeName.find(colorSet))
{
string setNumber = sattributeName.substr(colorSet.size(), sattributeName.size());
- inputPtr->value = Value::createValueFromStrings(setNumber, getTypeString());
+ inputPtr->value = Type::INTEGER.createValueFromStrings(setNumber);
}
else if (string::npos != sattributeName.find(uvSet))
{
string setNumber = sattributeName.substr(uvSet.size(), sattributeName.size());
- inputPtr->value = Value::createValueFromStrings(setNumber, getTypeString());
+ inputPtr->value = Type::INTEGER.createValueFromStrings(setNumber);
}
_attributeList[sattributeName] = inputPtr;
@@ -566,8 +566,8 @@ int GetStrideOfMetalType(MTLDataType type)
return nullptr;
}
-MaterialX::ValuePtr MslProgram::findUniformValue(const string& uniformName,
- const MslProgram::InputMap& uniformList)
+MaterialX::ConstValuePtr MslProgram::findUniformValue(const string& uniformName,
+ const MslProgram::InputMap& uniformList)
{
auto uniform = uniformList.find(uniformName);
if (uniform != uniformList.end())
@@ -925,31 +925,54 @@ int GetStrideOfMetalType(MTLDataType type)
{
if (arg.type == MTLArgumentTypeBuffer && arg.bufferDataType == MTLDataTypeStruct)
{
- for (MTLStructMember* member in arg.bufferStructType.members)
- {
- std::string uboObjectName = std::string(arg.name.UTF8String);
- std::string memberName = member.name.UTF8String;
- std::string uboDotMemberName = uboObjectName + "." + memberName;
+ const auto uboObjectName = string(arg.name.UTF8String);
- InputPtr inputPtr = std::make_shared(arg.index, member.dataType, arg.bufferDataSize, EMPTY_STRING);
- _uniformList[uboDotMemberName] = inputPtr;
- _globalUniformNameList[memberName] = uboDotMemberName;
-
- if (MTLArrayType* arrayMember = member.arrayType)
+ const auto addUniformToList =
+ [this, uboObjectName]
+ (MTLStructMember* member, int index, int size, const string& memberNamePrefix) -> void
+ {
+ auto addUniformToList_impl =
+ [this, uboObjectName]
+ (MTLStructMember* member, int index, int size, const string& memberNamePrefix, auto& addUniformToList_ref) -> void
{
- for (int i = 0; i < arrayMember.arrayLength; ++i)
+ auto memberName = memberNamePrefix + member.name.UTF8String;
+
+ if (MTLStructType* structMember = member.structType)
{
- for (MTLStructMember* ArrayOfStructMember in arrayMember.elementStructType.members)
+ for (MTLStructMember* subMember in structMember.members)
{
- std::string memberNameDotSubmember = memberName + "[" + std::to_string(i) + "]." + ArrayOfStructMember.name.UTF8String;
- std::string uboDotMemberNameDotSubmemberName = uboObjectName + "." + memberNameDotSubmember;
+ auto namePrefix = memberName + ".";
+ addUniformToList_ref(subMember, subMember.argumentIndex, subMember.offset, namePrefix, addUniformToList_ref);
+ }
+ }
+ else
+ {
+ auto uboDotMemberName = uboObjectName + "." + memberName;
+
+ InputPtr inputPtr = std::make_shared(index, member.dataType, size, EMPTY_STRING);
+ this->_uniformList[uboDotMemberName] = inputPtr;
+ this->_globalUniformNameList[memberName] = uboDotMemberName;
- InputPtr inputPtr = std::make_shared(ArrayOfStructMember.argumentIndex, ArrayOfStructMember.dataType, ArrayOfStructMember.offset, EMPTY_STRING);
- _uniformList[uboDotMemberNameDotSubmemberName] = inputPtr;
- _globalUniformNameList[memberNameDotSubmember] = uboDotMemberNameDotSubmemberName;
+ if (MTLArrayType* arrayMember = member.arrayType)
+ {
+ for (int i = 0; i < arrayMember.arrayLength; ++i)
+ {
+ for (MTLStructMember* ArrayOfStructMember in arrayMember.elementStructType.members)
+ {
+ auto namePrefix = memberName + "[" + std::to_string(i) + "].";
+ addUniformToList_ref(ArrayOfStructMember, ArrayOfStructMember.argumentIndex, ArrayOfStructMember.offset, namePrefix, addUniformToList_ref);
+ }
+ }
}
}
- }
+ };
+
+ return addUniformToList_impl(member, index, size, memberNamePrefix, addUniformToList_impl);
+ };
+
+ for (MTLStructMember* member in arg.bufferStructType.members)
+ {
+ addUniformToList(member, arg.index, arg.bufferDataSize, "");
}
}
@@ -1006,55 +1029,90 @@ int GetStrideOfMetalType(MTLDataType type)
for (size_t i = 0; i < uniforms.size(); ++i)
{
const ShaderPort* v = uniforms[i];
- MTLDataType resourceType = mapTypeToMetalType(v->getType());
-
- // There is no way to match with an unnamed variable
- if (v->getVariable().empty())
- {
- continue;
- }
- // Ignore types which are unsupported in MSL.
- if (resourceType == MTLDataTypeNone)
- {
- continue;
- }
+ const string& variablePath = v->getPath();
+ const string& variableSemantic = v->getSemantic();
- auto inputIt = _uniformList.find(v->getVariable());
- if (inputIt == _uniformList.end())
+ const auto populateUniformInput =
+ [this, uniforms, variablePath, variableSemantic, &errors, &uniformTypeMismatchFound]
+ (TypeDesc variableTypeDesc, const string& variableName, ConstValuePtr variableValue) -> void
{
- if (v->getType() == Type::FILENAME)
+ auto populateUniformInput_impl =
+ [this, uniforms, variablePath, variableSemantic, &errors, &uniformTypeMismatchFound]
+ (TypeDesc variableTypeDesc, const string& variableName, ConstValuePtr variableValue, auto& populateUniformInput_ref) -> void
{
- inputIt = _uniformList.find(TEXTURE_NAME(v->getVariable()));
- }
- else
- {
- inputIt = _uniformList.find(uniforms.getInstance() + "." + v->getVariable());
- }
- }
+ // There is no way to match with an unnamed variable
+ if (variableName.empty())
+ {
+ return;
+ }
- if (inputIt != _uniformList.end())
- {
- Input* input = inputIt->second.get();
- input->path = v->getPath();
- input->value = v->getValue();
- if (input->resourceType == resourceType)
- {
- input->typeString = v->getType().getName();
- }
- else
- {
- errors.push_back(
- "Pixel shader uniform block type mismatch [" + uniforms.getName() + "]. "
- + "Name: \"" + v->getVariable()
- + "\". Type: \"" + v->getType().getName()
- + "\". Semantic: \"" + v->getSemantic()
- + "\". Value: \"" + (v->getValue() ? v->getValue()->getValueString() : "")
- + "\". resourceType: " + std::to_string(mapTypeToMetalType(v->getType()))
- );
- uniformTypeMismatchFound = true;
- }
- }
+ MTLDataType resourceType = mapTypeToMetalType(variableTypeDesc);
+ // Ignore types which are unsupported in MSL.
+ if (resourceType == MTLDataTypeNone)
+ {
+ return;
+ }
+
+ if (!variableTypeDesc.isStruct())
+ {
+ auto inputIt = _uniformList.find(variableName);
+
+ if (inputIt == _uniformList.end()) {
+ if(variableTypeDesc == Type::FILENAME)
+ {
+ inputIt = _uniformList.find(TEXTURE_NAME(variableName));
+ }
+ else
+ {
+ inputIt = _uniformList.find(uniforms.getInstance() + "." + variableName);
+ }
+ }
+
+ if (inputIt != _uniformList.end())
+ {
+ Input* input = inputIt->second.get();
+ input->path = variablePath;
+ input->value = variableValue;
+ if (input->resourceType == resourceType)
+ {
+ input->typeString = variableTypeDesc.getName();
+ }
+ else
+ {
+ errors.push_back(
+ "Pixel shader uniform block type mismatch [" + uniforms.getName() + "]. "
+ + "Name: \"" + variableName
+ + "\". Type: \"" + variableTypeDesc.getName()
+ + "\". Semantic: \"" + variableSemantic
+ + "\". Value: \"" + (variableValue ? variableValue->getValueString() : "")
+ + "\". resourceType: " + std::to_string(mapTypeToMetalType(variableTypeDesc))
+ );
+ uniformTypeMismatchFound = true;
+ }
+ }
+ }
+ else
+ {
+ auto structTypeDesc = StructTypeDesc::get(variableTypeDesc.getStructIndex());
+ auto aggregateValue = std::static_pointer_cast(variableValue);
+
+ const auto& members = structTypeDesc.getMembers();
+ for (size_t i = 0, n = members.size(); i < n; ++i)
+ {
+ const auto& structMember = members[i];
+ auto memberVariableName = variableName+"."+structMember._name;
+ auto memberVariableValue = aggregateValue->getMemberValue(i);
+
+ populateUniformInput_ref(structMember._typeDesc, memberVariableName, memberVariableValue, populateUniformInput_ref);
+ }
+ }
+ };
+
+ return populateUniformInput_impl(variableTypeDesc, variableName, variableValue, populateUniformInput_impl);
+ };
+
+ populateUniformInput(v->getType(), v->getVariable(), v->getValue());
}
}
@@ -1231,7 +1289,7 @@ int GetStrideOfMetalType(MTLDataType type)
return false;
};
- auto setValue = [](MaterialX::ValuePtr value, std::vector& data, size_t offset)
+ auto setValue = [](MaterialX::ConstValuePtr value, std::vector& data, size_t offset)
{
if (value->getTypeString() == "float")
{
@@ -1307,7 +1365,7 @@ throw ExceptionRenderError(
{
if (!setCommonUniform(lightHandler, cam, member.name.UTF8String, uniformBufferData, member.offset))
{
- MaterialX::ValuePtr value = _uniformList[string(arg.name.UTF8String) + "." + member.name.UTF8String]->value;
+ auto value = _uniformList[string(arg.name.UTF8String) + "." + member.name.UTF8String]->value;
if (value)
{
setValue(value, uniformBufferData, member.offset);
@@ -1332,39 +1390,60 @@ throw ExceptionRenderError(
if (!setCommonUniform(lightHandler, cam, member.name.UTF8String, uniformBufferData, member.offset))
{
- auto uniformInfo = _uniformList.find(uniformName);
- if (uniformInfo != _uniformList.end())
- {
- MaterialX::ValuePtr value = uniformInfo->second->value;
- if (value)
- {
- setValue(value, uniformBufferData, member.offset);
- }
- }
- else
- {
- }
- }
-
- if (MTLArrayType* arrayMember = member.arrayType)
- {
- for (int i = 0; i < arrayMember.arrayLength; ++i)
+ const auto setUniformValue =
+ [this, setValue]
+ (MTLStructMember* member, const string& uniformName, std::vector& uniformBufferData, int offset ) -> void
{
- for (MTLStructMember* ArrayOfStructMember in arrayMember.elementStructType.members)
+ auto setUniformValue_impl =
+ [this, setValue]
+ (MTLStructMember* member, const string& uniformName, std::vector& uniformBufferData, int offset, auto &setUniformValue_ref ) -> void
{
- string uniformNameSubArray = uniformName + "[" + std::to_string(i) + "]." + ArrayOfStructMember.name.UTF8String;
-
- auto uniformInfo = _uniformList.find(uniformNameSubArray);
- if (uniformInfo != _uniformList.end())
+ if(MTLArrayType* arrayMember = member.arrayType)
{
- MaterialX::ValuePtr value = uniformInfo->second->value;
- if (value)
+ for(int i = 0; i < arrayMember.arrayLength; ++i)
{
- setValue(value, uniformBufferData, member.offset + i * arrayMember.stride + ArrayOfStructMember.offset);
+ for (MTLStructMember* ArrayOfStructMember in arrayMember.elementStructType.members)
+ {
+ string uniformNameSubArray = uniformName + "[" + std::to_string(i) + "]." + ArrayOfStructMember.name.UTF8String;
+ auto uniformInfo = _uniformList.find(uniformNameSubArray);
+ if (uniformInfo != _uniformList.end())
+ {
+ auto value = uniformInfo->second->value;
+ if(value)
+ {
+ setValue(value, uniformBufferData, offset + i * arrayMember.stride + ArrayOfStructMember.offset);
+ }
+ }
+ }
}
}
- }
- }
+ else if (MTLStructType* structMember = member.structType)
+ {
+ // this code does not support struct recursion yet....
+ for (MTLStructMember* subMember in structMember.members)
+ {
+ string subUniformName = uniformName+"."+subMember.name.UTF8String;
+ setUniformValue_ref(subMember, subUniformName, uniformBufferData, offset+subMember.offset, setUniformValue_ref);
+ }
+ }
+ else
+ {
+ auto uniformInfo = _uniformList.find(uniformName);
+ if (uniformInfo != _uniformList.end())
+ {
+ auto value = uniformInfo->second->value;
+ if(value)
+ {
+ setValue(value, uniformBufferData, offset);
+ }
+ }
+ }
+ };
+
+ return setUniformValue_impl(member, uniformName, uniformBufferData, offset, setUniformValue_impl);
+ };
+
+ setUniformValue(member, uniformName, uniformBufferData, member.offset);
}
}
@@ -1415,14 +1494,15 @@ throw ExceptionRenderError(
// A "filename" is not indicative of type, so just return a 2d sampler.
return MTLDataTypeTexture;
}
- else if (type == Type::BSDF ||
- type == Type::MATERIAL ||
+ else if (type == Type::BSDF ||
+ type == Type::MATERIAL ||
type == Type::DISPLACEMENTSHADER ||
- type == Type::EDF ||
- type == Type::VDF ||
- type == Type::SURFACESHADER ||
- type == Type::LIGHTSHADER ||
- type == Type::VOLUMESHADER)
+ type == Type::EDF ||
+ type == Type::VDF ||
+ type == Type::SURFACESHADER ||
+ type == Type::LIGHTSHADER ||
+ type == Type::VOLUMESHADER ||
+ type.isStruct())
return MTLDataTypeStruct;
return MTLDataTypeNone;
diff --git a/source/MaterialXTest/CMakeLists.txt b/source/MaterialXTest/CMakeLists.txt
index 4835787ed8..c3fae603dc 100644
--- a/source/MaterialXTest/CMakeLists.txt
+++ b/source/MaterialXTest/CMakeLists.txt
@@ -96,11 +96,6 @@ endif()
add_custom_command(TARGET MaterialXTest POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_directory
${CMAKE_CURRENT_SOURCE_DIR}/../../libraries ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/libraries)
-if(MATERIALX_OSL_LEGACY_CLOSURES)
- add_custom_command(TARGET MaterialXTest POST_BUILD
- COMMAND ${CMAKE_COMMAND} -E rename
- ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/libraries/pbrlib/genosl/pbrlib_genosl_impl.legacy ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/libraries/pbrlib/genosl/pbrlib_genosl_impl.mtlx)
-endif()
if(MATERIALX_BUILD_GEN_MDL)
install(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/../../source/MaterialXGenMdl/mdl/"
diff --git a/source/MaterialXTest/MaterialXCore/Document.cpp b/source/MaterialXTest/MaterialXCore/Document.cpp
index 94f8b98708..b593969ccb 100644
--- a/source/MaterialXTest/MaterialXCore/Document.cpp
+++ b/source/MaterialXTest/MaterialXCore/Document.cpp
@@ -10,8 +10,6 @@
#include
#include
-#include
-
namespace mx = MaterialX;
TEST_CASE("Document", "[document]")
@@ -123,16 +121,6 @@ TEST_CASE("Document", "[document]")
REQUIRE(doc->validate());
}
-void printDifferences(const mx::ElementEquivalenceResultVec& results, const std::string& label)
-{
- for (const mx::ElementEquivalenceResult& result : results)
- {
- std::cout << label << ": " << "Element: " << result.path1 <<
- ", Element: " << result.path2 << ", Difference Type: " << result.differenceType
- << ", Value: " << result.attributeName << std::endl;
- }
-}
-
TEST_CASE("Document equivalence", "[document]")
{
mx::DocumentPtr doc = mx::createDocument();
@@ -162,6 +150,9 @@ TEST_CASE("Document equivalence", "[document]")
unsigned int index = 0;
mx::ElementPtr child = doc->addNodeGraph("mygraph");
mx::NodeGraphPtr graph = child->asA();
+ // Add comment block at the start of the first doc to check skipping
+ mx::ElementPtr comment = doc->addChildOfCategory(mx::CommentElement::CATEGORY);
+ comment->setDocString("Comment 1");
for (auto it = inputMap.begin(); it != inputMap.end(); ++it)
{
const std::string inputType = (*it).first;
@@ -217,69 +208,42 @@ TEST_CASE("Document equivalence", "[document]")
input->setName("input_" + inputType);
}
}
+ // Add comment blocks at end of second doc to check value and count checks
+ comment = doc2->addChildOfCategory(mx::CommentElement::CATEGORY);
+ comment->setDocString("Comment 2");
+ comment = doc2->addChildOfCategory(mx::CommentElement::CATEGORY);
+ comment->setDocString("Comment 3");
mx::ElementEquivalenceOptions options;
mx::ElementEquivalenceResultVec results;
- // Check skipping all value compares
- options.skipValueComparisons = true;
+ // Check that this fails when not performing value comparisons
+ options.performValueComparisons = false;
bool equivalent = doc->isEquivalent(doc2, options, &results);
- if (equivalent)
- {
- std::cout << "Unexpected skip value equivalence:" << std::endl;
- std::cout << "Document 1: " << mx::prettyPrint(doc) << std::endl;
- std::cout << "Document 2: " << mx::prettyPrint(doc2) << std::endl;
- }
- else
- {
- printDifferences(results, "Expected value differences");
- }
REQUIRE(!equivalent);
// Check attibute values
- options.skipValueComparisons = false;
+ options.performValueComparisons = true;
results.clear();
equivalent = doc->isEquivalent(doc2, options, &results);
- if (!equivalent)
- {
- printDifferences(results, "Unexpected value difference");
- std::cout << "Document 1: " << mx::prettyPrint(doc) << std::endl;
- std::cout << "Document 2: " << mx::prettyPrint(doc2) << std::endl;
- }
REQUIRE(equivalent);
unsigned int currentPrecision = mx::Value::getFloatPrecision();
// This will compare 0.012345608 versus: 1, 0.012345611 for input10
- options.precision = 8;
+ options.floatPrecision = 8;
equivalent = doc->isEquivalent(doc2, options);
- if (equivalent)
- {
- std::cout << "Unexpected precision equivalence:" << std::endl;
- std::cout << "Document 1: " << mx::prettyPrint(doc) << std::endl;
- std::cout << "Document 2: " << mx::prettyPrint(doc2) << std::endl;
- }
- else
- {
- printDifferences(results, "Expected precision difference");
- }
REQUIRE(!equivalent);
- options.precision = currentPrecision;
+ options.floatPrecision = currentPrecision;
// Check attribute filtering of inputs
results.clear();
- options.skipAttributes = { mx::ValueElement::UI_MIN_ATTRIBUTE, mx::ValueElement::UI_MAX_ATTRIBUTE };
+ options.attributeExclusionList = { mx::ValueElement::UI_MIN_ATTRIBUTE, mx::ValueElement::UI_MAX_ATTRIBUTE };
for (mx::InputPtr floatInput : floatInputs)
{
floatInput->setAttribute(mx::ValueElement::UI_MIN_ATTRIBUTE, "0.9");
floatInput->setAttribute(mx::ValueElement::UI_MAX_ATTRIBUTE, "100.0");
}
equivalent = doc->isEquivalent(doc2, options, &results);
- if (!equivalent)
- {
- printDifferences(results, "Unexpected filtering differences");
- std::cout << "Document 1: " << mx::prettyPrint(doc) << std::endl;
- std::cout << "Document 2: " << mx::prettyPrint(doc2) << std::endl;
- }
REQUIRE(equivalent);
for (mx::InputPtr floatInput : floatInputs)
{
@@ -293,16 +257,6 @@ TEST_CASE("Document equivalence", "[document]")
mismatchElement->setName("mismatch_color4");
results.clear();
equivalent = doc->isEquivalent(doc2, options, &results);
- if (!equivalent)
- {
- printDifferences(results, "Expected name mismatch differences");
- }
- else
- {
- std::cout << "Unexpected name match equivalence:" << std::endl;
- std::cout << "Document 1: " << mx::prettyPrint(doc) << std::endl;
- std::cout << "Document 2: " << mx::prettyPrint(doc2) << std::endl;
- }
REQUIRE(!equivalent);
mismatchElement->setName(previousName);
results.clear();
@@ -320,15 +274,5 @@ TEST_CASE("Document equivalence", "[document]")
nodeGraph2->setNodeDefString("ND_mygraph");
results.clear();
equivalent = doc->isEquivalent(doc2, options, &results);
- if (!equivalent)
- {
- printDifferences(results, "Expected functional graph differences");
- }
- else
- {
- std::cout << "Unexpected functional graph equivalence:" << std::endl;
- std::cout << "Document 1: " << mx::prettyPrint(doc) << std::endl;
- std::cout << "Document 2: " << mx::prettyPrint(doc2) << std::endl;
- }
REQUIRE(!equivalent);
}
diff --git a/source/MaterialXTest/MaterialXCore/Node.cpp b/source/MaterialXTest/MaterialXCore/Node.cpp
index ef746bfe05..f3ce7d40de 100644
--- a/source/MaterialXTest/MaterialXCore/Node.cpp
+++ b/source/MaterialXTest/MaterialXCore/Node.cpp
@@ -159,12 +159,12 @@ TEST_CASE("Node", "[node]")
REQUIRE(typeDef->getMembers().size() == scalarCount);
// Reference the custom type.
- std::string d65("400.0,82.75,500.0,109.35,600.0,90.01,700.0,71.61,800.0,59.45");
+ std::string d65("{400;82.75;500;109.35;600;90.01;700;71.61;800;59.45}");
constant->setInputValue("value", d65, "spectrum");
REQUIRE(constant->getInput("value")->getType() == "spectrum");
REQUIRE(constant->getInput("value")->getValueString() == d65);
- REQUIRE(constant->getInputValue("value")->isA());
- REQUIRE(constant->getInputValue("value")->asA() == d65);
+ REQUIRE(constant->getInputValue("value")->isA());
+ REQUIRE(constant->getInputValue("value")->asA().getValueString() == d65);
// Validate the document.
REQUIRE(doc->validate());
diff --git a/source/MaterialXTest/MaterialXGenGlsl/GenGlsl.cpp b/source/MaterialXTest/MaterialXGenGlsl/GenGlsl.cpp
index de50b3671d..979320bd91 100644
--- a/source/MaterialXTest/MaterialXGenGlsl/GenGlsl.cpp
+++ b/source/MaterialXTest/MaterialXGenGlsl/GenGlsl.cpp
@@ -81,7 +81,7 @@ TEST_CASE("GenShader: GLSL Implementation Check", "[genglsl]")
mx::StringSet generatorSkipNodeTypes;
mx::StringSet generatorSkipNodeDefs;
- GenShaderUtil::checkImplementations(context, generatorSkipNodeTypes, generatorSkipNodeDefs, 29);
+ GenShaderUtil::checkImplementations(context, generatorSkipNodeTypes, generatorSkipNodeDefs);
}
TEST_CASE("GenShader: GLSL Unique Names", "[genglsl]")
diff --git a/source/MaterialXTest/MaterialXGenGlsl/GenGlsl.h b/source/MaterialXTest/MaterialXGenGlsl/GenGlsl.h
index 94f1b64f34..0e0f296ad2 100644
--- a/source/MaterialXTest/MaterialXGenGlsl/GenGlsl.h
+++ b/source/MaterialXTest/MaterialXGenGlsl/GenGlsl.h
@@ -51,7 +51,7 @@ class GlslShaderGeneratorTester : public GenShaderUtil::ShaderGeneratorTester
{
whiteList =
{
- "ambientocclusion", "arrayappend", "screen", "curveadjust", "displacementshader", "volumeshader",
+ "screen", "displacementshader", "volumeshader",
"IM_constant_", "IM_dot_", "IM_geompropvalue_boolean", "IM_geompropvalue_string", "IM_geompropvalue_filename",
"IM_light_genglsl", "IM_point_light_genglsl", "IM_spot_light_genglsl", "IM_directional_light_genglsl",
"IM_angle", "volumematerial", "ND_volumematerial"
diff --git a/source/MaterialXTest/MaterialXGenMdl/GenMdl.cpp b/source/MaterialXTest/MaterialXGenMdl/GenMdl.cpp
index 2d05b1552c..4bec0016de 100644
--- a/source/MaterialXTest/MaterialXGenMdl/GenMdl.cpp
+++ b/source/MaterialXTest/MaterialXGenMdl/GenMdl.cpp
@@ -94,7 +94,7 @@ TEST_CASE("GenShader: MDL Implementation Check", "[genmdl]")
mx::StringSet generatorSkipNodeDefs;
- GenShaderUtil::checkImplementations(context, generatorSkipNodeTypes, generatorSkipNodeDefs, 30);
+ GenShaderUtil::checkImplementations(context, generatorSkipNodeTypes, generatorSkipNodeDefs);
}
@@ -225,15 +225,9 @@ void MdlShaderGeneratorTester::compileSource(const std::vector& so
moduleToTest = moduleToTest.substr(0, moduleToTest.size() - sourceCodePaths[0].getExtension().length() - 1);
std::string renderExec(MATERIALX_MDL_RENDER_EXECUTABLE);
- bool testMDLC = renderExec.empty();
- if (testMDLC)
+ std::string mdlcExec(MATERIALX_MDLC_EXECUTABLE);
+ if (!mdlcExec.empty()) // always run compiler
{
- std::string mdlcExec(MATERIALX_MDLC_EXECUTABLE);
- if (mdlcExec.empty())
- {
- return;
- }
-
std::string mdlcCommand = mdlcExec;
// use the same paths as the resolver
@@ -264,12 +258,19 @@ void MdlShaderGeneratorTester::compileSource(const std::vector& so
_logFile << "\tReturn code: " << std::to_string(returnValue) << std::endl;
writeErrorCode = true;
}
- _logFile << "\tError: " << line << std::endl;
+ if (line.find(": Warning ") != std::string::npos)
+ {
+ _logFile << "\tWarning: " << line << std::endl;
+ }
+ else
+ {
+ _logFile << "\tError: " << line << std::endl;
+ }
}
CHECK(returnValue == 0);
}
- else
+ if (!renderExec.empty()) // render if renderer is availabe
{
std::string renderCommand = renderExec;
@@ -358,6 +359,7 @@ TEST_CASE("GenShader: MDL Shader Generation", "[genmdl]")
mx::FilePathVec testRootPaths;
testRootPaths.push_back(searchPath.find("resources/Materials/TestSuite"));
testRootPaths.push_back(searchPath.find("resources/Materials/Examples/StandardSurface"));
+ testRootPaths.push_back(searchPath.find("resources/Materials/Examples/UsdPreviewSurface"));
const mx::FilePath logPath("genmdl_mdl_generate_test.txt");
diff --git a/source/MaterialXTest/MaterialXGenMdl/GenMdl.h b/source/MaterialXTest/MaterialXGenMdl/GenMdl.h
index ab92a5dacf..e51dbbd7e5 100644
--- a/source/MaterialXTest/MaterialXGenMdl/GenMdl.h
+++ b/source/MaterialXTest/MaterialXGenMdl/GenMdl.h
@@ -76,7 +76,7 @@ class MdlShaderGeneratorTester : public GenShaderUtil::ShaderGeneratorTester
{
whiteList =
{
- "ambientocclusion", "arrayappend", "backfacing", "screen", "curveadjust", "displacementshader",
+ "backfacing", "screen", "displacementshader",
"volumeshader", "IM_constant_", "IM_dot_", "IM_geomattrvalue", "IM_angle",
"geompropvalue", "surfacematerial", "volumematerial",
"IM_absorption_vdf_", "IM_mix_vdf_", "IM_add_vdf_", "IM_multiply_vdf",
diff --git a/source/MaterialXTest/MaterialXGenMsl/GenMsl.cpp b/source/MaterialXTest/MaterialXGenMsl/GenMsl.cpp
index 3cab2b31b0..32baaec5f0 100644
--- a/source/MaterialXTest/MaterialXGenMsl/GenMsl.cpp
+++ b/source/MaterialXTest/MaterialXGenMsl/GenMsl.cpp
@@ -84,12 +84,7 @@ TEST_CASE("GenShader: MSL Implementation Check", "[genmsl]")
mx::StringSet generatorSkipNodeTypes;
mx::StringSet generatorSkipNodeDefs;
- generatorSkipNodeDefs.insert("ND_chiang_hair_roughness");
- generatorSkipNodeDefs.insert("ND_chiang_hair_absorption_from_color");
- generatorSkipNodeDefs.insert("ND_deon_hair_absorption_from_melanin");
- generatorSkipNodeDefs.insert("ND_chiang_hair_bsdf");
-
- GenShaderUtil::checkImplementations(context, generatorSkipNodeTypes, generatorSkipNodeDefs, 33);
+ GenShaderUtil::checkImplementations(context, generatorSkipNodeTypes, generatorSkipNodeDefs);
}
TEST_CASE("GenShader: MSL Unique Names", "[genmsl]")
diff --git a/source/MaterialXTest/MaterialXGenMsl/GenMsl.h b/source/MaterialXTest/MaterialXGenMsl/GenMsl.h
index 2e66e3a3a2..27a911f6d9 100644
--- a/source/MaterialXTest/MaterialXGenMsl/GenMsl.h
+++ b/source/MaterialXTest/MaterialXGenMsl/GenMsl.h
@@ -43,8 +43,6 @@ class MslShaderGeneratorTester : public GenShaderUtil::ShaderGeneratorTester
void addSkipFiles() override
{
- _skipFiles.insert("hair_bsdf.mtlx");
- _skipFiles.insert("hair_surfaceshader.mtlx");
}
void setupDependentLibraries() override
@@ -72,7 +70,7 @@ class MslShaderGeneratorTester : public GenShaderUtil::ShaderGeneratorTester
{
whiteList =
{
- "ambientocclusion", "arrayappend", "backfacing", "screen", "curveadjust", "displacementshader",
+ "backfacing", "screen", "displacementshader",
"volumeshader", "IM_constant_", "IM_dot_", "IM_geompropvalue_boolean", "IM_geompropvalue_string", "IM_geompropvalue_filename",
"IM_light_genmsl", "IM_point_light_genmsl", "IM_spot_light_genmsl", "IM_directional_light_genmsl",
"IM_angle", "surfacematerial", "volumematerial", "ND_surfacematerial", "ND_volumematerial", "ND_backface_util", "IM_backface_util_genmsl"
diff --git a/source/MaterialXTest/MaterialXGenOsl/GenOsl.cpp b/source/MaterialXTest/MaterialXGenOsl/GenOsl.cpp
index 21cd12e9f2..6e613c85b8 100644
--- a/source/MaterialXTest/MaterialXGenOsl/GenOsl.cpp
+++ b/source/MaterialXTest/MaterialXGenOsl/GenOsl.cpp
@@ -89,12 +89,8 @@ TEST_CASE("GenShader: OSL Implementation Check", "[genosl]")
generatorSkipNodeTypes.insert("light");
mx::StringSet generatorSkipNodeDefs;
- generatorSkipNodeDefs.insert("ND_chiang_hair_roughness");
- generatorSkipNodeDefs.insert("ND_chiang_hair_absorption_from_color");
- generatorSkipNodeDefs.insert("ND_deon_hair_absorption_from_melanin");
- generatorSkipNodeDefs.insert("ND_chiang_hair_bsdf");
- GenShaderUtil::checkImplementations(context, generatorSkipNodeTypes, generatorSkipNodeDefs, 34);
+ GenShaderUtil::checkImplementations(context, generatorSkipNodeTypes, generatorSkipNodeDefs);
}
TEST_CASE("GenShader: OSL Unique Names", "[genosl]")
diff --git a/source/MaterialXTest/MaterialXGenOsl/GenOsl.h b/source/MaterialXTest/MaterialXGenOsl/GenOsl.h
index b6004334c1..bb1ce5b6f9 100644
--- a/source/MaterialXTest/MaterialXGenOsl/GenOsl.h
+++ b/source/MaterialXTest/MaterialXGenOsl/GenOsl.h
@@ -45,8 +45,6 @@ class OslShaderGeneratorTester : public GenShaderUtil::ShaderGeneratorTester
void addSkipFiles() override
{
- _skipFiles.insert("hair_bsdf.mtlx");
- _skipFiles.insert("hair_surfaceshader.mtlx");
}
// Ignore light shaders in the document for OSL
@@ -65,7 +63,7 @@ class OslShaderGeneratorTester : public GenShaderUtil::ShaderGeneratorTester
{
whiteList =
{
- "ambientocclusion", "arrayappend", "backfacing", "screen", "curveadjust", "displacementshader",
+ "backfacing", "screen", "displacementshader",
"volumeshader", "IM_constant_", "IM_dot_", "IM_geompropvalue", "IM_geompropvalueuniform", "IM_angle", "ND_backface_util"
};
ShaderGeneratorTester::getImplementationWhiteList(whiteList);
diff --git a/source/MaterialXTest/MaterialXGenShader/GenShaderUtil.cpp b/source/MaterialXTest/MaterialXGenShader/GenShaderUtil.cpp
index 4a8e61645a..40f89c001f 100644
--- a/source/MaterialXTest/MaterialXGenShader/GenShaderUtil.cpp
+++ b/source/MaterialXTest/MaterialXGenShader/GenShaderUtil.cpp
@@ -67,8 +67,7 @@ bool getShaderSource(mx::GenContext& context,
// Check that implementations exist for all nodedefs supported per generator
void checkImplementations(mx::GenContext& context,
const mx::StringSet& generatorSkipNodeTypes,
- const mx::StringSet& generatorSkipNodeDefs,
- unsigned int expectedSkipCount)
+ const mx::StringSet& generatorSkipNodeDefs)
{
const mx::ShaderGenerator& shadergen = context.getShaderGenerator();
@@ -90,10 +89,8 @@ void checkImplementations(mx::GenContext& context,
// Node types to explicitly skip temporarily.
mx::StringSet skipNodeTypes =
{
- "ambientocclusion",
"displacement",
"volume",
- "curveadjust",
"conical_edf",
"measured_edf",
"absorption_vdf",
@@ -268,7 +265,6 @@ void checkImplementations(mx::GenContext& context,
std::cerr << (std::string("Missing list: ") + missing_str) << std::endl;
}
REQUIRE(missing == 0);
- REQUIRE(skipped == expectedSkipCount);
implDumpBuffer.close();
}
@@ -649,6 +645,9 @@ void ShaderGeneratorTester::validate(const mx::GenOptions& generateOptions, cons
addColorManagement();
addUnitSystem();
+ // Register struct typedefs from the library files.
+ _shaderGenerator->loadStructTypeDefs(_dependLib);
+
// Test suite setup
addSkipFiles();
@@ -705,6 +704,8 @@ void ShaderGeneratorTester::validate(const mx::GenOptions& generateOptions, cons
preprocessDocument(doc);
_shaderGenerator->registerShaderMetadata(doc, context);
+ _shaderGenerator->loadStructTypeDefs(doc);
+
// For each new file clear the implementation cache.
// Since the new file might contain implementations with names
// colliding with implementations in previous test cases.
diff --git a/source/MaterialXTest/MaterialXGenShader/GenShaderUtil.h b/source/MaterialXTest/MaterialXGenShader/GenShaderUtil.h
index 2bac14e435..d4876a03f7 100644
--- a/source/MaterialXTest/MaterialXGenShader/GenShaderUtil.h
+++ b/source/MaterialXTest/MaterialXGenShader/GenShaderUtil.h
@@ -46,8 +46,7 @@ bool generateCode(mx::GenContext& context, const std::string& shaderName, mx::Ty
// Check that implementations exist for all nodedefs supported per generator
void checkImplementations(mx::GenContext& context,
const mx::StringSet& generatorSkipNodeTypes,
- const mx::StringSet& generatorSkipNodeDefs,
- unsigned int expectedSkipCount);
+ const mx::StringSet& generatorSkipNodeDefs);
// Utility test to check unique name generation on a shader generator
void testUniqueNames(mx::GenContext& context, const std::string& stage);
diff --git a/source/MaterialXTest/MaterialXRenderOsl/GenReference.cpp b/source/MaterialXTest/MaterialXRenderOsl/GenReference.cpp
index 3184d892e9..05c83ae82e 100644
--- a/source/MaterialXTest/MaterialXRenderOsl/GenReference.cpp
+++ b/source/MaterialXTest/MaterialXRenderOsl/GenReference.cpp
@@ -65,8 +65,7 @@ TEST_CASE("GenReference: OSL Reference", "[genreference]")
// Generate reference shaders.
// Ignore the following nodes:
const mx::StringSet ignoreNodeList = { "surfacematerial", "volumematerial",
- "constant_filename", "arrayappend",
- "dot_filename"};
+ "constant_filename", "dot_filename"};
bool failedGeneration = false;
for (const mx::NodeDefPtr& nodedef : stdlib->getNodeDefs())
diff --git a/source/MaterialXView/Editor.cpp b/source/MaterialXView/Editor.cpp
index abba9ce10e..6d64c55b30 100644
--- a/source/MaterialXView/Editor.cpp
+++ b/source/MaterialXView/Editor.cpp
@@ -18,11 +18,11 @@ namespace
class EditorColorPicker : public ng::ColorPicker
{
public:
- EditorColorPicker(ng::Widget* parent, const ng::Color& color) :
+ EditorColorPicker(ng::ref parent, const ng::Color& color) :
ng::ColorPicker(parent, color)
{
- ng::Popup* popup = this->popup();
- ng::Widget* floatGroup = new ng::Widget(popup);
+ ng::ref popup = this->popup();
+ ng::ref floatGroup = new ng::Widget(popup);
auto layout = new ng::GridLayout(ng::Orientation::Horizontal, 2,
ng::Alignment::Middle, 2, 2);
layout->set_col_alignment({ ng::Alignment::Fill, ng::Alignment::Fill });
@@ -60,7 +60,7 @@ class EditorColorPicker : public ng::ColorPicker
protected:
// Additional numeric entry / feedback widgets
- ng::FloatBox* _colorWidgets[4];
+ ng::ref> _colorWidgets[4];
};
} // anonymous namespace
@@ -70,10 +70,6 @@ class EditorColorPicker : public ng::ColorPicker
//
PropertyEditor::PropertyEditor() :
- _window(nullptr),
- _container(nullptr),
- _gridLayout2(nullptr),
- _gridLayout3(nullptr),
_visible(false),
_fileDialogsForImages(true)
{
@@ -81,7 +77,7 @@ PropertyEditor::PropertyEditor() :
void PropertyEditor::create(Viewer& parent)
{
- ng::Window* parentWindow = parent.getWindow();
+ ng::ref parentWindow = parent.getWindow();
// Remove the window associated with the form.
// This is done by explicitly creating and owning the window
@@ -110,7 +106,7 @@ void PropertyEditor::create(Viewer& parent)
_window->set_position(previousPosition);
_window->set_visible(_visible);
- ng::VScrollPanel* scroll_panel = new ng::VScrollPanel(_window);
+ ng::ref scroll_panel = new ng::VScrollPanel(_window);
scroll_panel->set_fixed_height(300);
_container = new ng::Widget(scroll_panel);
_container->set_layout(new ng::GroupLayout(1, 1, 1, 1));
@@ -127,7 +123,7 @@ void PropertyEditor::create(Viewer& parent)
}
void PropertyEditor::addItemToForm(const mx::UIPropertyItem& item, const std::string& group,
- ng::Widget* container, Viewer* viewer, bool editable)
+ ng::ref container, Viewer* viewer, bool editable)
{
const mx::UIProperties& ui = item.ui;
mx::ValuePtr value = item.variable->getValue();
@@ -148,9 +144,9 @@ void PropertyEditor::addItemToForm(const mx::UIPropertyItem& item, const std::st
if (!group.empty())
{
- ng::Widget* twoColumns = new ng::Widget(container);
+ ng::ref twoColumns = new ng::Widget(container);
twoColumns->set_layout(_gridLayout2);
- ng::Label* groupLabel = new ng::Label(twoColumns, group);
+ ng::ref groupLabel = new ng::Label(twoColumns, group);
groupLabel->set_font_size(20);
groupLabel->set_font("sans-bold");
new ng::Label(twoColumns, "");
@@ -187,11 +183,11 @@ void PropertyEditor::addItemToForm(const mx::UIPropertyItem& item, const std::st
const size_t valueIndex = indexInEnumeration();
if (INVALID_INDEX != valueIndex)
{
- ng::Widget* twoColumns = new ng::Widget(container);
+ ng::ref twoColumns = new ng::Widget(container);
twoColumns->set_layout(_gridLayout2);
new ng::Label(twoColumns, label);
- ng::ComboBox* comboBox = new ng::ComboBox(twoColumns, { "" });
+ ng::ref comboBox = new ng::ComboBox(twoColumns, { "" });
comboBox->set_enabled(editable);
comboBox->set_items(enumeration);
comboBox->set_selected_index(static_cast(valueIndex));
@@ -215,7 +211,7 @@ void PropertyEditor::addItemToForm(const mx::UIPropertyItem& item, const std::st
}
else
{
- ng::Widget* twoColumns = new ng::Widget(container);
+ ng::ref twoColumns = new ng::Widget(container);
twoColumns->set_layout(_gridLayout2);
new ng::Label(twoColumns, label);
@@ -252,9 +248,9 @@ void PropertyEditor::addItemToForm(const mx::UIPropertyItem& item, const std::st
// Float widget
else if (value->isA())
{
- ng::Widget* threeColumns = new ng::Widget(container);
+ ng::ref threeColumns = new ng::Widget(container);
threeColumns->set_layout(_gridLayout3);
- ng::FloatBox* floatBox = createFloatWidget(threeColumns, label, value->asA(), &ui, [viewer, path](float value)
+ ng::ref> floatBox = createFloatWidget(threeColumns, label, value->asA(), &ui, [viewer, path](float value)
{
mx::MaterialPtr material = viewer->getSelectedMaterial();
if (material)
@@ -269,12 +265,12 @@ void PropertyEditor::addItemToForm(const mx::UIPropertyItem& item, const std::st
// Boolean widget
else if (value->isA())
{
- ng::Widget* twoColumns = new ng::Widget(container);
+ ng::ref twoColumns = new ng::Widget(container);
twoColumns->set_layout(_gridLayout2);
bool v = value->asA();
new ng::Label(twoColumns, label);
- ng::CheckBox* boolVar = new ng::CheckBox(twoColumns, "");
+ ng::ref boolVar = new ng::CheckBox(twoColumns, "");
boolVar->set_checked(v);
boolVar->set_font_size(15);
boolVar->set_callback([path, viewer](bool v)
@@ -290,7 +286,7 @@ void PropertyEditor::addItemToForm(const mx::UIPropertyItem& item, const std::st
// Color3 input. Can map to a combo box if an enumeration
else if (value->isA())
{
- ng::Widget* twoColumns = new ng::Widget(container);
+ ng::ref twoColumns = new ng::Widget(container);
twoColumns->set_layout(_gridLayout2);
// Determine if there is an enumeration for this
@@ -312,7 +308,7 @@ void PropertyEditor::addItemToForm(const mx::UIPropertyItem& item, const std::st
// Create a combo box. The items are the enumerations in order.
if (index >= 0)
{
- ng::ComboBox* comboBox = new ng::ComboBox(twoColumns, { "" });
+ ng::ref comboBox = new ng::ComboBox(twoColumns, { "" });
comboBox->set_enabled(editable);
comboBox->set_items(enumeration);
comboBox->set_selected_index(index);
@@ -353,7 +349,7 @@ void PropertyEditor::addItemToForm(const mx::UIPropertyItem& item, const std::st
// Color4 input
else if (value->isA())
{
- ng::Widget* twoColumns = new ng::Widget(container);
+ ng::ref twoColumns = new ng::Widget(container);
twoColumns->set_layout(_gridLayout2);
new ng::Label(twoColumns, label);
@@ -376,7 +372,7 @@ void PropertyEditor::addItemToForm(const mx::UIPropertyItem& item, const std::st
// Vec 2 widget
else if (value->isA())
{
- ng::Widget* twoColumns = new ng::Widget(container);
+ ng::ref twoColumns = new ng::Widget(container);
twoColumns->set_layout(_gridLayout2);
mx::Vector2 v = value->asA();
@@ -415,7 +411,7 @@ void PropertyEditor::addItemToForm(const mx::UIPropertyItem& item, const std::st
// Vec 3 input
else if (value->isA())
{
- ng::Widget* twoColumns = new ng::Widget(container);
+ ng::ref twoColumns = new ng::Widget(container);
twoColumns->set_layout(_gridLayout2);
mx::Vector3 v = value->asA();
@@ -470,7 +466,7 @@ void PropertyEditor::addItemToForm(const mx::UIPropertyItem& item, const std::st
// Vec 4 input
else if (value->isA())
{
- ng::Widget* twoColumns = new ng::Widget(container);
+ ng::ref twoColumns = new ng::Widget(container);
twoColumns->set_layout(_gridLayout2);
mx::Vector4 v = value->asA();
@@ -542,16 +538,17 @@ void PropertyEditor::addItemToForm(const mx::UIPropertyItem& item, const std::st
std::string v = value->asA();
if (!v.empty())
{
- ng::Widget* twoColumns = new ng::Widget(container);
+ ng::ref twoColumns = new ng::Widget(container);
twoColumns->set_layout(_gridLayout2);
if (item.variable->getType() == mx::Type::FILENAME)
{
new ng::Label(twoColumns, label);
- ng::Button* buttonVar = new ng::Button(twoColumns, mx::FilePath(v).getBaseName());
+ ng::ref buttonVar = new ng::Button(twoColumns, mx::FilePath(v).getBaseName());
buttonVar->set_enabled(editable);
buttonVar->set_font_size(15);
- buttonVar->set_callback([buttonVar, path, viewer]()
+ auto buttonVarPtr = buttonVar.get();
+ buttonVar->set_callback([buttonVarPtr, path, viewer]()
{
mx::MaterialPtr material = viewer->getSelectedMaterial();
mx::ShaderPort* uniform = material ? material->findUniform(path) : nullptr;
@@ -572,7 +569,7 @@ void PropertyEditor::addItemToForm(const mx::UIPropertyItem& item, const std::st
if (!filename.empty())
{
uniform->setValue(mx::Value::createValue(filename));
- buttonVar->set_caption(mx::FilePath(filename).getBaseName());
+ buttonVarPtr->set_caption(mx::FilePath(filename).getBaseName());
viewer->perform_layout();
}
}
@@ -583,7 +580,7 @@ void PropertyEditor::addItemToForm(const mx::UIPropertyItem& item, const std::st
else
{
new ng::Label(twoColumns, label);
- ng::TextBox* stringVar = new ng::TextBox(twoColumns, v);
+ ng::ref stringVar = new ng::TextBox(twoColumns, v);
stringVar->set_fixed_size({ 100, 20 });
stringVar->set_font_size(15);
stringVar->set_callback([path, viewer](const std::string& v)
@@ -629,14 +626,12 @@ void PropertyEditor::updateContents(Viewer* viewer)
}
if (!shaderName.empty() && shaderName != "surface")
{
- ng::Widget* twoColumns = new ng::Widget(_container);
+ ng::ref twoColumns = new ng::Widget(_container);
twoColumns->set_layout(_gridLayout2);
- ng::Widget* threeColumns = new ng::Widget(_container);
- threeColumns->set_layout(_gridLayout3);
- ng::Label* modelLabel = new ng::Label(twoColumns, "Shading Model");
+ ng::ref modelLabel = new ng::Label(twoColumns, "Shading Model");
modelLabel->set_font_size(20);
modelLabel->set_font("sans-bold");
- ng::Label* nameLabel = new ng::Label(twoColumns, shaderName);
+ ng::ref nameLabel = new ng::Label(twoColumns, shaderName);
nameLabel->set_font_size(20);
}
}
@@ -688,15 +683,15 @@ void PropertyEditor::updateContents(Viewer* viewer)
viewer->perform_layout();
}
-ng::FloatBox* createFloatWidget(ng::Widget* parent, const std::string& label, float value,
- const mx::UIProperties* ui, std::function callback)
+ng::ref> createFloatWidget(ng::ref parent, const std::string& label, float value,
+ const mx::UIProperties* ui, std::function callback)
{
new ng::Label(parent, label);
- ng::Slider* slider = new ng::Slider(parent);
+ ng::ref slider = new ng::Slider(parent);
slider->set_value(value);
- ng::FloatBox* box = new ng::FloatBox(parent, value);
+ ng::ref> box = new ng::FloatBox(parent, value);
box->set_fixed_width(60);
box->set_font_size(15);
box->set_alignment(ng::TextBox::Alignment::Right);
@@ -734,29 +729,31 @@ ng::FloatBox* createFloatWidget(ng::Widget* parent, const std::string& la
}
}
- slider->set_callback([box, callback](float value)
+ auto sliderPtr = slider.get();
+ auto boxPtr = box.get();
+ slider->set_callback([boxPtr, callback](float value)
{
- box->set_value(value);
+ boxPtr->set_value(value);
callback(value);
});
- box->set_callback([slider, callback](float value)
+ box->set_callback([sliderPtr, callback](float value)
{
- slider->set_value(value);
+ sliderPtr->set_value(value);
callback(value);
});
return box;
}
-ng::IntBox* createIntWidget(ng::Widget* parent, const std::string& label, int value,
- const mx::UIProperties* ui, std::function callback)
+ng::ref> createIntWidget(ng::ref parent, const std::string& label, int value,
+ const mx::UIProperties* ui, std::function callback)
{
new ng::Label(parent, label);
- ng::Slider* slider = new ng::Slider(parent);
+ ng::ref slider = new ng::Slider(parent);
slider->set_value((float) value);
- ng::IntBox* box = new ng::IntBox(parent, value);
+ ng::ref> box = new ng::IntBox(parent, value);
box->set_fixed_width(60);
box->set_font_size(15);
box->set_alignment(ng::TextBox::Alignment::Right);
@@ -794,14 +791,16 @@ ng::IntBox* createIntWidget(ng::Widget* parent, const std::string& label, i
}
}
- slider->set_callback([box, callback](float value)
+ auto sliderPtr = slider.get();
+ auto boxPtr = box.get();
+ slider->set_callback([boxPtr, callback](float value)
{
- box->set_value((int) value);
+ boxPtr->set_value((int) value);
callback((int) value);
});
- box->set_callback([slider, callback](int value)
+ box->set_callback([sliderPtr, callback](int value)
{
- slider->set_value((float) value);
+ sliderPtr->set_value((float) value);
callback(value);
});
diff --git a/source/MaterialXView/Editor.h b/source/MaterialXView/Editor.h
index b1fb4a3ade..b99f1f160c 100644
--- a/source/MaterialXView/Editor.h
+++ b/source/MaterialXView/Editor.h
@@ -39,7 +39,7 @@ class PropertyEditor
}
}
- ng::Window* getWindow()
+ ng::ref getWindow()
{
return _window;
}
@@ -47,19 +47,19 @@ class PropertyEditor
protected:
void create(Viewer& parent);
void addItemToForm(const mx::UIPropertyItem& item, const std::string& group,
- ng::Widget* container, Viewer* viewer, bool editable);
+ ng::ref container, Viewer* viewer, bool editable);
- ng::Window* _window;
- ng::Widget* _container;
- ng::GridLayout* _gridLayout2;
- ng::GridLayout* _gridLayout3;
+ ng::ref _window;
+ ng::ref _container;
+ ng::ref _gridLayout2;
+ ng::ref _gridLayout3;
bool _visible;
bool _fileDialogsForImages;
};
-ng::FloatBox* createFloatWidget(ng::Widget* parent, const std::string& label, float value,
- const mx::UIProperties* ui, std::function callback = nullptr);
-ng::IntBox* createIntWidget(ng::Widget* parent, const std::string& label, int value,
- const mx::UIProperties* ui, std::function callback);
+ng::ref> createFloatWidget(ng::ref parent, const std::string& label, float value,
+ const mx::UIProperties* ui, std::function callback = nullptr);
+ng::ref> createIntWidget(ng::ref parent, const std::string& label, int value,
+ const mx::UIProperties* ui, std::function callback);
#endif // MATERIALXVIEW_EDITOR_H
diff --git a/source/MaterialXView/Viewer.cpp b/source/MaterialXView/Viewer.cpp
index 24aea1eb42..aefdf2d401 100644
--- a/source/MaterialXView/Viewer.cpp
+++ b/source/MaterialXView/Viewer.cpp
@@ -158,7 +158,6 @@ Viewer::Viewer(const std::string& materialFilename,
const mx::Color3& screenColor) :
ng::Screen(ng::Vector2i(screenWidth, screenHeight), "MaterialXView",
true, false, true, true, USE_FLOAT_BUFFER, 4, 0),
- _window(nullptr),
_materialFilename(materialFilename),
_meshFilename(meshFilename),
_envRadianceFilename(envRadianceFilename),
@@ -184,11 +183,7 @@ Viewer::Viewer(const std::string& materialFilename,
_shadowSoftness(1),
_ambientOcclusionGain(0.6f),
_selectedGeom(0),
- _geomLabel(nullptr),
- _geometrySelectionBox(nullptr),
_selectedMaterial(0),
- _materialLabel(nullptr),
- _materialSelectionBox(nullptr),
_identityCamera(mx::Camera::create()),
_viewCamera(mx::Camera::create()),
_envCamera(mx::Camera::create()),
@@ -232,9 +227,6 @@ Viewer::Viewer(const std::string& materialFilename,
_bakeHeight(0),
_bakeDocumentPerMaterial(false),
_frameTiming(false),
- _timingLabel(nullptr),
- _timingPanel(nullptr),
- _timingText(nullptr),
_avgFrameTime(0.0)
{
// Resolve input filenames, taking both the provided search path and
@@ -295,11 +287,11 @@ void Viewer::initialize()
_imageHandler->setSearchPath(_searchPath);
// Initialize user interfaces.
- createLoadMeshInterface(_window, "Load Mesh");
- createLoadMaterialsInterface(_window, "Load Material");
- createLoadEnvironmentInterface(_window, "Load Environment");
- createPropertyEditorInterface(_window, "Property Editor");
- createAdvancedSettings(_window);
+ createLoadMeshInterface((ng::ref) _window, "Load Mesh");
+ createLoadMaterialsInterface((ng::ref) _window, "Load Material");
+ createLoadEnvironmentInterface((ng::ref) _window, "Load Environment");
+ createPropertyEditorInterface((ng::ref) _window, "Property Editor");
+ createAdvancedSettings((ng::ref) _window);
// Create geometry selection box.
_geomLabel = new ng::Label(_window, "Select Geometry");
@@ -562,9 +554,9 @@ mx::ElementPredicate Viewer::getElementPredicate()
};
}
-void Viewer::createLoadMeshInterface(Widget* parent, const std::string& label)
+void Viewer::createLoadMeshInterface(ng::ref parent, const std::string& label)
{
- ng::Button* meshButton = new ng::Button(parent, label);
+ ng::ref meshButton = new ng::Button(parent, label);
meshButton->set_icon(FA_FOLDER);
meshButton->set_tooltip("Load a new geometry in the OBJ or glTF format.");
meshButton->set_callback([this]()
@@ -590,9 +582,9 @@ void Viewer::createLoadMeshInterface(Widget* parent, const std::string& label)
});
}
-void Viewer::createLoadMaterialsInterface(Widget* parent, const std::string& label)
+void Viewer::createLoadMaterialsInterface(ng::ref parent, const std::string& label)
{
- ng::Button* materialButton = new ng::Button(parent, label);
+ ng::ref materialButton = new ng::Button(parent, label);
materialButton->set_icon(FA_FOLDER);
materialButton->set_tooltip("Load a material document in the MTLX format.");
materialButton->set_callback([this]()
@@ -608,9 +600,9 @@ void Viewer::createLoadMaterialsInterface(Widget* parent, const std::string& lab
});
}
-void Viewer::createLoadEnvironmentInterface(Widget* parent, const std::string& label)
+void Viewer::createLoadEnvironmentInterface(ng::ref parent, const std::string& label)
{
- ng::Button* envButton = new ng::Button(parent, label);
+ ng::ref envButton = new ng::Button(parent, label);
envButton->set_icon(FA_FOLDER);
envButton->set_tooltip("Load a lat-long environment light in the HDR format.");
envButton->set_callback([this]()
@@ -634,9 +626,9 @@ void Viewer::createLoadEnvironmentInterface(Widget* parent, const std::string& l
});
}
-void Viewer::createSaveMaterialsInterface(Widget* parent, const std::string& label)
+void Viewer::createSaveMaterialsInterface(ng::ref parent, const std::string& label)
{
- ng::Button* materialButton = new ng::Button(parent, label);
+ ng::ref materialButton = new ng::Button(parent, label);
materialButton->set_icon(FA_SAVE);
materialButton->set_tooltip("Save a material document in the MTLX format.");
materialButton->set_callback([this]()
@@ -664,9 +656,9 @@ void Viewer::createSaveMaterialsInterface(Widget* parent, const std::string& lab
});
}
-void Viewer::createPropertyEditorInterface(Widget* parent, const std::string& label)
+void Viewer::createPropertyEditorInterface(ng::ref parent, const std::string& label)
{
- ng::Button* editorButton = new ng::Button(parent, label);
+ ng::ref editorButton = new ng::Button(parent, label);
editorButton->set_flags(ng::Button::ToggleButton);
editorButton->set_tooltip("View or edit properties of the current material.");
editorButton->set_change_callback([this](bool state)
@@ -676,43 +668,41 @@ void Viewer::createPropertyEditorInterface(Widget* parent, const std::string& la
});
}
-void Viewer::createDocumentationInterface(Widget* parent, ng::VScrollPanel* scrollPanel)
+void Viewer::createDocumentationInterface(ng::ref parent)
{
- ng::GridLayout* documentationLayout = new ng::GridLayout(ng::Orientation::Vertical, 3,
- ng::Alignment::Minimum, 13, 5);
+ ng::ref documentationLayout = new ng::GridLayout(ng::Orientation::Vertical, 3,
+ ng::Alignment::Minimum, 13, 5);
documentationLayout->set_row_alignment({ ng::Alignment::Minimum, ng::Alignment::Maximum });
- ng::Widget* documentationGroup = new ng::Widget(parent);
+ ng::ref documentationGroup = new ng::Widget(parent);
documentationGroup->set_layout(documentationLayout);
- ng::Label* documentationLabel = new ng::Label(documentationGroup, "Documentation");
+ ng::ref documentationLabel = new ng::Label(documentationGroup, "Documentation");
documentationLabel->set_font_size(20);
documentationLabel->set_font("sans-bold");
- ng::Button* shortcutsButton = new ng::Button(documentationGroup, "Keyboard Shortcuts");
- shortcutsButton->set_flags(ng::Button::ToggleButton);
- shortcutsButton->set_icon(FA_CARET_RIGHT);
- shortcutsButton->set_fixed_width(230);
+ _shortcutsButton = new ng::Button(documentationGroup, "Keyboard Shortcuts");
+ _shortcutsButton->set_flags(ng::Button::ToggleButton);
+ _shortcutsButton->set_icon(FA_CARET_RIGHT);
+ _shortcutsButton->set_fixed_width(230);
- ng::Widget* shortcutsTable = new ng::Widget(documentationGroup);
- shortcutsTable->set_layout(new ng::GroupLayout(13));
- shortcutsTable->set_visible(false);
+ _shortcutsTable = new ng::Widget(documentationGroup);
+ _shortcutsTable->set_layout(new ng::GroupLayout(13));
+ _shortcutsTable->set_visible(false);
- // recompute layout when showing/hiding shortcuts.
- shortcutsButton->set_change_callback([this, scrollPanel, shortcutsButton,
- shortcutsTable](bool state)
+ // Recompute layout when showing/hiding shortcuts.
+ _shortcutsButton->set_change_callback([this](bool state)
{
- shortcutsTable->set_visible(state);
- shortcutsButton->set_icon(state ? FA_CARET_DOWN : FA_CARET_RIGHT);
- scrollPanel->set_scroll(state ? 0.73f : 1.0f);
+ _shortcutsButton->set_icon(state ? FA_CARET_DOWN : FA_CARET_RIGHT);
+ _shortcutsTable->set_visible(state);
perform_layout();
});
// 2 cell layout for (key, description) pair.
- ng::GridLayout* gridLayout2 = new ng::GridLayout(ng::Orientation::Horizontal, 2,
- ng::Alignment::Minimum, 2, 2);
+ ng::ref gridLayout2 = new ng::GridLayout(ng::Orientation::Horizontal, 2,
+ ng::Alignment::Minimum, 2, 2);
gridLayout2->set_col_alignment({ ng::Alignment::Minimum, ng::Alignment::Maximum });
- const std::vector> KEYBOARD_SHORTCUTS =
+ const std::array, 16> KEYBOARD_SHORTCUTS =
{
std::make_pair("R", "Reload the current material from file. "
"Hold SHIFT to reload all standard libraries as well."),
@@ -741,73 +731,73 @@ void Viewer::createDocumentationInterface(Widget* parent, ng::VScrollPanel* scro
for (const auto& shortcut : KEYBOARD_SHORTCUTS)
{
- ng::Widget* twoColumns = new ng::Widget(shortcutsTable);
+ ng::ref twoColumns = new ng::Widget(_shortcutsTable);
twoColumns->set_layout(gridLayout2);
- ng::Label* keyLabel = new ng::Label(twoColumns, shortcut.first);
+ ng::ref keyLabel = new ng::Label(twoColumns, shortcut.first);
keyLabel->set_font("sans-bold");
keyLabel->set_font_size(16);
keyLabel->set_fixed_width(40);
- ng::Label* descriptionLabel = new ng::Label(twoColumns, shortcut.second);
+ ng::ref descriptionLabel = new ng::Label(twoColumns, shortcut.second);
descriptionLabel->set_font_size(16);
descriptionLabel->set_fixed_width(160);
}
}
-void Viewer::createAdvancedSettings(Widget* parent)
+void Viewer::createAdvancedSettings(ng::ref parent)
{
- ng::PopupButton* advancedButton = new ng::PopupButton(parent, "Advanced Settings");
+ ng::ref advancedButton = new ng::PopupButton(parent, "Advanced Settings");
advancedButton->set_icon(FA_TOOLS);
advancedButton->set_chevron_icon(-1);
advancedButton->set_tooltip("Asset and rendering options.");
- ng::Popup* advancedPopupParent = advancedButton->popup();
+ ng::ref advancedPopupParent = advancedButton->popup();
advancedPopupParent->set_layout(new ng::GroupLayout());
- ng::VScrollPanel* scrollPanel = new ng::VScrollPanel(advancedPopupParent);
+ ng::ref scrollPanel = new ng::VScrollPanel(advancedPopupParent);
scrollPanel->set_fixed_height(500);
- ng::Widget* advancedPopup = new ng::Widget(scrollPanel);
+ ng::ref advancedPopup = new ng::Widget(scrollPanel);
advancedPopup->set_layout(new ng::BoxLayout(ng::Orientation::Vertical));
- ng::Widget* settingsGroup = new ng::Widget(advancedPopup);
+ ng::ref settingsGroup = new ng::Widget(advancedPopup);
settingsGroup->set_layout(new ng::GroupLayout(13));
- ng::Label* viewLabel = new ng::Label(settingsGroup, "Viewing Options");
+ ng::ref viewLabel = new ng::Label(settingsGroup, "Viewing Options");
viewLabel->set_font_size(20);
viewLabel->set_font("sans-bold");
- ng::CheckBox* drawEnvironmentBox = new ng::CheckBox(settingsGroup, "Draw Environment");
+ ng::ref drawEnvironmentBox = new ng::CheckBox(settingsGroup, "Draw Environment");
drawEnvironmentBox->set_checked(_drawEnvironment);
drawEnvironmentBox->set_callback([this](bool enable)
{
_drawEnvironment = enable;
});
- ng::CheckBox* outlineSelectedGeometryBox = new ng::CheckBox(settingsGroup, "Outline Selected Geometry");
+ ng::ref outlineSelectedGeometryBox = new ng::CheckBox(settingsGroup, "Outline Selected Geometry");
outlineSelectedGeometryBox->set_checked(_outlineSelection);
outlineSelectedGeometryBox->set_callback([this](bool enable)
{
_outlineSelection = enable;
});
- ng::Label* renderLabel = new ng::Label(settingsGroup, "Render Options");
+ ng::ref renderLabel = new ng::Label(settingsGroup, "Render Options");
renderLabel->set_font_size(20);
renderLabel->set_font("sans-bold");
- ng::CheckBox* transparencyBox = new ng::CheckBox(settingsGroup, "Render Transparency");
+ ng::ref transparencyBox = new ng::CheckBox(settingsGroup, "Render Transparency");
transparencyBox->set_checked(_renderTransparency);
transparencyBox->set_callback([this](bool enable)
{
_renderTransparency = enable;
});
- ng::CheckBox* doubleSidedBox = new ng::CheckBox(settingsGroup, "Render Double-Sided");
+ ng::ref doubleSidedBox = new ng::CheckBox(settingsGroup, "Render Double-Sided");
doubleSidedBox->set_checked(_renderDoubleSided);
doubleSidedBox->set_callback([this](bool enable)
{
_renderDoubleSided = enable;
});
- ng::CheckBox* importanceSampleBox = new ng::CheckBox(settingsGroup, "Environment FIS");
+ ng::ref importanceSampleBox = new ng::CheckBox(settingsGroup, "Environment FIS");
importanceSampleBox->set_checked(_genContext.getOptions().hwSpecularEnvironmentMethod == mx::SPECULAR_ENVIRONMENT_FIS);
_lightHandler->setUsePrefilteredMap(_genContext.getOptions().hwSpecularEnvironmentMethod != mx::SPECULAR_ENVIRONMENT_FIS);
importanceSampleBox->set_callback([this](bool enable)
@@ -820,7 +810,7 @@ void Viewer::createAdvancedSettings(Widget* parent)
reloadShaders();
});
- ng::CheckBox* refractionBox = new ng::CheckBox(settingsGroup, "Transmission Refraction");
+ ng::ref refractionBox = new ng::CheckBox(settingsGroup, "Transmission Refraction");
refractionBox->set_checked(_genContext.getOptions().hwTransmissionRenderMethod == mx::TRANSMISSION_REFRACTION);
refractionBox->set_callback([this](bool enable)
{
@@ -831,14 +821,14 @@ void Viewer::createAdvancedSettings(Widget* parent)
reloadShaders();
});
- ng::CheckBox* refractionSidedBox = new ng::CheckBox(settingsGroup, "Refraction Two-Sided");
+ ng::ref refractionSidedBox = new ng::CheckBox(settingsGroup, "Refraction Two-Sided");
refractionSidedBox->set_checked(_lightHandler->getRefractionTwoSided());
refractionSidedBox->set_callback([this](bool enable)
{
_lightHandler->setRefractionTwoSided(enable);
});
- ng::CheckBox* shaderInterfaceBox = new ng::CheckBox(settingsGroup, "Reduce Shader Interface");
+ ng::ref shaderInterfaceBox = new ng::CheckBox(settingsGroup, "Reduce Shader Interface");
shaderInterfaceBox->set_checked(_genContext.getOptions().shaderInterfaceType == mx::SHADER_INTERFACE_REDUCED);
shaderInterfaceBox->set_callback([this](bool enable)
{
@@ -846,11 +836,11 @@ void Viewer::createAdvancedSettings(Widget* parent)
setShaderInterfaceType(interfaceType);
});
- Widget* albedoGroup = new Widget(settingsGroup);
+ ng::ref albedoGroup = new Widget(settingsGroup);
albedoGroup->set_layout(new ng::BoxLayout(ng::Orientation::Horizontal));
new ng::Label(albedoGroup, "Albedo Method:");
mx::StringVec albedoOptions = { "Analytic", "Table", "MC" };
- ng::ComboBox* albedoBox = new ng::ComboBox(albedoGroup, albedoOptions);
+ ng::ref albedoBox = new ng::ComboBox(albedoGroup, albedoOptions);
albedoBox->set_chevron_icon(-1);
albedoBox->set_selected_index((int) _genContext.getOptions().hwDirectionalAlbedoMethod );
albedoBox->set_callback([this](int index)
@@ -877,7 +867,7 @@ void Viewer::createAdvancedSettings(Widget* parent)
}
});
- Widget* sampleGroup = new Widget(settingsGroup);
+ ng::ref sampleGroup = new Widget(settingsGroup);
sampleGroup->set_layout(new ng::BoxLayout(ng::Orientation::Horizontal));
new ng::Label(sampleGroup, "Environment Samples:");
mx::StringVec sampleOptions;
@@ -887,7 +877,7 @@ void Viewer::createAdvancedSettings(Widget* parent)
sampleOptions.push_back(std::to_string(i));
m_process_events = true;
}
- ng::ComboBox* sampleBox = new ng::ComboBox(sampleGroup, sampleOptions);
+ ng::ref sampleBox = new ng::ComboBox(sampleGroup, sampleOptions);
sampleBox->set_chevron_icon(-1);
sampleBox->set_selected_index((int)std::log2(_lightHandler->getEnvSampleCount() / MIN_ENV_SAMPLE_COUNT) / 2);
sampleBox->set_callback([this](int index)
@@ -895,30 +885,30 @@ void Viewer::createAdvancedSettings(Widget* parent)
_lightHandler->setEnvSampleCount(MIN_ENV_SAMPLE_COUNT * (int) std::pow(4, index));
});
- ng::Label* lightingLabel = new ng::Label(settingsGroup, "Lighting Options");
+ ng::ref lightingLabel = new ng::Label(settingsGroup, "Lighting Options");
lightingLabel->set_font_size(20);
lightingLabel->set_font("sans-bold");
- ng::CheckBox* directLightingBox = new ng::CheckBox(settingsGroup, "Direct Lighting");
+ ng::ref directLightingBox = new ng::CheckBox(settingsGroup, "Direct Lighting");
directLightingBox->set_checked(_lightHandler->getDirectLighting());
directLightingBox->set_callback([this](bool enable)
{
_lightHandler->setDirectLighting(enable);
});
- ng::CheckBox* indirectLightingBox = new ng::CheckBox(settingsGroup, "Indirect Lighting");
+ ng::ref indirectLightingBox = new ng::CheckBox(settingsGroup, "Indirect Lighting");
indirectLightingBox->set_checked(_lightHandler->getIndirectLighting());
indirectLightingBox->set_callback([this](bool enable)
{
_lightHandler->setIndirectLighting(enable);
});
- ng::Widget* lightRotationRow = new ng::Widget(settingsGroup);
+ ng::ref lightRotationRow = new ng::Widget(settingsGroup);
lightRotationRow->set_layout(new ng::BoxLayout(ng::Orientation::Horizontal));
mx::UIProperties ui;
ui.uiMin = mx::Value::createValue(0.0f);
ui.uiMax = mx::Value::createValue(360.0f);
- ng::FloatBox* lightRotationBox = createFloatWidget(lightRotationRow, "Light Rotation:",
+ ng::ref> lightRotationBox = createFloatWidget(lightRotationRow, "Light Rotation:",
_lightRotation, &ui, [this](float value)
{
_lightRotation = value;
@@ -926,11 +916,11 @@ void Viewer::createAdvancedSettings(Widget* parent)
});
lightRotationBox->set_editable(true);
- ng::Label* shadowingLabel = new ng::Label(settingsGroup, "Shadowing Options");
+ ng::ref shadowingLabel = new ng::Label(settingsGroup, "Shadowing Options");
shadowingLabel->set_font_size(20);
shadowingLabel->set_font("sans-bold");
- ng::CheckBox* shadowMapBox = new ng::CheckBox(settingsGroup, "Shadow Map");
+ ng::ref shadowMapBox = new ng::CheckBox(settingsGroup, "Shadow Map");
shadowMapBox->set_checked(_genContext.getOptions().hwShadowMap);
shadowMapBox->set_callback([this](bool enable)
{
@@ -938,7 +928,7 @@ void Viewer::createAdvancedSettings(Widget* parent)
reloadShaders();
});
- ng::CheckBox* ambientOcclusionBox = new ng::CheckBox(settingsGroup, "Ambient Occlusion");
+ ng::ref ambientOcclusionBox = new ng::CheckBox(settingsGroup, "Ambient Occlusion");
ambientOcclusionBox->set_checked(_genContext.getOptions().hwAmbientOcclusion);
ambientOcclusionBox->set_callback([this](bool enable)
{
@@ -946,23 +936,23 @@ void Viewer::createAdvancedSettings(Widget* parent)
reloadShaders();
});
- ng::Widget* ambientOcclusionGainRow = new ng::Widget(settingsGroup);
+ ng::ref ambientOcclusionGainRow = new ng::Widget(settingsGroup);
ambientOcclusionGainRow->set_layout(new ng::BoxLayout(ng::Orientation::Horizontal));
- ng::FloatBox* ambientOcclusionGainBox = createFloatWidget(ambientOcclusionGainRow, "AO Gain:",
+ ng::ref> ambientOcclusionGainBox = createFloatWidget(ambientOcclusionGainRow, "AO Gain:",
_ambientOcclusionGain, nullptr, [this](float value)
{
_ambientOcclusionGain = value;
});
ambientOcclusionGainBox->set_editable(true);
- ng::Label* sceneLabel = new ng::Label(settingsGroup, "Scene Options");
+ ng::ref sceneLabel = new ng::Label(settingsGroup, "Scene Options");
sceneLabel->set_font_size(20);
sceneLabel->set_font("sans-bold");
- Widget* unitGroup = new Widget(settingsGroup);
+ ng::ref unitGroup = new Widget(settingsGroup);
unitGroup->set_layout(new ng::BoxLayout(ng::Orientation::Horizontal));
new ng::Label(unitGroup, "Distance Unit:");
- ng::ComboBox* distanceUnitBox = new ng::ComboBox(unitGroup, _distanceUnitOptions);
+ ng::ref distanceUnitBox = new ng::ComboBox(unitGroup, _distanceUnitOptions);
distanceUnitBox->set_fixed_size(ng::Vector2i(100, 20));
distanceUnitBox->set_chevron_icon(-1);
if (_distanceUnitConverter)
@@ -986,68 +976,68 @@ void Viewer::createAdvancedSettings(Widget* parent)
m_process_events = true;
});
- ng::Label* meshLoading = new ng::Label(settingsGroup, "Mesh Loading Options");
+ ng::ref meshLoading = new ng::Label(settingsGroup, "Mesh Loading Options");
meshLoading->set_font_size(20);
meshLoading->set_font("sans-bold");
- ng::CheckBox* splitUdimsBox = new ng::CheckBox(settingsGroup, "Split By UDIMs");
+ ng::ref splitUdimsBox = new ng::CheckBox(settingsGroup, "Split By UDIMs");
splitUdimsBox->set_checked(_splitByUdims);
splitUdimsBox->set_callback([this](bool enable)
{
_splitByUdims = enable;
});
- ng::Label* materialLoading = new ng::Label(settingsGroup, "Material Loading Options");
+ ng::ref materialLoading = new ng::Label(settingsGroup, "Material Loading Options");
materialLoading->set_font_size(20);
materialLoading->set_font("sans-bold");
- ng::CheckBox* mergeMaterialsBox = new ng::CheckBox(settingsGroup, "Merge Materials");
+ ng::ref mergeMaterialsBox = new ng::CheckBox(settingsGroup, "Merge Materials");
mergeMaterialsBox->set_checked(_mergeMaterials);
mergeMaterialsBox->set_callback([this](bool enable)
{
_mergeMaterials = enable;
});
- ng::CheckBox* showInputsBox = new ng::CheckBox(settingsGroup, "Show All Inputs");
+ ng::ref showInputsBox = new ng::CheckBox(settingsGroup, "Show All Inputs");
showInputsBox->set_checked(_showAllInputs);
showInputsBox->set_callback([this](bool enable)
{
_showAllInputs = enable;
});
- ng::CheckBox* flattenBox = new ng::CheckBox(settingsGroup, "Flatten Subgraphs");
+ ng::ref flattenBox = new ng::CheckBox(settingsGroup, "Flatten Subgraphs");
flattenBox->set_checked(_flattenSubgraphs);
flattenBox->set_callback([this](bool enable)
{
_flattenSubgraphs = enable;
});
- ng::Label* envLoading = new ng::Label(settingsGroup, "Environment Loading Options");
+ ng::ref envLoading = new ng::Label(settingsGroup, "Environment Loading Options");
envLoading->set_font_size(20);
envLoading->set_font("sans-bold");
- ng::CheckBox* normalizeEnvBox = new ng::CheckBox(settingsGroup, "Normalize Environment");
+ ng::ref normalizeEnvBox = new ng::CheckBox(settingsGroup, "Normalize Environment");
normalizeEnvBox->set_checked(_normalizeEnvironment);
normalizeEnvBox->set_callback([this](bool enable)
{
_normalizeEnvironment = enable;
});
- ng::CheckBox* splitDirectLightBox = new ng::CheckBox(settingsGroup, "Split Direct Light");
+ ng::ref splitDirectLightBox = new ng::CheckBox(settingsGroup, "Split Direct Light");
splitDirectLightBox->set_checked(_splitDirectLight);
splitDirectLightBox->set_callback([this](bool enable)
{
_splitDirectLight = enable;
});
- ng::Label* translationLabel = new ng::Label(settingsGroup, "Translation Options (T)");
+ ng::ref translationLabel = new ng::Label(settingsGroup, "Translation Options (T)");
translationLabel->set_font_size(20);
translationLabel->set_font("sans-bold");
- ng::Widget* targetShaderGroup = new ng::Widget(settingsGroup);
+ ng::ref targetShaderGroup = new ng::Widget(settingsGroup);
targetShaderGroup->set_layout(new ng::BoxLayout(ng::Orientation::Horizontal));
new ng::Label(targetShaderGroup, "Target Shader");
- ng::TextBox* targetShaderBox = new ng::TextBox(targetShaderGroup, _targetShader);
+ ng::ref targetShaderBox = new ng::TextBox(targetShaderGroup, _targetShader);
targetShaderBox->set_callback([this](const std::string& choice)
{
_targetShader = choice;
@@ -1056,46 +1046,46 @@ void Viewer::createAdvancedSettings(Widget* parent)
targetShaderBox->set_font_size(16);
targetShaderBox->set_editable(true);
- ng::Label* textureLabel = new ng::Label(settingsGroup, "Texture Baking Options (B)");
+ ng::ref textureLabel = new ng::Label(settingsGroup, "Texture Baking Options (B)");
textureLabel->set_font_size(20);
textureLabel->set_font("sans-bold");
- ng::CheckBox* bakeHdrBox = new ng::CheckBox(settingsGroup, "Bake HDR Textures");
+ ng::ref bakeHdrBox = new ng::CheckBox(settingsGroup, "Bake HDR Textures");
bakeHdrBox->set_checked(_bakeHdr);
bakeHdrBox->set_callback([this](bool enable)
{
_bakeHdr = enable;
});
- ng::CheckBox* bakeAverageBox = new ng::CheckBox(settingsGroup, "Bake Averaged Textures");
+ ng::ref bakeAverageBox = new ng::CheckBox(settingsGroup, "Bake Averaged Textures");
bakeAverageBox->set_checked(_bakeAverage);
bakeAverageBox->set_callback([this](bool enable)
{
_bakeAverage = enable;
});
- ng::CheckBox* bakeOptimized = new ng::CheckBox(settingsGroup, "Optimize Baked Constants");
+ ng::ref bakeOptimized = new ng::CheckBox(settingsGroup, "Optimize Baked Constants");
bakeOptimized->set_checked(_bakeOptimize);
bakeOptimized->set_callback([this](bool enable)
{
_bakeOptimize = enable;
});
- ng::CheckBox* bakeDocumentPerMaterial= new ng::CheckBox(settingsGroup, "Bake Document Per Material");
+ ng::ref bakeDocumentPerMaterial= new ng::CheckBox(settingsGroup, "Bake Document Per Material");
bakeDocumentPerMaterial->set_checked(_bakeDocumentPerMaterial);
bakeDocumentPerMaterial->set_callback([this](bool enable)
{
_bakeDocumentPerMaterial = enable;
});
- ng::Label* wedgeLabel = new ng::Label(settingsGroup, "Wedge Render Options (W)");
+ ng::ref wedgeLabel = new ng::Label(settingsGroup, "Wedge Render Options (W)");
wedgeLabel->set_font_size(20);
wedgeLabel->set_font("sans-bold");
- ng::Widget* wedgeNameGroup = new ng::Widget(settingsGroup);
+ ng::ref wedgeNameGroup = new ng::Widget(settingsGroup);
wedgeNameGroup->set_layout(new ng::BoxLayout(ng::Orientation::Horizontal));
new ng::Label(wedgeNameGroup, "Property Name");
- ng::TextBox* wedgeNameBox = new ng::TextBox(wedgeNameGroup, _wedgePropertyName);
+ ng::ref wedgeNameBox = new ng::TextBox(wedgeNameGroup, _wedgePropertyName);
wedgeNameBox->set_callback([this](const std::string& choice)
{
_wedgePropertyName = choice;
@@ -1104,12 +1094,12 @@ void Viewer::createAdvancedSettings(Widget* parent)
wedgeNameBox->set_font_size(16);
wedgeNameBox->set_editable(true);
- ng::Widget* wedgeMinGroup = new ng::Widget(settingsGroup);
+ ng::ref wedgeMinGroup = new ng::Widget(settingsGroup);
wedgeMinGroup->set_layout(new ng::BoxLayout(ng::Orientation::Horizontal));
mx::UIProperties wedgeProp;
wedgeProp.uiSoftMin = mx::Value::createValue(0.0f);
wedgeProp.uiSoftMax = mx::Value::createValue(1.0f);
- ng::FloatBox* wedgeMinBox = createFloatWidget(wedgeMinGroup, "Property Min:",
+ ng::ref> wedgeMinBox = createFloatWidget(wedgeMinGroup, "Property Min:",
_wedgePropertyMax, &wedgeProp, [this](float value)
{
_wedgePropertyMin = value;
@@ -1117,9 +1107,9 @@ void Viewer::createAdvancedSettings(Widget* parent)
wedgeMinBox->set_value(0.0);
wedgeMinBox->set_editable(true);
- ng::Widget* wedgeMaxGroup = new ng::Widget(settingsGroup);
+ ng::ref wedgeMaxGroup = new ng::Widget(settingsGroup);
wedgeMaxGroup->set_layout(new ng::BoxLayout(ng::Orientation::Horizontal));
- ng::FloatBox* wedgeMaxBox = createFloatWidget(wedgeMaxGroup, "Property Max:",
+ ng::ref> wedgeMaxBox = createFloatWidget(wedgeMaxGroup, "Property Max:",
_wedgePropertyMax, &wedgeProp, [this](float value)
{
_wedgePropertyMax = value;
@@ -1127,13 +1117,13 @@ void Viewer::createAdvancedSettings(Widget* parent)
wedgeMaxBox->set_value(1.0);
wedgeMaxBox->set_editable(true);
- ng::Widget* wedgeCountGroup = new ng::Widget(settingsGroup);
+ ng::ref wedgeCountGroup = new ng::Widget(settingsGroup);
wedgeCountGroup->set_layout(new ng::BoxLayout(ng::Orientation::Horizontal));
mx::UIProperties wedgeCountProp;
wedgeCountProp.uiMin = mx::Value::createValue(1);
wedgeCountProp.uiSoftMax = mx::Value::createValue(8);
wedgeCountProp.uiStep = mx::Value::createValue(1);
- ng::IntBox* wedgeCountBox = createIntWidget(wedgeCountGroup, "Image Count:",
+ ng::ref> wedgeCountBox = createIntWidget(wedgeCountGroup, "Image Count:",
_wedgeImageCount, &wedgeCountProp, [this](int value)
{
_wedgeImageCount = value;
@@ -1141,7 +1131,7 @@ void Viewer::createAdvancedSettings(Widget* parent)
wedgeCountBox->set_value(8);
wedgeCountBox->set_editable(true);
- createDocumentationInterface(advancedPopup, scrollPanel);
+ createDocumentationInterface(advancedPopup);
}
void Viewer::updateGeometrySelections()
@@ -1769,6 +1759,9 @@ void Viewer::initContext(mx::GenContext& context)
unitSystem->setUnitConverterRegistry(_unitRegistry);
context.getShaderGenerator().setUnitSystem(unitSystem);
context.getOptions().targetDistanceUnit = "meter";
+
+ // Initialize the struct typedefs from the stdlib
+ context.getShaderGenerator().loadStructTypeDefs(_stdLib);
}
void Viewer::loadStandardLibraries()
@@ -2438,7 +2431,7 @@ void Viewer::updateCameras()
void Viewer::updateDisplayedProperties()
{
_propertyEditor.updateContents(this);
- createSaveMaterialsInterface(_propertyEditor.getWindow(), "Save Material");
+ createSaveMaterialsInterface((ng::ref) _propertyEditor.getWindow(), "Save Material");
perform_layout();
}
diff --git a/source/MaterialXView/Viewer.h b/source/MaterialXView/Viewer.h
index 08712f3c78..8f0257e1e1 100644
--- a/source/MaterialXView/Viewer.h
+++ b/source/MaterialXView/Viewer.h
@@ -179,7 +179,7 @@ class Viewer : public ng::Screen
}
// Return the underlying NanoGUI window.
- ng::Window* getWindow() const
+ ng::ref getWindow() const
{
return _window;
}
@@ -283,13 +283,13 @@ class Viewer : public ng::Screen
void updateMaterialSelectionUI();
void updateDisplayedProperties();
- void createLoadMeshInterface(Widget* parent, const std::string& label);
- void createLoadMaterialsInterface(Widget* parent, const std::string& label);
- void createLoadEnvironmentInterface(Widget* parent, const std::string& label);
- void createSaveMaterialsInterface(Widget* parent, const std::string& label);
- void createPropertyEditorInterface(Widget* parent, const std::string& label);
- void createAdvancedSettings(Widget* parent);
- void createDocumentationInterface(Widget* parent, ng::VScrollPanel* scrollPanel);
+ void createLoadMeshInterface(ng::ref parent, const std::string& label);
+ void createLoadMaterialsInterface(ng::ref parent, const std::string& label);
+ void createLoadEnvironmentInterface(ng::ref parent, const std::string& label);
+ void createSaveMaterialsInterface(ng::ref parent, const std::string& label);
+ void createPropertyEditorInterface(ng::ref parent, const std::string& label);
+ void createAdvancedSettings(ng::ref parent);
+ void createDocumentationInterface(ng::ref parent);
// Return the ambient occlusion image, if any, associated with the given material.
mx::ImagePtr getAmbientOcclusionImage(mx::MaterialPtr material);
@@ -318,7 +318,7 @@ class Viewer : public ng::Screen
void setShaderInterfaceType(mx::ShaderInterfaceType interfaceType);
private:
- ng::Window* _window;
+ ng::ref _window;
RenderPipelinePtr _renderPipeline;
mx::FilePath _materialFilename;
@@ -380,15 +380,15 @@ class Viewer : public ng::Screen
// Geometry selections
std::vector _geometryList;
size_t _selectedGeom;
- ng::Label* _geomLabel;
- ng::ComboBox* _geometrySelectionBox;
+ ng::ref _geomLabel;
+ ng::ref _geometrySelectionBox;
// Material selections
std::vector _materials;
mx::MaterialPtr _wireMaterial;
size_t _selectedMaterial;
- ng::Label* _materialLabel;
- ng::ComboBox* _materialSelectionBox;
+ ng::ref _materialLabel;
+ ng::ref _materialSelectionBox;
PropertyEditor _propertyEditor;
// Material assignments
@@ -475,11 +475,15 @@ class Viewer : public ng::Screen
// Frame timing
bool _frameTiming;
- ng::Label* _timingLabel;
- ng::Widget* _timingPanel;
- ng::TextBox* _timingText;
+ ng::ref _timingLabel;
+ ng::ref _timingPanel;
+ ng::ref _timingText;
mx::ScopedTimer _frameTimer;
double _avgFrameTime;
+
+ // Documentation UI
+ ng::ref _shortcutsButton;
+ ng::ref