diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index d5ac9d3f79..492110dd88 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -18,75 +18,75 @@ jobs: fail-fast: false matrix: include: - - name: Linux_GCC_9_Python37 - os: ubuntu-20.04 + - name: Linux_GCC_10_Python37 + os: ubuntu-22.04 compiler: gcc - compiler_version: "9" + compiler_version: "10" python: 3.7 - cmake_config: -DMATERIALX_BUILD_SHARED_LIBS=ON + cmake_config: -DMATERIALX_BUILD_SHARED_LIBS=ON -DMATERIALX_BUILD_MONOLITHIC=ON - - name: Linux_GCC_11_Python39 - os: ubuntu-20.04 + - name: Linux_GCC_13_Python311 + os: ubuntu-24.04 compiler: gcc - compiler_version: "11" - python: 3.9 + compiler_version: "13" + python: 3.11 build_javascript: ON - - name: Linux_GCC_12_Python311 - os: ubuntu-22.04 + - name: Linux_GCC_14_Python312 + os: ubuntu-24.04 compiler: gcc - compiler_version: "12" - python: 3.11 - upload_shaders: ON + compiler_version: "14" + python: 3.12 - - name: Linux_Clang_10_Python37 - os: ubuntu-20.04 + - name: Linux_GCC_CoverageAnalysis + os: ubuntu-24.04 + compiler: gcc + compiler_version: "None" + python: None + coverage_analysis: ON + cmake_config: -DMATERIALX_COVERAGE_ANALYSIS=ON -DMATERIALX_BUILD_RENDER=OFF -DMATERIALX_BUILD_PYTHON=OFF + + - name: Linux_Clang_13_Python37 + os: ubuntu-22.04 compiler: clang - compiler_version: "10" + compiler_version: "13" python: 3.7 cmake_config: -DMATERIALX_BUILD_SHARED_LIBS=ON - static_analysis: ON - - name: Linux_Clang_14_Python311 - os: ubuntu-22.04 + - name: Linux_Clang_18_Python312 + os: ubuntu-24.04 compiler: clang - compiler_version: "14" - python: 3.11 + compiler_version: "18" + python: 3.12 test_render: ON clang_format: ON - - name: Linux_Clang_14_DynamicAnalysis - os: ubuntu-22.04 - compiler: clang - compiler_version: "14" - python: None - cmake_config: -DMATERIALX_DYNAMIC_ANALYSIS=ON - dynamic_analysis: ON - - - name: MacOS_Xcode_11_Python37 - os: macos-11 + - name: MacOS_Xcode_14_Python39 + os: macos-13 compiler: xcode - compiler_version: "11.7" + compiler_version: "14.1" cmake_config: -DMATERIALX_BUILD_SHARED_LIBS=ON - python: 3.7 - - - name: MacOS_Xcode_13_Python39 - os: macos-12 - compiler: xcode - compiler_version: "13.4" python: 3.9 - - name: MacOS_Xcode_14_Python311 - os: macos-13 + - 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 + + - name: MacOS_Xcode_15_Python312 + os: macos-14 + compiler: xcode + compiler_version: "15.4" + python: 3.12 test_shaders: ON - name: iOS_Xcode_15 - os: macos-13 + os: macos-14 compiler: xcode - compiler_version: "15.0" + compiler_version: "15.4" python: None cmake_config: -DMATERIALX_BUILD_IOS=ON -DCMAKE_OSX_SYSROOT=`xcrun --sdk iphoneos --show-sdk-path` -DCMAKE_OSX_ARCHITECTURES=arm64 @@ -96,22 +96,23 @@ jobs: python: 3.7 cmake_config: -G "Visual Studio 16 2019" -A "Win32" -DMATERIALX_BUILD_SHARED_LIBS=ON - - name: Windows_VS2022_x64_Python39 + - name: Windows_VS2022_x64_Python311 os: windows-2022 architecture: x64 - python: 3.9 + python: 3.11 cmake_config: -G "Visual Studio 17 2022" -A "x64" + test_shaders: ON - - name: Windows_VS2022_x64_Python311 + - name: Windows_VS2022_x64_Python312 os: windows-2022 architecture: x64 - python: 3.11 + python: 3.12 cmake_config: -G "Visual Studio 17 2022" -A "x64" - test_shaders: ON + upload_shaders: ON steps: - name: Sync Repository - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: submodules: recursive @@ -119,29 +120,33 @@ jobs: if: runner.os == 'Linux' run: | sudo apt-get update - sudo apt-get install xorg-dev mesa-utils - if [ "${{ matrix.compiler }}" = "gcc" ]; then - sudo apt-get install -y g++-${{ matrix.compiler_version }} g++-${{ matrix.compiler_version }}-multilib - echo "CC=gcc-${{ matrix.compiler_version }}" >> $GITHUB_ENV - echo "CXX=g++-${{ matrix.compiler_version }}" >> $GITHUB_ENV - else - sudo apt-get install -y clang-${{ matrix.compiler_version }} libc++-${{ matrix.compiler_version }}-dev libc++abi-${{ matrix.compiler_version }}-dev - echo "CC=clang-${{ matrix.compiler_version }}" >> $GITHUB_ENV - echo "CXX=clang++-${{ matrix.compiler_version }}" >> $GITHUB_ENV + sudo apt-get install xorg-dev + if [ "${{ matrix.compiler_version }}" != 'None' ]; then + if [ "${{ matrix.compiler }}" = "gcc" ]; then + sudo apt-get install -y g++-${{ matrix.compiler_version }} + echo "CC=gcc-${{ matrix.compiler_version }}" >> $GITHUB_ENV + echo "CXX=g++-${{ matrix.compiler_version }}" >> $GITHUB_ENV + else + sudo apt-get install -y clang-${{ matrix.compiler_version }} + echo "CC=clang-${{ matrix.compiler_version }}" >> $GITHUB_ENV + echo "CXX=clang++-${{ matrix.compiler_version }}" >> $GITHUB_ENV + fi fi - name: Install Dependencies (MacOS) if: runner.os == 'macOS' run: | - if [ "${{ matrix.compiler }}" = "gcc" ]; then - brew install gcc@${{ matrix.compiler_version }} - echo "CC=gcc-${{ matrix.compiler_version }}" >> $GITHUB_ENV - echo "CXX=g++-${{ matrix.compiler_version }}" >> $GITHUB_ENV - else - ls -ls /Applications/ - sudo xcode-select -switch /Applications/Xcode_${{ matrix.compiler_version }}.app - echo "CC=clang" >> $GITHUB_ENV - echo "CXX=clang++" >> $GITHUB_ENV + if [ "${{ matrix.compiler_version }}" != 'None' ]; then + if [ "${{ matrix.compiler }}" = "gcc" ]; then + brew install gcc@${{ matrix.compiler_version }} + echo "CC=gcc-${{ matrix.compiler_version }}" >> $GITHUB_ENV + echo "CXX=g++-${{ matrix.compiler_version }}" >> $GITHUB_ENV + else + ls -ls /Applications/ + sudo xcode-select -switch /Applications/Xcode_${{ matrix.compiler_version }}.app + echo "CC=clang" >> $GITHUB_ENV + echo "CXX=clang++" >> $GITHUB_ENV + fi fi - name: Install Dependencies (Windows) @@ -155,11 +160,15 @@ jobs: - name: Install Python ${{ matrix.python }} if: matrix.python != 'None' - uses: actions/setup-python@v4 + uses: actions/setup-python@v5 with: python-version: ${{ matrix.python }} architecture: ${{ matrix.architecture }} + - name: Install Python Dependencies + if: matrix.python != 'None' + run: pip install setuptools + - name: Install Emscripten if: matrix.build_javascript == 'ON' run: | @@ -172,23 +181,19 @@ jobs: - name: Install Node if: matrix.build_javascript == 'ON' - uses: actions/setup-node@v3 + uses: actions/setup-node@v4 with: node-version: '16' - name: Run Clang Format if: matrix.clang_format == 'ON' - run: find source \( -name *.h -o -name *.cpp -o -name *.mm \) ! -path "*/External/*" ! -path "*/NanoGUI/*" | xargs clang-format -i --verbose + run: find source \( -name *.h -o -name *.cpp -o -name *.mm -o -name *.inl \) ! -path "*/External/*" ! -path "*/NanoGUI/*" | xargs clang-format -i --verbose - name: CMake Generate - run: | - mkdir build - cd build - cmake -DMATERIALX_BUILD_PYTHON=ON -DMATERIALX_BUILD_VIEWER=ON -DMATERIALX_BUILD_GRAPH_EDITOR=ON -DMATERIALX_TEST_RENDER=OFF -DMATERIALX_WARNINGS_AS_ERRORS=ON -DCMAKE_EXPORT_COMPILE_COMMANDS=ON ${{matrix.cmake_config}} .. + run: cmake -S . -B build -DMATERIALX_BUILD_PYTHON=ON -DMATERIALX_BUILD_VIEWER=ON -DMATERIALX_BUILD_GRAPH_EDITOR=ON -DMATERIALX_BUILD_TESTS=ON -DMATERIALX_TEST_RENDER=OFF -DMATERIALX_WARNINGS_AS_ERRORS=ON ${{matrix.cmake_config}} - name: CMake Build - run: cmake --build . --target install --config Release --parallel 2 - working-directory: build + run: cmake --build build --target install --config Release --parallel 2 - name: CMake Unit Tests run: ctest -VV --output-on-failure --build-config Release @@ -207,6 +212,10 @@ jobs: python Scripts/generateshader.py ../resources/Materials/Examples/StandardSurface --target osl python Scripts/generateshader.py ../resources/Materials/Examples/StandardSurface --target mdl python Scripts/generateshader.py ../resources/Materials/Examples/StandardSurface --target msl + python Scripts/generateshader.py ../resources/Materials/Examples/OpenPbr --target glsl + python Scripts/generateshader.py ../resources/Materials/Examples/OpenPbr --target osl + python Scripts/generateshader.py ../resources/Materials/Examples/OpenPbr --target mdl + python Scripts/generateshader.py ../resources/Materials/Examples/OpenPbr --target msl working-directory: python - name: Shader Validation Tests (Windows) @@ -214,19 +223,32 @@ jobs: run: | vcpkg/vcpkg install glslang --triplet=x64-windows glslangValidator.exe -v - python python/Scripts/generateshader.py resources/Materials/Examples/StandardSurface --target glsl --validator glslangValidator.exe --vulkanGlsl True --validatorArgs="-V --aml" - python python/Scripts/generateshader.py resources/Materials/Examples/StandardSurface --target essl --validator glslangValidator.exe + python python/Scripts/generateshader.py resources/Materials/Examples --target glsl --validator glslangValidator.exe + python python/Scripts/generateshader.py resources/Materials/Examples --target essl --validator glslangValidator.exe - name: Shader Validation Tests (MacOS) if: matrix.test_shaders == 'ON' && runner.os == 'macOS' run: | - python python/Scripts/generateshader.py resources/Materials/Examples/StandardSurface --target msl --validator "xcrun metal --language=metal" --validatorArgs="-w" + python python/Scripts/generateshader.py resources/Materials/Examples --target msl --validator "xcrun metal --language=metal" --validatorArgs="-w" + python python/Scripts/generateshader.py resources/Materials/TestSuite/stdlib --target msl --validator "xcrun metal --language=metal" --validatorArgs="-w" + + - name: Coverage Analysis Tests + if: matrix.coverage_analysis == 'ON' + run: | + sudo apt-get install gcovr + mkdir coverage + gcovr --html --html-details --output coverage/index.html --exclude .*\/External\/.* --root .. . + working-directory: build - name: Static Analysis Tests - if: matrix.static_analysis == 'ON' && runner.os == 'Linux' + if: matrix.static_analysis == 'ON' run: | - sudo apt-get install cppcheck - cppcheck --project=build/compile_commands.json --error-exitcode=1 --suppress=*:*/External/* --suppress=*:*/NanoGUI/* + if [ "${{ runner.os }}" = "Linux" ]; then + sudo apt-get install cppcheck + else + brew install cppcheck + fi + cppcheck --project=build/compile_commands.json --error-exitcode=1 --suppress=normalCheckLevelMaxBranches --suppress=*:*/External/* --suppress=*:*/NanoGUI/* - name: Initialize Virtual Framebuffer if: matrix.test_render == 'ON' && runner.os == 'Linux' @@ -234,7 +256,6 @@ jobs: Xvfb :1 -screen 0 1280x960x24 & echo "DISPLAY=:1" >> $GITHUB_ENV echo "LIBGL_ALWAYS_SOFTWARE=1" >> $GITHUB_ENV - echo "GALLIUM_DRIVER=llvmpipe" >> $GITHUB_ENV - name: Render Script Tests if: matrix.test_render == 'ON' @@ -248,48 +269,52 @@ jobs: run: | ../installed/bin/MaterialXView --material brass_average_baked.mtlx --mesh ../../resources/Geometry/sphere.obj --screenWidth 128 --screenHeight 128 --cameraZoom 1.4 --shadowMap false --captureFilename Viewer_BrassAverage.png ../installed/bin/MaterialXView --material usd_preview_surface_carpaint.mtlx --mesh ../../resources/Geometry/sphere.obj --screenWidth 128 --screenHeight 128 --cameraZoom 1.4 --shadowMap false --captureFilename Viewer_CarpaintTranslated.png + ../installed/bin/MaterialXView --material open_pbr_carpaint.mtlx --mesh ../../resources/Geometry/sphere.obj --screenWidth 128 --screenHeight 128 --cameraZoom 1.4 --shadowMap false --captureFilename Viewer_OpenPBRCarpaintTranslated.png ../installed/bin/MaterialXGraphEditor --material ../../resources/Materials/Examples/StandardSurface/standard_surface_marble_solid.mtlx --viewWidth 128 --viewHeight 128 --captureFilename GraphEditor_MarbleSolid.png working-directory: build/render - name: Upload Installed Package if: matrix.python != 'None' - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: MaterialX_${{ matrix.name }} path: build/installed/ - name: Upload Formatted Source if: matrix.clang_format == 'ON' - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: MaterialX_ClangFormat path: source - name: Upload Reference Shaders - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 if: matrix.upload_shaders == 'ON' with: name: Reference_Shaders_${{ matrix.name }} path: build/bin/reference/ - name: Upload Renders - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 if: matrix.test_render == 'ON' with: name: Renders_${{ matrix.name }} path: build/render/*.png + - name: Upload Coverage Report + uses: actions/upload-artifact@v4 + if: matrix.coverage_analysis == 'ON' + with: + name: MaterialX_Coverage + path: build/coverage + - name: JavaScript CMake Generate if: matrix.build_javascript == 'ON' - run: | - mkdir javascript/build - cd javascript/build - cmake -DMATERIALX_BUILD_JS=ON -DMATERIALX_EMSDK_PATH=${{ env.EMSDK }} -DMATERIALX_BUILD_RENDER=OFF -DMATERIALX_BUILD_TESTS=OFF -DMATERIALX_BUILD_GEN_OSL=OFF -DMATERIALX_BUILD_GEN_MDL=OFF ../.. + run: cmake -S . -B javascript/build -DMATERIALX_BUILD_JS=ON -DMATERIALX_EMSDK_PATH=${{ env.EMSDK }} - name: JavaScript CMake Build if: matrix.build_javascript == 'ON' - run: cmake --build . --target install --config Release --parallel 2 - working-directory: javascript/build + run: cmake --build javascript/build --target install --config Release --parallel 2 - name: JavaScript Unit Tests if: matrix.build_javascript == 'ON' @@ -307,8 +332,8 @@ jobs: working-directory: javascript/MaterialXView - name: Deploy Web Viewer - if: matrix.build_javascript == 'ON' && github.ref == 'refs/heads/main' - uses: JamesIves/github-pages-deploy-action@v4 + if: matrix.build_javascript == 'ON' && github.event_name != 'pull_request' + uses: JamesIves/github-pages-deploy-action@v4.6.4 with: branch: gh-pages folder: javascript/MaterialXView/dist @@ -316,25 +341,24 @@ jobs: - name: Upload JavaScript Package if: matrix.build_javascript == 'ON' - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: MaterialX_JavaScript path: javascript/build/installed/JavaScript/MaterialX - if-no-files-found: ignore sdist: name: Python SDist - runs-on: ubuntu-latest + runs-on: ubuntu-22.04 if: github.repository == 'AcademySoftwareFoundation/MaterialX' outputs: sdist_filename: ${{ steps.generate.outputs.filename }} steps: - name: Sync Repository - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Install Python - uses: actions/setup-python@v4 + uses: actions/setup-python@v5 with: python-version: 3.11 @@ -346,7 +370,7 @@ jobs: echo "filename=$(ls dist)" >> "$GITHUB_OUTPUT" - name: Upload SDist - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: MaterialX_Python_SDist path: dist/*.tar.gz @@ -359,26 +383,26 @@ jobs: strategy: fail-fast: false matrix: - python-minor: ['7', '8', '9', '10', '11'] - os: ['ubuntu-latest', 'macos-latest', 'windows-latest'] + python-minor: ['7', '8', '9', '10', '11', '12'] + os: ['ubuntu-22.04', 'windows-2022', 'macos-13'] steps: - name: Sync Repository - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Install Python 3.${{ matrix.python-minor }} - uses: actions/setup-python@v4 + uses: actions/setup-python@v5 with: python-version: 3.${{ matrix.python-minor }} - name: Download Sdist - uses: actions/download-artifact@v3 + uses: actions/download-artifact@v4 with: name: MaterialX_Python_SDist path: sdist - name: Build Wheel - uses: pypa/cibuildwheel@v2.13.1 + uses: pypa/cibuildwheel@v2.19.2 with: package-dir: ${{ github.workspace }}/sdist/${{ needs.sdist.outputs.sdist_filename }} env: @@ -389,7 +413,6 @@ jobs: # manylinux2014 is CentOS 7 based. Which means GCC 10 and glibc 2.17. CIBW_MANYLINUX_X86_64_IMAGE: manylinux2014 CIBW_BEFORE_ALL_LINUX: yum install -y libXt-devel - CIBW_BEFORE_ALL_MACOS: sudo xcode-select -switch /Applications/Xcode_13.4.app CIBW_BUILD_VERBOSITY: 1 CIBW_ENVIRONMENT: CMAKE_BUILD_PARALLEL_LEVEL=2 # CIBW_BUILD_FRONTEND: build # https://github.com/pypa/build @@ -405,7 +428,7 @@ jobs: working-directory: python - name: Upload Wheel - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: - name: MaterialX_Python_Wheels + name: MaterialX_Python_Wheel_${{ runner.os }}_3_${{ matrix.python-minor }} path: wheelhouse/*.whl diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000000..6ddb62f2b4 --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,43 @@ +name: release + +on: + release: + types: [published] + +permissions: + contents: read + +jobs: + + release: + name: Release Signing + runs-on: ubuntu-latest + env: + RELEASE_TAG: ${{ github.ref_name }} + permissions: + contents: write + id-token: write + repository-projects: write + + steps: + - name: Sync Repository + uses: actions/checkout@v4 + with: + submodules: recursive + + - name: Create Archive Name + run: echo "MATERIALX_ARCHIVE=MaterialX-${RELEASE_TAG//v}" >> $GITHUB_ENV + + - name: Generate Archives + run: | + git archive --prefix ${MATERIALX_ARCHIVE}/ --output ${MATERIALX_ARCHIVE}.zip ${RELEASE_TAG} + git archive --prefix ${MATERIALX_ARCHIVE}/ --output ${MATERIALX_ARCHIVE}.tar.gz ${RELEASE_TAG} + + - name: Sign and Upload Archives + uses: sigstore/gh-action-sigstore-python@v3.0.0 + with: + inputs: | + ${{ env.MATERIALX_ARCHIVE }}.zip + ${{ env.MATERIALX_ARCHIVE }}.tar.gz + upload-signing-artifacts: true + release-signing-artifacts: false diff --git a/CHANGELOG.md b/CHANGELOG.md index 5704c54b84..eddf285ac2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,64 @@ # Change Log +## [1.38.10] - 2024-04-12 + +### Added + +- Added support for [environment light intensity](https://github.com/AcademySoftwareFoundation/MaterialX/pull/1737) in generated GLSL shaders. + +### Changed + +- Removed an [extra suffix](https://github.com/AcademySoftwareFoundation/MaterialX/pull/1744) from element names in texture baking. + +### Fixed + +- Moved environment prefilter functions to their [referencing GLSL files](https://github.com/AcademySoftwareFoundation/MaterialX/pull/1748), addressing shader compilation errors in USD. +- Enabled color and unit transforms on [root nodes](https://github.com/AcademySoftwareFoundation/MaterialX/pull/1757) in shader generation, addressing missing color transforms in USD. +- Updated [document caches](https://github.com/AcademySoftwareFoundation/MaterialX/pull/1753) to store elements in declaration order, addressing compiler-dependent behavior in nodedef lookups. +- Switched to [framework linkage](https://github.com/AcademySoftwareFoundation/MaterialX/pull/1752) for OpenGL libraries on MacOS, addressing build issues in downstream projects. +- Switched to [legacy OpenGL libraries](https://github.com/AcademySoftwareFoundation/MaterialX/pull/1766) for Python wheels on Linux, addressing missing OpenGL functionality in Python wheels. +- Added a [missing vertex data prefix](https://github.com/AcademySoftwareFoundation/MaterialX/pull/1762) in Vulkan GLSL shader generation. + +## [1.38.9] - 2024-02-26 + +### Added + +- Added an initial NPR (non-photorealistic rendering) data library to MaterialX, supporting the [View Direction](https://github.com/AcademySoftwareFoundation/MaterialX/pull/1631), [Facing Ratio](https://github.com/AcademySoftwareFoundation/MaterialX/pull/1671), and [Gooch Shading](https://github.com/AcademySoftwareFoundation/MaterialX/pull/1674) nodes. +- Added new nodes to the standard data library, including [Reflect](https://github.com/AcademySoftwareFoundation/MaterialX/pull/1690), [Refract](https://github.com/AcademySoftwareFoundation/MaterialX/pull/1698), [Safe Power](https://github.com/AcademySoftwareFoundation/MaterialX/pull/1689), [Create Matrix](https://github.com/AcademySoftwareFoundation/MaterialX/pull/1553), and [Round](https://github.com/AcademySoftwareFoundation/MaterialX/pull/1678). +- Added support for the generation of [pre-filtered environment maps](https://github.com/AcademySoftwareFoundation/MaterialX/pull/1420) in MaterialX GLSL and MSL. +- Added support for [geometry drag & drop](https://github.com/AcademySoftwareFoundation/MaterialX/pull/1663), [frame capture](https://github.com/AcademySoftwareFoundation/MaterialX/pull/1636), [UI ranges](https://github.com/AcademySoftwareFoundation/MaterialX/pull/1623) and [enumerated values](https://github.com/AcademySoftwareFoundation/MaterialX/pull/1632) in the MaterialX Web Viewer. +- Added [floating popups](https://github.com/AcademySoftwareFoundation/MaterialX/pull/1565) for hovered pins in the MaterialX Graph Editor. +- Added [UI ranges](https://github.com/AcademySoftwareFoundation/MaterialX/pull/1646) to the 'useSpecularWorkflow' and 'normal' inputs of the UsdPreviewSurface shading model. +- Added [versioning rules](https://github.com/AcademySoftwareFoundation/MaterialX/pull/1664) for the MaterialX API and data libraries to the developer guide. +- Added initial C++ [fuzz tests](https://github.com/AcademySoftwareFoundation/MaterialX/pull/1605) and [coverage tests](https://github.com/AcademySoftwareFoundation/MaterialX/pull/1548) to GitHub Actions CI. +- Added [GCC 13, Clang 15](https://github.com/AcademySoftwareFoundation/MaterialX/pull/1602), and [Python 3.12](https://github.com/AcademySoftwareFoundation/MaterialX/pull/1588) builds to GitHub Actions CI. + +### Changed + +- Enabled the [new OSL closures](https://github.com/AcademySoftwareFoundation/MaterialX/pull/1702) by default in shader generation, with the MATERIALX_OSL_LEGACY_CLOSURES flag used to request legacy closures. +- Updated the MaterialX Web Viewer to [three.js r152](https://github.com/AcademySoftwareFoundation/MaterialX/pull/1615). +- Switched to a more efficient representation of [HDR images](https://github.com/AcademySoftwareFoundation/MaterialX/pull/1616) in the MaterialX Web Viewer. +- Improved the logic for [connecting pins](https://github.com/AcademySoftwareFoundation/MaterialX/pull/1569) in the MaterialX Graph Editor. +- Improved the handling of [filename inputs](https://github.com/AcademySoftwareFoundation/MaterialX/pull/1547) in OSL shader generation. +- Reduced the size of the MaterialX data libraries, improving the use of [graph definitions](https://github.com/AcademySoftwareFoundation/MaterialX/pull/1653) and merging [duplicate implementations](https://github.com/AcademySoftwareFoundation/MaterialX/pull/1642). +- Raised the minimum CMake version to [CMake 3.16](https://github.com/AcademySoftwareFoundation/MaterialX/pull/1607). +- Updated the C++ unit test library to [Catch 2.13.10](https://github.com/AcademySoftwareFoundation/MaterialX/pull/1566). + +### Fixed + +- Fixed the attenuation of [coated emission](https://github.com/AcademySoftwareFoundation/MaterialX/pull/1534) in the Standard Surface shading model. +- Fixed the implementation of the [overlay node](https://github.com/AcademySoftwareFoundation/MaterialX/pull/1539) in shader generation. +- Fixed an edge case for [type pointer comparisons](https://github.com/AcademySoftwareFoundation/MaterialX/pull/1665) in shader generation. +- Fixed an edge case for [transform nodes](https://github.com/AcademySoftwareFoundation/MaterialX/pull/1560) in GLSL and MSL shader generation. +- Fixed the implementation of [mx_hsvtorgb](https://github.com/AcademySoftwareFoundation/MaterialX/pull/1584) in MDL shader generation. +- Fixed [orphaned links](https://github.com/AcademySoftwareFoundation/MaterialX/pull/1667) when deleting nodes in the MaterialX Graph Editor. +- Fixed [scroll wheel interactions](https://github.com/AcademySoftwareFoundation/MaterialX/pull/1578) across windows of the MaterialX Graph Editor. +- Fixed the generation of unused [imgui.ini files](https://github.com/AcademySoftwareFoundation/MaterialX/pull/1570) in the MaterialX Graph Editor. +- Fixed a dependency on [module import order](https://github.com/AcademySoftwareFoundation/MaterialX/pull/1595) in MaterialX Python. +- Fixed an [off-by-one index check](https://github.com/AcademySoftwareFoundation/MaterialX/pull/1582) in Element::setChildIndex. +- Fixed a [missing null check](https://github.com/AcademySoftwareFoundation/MaterialX/pull/1601) in Graph::propertyEditor. +- Fixed cases where [absolute paths](https://github.com/AcademySoftwareFoundation/MaterialX/pull/1603) were stored in MaterialXConfig.cmake. + ## [1.38.8] - 2023-09-08 ### Added diff --git a/CMakeLists.txt b/CMakeLists.txt index 1e8763d6c7..1465bfe403 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,11 +1,11 @@ # MaterialX Version set(MATERIALX_MAJOR_VERSION 1) set(MATERIALX_MINOR_VERSION 38) -set(MATERIALX_BUILD_VERSION 8) +set(MATERIALX_BUILD_VERSION 10) set(MATERIALX_LIBRARY_VERSION ${MATERIALX_MAJOR_VERSION}.${MATERIALX_MINOR_VERSION}.${MATERIALX_BUILD_VERSION}) # Cmake setup -cmake_minimum_required(VERSION 3.5) +cmake_minimum_required(VERSION 3.16) set(CMAKE_CXX_STANDARD 14) set(CMAKE_POSITION_INDEPENDENT_CODE TRUE) set(CMAKE_MACOSX_RPATH ON) @@ -45,6 +45,7 @@ option(MATERIALX_BUILD_GEN_MSL "Build the MSL shader generator back-end." ON) option(MATERIALX_BUILD_RENDER "Build the MaterialX Render modules." ON) option(MATERIALX_BUILD_OIIO "Build OpenImageIO support for MaterialXRender." OFF) option(MATERIALX_BUILD_TESTS "Build unit tests." ON) +option(MATERIALX_BUILD_BENCHMARK_TESTS "Build benchmark tests." OFF) option(MATERIALX_BUILD_SHARED_LIBS "Build MaterialX libraries as shared rather than static." OFF) option(MATERIALX_PYTHON_LTO "Enable link-time optimizations for MaterialX Python." ON) @@ -52,20 +53,29 @@ option(MATERIALX_INSTALL_PYTHON "Install the MaterialX Python package as a third option(MATERIALX_INSTALL_RESOURCES "Install the resources folder when building render modules." ON) option(MATERIALX_TEST_RENDER "Run rendering tests for MaterialX Render module. GPU required for graphics validation." ON) option(MATERIALX_WARNINGS_AS_ERRORS "Interpret all compiler warnings as errors." OFF) +option(MATERIALX_COVERAGE_ANALYSIS "Build MaterialX libraries with coverage analysis on supporting platforms." OFF) option(MATERIALX_DYNAMIC_ANALYSIS "Build MaterialX libraries with dynamic analysis on supporting platforms." OFF) -option(MATERIALX_OSL_LEGACY_CLOSURES "Build OSL shader generation supporting the legacy OSL closures." ON) +option(MATERIALX_OSL_LEGACY_CLOSURES "Build OSL shader generation supporting the legacy OSL closures." OFF) option(MATERIALX_BUILD_IOS "Build MaterialX for iOS." OFF) if (MATERIALX_BUILD_IOS) set(CMAKE_SYSTEM_NAME iOS) add_definitions(-DTARGET_OS_IOS=1) - set(MATERIALX_BUILD_PYTHON OFF) - set(MATERIALX_BUILD_VIEWER OFF) - set(MATERIALX_BUILD_GRAPH_EDITOR OFF) - set(MATERIALX_BUILD_GEN_GLSL OFF) - set(MATERIALX_BUILD_GEN_OSL OFF) - set(MATERIALX_BUILD_GEN_MDL OFF) - set(MATERIALX_BUILD_TESTS OFF) + set(MATERIALX_BUILD_PYTHON OFF) + set(MATERIALX_BUILD_VIEWER OFF) + set(MATERIALX_BUILD_GRAPH_EDITOR OFF) + set(MATERIALX_BUILD_GEN_GLSL OFF) + set(MATERIALX_BUILD_GEN_OSL OFF) + set(MATERIALX_BUILD_GEN_MDL OFF) + set(MATERIALX_BUILD_TESTS OFF) +endif() + +if (MATERIALX_BUILD_JS) + set(MATERIALX_BUILD_GEN_OSL OFF) + set(MATERIALX_BUILD_GEN_MSL OFF) + set(MATERIALX_BUILD_GEN_MDL OFF) + set(MATERIALX_BUILD_RENDER OFF) + set(MATERIALX_BUILD_TESTS OFF) endif() set(MATERIALX_PYTHON_VERSION "" CACHE STRING @@ -79,10 +89,6 @@ set(MATERIALX_PYTHON_PYBIND11_DIR "" CACHE PATH set(MATERIALX_OIIO_DIR "" CACHE PATH "Path to the root folder of the OpenImageIO installation.") -if (MATERIALX_BUILD_JS) - set(MATERIALX_BUILD_GEN_GLSL ON) -endif() - # Settings to define installation layout set(MATERIALX_INSTALL_INCLUDE_PATH "include" CACHE STRING "Install header include path (e.g. 'inc', 'include').") set(MATERIALX_INSTALL_LIB_PATH "lib" CACHE STRING "Install lib path (e.g. 'libs', 'lib').") @@ -130,6 +136,7 @@ mark_as_advanced(MATERIALX_BUILD_GEN_MSL) mark_as_advanced(MATERIALX_BUILD_RENDER) mark_as_advanced(MATERIALX_BUILD_OIIO) mark_as_advanced(MATERIALX_BUILD_TESTS) +mark_as_advanced(MATERIALX_BUILD_BENCHMARK_TESTS) mark_as_advanced(MATERIALX_BUILD_SHARED_LIBS) mark_as_advanced(MATERIALX_NAMESPACE_SUFFIX) mark_as_advanced(MATERIALX_LIBNAME_SUFFIX) @@ -138,6 +145,7 @@ mark_as_advanced(MATERIALX_INSTALL_PYTHON) mark_as_advanced(MATERIALX_INSTALL_RESOURCES) mark_as_advanced(MATERIALX_TEST_RENDER) mark_as_advanced(MATERIALX_WARNINGS_AS_ERRORS) +mark_as_advanced(MATERIALX_COVERAGE_ANALYSIS) mark_as_advanced(MATERIALX_DYNAMIC_ANALYSIS) mark_as_advanced(MATERIALX_PYTHON_VERSION) mark_as_advanced(MATERIALX_PYTHON_EXECUTABLE) @@ -175,6 +183,9 @@ endif() if(MATERIALX_TEST_RENDER) add_definitions(-DMATERIALX_TEST_RENDER) endif() +if (MATERIALX_BUILD_BENCHMARK_TESTS) + add_definitions(-DMATERIALX_BUILD_BENCHMARK_TESTS) +endif() if (MATERIALX_BUILD_GEN_MDL) add_definitions(-DMATERIALX_MDLC_EXECUTABLE=\"${MATERIALX_MDLC_EXECUTABLE}\") @@ -228,6 +239,10 @@ else() if(MATERIALX_WARNINGS_AS_ERRORS) add_compile_options(-Werror) endif() + if(MATERIALX_COVERAGE_ANALYSIS) + add_compile_options(--coverage -O0) + add_link_options(--coverage) + endif() if(MATERIALX_DYNAMIC_ANALYSIS) set(DYNAMIC_ANALYSIS_OPTIONS -fsanitize=address -fsanitize=leak -fsanitize=undefined -fno-sanitize-recover=all) add_compile_options(${DYNAMIC_ANALYSIS_OPTIONS}) @@ -328,14 +343,12 @@ if(MATERIALX_BUILD_JS) add_subdirectory(source/JsMaterialX) endif() -if(${CMAKE_VERSION} VERSION_GREATER "3.6.2") - if(MATERIALX_BUILD_VIEWER) - set_property(DIRECTORY PROPERTY VS_STARTUP_PROJECT MaterialXView) - elseif(MATERIALX_BUILD_GRAPH_EDITOR) - set_property(DIRECTORY PROPERTY VS_STARTUP_PROJECT MaterialXGraphEditor) - elseif(MATERIALX_BUILD_TESTS) - set_property(DIRECTORY PROPERTY VS_STARTUP_PROJECT MaterialXTest) - endif() +if(MATERIALX_BUILD_VIEWER) + set_property(DIRECTORY PROPERTY VS_STARTUP_PROJECT MaterialXView) +elseif(MATERIALX_BUILD_GRAPH_EDITOR) + set_property(DIRECTORY PROPERTY VS_STARTUP_PROJECT MaterialXGraphEditor) +elseif(MATERIALX_BUILD_TESTS) + set_property(DIRECTORY PROPERTY VS_STARTUP_PROJECT MaterialXTest) endif() # Install root-level documents diff --git a/GOVERNANCE.md b/GOVERNANCE.md index b4520d9e3c..3cfcab6cd8 100644 --- a/GOVERNANCE.md +++ b/GOVERNANCE.md @@ -48,7 +48,7 @@ The current Voting Members of the MaterialX TSC are: - Doug Smythe - Industrial Light & Magic - Niklas Harrysson - Lumiere Software - Orn Gunnarsson - Autodesk -- David Larsson - Adobe +- Andréa Machizaud - Adobe ### Stakeholders @@ -62,17 +62,16 @@ MaterialX project, though they are encouraged to do so. The current Stakeholders of the MaterialX TSC are: -- Eric Bourque - Autodesk -- Fran Gonzalez - Pixar RenderMan +- Henrik Edstrom - Autodesk +- Fran González García - Pixar RenderMan - Dhruv Govil - Apple - Rafal Jaroszkiewicz - SideFX -- Lee Kerley - Sony Pictures Imageworks +- Ole Gulbrandsen - Sony Pictures Imageworks - Lutz Kettner - NVIDIA +- Chris Kulla - Epic Games - Bernard Kwok - Khronos Group -- Jonathan Litt - Epic Games - André Mazzone - ILM - Magnus Pettersson - IKEA -- Brian Savery - AMD ### TSC Nomination and Succession diff --git a/README.md b/README.md index e6c6e2d0e4..ddccb4a9db 100644 --- a/README.md +++ b/README.md @@ -60,13 +60,13 @@ The Open Chess Set is an open reference asset, consisting of a [MaterialX file]( The following packages contain pre-built binaries for the latest release, including the MaterialX viewer, Python libraries, and example assets: -- [Microsoft Windows (Visual Studio 2022, Python 3.9)](https://github.com/AcademySoftwareFoundation/MaterialX/releases/latest/download/MaterialX_Windows_VS2022_x64_Python39.zip) -- [MacOS (Xcode 13, Python 3.9)](https://github.com/AcademySoftwareFoundation/MaterialX/releases/latest/download/MaterialX_MacOS_Xcode_13_Python39.zip) -- [Linux (GCC 11, Python 3.9)](https://github.com/AcademySoftwareFoundation/MaterialX/releases/latest/download/MaterialX_Linux_GCC_11_Python39.zip) +- [Microsoft Windows (Visual Studio 2022, Python 3.11)](https://github.com/AcademySoftwareFoundation/MaterialX/releases/latest/download/MaterialX_Windows_VS2022_x64_Python311.zip) +- [MacOS (Xcode 14, Python 3.11)](https://github.com/AcademySoftwareFoundation/MaterialX/releases/latest/download/MaterialX_MacOS_Xcode_14_Python311.zip) +- [Linux (GCC 12, Python 3.11)](https://github.com/AcademySoftwareFoundation/MaterialX/releases/latest/download/MaterialX_Linux_GCC_12_Python311.zip) ### Additional Resources - The [Developer Guide](http://www.materialx.org/docs/api/index.html) contains a developer-oriented overview of MaterialX with API documentation. - The [Python Scripts](python/Scripts) folder contains standalone examples of MaterialX Python code. - The [JavaScript](javascript) folder contains details on building JavaScript bindings for MaterialX. -- Presentations at [ASWF Open Source Days](http://www.materialx.org/assets/ASWF_OSD2022_MaterialX_OSL_Final.pdf) and the [SIGGRAPH Physically Based Shading Course](https://blog.selfshadow.com/publications/s2020-shading-course/#materialx) provide details on the roadmap for MaterialX development. +- Presentations at [ASWF Open Source Days](https://materialx.org/assets/ASWF_OSD2023_MaterialX_Final.pdf) and the [SIGGRAPH Physically Based Shading Course](https://blog.selfshadow.com/publications/s2020-shading-course/#materialx) provide details on the roadmap for MaterialX development. diff --git a/documents/DeveloperGuide/MainPage.md b/documents/DeveloperGuide/MainPage.md index 79441a3e4d..68bd57ce5a 100644 --- a/documents/DeveloperGuide/MainPage.md +++ b/documents/DeveloperGuide/MainPage.md @@ -1,6 +1,6 @@ # MaterialX Overview -MaterialX is an open standard for transfer of rich material and look-development content between applications and renderers. Originated at Lucasfilm in 2012, MaterialX has been used by Industrial Light & Magic (ILM) in feature films such as _Star Wars: The Force Awakens_ and real-time experiences such as _Trials on Tatooine_, and it remains the central material format for new ILM productions. +MaterialX is an open standard for representing rich material and look-development content in computer graphics, enabling its platform-independent description and exchange across applications and renderers. Launched at [Industrial Light & Magic](https://www.ilm.com/) in 2012, MaterialX has been a key technology in their feature films and real-time experiences since _Star Wars: The Force Awakens_ and _Millennium Falcon: Smugglers Run_. The project was released as open source in 2017, with companies including Sony Pictures Imageworks, Pixar, Autodesk, Adobe, and SideFX contributing to its ongoing development. In 2021, MaterialX became the seventh hosted project of the [Academy Software Foundation](https://www.aswf.io/). ### Quick Start for Developers @@ -58,9 +58,24 @@ Building the `install` target of your project will install the MaterialX C++ and ### MaterialX Versioning -The MaterialX codebase uses a modified semantic versioning system where the *major* and *minor* versions match that of the corresponding MaterialX [specification](https://www.materialx.org/Specification.html), and the *build* version represents engineering advances within that specification version. MaterialX documents are similarly marked with the specification version they were authored in, and they are valid to load into any MaterialX codebase with an equal or higher specification version. +The MaterialX codebase uses a modified semantic versioning system where the *major* and *minor* versions match that of the corresponding MaterialX [specification](https://github.com/AcademySoftwareFoundation/MaterialX/blob/main/documents/Specification/MaterialX.Specification.md), and the *build* version represents engineering advances within that specification version. MaterialX documents are similarly marked with the specification version they were authored in, and they are valid to load into any MaterialX codebase with an equal or higher specification version. -Upgrading of MaterialX documents from earlier versions is handled at import time by the Document::upgradeVersion method, which applies the syntax and node interface upgrades that have occurred in previous specification revisions. This allows the syntax conventions of MaterialX and the names and interfaces of nodes to evolve over time, without invalidating documents from earlier versions. +Upgrading of MaterialX documents from earlier versions is handled at import time by the `Document::upgradeVersion` method, which applies the syntax and node interface upgrades that have occurred in previous specification revisions. This allows the syntax conventions of MaterialX and the names and interfaces of nodes to evolve over time, without invalidating documents from earlier versions. + +#### MaterialX API Changes + +The following rules describe the categories of changes to the [MaterialX API](https://materialx.org/docs/api/classes.html) that are allowed in version upgrades: + +- In *build* version upgrades, only non-breaking changes to the MaterialX API are allowed. For any API call that is modified in a build version upgrade, backwards compatibility should be maintained using deprecated C++ and Python wrappers for the original API call. +- In *minor* and *major* version upgrades, breaking changes to the MaterialX API are allowed, though their benefit should be carefully weighed against their cost. Any breaking changes to API calls should be highlighted in the release notes for the new version. + +#### MaterialX Data Library Changes + +The following rules describe the categories of changes to the [MaterialX Data Libraries](https://github.com/AcademySoftwareFoundation/MaterialX/tree/main/libraries) that are allowed in version upgrades: + +- In *build* version upgrades, only additive changes and fixes to the MaterialX data libraries are allowed. Additive changes are allowed to introduce new nodes, node versions, and node inputs with backwards-compatible default values. Data library fixes are allowed to update a node implementation to improve its alignment with the specification, without making any changes to its name or interface. +- In *minor* version upgrades, changes to the names and interfaces of MaterialX nodes are allowed, with the requirement that version upgrade logic be used to maintain the validity and visual interpretation of documents from earlier versions. +- In *major* version upgrades, changes to the syntax rules of MaterialX documents are allowed, with the requirement that version upgrade logic be used to maintain the validity and visual interpretation of documents from earlier versions. These changes usually require synchronized updates to both the MaterialX API and data libraries. ### Additional Links diff --git a/documents/DeveloperGuide/ShaderGeneration.md b/documents/DeveloperGuide/ShaderGeneration.md index 059b34d580..01bd823ec4 100644 --- a/documents/DeveloperGuide/ShaderGeneration.md +++ b/documents/DeveloperGuide/ShaderGeneration.md @@ -33,37 +33,41 @@ Figure 2. The first option is to keep inline code in a file. The file extension ```xml // Nodedef elements for node - - - + + + + - - - + + + + <... more types ...> // Implementation elements for node - - + + <... more types ...> // Nodedef elements for node - - - - + + + + + - - - - + + + + + <... more types ...> // Implementation elements for node - - + + <... more types ...> ``` ```c++ @@ -79,30 +83,29 @@ For nodes that can’t be implemented by inline expressions a function definitio ```xml // Nodedef element - - - - - - - - - - - + + + + + + + + + + + + // Implementation element - + ``` ```c++ // File 'mx_image_color3.osl' contains: void mx_image_color3(string file, string layer, color defaultvalue, - vector2 texcoord, string filtertype, - string uaddressmode, string vaddressmode, - string framerange, int frameoffset, - string frameendaction, output color out) + vector2 texcoord, string uaddressmode, string vaddressmode, string filtertype, + string framerange, int frameoffset, string frameendaction, + output color out) { // Sample the texture out = texture(file, texcoord.x, texcoord.y, @@ -120,40 +123,28 @@ As an alternative to defining source code, there is also an option to reference This is useful for creating a compound for a set of nodes performing some common operation. It can then be referenced as a node inside other nodegraphs. It is also useful for creating compatibility graphs for unknown nodes. If a node is created by some third party, and its implementation is unknown or proprietary, a compatibility graph can be created using known nodes and be referenced as a stand-in implementation. Linking a nodegraph to a nodedef is done by simply setting a nodedef attribute on the nodegraph definition. See Figure 4 for an example. ```xml - - + + + + - - - - - + + - - - - - - - - - - + + - - - - - - - - - - + + + + + + + - + ``` **Figure 4**: Checker node implementation using a nodegraph. @@ -161,10 +152,9 @@ This is useful for creating a compound for a set of nodes performing some common ### 1.3.4 Dynamic Code Generation In some situations static source code is not enough to implement a node. The code might need to be customized depending on parameters set on the node. Or for a hardware render target vertex streams or uniform inputs might need to be created in order to supply the data needed for the node implementation. -In this case, a C++ class can be added to handle the implementation of the node. The class should be derived from the base class `ShaderNodeImpl`. It should specify what language and target it is for by overriding `getLanguage()` and `getTarget()`. It can also be specified to support all languages or all targets by setting the identifier to an empty string, as done for the target identifier in the example below. It then needs to be registered for a `ShaderGenerator` by calling `ShaderGenerator::registerImplementation()`. See Figure 5 for an example. +In this case, a C++ class can be added to handle the implementation of the node. The class should be derived from the base class `ShaderNodeImpl`. It should specify what target it is for by overriding `getTarget()`. It then needs to be registered for a `ShaderGenerator` by calling `ShaderGenerator::registerImplementation()`. See Figure 5 for an example. -When a `ShaderNodeImpl` class is used for a nodedef the corresponding `` -element doesn’t need a file attribute, since no static source code is used. The `` element will then act only as a declaration that there exists an implementation for the nodedef for a particular language and target. +When a `ShaderNodeImpl` class is used for a nodedef the corresponding `` element doesn’t need a file attribute, since no static source code is used. The `` element will then act only as a declaration that there exists an implementation for the nodedef for a particular target. Note that by using a `ShaderNodeImpl` class for your node's implementation it is no longer data driven, as in the other three methods above. So it's recommended to use this only when inline expressions or static source code functions are not enough to handle the implementation of a node. @@ -175,8 +165,7 @@ class FooOsl : public ShaderNodeImpl public: static ShaderNodeImplPtr create() { return std::make_shared(); } - const string& getLanguage() const override { return LANGUAGE_OSL; } - const string& getTarget() const override { return EMPTY_STRING; } + const string& getTarget() const override { return OslShaderGenerator::TARGET; } void emitFunctionDefinition(const ShaderNode& node, GenContext& context, ShaderStage& stage) const override @@ -291,7 +280,8 @@ class TexCoordGlsl : public ShaderNodeImpl const string index = indexInput ? indexInput->getValue()->getValueString() : "0"; const string variable = "texcoord_" + index; - BEGIN_SHADER_STAGE(stage, Stage::VERTEX) + DEFINE_SHADER_STAGE(stage, Stage::VERTEX) + { VariableBlock& vertexData = stage.getOutputBlock(HW::VERTEX_DATA); const string prefix = vertexData.getInstance() + "."; ShaderPort* texcoord = vertexData[variable]; @@ -300,9 +290,10 @@ class TexCoordGlsl : public ShaderNodeImpl shadergen.emitLine(prefix + texcoord->getVariable() + " = i_" + variable, stage); texcoord->setEmitted(); } - END_SHADER_STAGE(shader, Stage::VERTEX) + } - BEGIN_SHADER_STAGE(stage, Stage::PIXEL) + DEFINE_SHADER_STAGE(stage, Stage::PIXEL) + { VariableBlock& vertexData = stage.getInputBlock(HW::VERTEX_DATA); const string prefix = vertexData.getInstance() + "."; ShaderPort* texcoord = vertexData[variable]; @@ -310,7 +301,7 @@ class TexCoordGlsl : public ShaderNodeImpl shadergen.emitOutput(node.getOutput(), true, false, context, stage); shadergen.emitString(" = " + prefix + texcoord->getVariable(), stage); shadergen.emitLineEnd(stage); - END_SHADER_STAGE(shader, Stage::PIXEL) + } } }; ``` diff --git a/documents/Specification/MaterialX.GeomExts.md b/documents/Specification/MaterialX.GeomExts.md index fb0d581ed8..5ff300de01 100644 --- a/documents/Specification/MaterialX.GeomExts.md +++ b/documents/Specification/MaterialX.GeomExts.md @@ -113,7 +113,7 @@ Collections are recipes for building a list of geometries (which can be any path A **<collection>** element contains lists of geometry expressions and/or collections to be included, and an optional list of geometry expressions to be excluded: -``` +```xml @@ -132,7 +132,7 @@ As a shorthand convenience, MaterialX allows the specification of a `geomprefix` So the following MTLX file snippets are equivalent: -``` +```xml @@ -176,7 +176,7 @@ The most common use for geominfo elements is to define the filenames (or portion A **<geominfo>** element contains one or more geometry property and/or token definitions, and associates them and their values with all geometries listed in the `geom` or `collection` attribute of the <geominfo>: -``` +```xml ...geometry property and token value definitions... @@ -200,7 +200,7 @@ The core MaterialX Specification defines a Geometric Property, or "geomprop", as MaterialX Geometry Extensions expands upons this by allowing the use of <geomprop> elements to define specific uniform values of a geometric property with specific geometries, as opposed to relying on those values being defined externally. This could include application-specific metadata, attributes passed from a lighting package to a renderer, or other geometry-specific data. A geomprop may also specify a `unittype` and `unit` if appropriate to indicate that the geometric property's value is in that unit; see the [**Units** section of the main MaterialX Specification](./MaterialX.Specification.md#units), although typically the <geompropdef> would define the `unittype` and `unit`, and a geomprop would only provide an overriding `unit` if the unit for its value differed from the geompropdef's defined default unit. -``` +```xml ``` @@ -216,7 +216,7 @@ Only float and vectorN geometric properties may specify a `unittype` an For example, one could specify a unique surface ID value associated with a geometry: -``` +```xml @@ -225,13 +225,13 @@ For example, one could specify a unique surface ID value associated with a geome GeomProp values can be accessed from a nodegraph using a `` node: -``` +```xml ``` A <geomprop> can also be used to define a default value for an intrinsic varying geometric property such as "geomcolor" for the geometry specified by the enclosing <geominfo>, which would be returned by the corresponding Geometric node (e.g. <geomcolor>) if the current geometry did not itself define values for that property. -``` +```xml @@ -243,7 +243,7 @@ A <geomprop> can also be used to define a default value for an intrinsic vary Token elements may be used within <geominfo> elements to define constant (typically string or integer) named values associated with specific geometries. These geometry token values can be substituted into filenames within image nodes; see the [**Additional Filename Substitutions**](#additional-filename-substitutions) section above for details: -``` +```xml ``` @@ -257,7 +257,7 @@ Token elements have the following attributes: For example, one could specify a texture identifier value associated with a geometry: -``` +```xml @@ -265,7 +265,7 @@ For example, one could specify a texture identifier value associated with a geom and then reference that token's value in a filename: -``` +```xml @@ -279,7 +279,7 @@ The <txtid> in the file name would be replaced by whatever value the txtid to TokenDefault elements define the default value for a specified geometry token name; this default value will be used in a filename string substitution if an explicit token value is not defined for the current geometry. Since TokenDefault does not apply to any geometry in particular, it must be used outside of a <geominfo> element. -``` +```xml ``` @@ -288,7 +288,7 @@ TokenDefault elements define the default value for a specified geometry token na Workflows involving textures with implicitly-computed filenames based on u,v coordinates (such as <UDIM> and <UVTILE>) can be made more efficient by explicitly listing the set of values that they resolve to for any given geometry. The MaterialX specification reserves two geomprop names for this purpose, `udimset` and `uvtileset`, each of which is a stringarray containing a comma-separated list of UDIM or UVTILE values: -``` +```xml @@ -313,7 +313,7 @@ A MaterialX document can contain multiple property and/or look elements. A **<property>** element defines the name, type and value of a look-specific non-material property of geometry; <**propertyset**> elements are used to group a number of <property>s into a single named object. The connection between properties or propertysets and specific geometries or collections is done in a <look> element, so that these properties can be reused across different geometries, and enabled in some looks but not others. <Property> elements may only be used within <propertyset>s; they may not be used independently, although a dedicated <propertyassign> element may be used within a <look> to declare a property name, type, value and assignment all at once. -``` +```xml @@ -338,7 +338,7 @@ In the example above, the "trace_maxdiffusedepth" property is target-specific, h A **<look>** element contains one or more material, variant, visibility and/or propertyset assignment declarations: -``` +```xml ...materialassign, variantassign, visibilityassign, property/propertysetassign declarations... @@ -348,7 +348,7 @@ Looks can inherit the assignments from another look by including an `inherit` at A number of looks can be grouped together into a **LookGroup**, e.g. to indicate which looks are defined for a particular asset: -``` +```xml ``` @@ -368,7 +368,7 @@ For elements which make assignments to geometries, the pathed names within `geom MaterialAssign elements are used within a <look> to connect a specified material to one or more geometries or collections (either a `geom` or a `collection` may be specified, but not both). -``` +```xml @@ -383,7 +383,7 @@ Material assignments are generally assumed to be mutually-exclusive, that is, an VariantAssign elements are used within a <materialassign> or a <look> to apply the values defined in one variant of a variantset to one assigned material, or to all applicable materials in a look. -``` +```xml @@ -407,7 +407,7 @@ In the above example, the input/token values defined within variant "var1" will Visibility elements are used within a <look> to define various types of generalized visibility between a "viewer" object and other geometries. A "viewer object" is simply a geometry that has the ability to "see" other geometries in some rendering context and thus may need to have the list of geometries that it "sees" in different contexts be specified; the most common examples are light sources and a primary rendering camera. -``` +```xml @@ -442,7 +442,7 @@ If the <visibility> `geom` or `collection` refers to light geometry, then ass For the "secondary" vistype, `viewergeom` should be renderable geometry rather than a light, to declare that certain other geometry is or is not visible to indirect bounce illumination or raytraced reflections in that `viewergeom`. In this example, "/b" would not be seen in reflections nor contribute indirect bounce illumination to "/a", while geometry "/c" would not be visible to _any_ secondary rays: -``` +```xml ``` @@ -452,7 +452,7 @@ For the "secondary" vistype, `viewergeom` should be renderable geometry rather t PropertyAssign and PropertySetAssign elements are used within a <look> to connect a specified property value or propertyset to one or more geometries or collections. -``` +```xml @@ -467,7 +467,7 @@ Either a `geom` or a `collection` may be specified, but not both. Multiple prop This example defines four collections, a light shader and material, and a propertyset, which are then used by two looks: -``` +```xml diff --git a/documents/Specification/MaterialX.Specification.md b/documents/Specification/MaterialX.Specification.md index 7e876bdb57..42b6cbbcaf 100644 --- a/documents/Specification/MaterialX.Specification.md +++ b/documents/Specification/MaterialX.Specification.md @@ -267,7 +267,7 @@ Types not defined with a specific semantic are assumed to have semantic="default Custom types are defined using the <typedef> element: -``` +```xml ``` @@ -292,7 +292,7 @@ The standard MaterialX distribution includes definitions for four "shader"-seman An MTLX file (with file extension ".mtlx") has the following general form: -``` +```xml @@ -303,7 +303,7 @@ That is, a standard XML declaration line followed by a root <materialx> eleme Standard XML XIncludes are supported ([http://en/wikipedia.org/wiki/XInclude](http://en/wikipedia.org/wiki/Xinclude)), as well as standard XML comments and the XML character entities `"`, `&`, `'`, `<` and `>`: -``` +```xml @@ -345,7 +345,7 @@ The working color space of a MaterialX document is defined by the `colorspace` a The color space of individual color image files and values may be defined via a `colorspace` attribute in an input which defines a filename or value. Color images and values in spaces other than the working color space are expected to be transformed by the application into the working space before computations are performed. In the example below, an image file has been defined in the “srgb_texture” color space, while its default value has been defined in “lin_rec709”; both should be transformed to the application’s working color space before being applied to any computations. -``` +```xml @@ -364,7 +364,7 @@ MaterialX allows floating-point and vector values to be defined in terms of a sp Unit types are defined using a <unittypedef> element, and a set of units of that type is defined using a <unitdef> element with one or more child <unit> elements: -``` +```xml @@ -397,7 +397,7 @@ References to elements in a different namespace are qualified using the syntax " Mtllib.mtlx contains the following (assuming that "..." contains any necessary material input connections and other element definitions): -``` +```xml ... @@ -412,7 +412,7 @@ Mtllib.mtlx contains the following (assuming that "..." contains any necessary m Then another MaterialX file could reference these materials like this: -``` +```xml ... @@ -423,7 +423,7 @@ Then another MaterialX file could reference these materials like this: Similarly, if a .mtlx file defining the "site_ops" namespace defined a custom color3-typed node "mynoise" with a single float input "f", it could be used in a node graph like this: -``` +```xml @@ -431,7 +431,7 @@ Similarly, if a .mtlx file defining the "site_ops" namespace defined a custom co A `namespace` attribute may also be added to individual <nodedef>s or <nodegraph>s, in which case the `name` and `node` of a <nodedef>, or just the `name` of a <nodegraph> will be assigned to the specified `namespace`. In a <nodegraph>, the `nodedef` must include a namespace reference if the <nodedef> to which it refers is defined in a specific namespace, even if it's the same namespace as the <nodegraph>: this is because the `namespace` only applies to the content that is created by or contained within an element, not to anything external referenced by that element. -``` +```xml @@ -453,14 +453,14 @@ Geometric Properties, or "geomprops", are intrinsic or user-defined surface coor One may also define custom geometric properties using a <geompropdef> element: -``` +```xml ``` e.g. -``` +```xml ``` @@ -469,13 +469,13 @@ The `type` of the geomprop may be any non-array MaterialX type, although `string Once defined, a custom geomprop name may be used any place that a standard geomprop can: -``` +```xml ``` A geompropdef may also specify a `unittype` and a `unit` to indicate that the geometric property is defined in terms of a specific unit. If a geomprop with a defined unit is accessed in a nodegraph using <geompropvalue>, the geometric property value will be converted from the unit specified by the geompropdef to the application-specified scene unit. -``` +```xml ``` @@ -487,7 +487,7 @@ As a shorthand convenience, MaterialX allows the specification of a `fileprefix` So the following snippets are equivalent: -``` +```xml @@ -538,7 +538,7 @@ Nodes are individual data generation or processing "blocks". Node functionality Individual node elements have the form: -``` +```xml @@ -560,7 +560,7 @@ Node elements contain zero or more <input> elements defining the name, type, A float/vectorN input of a node, or a "filename"-type input referring to an image file containing float or vectorN values, may specify a unit for its value by providing a `unit` attribute, and that unit must be one associated with the `unittype` for that input in the nodedef, if specified; please see the [Units](#units) section above for details on declaring units and unittypes. If the nodedef for a node (see the [Custom Nodes](#custom-nodes) section below) does not declare a `unittype` for an input, the node may do so; it is not permissible to provide a `unit` for a node input without a compatible `unittype` being defined on either the node or applicable nodedef. -``` +```xml @@ -570,7 +570,7 @@ Unless specified otherwise, all inputs default to a value of 0 in all channels f A node input must generally be connected to outputs of the same type, but float inputs may also be connected to any single channel within a multi-channel data types by adding an integer "channel" attribute, indicating the channel number (0-3) to extract from the input: -``` +```xml @@ -593,7 +593,7 @@ Standard MaterialX nodes have exactly one output, while custom nodes may have an A graph containing any number of nodes and output declarations forms a Node Graph, which may be enclosed within a <nodegraph> element to group them together into a single functional unit. Please see the [Custom Node Definition Using Node Graphs](#custom-node-definition-using-node-graphs) section below for details on how nodegraphs can be used to describe the functionality of new nodes. -``` +```xml ...node element(s)... ...output element(s)... @@ -606,7 +606,7 @@ A graph containing any number of nodes and output declarations forms a Node Grap Output data streams are defined using **<output>** elements, and may be used to declare which output streams are connectable to other MaterialX elements. Within a node graph, an <output> element declares an output stream that may be connected to a shader input or to the input of a referencing node in another graph when the nodegraph is the implementation of a custom node. See the [Custom Node Definition Using Node Graphs](#custom-node-definition-using-node-graphs) section for details on the use of node graphs as node implementations. -``` +```xml @@ -640,7 +640,7 @@ This section defines the Source Nodes that all MaterialX implementations are exp Texture nodes are used to read filtered image data from image or texture map files for processing within a node graph. -``` +```xml @@ -721,7 +721,7 @@ Arbitrary frame number expressions and speed changes are not supported. Procedural nodes are used to generate value data programmatically. -``` +```xml @@ -900,7 +900,7 @@ To scale or offset the noise pattern generated by `noise3d`, `fractal3d` or `cel Geometric nodes are used to reference local geometric properties from within a node graph: -``` +```xml @@ -982,7 +982,7 @@ Applications may also reference other renderer-specific named spaces, at the exp Global nodes generate color data using non-local geometric context, requiring access to geometric features beyond the surface point being processed. This non-local context can be provided by tracing rays into the scene, rasterizing scene geometry, or any other appropriate method. -``` +```xml @@ -1002,7 +1002,7 @@ Standard Global nodes: Application nodes are used to reference application-defined properties within a node graph, and have no inputs: -``` +```xml ``` @@ -1028,7 +1028,7 @@ Standard Application nodes: Operator nodes process one or more required input streams to form an output. Like other nodes, each operator must define its output type, which in most cases also determines the type(s) of the required input streams. -``` +```xml @@ -1084,6 +1084,12 @@ Math nodes have one or two spatially-varying inputs, and are used to perform a m * `in1` (float or colorN or vectorN): the value or nodename for the primary input * `in2` (same type as `in1` or float): the modulo value or nodename to divide by, cannot be 0 in any channel; default is 1.0 in all channels, which effectively returns the fractional part of a float value + + +* **`invert`**: subtract the incoming float/color/vector from "amount" in all channels, outputting: `amount - in`. + * `in` (float or colorN or vectorN): the value or nodename for the primary input + * `amount` (same type as `in` or float): the value or nodename to subtract from; default is 1.0 in all channels + * **`absval`**: the per-channel absolute value of the incoming float/color/vector. @@ -1496,7 +1502,7 @@ Blend nodes take two 1-4 channel inputs and apply the same operator to all chann | **`burn`** | 1-(1-B)/F | float, colorN | | **`dodge`** | B/(1-F) | float, colorN | | **`screen`** | 1-(1-F)(1-B) | float, colorN | -| **`overlay`** | 2FB if F<0.5;
1-(1-F)(1-B) if F>=0.5 | float, colorN | +| **`overlay`** | 2FB if B<0.5;
1-2(1-F)(1-B) if B>=0.5 | float, colorN | #### Merge Nodes @@ -1786,7 +1792,7 @@ A simple merge of two single-layer images with a separate mask image, followed b ![Nodegraph Example 1](media/nodegraph1.png "Nodegraph Example 1") -``` +```xml @@ -1818,7 +1824,7 @@ A more complex nodegraph using geometry properties to define two diffuse albedo ![Nodegraph Example 2](media/nodegraph2.png "Nodegraph Example 2") -``` +```xml @@ -1885,7 +1891,7 @@ MaterialX supports the definition of nodes, attributes and inputs that are speci Targets are declared using a <targetdef> element: -``` +```xml @@ -1893,7 +1899,7 @@ Targets are declared using a <targetdef> element: A target may inherit from another target, so that any reference to a parent target will automatically include any definitions specific to the inherited child target that do not have a definition for the parent target itself: -``` +```xml @@ -1913,14 +1919,14 @@ While the MaterialX specification describes the attributes and elements that are If an application requires additional information related to any MaterialX element, it may define and utilize additional attributes with non-standard names. Custom attributes are defined using <attributedef> elements: -``` +```xml ``` where _name_ is a unique name for the attributedef, _attrname_ is the name of the custom attribute to define, _type_ is the type of the attribute (typically string, stringarray, integer or boolean, although any MaterialX type is allowed), _defaultvalue_ is the default value for the attribute, _target_ is an optional list of targets to which this attribute applies, and _elements_ is an optional list of element names or elementname/inputname in which the attribute may be used. It is also permissible to provide enum and enumvalues attributes for an attributedef, to define specific labels and values that the custom attribute is allowed to take, using the same syntax and limitations as enum/enumvalues on nodedef inputs and tokens (see below). By default, a custom attribute is not emitted as metadata in generated shaders, but can be exported if the `exportable` attribute is set to "true". Examples: -``` +```xml @@ -1948,7 +1954,7 @@ Once defined, custom attributes may be used in exactly the same manner as standa If an application requires additional custom inputs within a standard MaterialX node, it may define a target application-specific <nodedef> for that node inheriting the base input definitions from the standard node's <nodedef>, then add inputs specific to that target application. -``` +```xml @@ -1958,7 +1964,7 @@ In the above example, a Maya-specific version of the color4-type <image> node When using a node, the definition appropriate for the current target will automatically be used, and other targets will ignore any inputs that are not part of the nodedef for that target. However, one may specify a documentational `target` attribute on an input to hint what target it is intended for if desired. In this example, the "preFilter" input has indicated that it is specific to the "maya" target. -``` +```xml @@ -1998,7 +2004,7 @@ NodeDefs must define one or more child <output> elements within the <noded The parameter interface of a custom node is specified via a set of child <input> and <token> elements of the <nodedef>, while documentation of the folder structure of a node may be defined using a number of <uifolder> elements, each of which may provide a doc attribute to provide documentation for that folder layer. A <uifolder> element may not contain any other elements; in particular, the <input>s and <token>s of the nodedef interface must be direct children of the <nodedef>. Nested folders may be indicated using a full path for the folder, with a "/" separator between folder levels. -``` +```xml @@ -2012,7 +2018,7 @@ The parameter interface of a custom node is specified via a set of child <inp **Input** elements are used within a <nodedef> to declare the spatially-varying and uniform inputs for a node: -``` +```xml ``` @@ -2047,7 +2053,7 @@ It is permissible to define a `value` or a `defaultgeomprop` for an input but no **Token** elements are used within a <nodedef> to declare uniform "interface token" string-substitution values to be referenced and substituted within filenames used in a node's nodegraph implementation: -``` +```xml ``` @@ -2068,7 +2074,7 @@ Please see the [Example Pre-Shader Compositing Material](#example-pre-shader-com **Output** elements are used within a <nodedef> to declare an output for node definitions, including the output's name, type, and default value or "defaultinput" connection: -``` +```xml ``` @@ -2103,7 +2109,7 @@ An <implementation> may define a `file` or `sourcecode` attribute, or neither Because the names used for node inputs (such as "normal" or "default") may conflict with the reserved words in various shading languages, or may simply be different for specific targets, <implementation> elements may contain a number of <input> elements to remap the `name`s of <input>s as specified in the <nodedef> to different `implname`s to indicate what the input name is actually called in the implementation's code. Only the inputs that need to be remapped to new `implname`s need to be listed; for each, it is recommended that the `type` of that input be listed for clarity, but if specified, it must match the type specified in the <nodedef>: <implementation>s are not allowed to change the type or any other attribute defined in the <nodedef>. In this example, the <implementation> declares that the "default" input defined in the "ND_image_color3" nodedef is actually called "default_value" in the "mx_image_color" function: -``` +```xml @@ -2112,7 +2118,7 @@ Because the names used for node inputs (such as "normal" or "default") may confl For uniform inputs and tokens whose nodedef description includes an enum list of allowable values, individual implementations may associate different target-specific resolved values for them potentially of a different type; these may be described by providing an `enumvalues` attribute on the uniform input or token within an <implementation> and if appropriate, an `impltype` to declare the target-specific type of these enumvalues. Note that if the type of an enum input in the nodedef is an array type, then the `impltype` (if specified) must also be an array type, while `enumvalues` is a list of values of the base (non-array) type. The following <implementation> states that for the "mystudio" target, the uaddressmode and vaddressmode inputs of the "image" node are actually called "extrapolate_u" and "extrapolate_v", are integers rather than strings, and take different values (e.g. "clamp" is 2): -``` +```xml element with a file attribute defining an external compiled implementation of a surface shader may contain one or more <aov> elements to declare the names and types of arbitrary output variables ("AOVs") which the shader can output to the renderer. AOVs must be of type float, color3, vector3, BSDF or EDF. Note that in MaterialX, AOVs for pre-shading "pattern" colors are normally of type color3, while post-shaded color-like values are normally of type BSDF and emissive color-like values are normally of type EDF. An <implementation> with a `nodegraph` attribute may not contain <aov> elements; instead, <aovoutput> elements within the nodegraph should be used. -``` +```xml @@ -2139,7 +2145,7 @@ An <implementation> element with a file attribute defining an external compil #### Example Custom Nodes Defined by External File Implementations -``` +```xml @@ -2179,7 +2185,7 @@ This example defines two templates for a custom operator node called "mariBlend" Here is an example of a two-output node definition and external implementation declaration. -``` +```xml @@ -2203,7 +2209,7 @@ A **<nodegraph>** element consists of at least one node element and at least A **functional nodegraph** is a nodegraph-based implementation for a specified <nodedef>, with the <nodedef> declaring the set of inputs that the nodegraph accepts: a functional nodegraph may not itself specify any direct child input elements. -``` +```xml ...node element(s)... ...output element(s)... @@ -2212,7 +2218,7 @@ A **functional nodegraph** is a nodegraph-based implementation for a specified & or -``` +```xml ...node element(s)... ...output element(s)... @@ -2223,7 +2229,7 @@ or The type(s) of the <output>(s) of the <nodedef> and the type(s) of the nodegraph <output>(s) must agree, and if there are multiple outputs, then the `name`s of the <output>s in the <nodegraph> and <nodedef> must also agree. The inputs and tokens of the <nodedef> can be referenced within <input> and <token> elements of nodes within the nodegraph implementation using `interfacename` attributes in place of `value` or `nodename` attributes, e.g. a nodedef input "i2" and interface token "diffmap" could be referenced as follows: -``` +```xml ``` @@ -2235,7 +2241,7 @@ Note that a uniform <input> of a node within the nodegraph may use `interface A **compound <nodegraph>** element may specify one or more child <input> and/or <token> elements. In this case, the <nodegraph> functions as a collapsible "wrapper" for the contained nodes. -``` +```xml [...input and/or token element(s)...] ...node and/or (compound) nodegraph element(s)... @@ -2250,7 +2256,7 @@ It is permissible to define multiple nodegraph- and/or file-based implementation #### Example Custom Node Defined by a Nodegraph -``` +```xml @@ -2277,7 +2283,7 @@ The inputs of the nodegraph are declared by the <nodedef>, and the nodes with Once defined with a <nodedef>, using a custom node within a node graph follows the same syntax as any other standard node: the name of the element is the name of the custom node, and the MaterialX type of the node's output is required; the custom node's child elements define connections of inputs to other node outputs as well as any input values for the custom node. -``` +```xml @@ -2292,7 +2298,7 @@ Once defined with a <nodedef>, using a custom node within a node graph follow When invoking nodes with multiple outputs, the `type` of the node should be declared as "multioutput", and other node inputs connecting to an output of the node must include an `output` attribute to specify which output of the node to connect to: -``` +```xml @@ -2313,7 +2319,7 @@ When invoking nodes with multiple outputs, the `type` of the node should be decl Custom nodes that output data types with a "shader" semantic are referred to in MaterialX as "Shader Nodes". Shaders, along with their inputs, are declared using the same <nodedef>, <implementation> and <nodegraph> elements described above: -``` +```xml ...input declarations... @@ -2331,7 +2337,7 @@ NodeDef elements defining shader nodes do not typically include `default` or `de As mentioned in the [Custom Data Types](#custom-data-types) section earlier, the standard MaterialX distribution includes the following standard data types for shaders: -``` +```xml @@ -2342,7 +2348,7 @@ These types all declare that they have "shader" semantic, but define different c Instantiation of shader nodes to give them specific values is done the same way as instantiating any other node type: -``` +```xml @@ -2352,7 +2358,7 @@ Instantiation of shader nodes to give them specific values is done the same way Instantiated shader nodes can also inherit from other shader nodes of the same class: -``` +```xml @@ -2398,7 +2404,7 @@ The Standard MaterialX Library defines the following nodes and node variants ope A functional nodegraph with either a "shader" or "material"-semantic output type may contain a number of <aovoutput> elements to declare arbitrary output variables ("AOVs") which the renderer can see and output as additional streams of information. AOVoutputs must be of type float, color3 or vector3 for pre-shading "pattern" values, or BSDF or EDF for shader-node output values; the renderer is expected to extract the appropriate color-like information from BSDF and EDF types. AOVs defined within a shader-semantic node instantiated within this functional nodegraph may be "passed along" and potentially renamed (but may not be modified or operated on in any way) by providing a sourceaov attribute in the <aovoutput>. -``` +```xml ``` @@ -2413,7 +2419,7 @@ The attributes for <aovoutput> elements are: Examples: -``` +```xml @@ -2424,7 +2430,7 @@ Examples: Example of using <aovoutput> with sourceaov to forward AOVs from within an instantiation of a shader-semantic node; this assumes that <standard_surface> has itself defined <aovoutput>s for "diffuse" and "specular" AOVs: -``` +```xml s for geometric Custom nodes that output data types with a "material" semantic are referred to in MaterialX as "Material Nodes". Material nodes typically have one or more "shader" semantic inputs which establish what shaders the material references; previous versions of MaterialX used <shaderref> elements to establish these shader-to-material connections. Material Nodes are declared using the same <nodedef> elements as described above: -``` +```xml ...additional shader or input declarations... @@ -2476,7 +2482,7 @@ The attributes for <nodedef> elements as they pertain to the declaration of m The standard MaterialX distribution includes a single material type definition used as the output type for all material nodes: -``` +```xml ``` @@ -2501,7 +2507,7 @@ as well as definitions for three standard material nodes, all outputting type "m Material nodes supporting multiple shaders of the same type for different rendering targets can be defined: -``` +```xml @@ -2514,7 +2520,7 @@ Material nodes supporting multiple shaders of the same type for different render Creating materials with specific values bound to shader inputs involves instantiating a Shader Node for each desired shader type and setting values on those shader nodes, and connecting the shader node(s) to the inputs of a Material Node: -``` +```xml @@ -2535,7 +2541,7 @@ Alternatively, and perhaps more usefully, a complete network of multiple shader Materials can inherit from other materials, to add or change shaders connected to different inputs; in this example, a displacement shader is added to the above "Mgold" material to create a new "Mgolddsp" material: -``` +```xml @@ -2555,7 +2561,7 @@ Inheritance of material-type custom nodes is also allowed, so that new or change A material to blend between three different surface layers using mask textures. This example also demonstrates the use of the "target" attribute of a shader implementation element to define multiple renderer-specific shaders of the same type referenced within a single material, and the use of interface tokens to define texture filenames. -``` +```xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/libraries/bxdf/standard_surface.mtlx b/libraries/bxdf/standard_surface.mtlx index 843885aa50..9d4d23551e 100644 --- a/libraries/bxdf/standard_surface.mtlx +++ b/libraries/bxdf/standard_surface.mtlx @@ -81,7 +81,7 @@ + doc="The thickness of the thin film layer on a surface. Use for materials such as multitone car paint or soap bubbles (in nanometers)." />
+ + + + @@ -398,8 +402,8 @@ - - + + diff --git a/libraries/bxdf/translation/open_pbr_to_standard_surface.mtlx b/libraries/bxdf/translation/open_pbr_to_standard_surface.mtlx new file mode 100644 index 0000000000..bff214fc19 --- /dev/null +++ b/libraries/bxdf/translation/open_pbr_to_standard_surface.mtlx @@ -0,0 +1,362 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/libraries/bxdf/translation/standard_surface_to_open_pbr.mtlx b/libraries/bxdf/translation/standard_surface_to_open_pbr.mtlx new file mode 100644 index 0000000000..efbe39a053 --- /dev/null +++ b/libraries/bxdf/translation/standard_surface_to_open_pbr.mtlx @@ -0,0 +1,309 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/libraries/bxdf/translation/standard_surface_to_usd.mtlx b/libraries/bxdf/translation/standard_surface_to_usd.mtlx index b6e28805dd..5da2457857 100644 --- a/libraries/bxdf/translation/standard_surface_to_usd.mtlx +++ b/libraries/bxdf/translation/standard_surface_to_usd.mtlx @@ -12,6 +12,8 @@ + + @@ -44,13 +46,18 @@ + + + + + - + @@ -74,10 +81,14 @@ - + + + + + diff --git a/libraries/bxdf/usd_preview_surface.mtlx b/libraries/bxdf/usd_preview_surface.mtlx index 984bad0326..6efb288184 100644 --- a/libraries/bxdf/usd_preview_surface.mtlx +++ b/libraries/bxdf/usd_preview_surface.mtlx @@ -9,7 +9,7 @@ - + @@ -18,7 +18,7 @@ - + diff --git a/libraries/cmlib/cmlib_ng.mtlx b/libraries/cmlib/cmlib_ng.mtlx index 8045e80a4d..7c318f8467 100644 --- a/libraries/cmlib/cmlib_ng.mtlx +++ b/libraries/cmlib/cmlib_ng.mtlx @@ -296,7 +296,7 @@ - + @@ -333,7 +333,7 @@ - + diff --git a/libraries/nprlib/genglsl/nprlib_genglsl_impl.mtlx b/libraries/nprlib/genglsl/nprlib_genglsl_impl.mtlx new file mode 100644 index 0000000000..1a96f315e5 --- /dev/null +++ b/libraries/nprlib/genglsl/nprlib_genglsl_impl.mtlx @@ -0,0 +1,17 @@ + + + + + + + + + + + + diff --git a/libraries/nprlib/genmdl/nprlib_genmdl_impl.mtlx b/libraries/nprlib/genmdl/nprlib_genmdl_impl.mtlx new file mode 100644 index 0000000000..1c1a728bf9 --- /dev/null +++ b/libraries/nprlib/genmdl/nprlib_genmdl_impl.mtlx @@ -0,0 +1,17 @@ + + + + + + + + + + + + diff --git a/libraries/nprlib/genmsl/nprlib_genmsl_impl.mtlx b/libraries/nprlib/genmsl/nprlib_genmsl_impl.mtlx new file mode 100644 index 0000000000..615e9d8ce0 --- /dev/null +++ b/libraries/nprlib/genmsl/nprlib_genmsl_impl.mtlx @@ -0,0 +1,17 @@ + + + + + + + + + + + + diff --git a/libraries/nprlib/genosl/nprlib_genosl_impl.mtlx b/libraries/nprlib/genosl/nprlib_genosl_impl.mtlx new file mode 100644 index 0000000000..0b077b6406 --- /dev/null +++ b/libraries/nprlib/genosl/nprlib_genosl_impl.mtlx @@ -0,0 +1,17 @@ + + + + + + + + + + + + diff --git a/libraries/nprlib/nprlib_defs.mtlx b/libraries/nprlib/nprlib_defs.mtlx new file mode 100644 index 0000000000..f8770e3524 --- /dev/null +++ b/libraries/nprlib/nprlib_defs.mtlx @@ -0,0 +1,55 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/libraries/nprlib/nprlib_ng.mtlx b/libraries/nprlib/nprlib_ng.mtlx new file mode 100644 index 0000000000..f3db3f51ff --- /dev/null +++ b/libraries/nprlib/nprlib_ng.mtlx @@ -0,0 +1,114 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/libraries/pbrlib/genglsl/lib/mx39_microfacet.glsl b/libraries/pbrlib/genglsl/lib/mx39_microfacet.glsl new file mode 100644 index 0000000000..5637f388a0 --- /dev/null +++ b/libraries/pbrlib/genglsl/lib/mx39_microfacet.glsl @@ -0,0 +1,30 @@ +#include "mx_microfacet.glsl" + +float mx39_pow6(float x) +{ + float x2 = mx_square(x); + return mx_square(x2) * x2; +} + +// Generate a cosine-weighted sample on the unit hemisphere. +vec3 mx39_cosine_sample_hemisphere(vec2 Xi) +{ + float phi = 2.0 * M_PI * Xi.x; + float cosTheta = sqrt(Xi.y); + float sinTheta = sqrt(1.0 - Xi.y); + return vec3(cos(phi) * sinTheta, + sin(phi) * sinTheta, + cosTheta); +} + +// Construct an orthonormal basis from a unit vector. +// https://graphics.pixar.com/library/OrthonormalB/paper.pdf +mat3 mx39_orthonormal_basis(vec3 N) +{ + float sign = (N.z < 0.0) ? -1.0 : 1.0; + float a = -1.0 / (sign + N.z); + float b = N.x * N.y * a; + vec3 X = vec3(1.0 + sign * N.x * N.x * a, sign * b, -sign * N.x); + vec3 Y = vec3(b, sign + N.y * N.y * a, -N.y); + return mat3(X, Y, N); +} diff --git a/libraries/pbrlib/genglsl/lib/mx39_microfacet_diffuse.glsl b/libraries/pbrlib/genglsl/lib/mx39_microfacet_diffuse.glsl new file mode 100644 index 0000000000..c7ef22b78a --- /dev/null +++ b/libraries/pbrlib/genglsl/lib/mx39_microfacet_diffuse.glsl @@ -0,0 +1,88 @@ +#include "mx39_microfacet.glsl" +#include "mx_microfacet_diffuse.glsl" + +const float FUJII_CONSTANT_1 = 0.5 - 2.0 / (3.0 * M_PI); +const float FUJII_CONSTANT_2 = 2.0 / 3.0 - 28.0 / (15.0 * M_PI); + +// Qualitative Oren-Nayar diffuse with simplified math: +// https://www1.cs.columbia.edu/CAVE/publications/pdfs/Oren_SIGGRAPH94.pdf +float mx39_oren_nayar_diffuse(float NdotV, float NdotL, float LdotV, float roughness) +{ + float s = LdotV - NdotL * NdotV; + float stinv = (s > 0.0) ? s / max(NdotL, NdotV) : 0.0; + + float sigma2 = mx_square(roughness); + float A = 1.0 - 0.5 * (sigma2 / (sigma2 + 0.33)); + float B = 0.45 * sigma2 / (sigma2 + 0.09); + + return A + B * stinv; +} + +// Rational quadratic fit to Monte Carlo data for Oren-Nayar directional albedo. +float mx39_oren_nayar_diffuse_dir_albedo_analytic(float NdotV, float roughness) +{ + vec2 r = vec2(1.0, 1.0) + + vec2(-0.4297, -0.6076) * roughness + + vec2(-0.7632, -0.4993) * NdotV * roughness + + vec2(1.4385, 2.0315) * mx_square(roughness); + return r.x / r.y; +} + +float mx39_oren_nayar_diffuse_dir_albedo(float NdotV, float roughness) +{ + float dirAlbedo = mx39_oren_nayar_diffuse_dir_albedo_analytic(NdotV, roughness); + return clamp(dirAlbedo, 0.0, 1.0); +} + +// Improved Oren-Nayar diffuse from Fujii: +// https://mimosa-pudica.net/improved-oren-nayar.html +float mx39_oren_nayar_fujii_diffuse_dir_albedo(float cosTheta, float roughness) +{ + float A = 1.0 / (1.0 + FUJII_CONSTANT_1 * roughness); + float B = roughness * A; + float Si = sqrt(max(0.0, 1.0 - mx_square(cosTheta))); + float G = Si * (acos(clamp(cosTheta, -1.0, 1.0)) - Si * cosTheta) + + 2.0 * ((Si / cosTheta) * (1.0 - Si * Si * Si) - Si) / 3.0; + return A + (B * G * M_PI_INV); +} + +float mx39_oren_nayar_fujii_diffuse_avg_albedo(float roughness) +{ + float A = 1.0 / (1.0 + FUJII_CONSTANT_1 * roughness); + return A * (1.0 + FUJII_CONSTANT_2 * roughness); +} + +// Energy-compensated Oren-Nayar diffuse from OpenPBR Surface: +// https://academysoftwarefoundation.github.io/OpenPBR/ +vec3 mx39_oren_nayar_compensated_diffuse(float NdotV, float NdotL, float LdotV, float roughness, vec3 color) +{ + float s = LdotV - NdotL * NdotV; + float stinv = (s > 0.0) ? s / max(NdotL, NdotV) : s; + + // Compute the single-scatter lobe. + float A = 1.0 / (1.0 + FUJII_CONSTANT_1 * roughness); + vec3 lobeSingleScatter = color * A * (1.0 + roughness * stinv); + + // Compute the multi-scatter lobe. + float dirAlbedoV = mx39_oren_nayar_fujii_diffuse_dir_albedo(NdotV, roughness); + float dirAlbedoL = mx39_oren_nayar_fujii_diffuse_dir_albedo(NdotL, roughness); + float avgAlbedo = mx39_oren_nayar_fujii_diffuse_avg_albedo(roughness); + vec3 colorMultiScatter = mx_square(color) * avgAlbedo / + (vec3(1.0) - color * max(0.0, 1.0 - avgAlbedo)); + vec3 lobeMultiScatter = colorMultiScatter * + max(M_FLOAT_EPS, 1.0 - dirAlbedoV) * + max(M_FLOAT_EPS, 1.0 - dirAlbedoL) / + max(M_FLOAT_EPS, 1.0 - avgAlbedo); + + // Return the sum. + return lobeSingleScatter + lobeMultiScatter; +} + +vec3 mx39_oren_nayar_compensated_diffuse_dir_albedo(float cosTheta, float roughness, vec3 color) +{ + float dirAlbedo = mx39_oren_nayar_fujii_diffuse_dir_albedo(cosTheta, roughness); + float avgAlbedo = mx39_oren_nayar_fujii_diffuse_avg_albedo(roughness); + vec3 colorMultiScatter = mx_square(color) * avgAlbedo / + (vec3(1.0) - color * max(0.0, 1.0 - avgAlbedo)); + return mix(colorMultiScatter, color, dirAlbedo); +} diff --git a/libraries/pbrlib/genglsl/lib/mx39_microfacet_sheen.glsl b/libraries/pbrlib/genglsl/lib/mx39_microfacet_sheen.glsl new file mode 100644 index 0000000000..4f94e9e0e1 --- /dev/null +++ b/libraries/pbrlib/genglsl/lib/mx39_microfacet_sheen.glsl @@ -0,0 +1,108 @@ +#include "mx39_microfacet.glsl" +#include "mx_microfacet_sheen.glsl" + +float mx_inversesqrt(float x) +{ +#ifdef __METAL_VERSION__ + return ::rsqrt(x); +#else + return inversesqrt(x); +#endif +} + +// The following functions are adapted from https://github.com/tizian/ltc-sheen. +// "Practical Multiple-Scattering Sheen Using Linearly Transformed Cosines", Zeltner et al. + +// Gaussian fit to directional albedo table. +float mx39_zeltner_sheen_dir_albedo(float x, float y) +{ + float s = y*(0.0206607 + 1.58491*y)/(0.0379424 + y*(1.32227 + y)); + float m = y*(-0.193854 + y*(-1.14885 + y*(1.7932 - 0.95943*y*y)))/(0.046391 + y); + float o = y*(0.000654023 + (-0.0207818 + 0.119681*y)*y)/(1.26264 + y*(-1.92021 + y)); + return exp(-0.5*mx_square((x - m)/s))/(s*sqrt(2.0*M_PI)) + o; +} + +// Rational fits to LTC matrix coefficients. +float mx39_zeltner_sheen_ltc_aInv(float x, float y) +{ + return (2.58126*x + 0.813703*y)*y/(1.0 + 0.310327*x*x + 2.60994*x*y); +} + +float mx39_zeltner_sheen_ltc_bInv(float x, float y) +{ + return sqrt(1.0 - x)*(y - 1.0)*y*y*y/(0.0000254053 + 1.71228*x - 1.71506*x*y + 1.34174*y*y); +} + +// V and N are assumed to be unit vectors. +mat3 mx39_orthonormal_basis_ltc(vec3 V, vec3 N, float NdotV) +{ + // Generate a tangent vector in the plane of V and N. + // This required to correctly orient the LTC lobe. + vec3 X = V - N*NdotV; + float lenSqr = dot(X, X); + if (lenSqr > 0.0) + { + X *= mx_inversesqrt(lenSqr); + vec3 Y = cross(N, X); + return mat3(X, Y, N); + } + + // If lenSqr == 0, then V == N, so any orthonormal basis will do. + return mx39_orthonormal_basis(N); +} + +// Multiplication by directional albedo is handled by the calling function. +float mx39_zeltner_sheen_brdf(vec3 L, vec3 V, vec3 N, float NdotV, float roughness) +{ + mat3 toLTC = transpose(mx39_orthonormal_basis_ltc(V, N, NdotV)); + vec3 w = toLTC * L; + + float aInv = mx39_zeltner_sheen_ltc_aInv(NdotV, roughness); + float bInv = mx39_zeltner_sheen_ltc_bInv(NdotV, roughness); + + // Transform w to original configuration (clamped cosine). + // |aInv 0 bInv| + // wo = M^-1 . w = | 0 aInv 0| . w + // | 0 0 1| + vec3 wo = vec3(aInv*w.x + bInv*w.z, aInv * w.y, w.z); + float lenSqr = dot(wo, wo); + + // D(w) = Do(M^-1.w / ||M^-1.w||) . |M^-1| / ||M^-1.w||^3 + // = Do(M^-1.w) . |M^-1| / ||M^-1.w||^4 + // = Do(wo) . |M^-1| / dot(wo, wo)^2 + // = Do(wo) . aInv^2 / dot(wo, wo)^2 + // = Do(wo) . (aInv / dot(wo, wo))^2 + return max(wo.z, 0.0) * M_PI_INV * mx_square(aInv / lenSqr); +} + +vec3 mx39_zeltner_sheen_importance_sample(vec2 Xi, vec3 V, vec3 N, float roughness, out float pdf) +{ + float NdotV = clamp(dot(N, V), 0.0, 1.0); + roughness = clamp(roughness, 0.01, 1.0); // Clamp to range of original impl. + + vec3 wo = mx39_cosine_sample_hemisphere(Xi); + + float aInv = mx39_zeltner_sheen_ltc_aInv(NdotV, roughness); + float bInv = mx39_zeltner_sheen_ltc_bInv(NdotV, roughness); + + // Transform wo from original configuration (clamped cosine). + // |1/aInv 0 -bInv/aInv| + // w = M . wo = | 0 1/aInv 0| . wo + // | 0 0 1| + vec3 w = vec3(wo.x/aInv - wo.z*bInv/aInv, wo.y / aInv, wo.z); + + float lenSqr = dot(w, w); + w *= mx_inversesqrt(lenSqr); + + // D(w) = Do(wo) . ||M.wo||^3 / |M| + // = Do(wo / ||M.wo||) . ||M.wo||^4 / |M| + // = Do(w) . ||M.wo||^4 / |M| (possible because M doesn't change z component) + // = Do(w) . dot(w, w)^2 * aInv^2 + // = Do(w) . (aInv * dot(w, w))^2 + pdf = max(w.z, 0.0) * M_PI_INV * mx_square(aInv * lenSqr); + + mat3 fromLTC = mx39_orthonormal_basis_ltc(V, N, NdotV); + w = fromLTC * w; + + return w; +} diff --git a/libraries/pbrlib/genglsl/lib/mx39_microfacet_specular.glsl b/libraries/pbrlib/genglsl/lib/mx39_microfacet_specular.glsl new file mode 100644 index 0000000000..fa4badc7e5 --- /dev/null +++ b/libraries/pbrlib/genglsl/lib/mx39_microfacet_specular.glsl @@ -0,0 +1,419 @@ +#include "mx39_microfacet.glsl" +#include "mx_microfacet_specular.glsl" + +const int MX39_FRESNEL_MODEL_DIELECTRIC = 0; +const int MX39_FRESNEL_MODEL_CONDUCTOR = 1; +const int MX39_FRESNEL_MODEL_SCHLICK = 2; + +// Parameters for Fresnel calculations +struct Mx39FresnelData +{ + // Fresnel model + int model; + bool airy; + + // Physical Fresnel + vec3 ior; + vec3 extinction; + + // Generalized Schlick Fresnel + vec3 F0; + vec3 F82; + vec3 F90; + float exponent; + + // Thin film + float tf_thickness; + float tf_ior; + + // Refraction + bool refraction; +}; + +// Convert a real-valued index of refraction to normal-incidence reflectivity. +float mx39_ior_to_f0(float ior) +{ + return mx_square((ior - 1.0) / (ior + 1.0)); +} + +// Convert normal-incidence reflectivity to real-valued index of refraction. +float mx39_f0_to_ior(float F0) +{ + float sqrtF0 = sqrt(clamp(F0, 0.01, 0.99)); + return (1.0 + sqrtF0) / (1.0 - sqrtF0); +} +vec3 mx39_f0_to_ior(vec3 F0) +{ + vec3 sqrtF0 = sqrt(clamp(F0, 0.01, 0.99)); + return (vec3(1.0) + sqrtF0) / (vec3(1.0) - sqrtF0); +} + +// https://renderwonk.com/publications/wp-generalization-adobe/gen-adobe.pdf +vec3 mx39_fresnel_hoffman_schlick(float cosTheta, Mx39FresnelData fd) +{ + const float COS_THETA_MAX = 1.0 / 7.0; + const float COS_THETA_FACTOR = 1.0 / (COS_THETA_MAX * pow(1.0 - COS_THETA_MAX, 6.0)); + + float x = clamp(cosTheta, 0.0, 1.0); + vec3 a = mix(fd.F0, fd.F90, pow(1.0 - COS_THETA_MAX, fd.exponent)) * (vec3(1.0) - fd.F82) * COS_THETA_FACTOR; + return mix(fd.F0, fd.F90, pow(1.0 - x, fd.exponent)) - a * x * mx39_pow6(1.0 - x); +} + +// https://seblagarde.wordpress.com/2013/04/29/memo-on-fresnel-equations/ +float mx39_fresnel_dielectric(float cosTheta, float ior) +{ + float c = cosTheta; + float g2 = ior*ior + c*c - 1.0; + if (g2 < 0.0) + { + // Total internal reflection + return 1.0; + } + + float g = sqrt(g2); + return 0.5 * mx_square((g - c) / (g + c)) * + (1.0 + mx_square(((g + c) * c - 1.0) / ((g - c) * c + 1.0))); +} + +// https://seblagarde.wordpress.com/2013/04/29/memo-on-fresnel-equations/ +vec2 mx39_fresnel_dielectric_polarized(float cosTheta, float ior) +{ + float cosTheta2 = mx_square(clamp(cosTheta, 0.0, 1.0)); + float sinTheta2 = 1.0 - cosTheta2; + + float t0 = max(ior * ior - sinTheta2, 0.0); + float t1 = t0 + cosTheta2; + float t2 = 2.0 * sqrt(t0) * cosTheta; + float Rs = (t1 - t2) / (t1 + t2); + + float t3 = cosTheta2 * t0 + sinTheta2 * sinTheta2; + float t4 = t2 * sinTheta2; + float Rp = Rs * (t3 - t4) / (t3 + t4); + + return vec2(Rp, Rs); +} + +// https://seblagarde.wordpress.com/2013/04/29/memo-on-fresnel-equations/ +void mx39_fresnel_conductor_polarized(float cosTheta, vec3 n, vec3 k, out vec3 Rp, out vec3 Rs) +{ + float cosTheta2 = mx_square(clamp(cosTheta, 0.0, 1.0)); + float sinTheta2 = 1.0 - cosTheta2; + vec3 n2 = n * n; + vec3 k2 = k * k; + + vec3 t0 = n2 - k2 - vec3(sinTheta2); + vec3 a2plusb2 = sqrt(t0 * t0 + 4.0 * n2 * k2); + vec3 t1 = a2plusb2 + vec3(cosTheta2); + vec3 a = sqrt(max(0.5 * (a2plusb2 + t0), 0.0)); + vec3 t2 = 2.0 * a * cosTheta; + Rs = (t1 - t2) / (t1 + t2); + + vec3 t3 = cosTheta2 * a2plusb2 + vec3(sinTheta2 * sinTheta2); + vec3 t4 = t2 * sinTheta2; + Rp = Rs * (t3 - t4) / (t3 + t4); +} + +vec3 mx39_fresnel_conductor(float cosTheta, vec3 n, vec3 k) +{ + vec3 Rp, Rs; + mx39_fresnel_conductor_polarized(cosTheta, n, k, Rp, Rs); + return 0.5 * (Rp + Rs); +} + +// https://belcour.github.io/blog/research/publication/2017/05/01/brdf-thin-film.html +void mx39_fresnel_conductor_phase_polarized(float cosTheta, float eta1, vec3 eta2, vec3 kappa2, out vec3 phiP, out vec3 phiS) +{ + vec3 k2 = kappa2 / eta2; + vec3 sinThetaSqr = vec3(1.0) - cosTheta * cosTheta; + vec3 A = eta2*eta2*(vec3(1.0)-k2*k2) - eta1*eta1*sinThetaSqr; + vec3 B = sqrt(A*A + mx_square(2.0*eta2*eta2*k2)); + vec3 U = sqrt((A+B)/2.0); + vec3 V = max(vec3(0.0), sqrt((B-A)/2.0)); + + phiS = atan(2.0*eta1*V*cosTheta, U*U + V*V - mx_square(eta1*cosTheta)); + phiP = atan(2.0*eta1*eta2*eta2*cosTheta * (2.0*k2*U - (vec3(1.0)-k2*k2) * V), + mx_square(eta2*eta2*(vec3(1.0)+k2*k2)*cosTheta) - eta1*eta1*(U*U+V*V)); +} + +// A Practical Extension to Microfacet Theory for the Modeling of Varying Iridescence +// https://belcour.github.io/blog/research/publication/2017/05/01/brdf-thin-film.html +vec3 mx39_fresnel_airy(float cosTheta, Mx39FresnelData fd) +{ + // XYZ to CIE 1931 RGB color space (using neutral E illuminant) + const mat3 XYZ_TO_RGB = mat3(2.3706743, -0.5138850, 0.0052982, -0.9000405, 1.4253036, -0.0146949, -0.4706338, 0.0885814, 1.0093968); + + // Assume vacuum on the outside + float eta1 = 1.0; + float eta2 = max(fd.tf_ior, eta1); + vec3 eta3 = (fd.model == MX39_FRESNEL_MODEL_SCHLICK) ? mx39_f0_to_ior(fd.F0) : fd.ior; + vec3 kappa3 = (fd.model == MX39_FRESNEL_MODEL_SCHLICK) ? vec3(0.0) : fd.extinction; + float cosThetaT = sqrt(1.0 - (1.0 - mx_square(cosTheta)) * mx_square(eta1 / eta2)); + + // First interface + vec2 R12 = mx39_fresnel_dielectric_polarized(cosTheta, eta2 / eta1); + if (cosThetaT <= 0.0) + { + // Total internal reflection + R12 = vec2(1.0); + } + vec2 T121 = vec2(1.0) - R12; + + // Second interface + vec3 R23p, R23s; + if (fd.model == MX39_FRESNEL_MODEL_SCHLICK) + { + vec3 f = mx39_fresnel_hoffman_schlick(cosThetaT, fd); + R23p = 0.5 * f; + R23s = 0.5 * f; + } + else + { + mx39_fresnel_conductor_polarized(cosThetaT, eta3 / eta2, kappa3 / eta2, R23p, R23s); + } + + // Phase shift + float cosB = cos(atan(eta2 / eta1)); + vec2 phi21 = vec2(cosTheta < cosB ? 0.0 : M_PI, M_PI); + vec3 phi23p, phi23s; + if (fd.model == MX39_FRESNEL_MODEL_SCHLICK) + { + phi23p = vec3((eta3[0] < eta2) ? M_PI : 0.0, + (eta3[1] < eta2) ? M_PI : 0.0, + (eta3[2] < eta2) ? M_PI : 0.0); + phi23s = phi23p; + } + else + { + mx39_fresnel_conductor_phase_polarized(cosThetaT, eta2, eta3, kappa3, phi23p, phi23s); + } + vec3 r123p = max(sqrt(R12.x*R23p), 0.0); + vec3 r123s = max(sqrt(R12.y*R23s), 0.0); + + // Iridescence term + vec3 I = vec3(0.0); + vec3 Cm, Sm; + + // Optical path difference + float distMeters = fd.tf_thickness * 1.0e-9; + float opd = 2.0 * eta2 * cosThetaT * distMeters; + + // Iridescence term using spectral antialiasing for Parallel polarization + + // Reflectance term for m=0 (DC term amplitude) + vec3 Rs = (mx_square(T121.x) * R23p) / (vec3(1.0) - R12.x*R23p); + I += R12.x + Rs; + + // Reflectance term for m>0 (pairs of diracs) + Cm = Rs - T121.x; + for (int m=1; m<=2; m++) + { + Cm *= r123p; + Sm = 2.0 * mx_eval_sensitivity(float(m) * opd, float(m)*(phi23p+vec3(phi21.x))); + I += Cm*Sm; + } + + // Iridescence term using spectral antialiasing for Perpendicular polarization + + // Reflectance term for m=0 (DC term amplitude) + vec3 Rp = (mx_square(T121.y) * R23s) / (vec3(1.0) - R12.y*R23s); + I += R12.y + Rp; + + // Reflectance term for m>0 (pairs of diracs) + Cm = Rp - T121.y; + for (int m=1; m<=2; m++) + { + Cm *= r123s; + Sm = 2.0 * mx_eval_sensitivity(float(m) * opd, float(m)*(phi23s+vec3(phi21.y))); + I += Cm*Sm; + } + + // Average parallel and perpendicular polarization + I *= 0.5; + + // Convert back to RGB reflectance + I = clamp(XYZ_TO_RGB * I, 0.0, 1.0); + + return I; +} + +Mx39FresnelData mx39_init_fresnel_dielectric(float ior, float tf_thickness, float tf_ior) +{ + Mx39FresnelData fd; + fd.model = MX39_FRESNEL_MODEL_DIELECTRIC; + fd.airy = tf_thickness > 0.0; + fd.ior = vec3(ior); + fd.extinction = vec3(0.0); + fd.F0 = vec3(0.0); + fd.F82 = vec3(0.0); + fd.F90 = vec3(0.0); + fd.exponent = 0.0; + fd.tf_thickness = tf_thickness; + fd.tf_ior = tf_ior; + fd.refraction = false; + return fd; +} + +Mx39FresnelData mx39_init_fresnel_conductor(vec3 ior, vec3 extinction, float tf_thickness, float tf_ior) +{ + Mx39FresnelData fd; + fd.model = MX39_FRESNEL_MODEL_CONDUCTOR; + fd.airy = tf_thickness > 0.0; + fd.ior = ior; + fd.extinction = extinction; + fd.F0 = vec3(0.0); + fd.F82 = vec3(0.0); + fd.F90 = vec3(0.0); + fd.exponent = 0.0; + fd.tf_thickness = tf_thickness; + fd.tf_ior = tf_ior; + fd.refraction = false; + return fd; +} + +Mx39FresnelData mx39_init_fresnel_schlick(vec3 F0, vec3 F82, vec3 F90, float exponent, float tf_thickness, float tf_ior) +{ + Mx39FresnelData fd; + fd.model = MX39_FRESNEL_MODEL_SCHLICK; + fd.airy = tf_thickness > 0.0; + fd.ior = vec3(0.0); + fd.extinction = vec3(0.0); + fd.F0 = F0; + fd.F82 = F82; + fd.F90 = F90; + fd.exponent = exponent; + fd.tf_thickness = tf_thickness; + fd.tf_ior = tf_ior; + fd.refraction = false; + return fd; +} + +vec3 mx39_compute_fresnel(float cosTheta, Mx39FresnelData fd) +{ + if (fd.airy) + { + return mx39_fresnel_airy(cosTheta, fd); + } + else if (fd.model == MX39_FRESNEL_MODEL_DIELECTRIC) + { + return vec3(mx39_fresnel_dielectric(cosTheta, fd.ior.x)); + } + else if (fd.model == MX39_FRESNEL_MODEL_CONDUCTOR) + { + return mx39_fresnel_conductor(cosTheta, fd.ior, fd.extinction); + } + else + { + return mx39_fresnel_hoffman_schlick(cosTheta, fd); + } +} + +#ifdef MX39_USING_ENVIRONMENT_NONE +vec3 mx39_environment_radiance(vec3 N, vec3 V, vec3 X, vec2 alpha, int distribution, Mx39FresnelData fd) +{ + return vec3(0.0); +} +#endif + +#ifdef MX39_USING_ENVIRONMENT_PREFILTER +vec3 mx39_environment_radiance(vec3 N, vec3 V, vec3 X, vec2 alpha, int distribution, Mx39FresnelData fd) +{ + N = mx_forward_facing_normal(N, V); + vec3 L = fd.refraction ? mx_refraction_solid_sphere(-V, N, fd.ior.x) : -reflect(V, N); + + float NdotV = clamp(dot(N, V), M_FLOAT_EPS, 1.0); + + float avgAlpha = mx_average_alpha(alpha); + vec3 F = mx39_compute_fresnel(NdotV, fd); + float G = mx_ggx_smith_G2(NdotV, NdotV, avgAlpha); + vec3 FG = fd.refraction ? vec3(1.0) - (F * G) : F * G; + + vec3 Li = mx_latlong_map_lookup(L, $envMatrix, mx_latlong_alpha_to_lod(avgAlpha), $envRadiance); + return Li * FG * $envLightIntensity; +} +#endif + +#ifdef MX39_USING_ENVIRONMENT_FIS +vec3 mx39_environment_radiance(vec3 N, vec3 V, vec3 X, vec2 alpha, int distribution, Mx39FresnelData fd) +{ + // Generate tangent frame. + X = normalize(X - dot(X, N) * N); + vec3 Y = cross(N, X); + mat3 tangentToWorld = mat3(X, Y, N); + + // Transform the view vector to tangent space. + V = vec3(dot(V, X), dot(V, Y), dot(V, N)); + + // Compute derived properties. + float NdotV = clamp(V.z, M_FLOAT_EPS, 1.0); + float avgAlpha = mx_average_alpha(alpha); + float G1V = mx_ggx_smith_G1(NdotV, avgAlpha); + + // Integrate outgoing radiance using filtered importance sampling. + // http://cgg.mff.cuni.cz/~jaroslav/papers/2008-egsr-fis/2008-egsr-fis-final-embedded.pdf + vec3 radiance = vec3(0.0); + int envRadianceSamples = $envRadianceSamples; + for (int i = 0; i < envRadianceSamples; i++) + { + vec2 Xi = mx_spherical_fibonacci(i, envRadianceSamples); + + // Compute the half vector and incoming light direction. + vec3 H = mx_ggx_importance_sample_VNDF(Xi, V, alpha); + vec3 L = fd.refraction ? mx_refraction_solid_sphere(-V, H, fd.ior.x) : -reflect(V, H); + + // Compute dot products for this sample. + float NdotL = clamp(L.z, M_FLOAT_EPS, 1.0); + float VdotH = clamp(dot(V, H), M_FLOAT_EPS, 1.0); + + // Sample the environment light from the given direction. + vec3 Lw = tangentToWorld * L; + float pdf = mx_ggx_NDF(H, alpha) * G1V / (4.0 * NdotV); + float lod = mx_latlong_compute_lod(Lw, pdf, float($envRadianceMips - 1), envRadianceSamples); + vec3 sampleColor = mx_latlong_map_lookup(Lw, $envMatrix, lod, $envRadiance); + + // Compute the Fresnel term. + vec3 F = mx39_compute_fresnel(VdotH, fd); + + // Compute the geometric term. + float G = mx_ggx_smith_G2(NdotL, NdotV, avgAlpha); + + // Compute the combined FG term, which is inverted for refraction. + vec3 FG = fd.refraction ? vec3(1.0) - (F * G) : F * G; + + // Add the radiance contribution of this sample. + // From https://cdn2.unrealengine.com/Resources/files/2013SiggraphPresentationsNotes-26915738.pdf + // incidentLight = sampleColor * NdotL + // microfacetSpecular = D * F * G / (4 * NdotL * NdotV) + // pdf = D * G1V / (4 * NdotV); + // radiance = incidentLight * microfacetSpecular / pdf + radiance += sampleColor * FG; + } + + // Apply the global component of the geometric term and normalize. + radiance /= G1V * float(envRadianceSamples); + + // Return the final radiance. + return radiance * $envLightIntensity; +} +#endif + +#ifdef MX39_USING_TRANSMISSION_OPACITY +vec3 mx39_surface_transmission(vec3 N, vec3 V, vec3 X, vec2 alpha, int distribution, Mx39FresnelData fd, vec3 tint) +{ + return tint; +} +#endif + +#ifdef MX39_USING_TRANSMISSION_REFRACT +vec3 mx39_surface_transmission(vec3 N, vec3 V, vec3 X, vec2 alpha, int distribution, Mx39FresnelData fd, vec3 tint) +{ + // Approximate the appearance of surface transmission as glossy + // environment map refraction, ignoring any scene geometry that might + // be visible through the surface. + fd.refraction = true; + if ($refractionTwoSided) + { + tint = mx_square(tint); + } + return mx39_environment_radiance(N, V, X, alpha, distribution, fd) * tint; +} +#endif diff --git a/libraries/pbrlib/genglsl/lib/mx_environment_fis.glsl b/libraries/pbrlib/genglsl/lib/mx_environment_fis.glsl index 575991e28d..6bfc64571e 100644 --- a/libraries/pbrlib/genglsl/lib/mx_environment_fis.glsl +++ b/libraries/pbrlib/genglsl/lib/mx_environment_fis.glsl @@ -1,15 +1,5 @@ #include "mx_microfacet_specular.glsl" -// https://developer.nvidia.com/gpugems/GPUGems3/gpugems3_ch20.html -// Section 20.4 Equation 13 -float mx_latlong_compute_lod(vec3 dir, float pdf, float maxMipLevel, int envSamples) -{ - const float MIP_LEVEL_OFFSET = 1.5; - float effectiveMaxMipLevel = maxMipLevel - MIP_LEVEL_OFFSET; - float distortion = sqrt(1.0 - mx_square(dir.y)); - return max(effectiveMaxMipLevel - 0.5 * log2(float(envSamples) * pdf * distortion), 0.0); -} - vec3 mx_environment_radiance(vec3 N, vec3 V, vec3 X, vec2 alpha, int distribution, FresnelData fd) { // Generate tangent frame. @@ -69,10 +59,13 @@ vec3 mx_environment_radiance(vec3 N, vec3 V, vec3 X, vec2 alpha, int distributio radiance /= G1V * float(envRadianceSamples); // Return the final radiance. - return radiance; + return radiance * $envLightIntensity; } vec3 mx_environment_irradiance(vec3 N) { - return mx_latlong_map_lookup(N, $envMatrix, 0.0, $envIrradiance); + vec3 Li = mx_latlong_map_lookup(N, $envMatrix, 0.0, $envIrradiance); + return Li * $envLightIntensity; } + +#define MX39_USING_ENVIRONMENT_FIS diff --git a/libraries/pbrlib/genglsl/lib/mx_environment_none.glsl b/libraries/pbrlib/genglsl/lib/mx_environment_none.glsl index f0a1da5989..f535c84757 100644 --- a/libraries/pbrlib/genglsl/lib/mx_environment_none.glsl +++ b/libraries/pbrlib/genglsl/lib/mx_environment_none.glsl @@ -9,3 +9,5 @@ vec3 mx_environment_irradiance(vec3 N) { return vec3(0.0); } + +#define MX39_USING_ENVIRONMENT_NONE diff --git a/libraries/pbrlib/genglsl/lib/mx_environment_prefilter.glsl b/libraries/pbrlib/genglsl/lib/mx_environment_prefilter.glsl index 6def6fb439..89e898a1e1 100644 --- a/libraries/pbrlib/genglsl/lib/mx_environment_prefilter.glsl +++ b/libraries/pbrlib/genglsl/lib/mx_environment_prefilter.glsl @@ -1,10 +1,10 @@ #include "mx_microfacet_specular.glsl" -float mx_latlong_compute_lod(float alpha) +// Return the mip level associated with the given alpha in a prefiltered environment. +float mx_latlong_alpha_to_lod(float alpha) { - // Select a mip level based on input alpha. - float lodBias = alpha < 0.25 ? sqrt(alpha) : 0.5*alpha + 0.375; - return lodBias * float($envRadianceMips); + float lodBias = (alpha < 0.25) ? sqrt(alpha) : 0.5 * alpha + 0.375; + return lodBias * float($envRadianceMips - 1); } vec3 mx_environment_radiance(vec3 N, vec3 V, vec3 X, vec2 alpha, int distribution, FresnelData fd) @@ -19,11 +19,14 @@ vec3 mx_environment_radiance(vec3 N, vec3 V, vec3 X, vec2 alpha, int distributio float G = mx_ggx_smith_G2(NdotV, NdotV, avgAlpha); vec3 FG = fd.refraction ? vec3(1.0) - (F * G) : F * G; - vec3 Li = mx_latlong_map_lookup(L, $envMatrix, mx_latlong_compute_lod(avgAlpha), $envRadiance); - return Li * FG; + vec3 Li = mx_latlong_map_lookup(L, $envMatrix, mx_latlong_alpha_to_lod(avgAlpha), $envRadiance); + return Li * FG * $envLightIntensity; } vec3 mx_environment_irradiance(vec3 N) { - return mx_latlong_map_lookup(N, $envMatrix, 0.0, $envIrradiance); + vec3 Li = mx_latlong_map_lookup(N, $envMatrix, 0.0, $envIrradiance); + return Li * $envLightIntensity; } + +#define MX39_USING_ENVIRONMENT_PREFILTER diff --git a/libraries/pbrlib/genglsl/lib/mx_table.glsl b/libraries/pbrlib/genglsl/lib/mx_generate_albedo_table.glsl similarity index 100% rename from libraries/pbrlib/genglsl/lib/mx_table.glsl rename to libraries/pbrlib/genglsl/lib/mx_generate_albedo_table.glsl diff --git a/libraries/pbrlib/genglsl/lib/mx_generate_prefilter_env.glsl b/libraries/pbrlib/genglsl/lib/mx_generate_prefilter_env.glsl new file mode 100644 index 0000000000..41bf33aae3 --- /dev/null +++ b/libraries/pbrlib/genglsl/lib/mx_generate_prefilter_env.glsl @@ -0,0 +1,78 @@ +#include "mx_microfacet_specular.glsl" + +// Construct an orthonormal basis from a unit vector. +// https://graphics.pixar.com/library/OrthonormalB/paper.pdf +mat3 mx_orthonormal_basis(vec3 N) +{ + float sign = (N.z < 0.0) ? -1.0 : 1.0; + float a = -1.0 / (sign + N.z); + float b = N.x * N.y * a; + vec3 X = vec3(1.0 + sign * N.x * N.x * a, sign * b, -sign * N.x); + vec3 Y = vec3(b, sign + N.y * N.y * a, -N.y); + return mat3(X, Y, N); +} + +// Return the alpha associated with the given mip level in a prefiltered environment. +float mx_latlong_lod_to_alpha(float lod) +{ + float lodBias = lod / float($envRadianceMips - 1); + return (lodBias < 0.5) ? mx_square(lodBias) : 2.0 * (lodBias - 0.375); +} + +// The inverse of mx_latlong_projection. +vec3 mx_latlong_map_projection_inverse(vec2 uv) +{ + float latitude = (uv.y - 0.5) * M_PI; + float longitude = (uv.x - 0.5) * M_PI * 2.0; + + float x = -cos(latitude) * sin(longitude); + float y = -sin(latitude); + float z = cos(latitude) * cos(longitude); + + return vec3(x, y, z); +} + +vec3 mx_generate_prefilter_env() +{ + // The tangent view vector is aligned with the normal. + vec3 V = vec3(0.0, 0.0, 1.0); + float NdotV = 1.0; + + // Compute derived properties. + vec2 uv = gl_FragCoord.xy * pow(2.0, $envPrefilterMip) / vec2(textureSize($envRadiance, 0)); + vec3 worldN = mx_latlong_map_projection_inverse(uv); + mat3 tangentToWorld = mx_orthonormal_basis(worldN); + float alpha = mx_latlong_lod_to_alpha(float($envPrefilterMip)); + float G1V = mx_ggx_smith_G1(NdotV, alpha); + + // Integrate the LD term for the given environment and alpha. + vec3 radiance = vec3(0.0, 0.0, 0.0); + float weight = 0.0; + int envRadianceSamples = 1024; + for (int i = 0; i < envRadianceSamples; i++) + { + vec2 Xi = mx_spherical_fibonacci(i, envRadianceSamples); + + // Compute the half vector and incoming light direction. + vec3 H = mx_ggx_importance_sample_VNDF(Xi, V, vec2(alpha)); + vec3 L = -V + 2.0 * H.z * H; + + // Compute dot products for this sample. + float NdotL = clamp(L.z, M_FLOAT_EPS, 1.0); + + // Compute the geometric term. + float G = mx_ggx_smith_G2(NdotL, NdotV, alpha); + + // Sample the environment light from the given direction. + vec3 Lw = tangentToWorld * L; + float pdf = mx_ggx_NDF(H, vec2(alpha)) * G1V / (4.0 * NdotV); + float lod = mx_latlong_compute_lod(Lw, pdf, float($envRadianceMips - 1), envRadianceSamples); + vec3 sampleColor = mx_latlong_map_lookup(Lw, $envMatrix, lod, $envRadiance); + + // Add the radiance contribution of this sample. + radiance += G * sampleColor; + weight += G; + } + + return radiance / weight; +} diff --git a/libraries/pbrlib/genglsl/lib/mx_microfacet_specular.glsl b/libraries/pbrlib/genglsl/lib/mx_microfacet_specular.glsl index 63aba17869..ddbc3f6f95 100644 --- a/libraries/pbrlib/genglsl/lib/mx_microfacet_specular.glsl +++ b/libraries/pbrlib/genglsl/lib/mx_microfacet_specular.glsl @@ -593,3 +593,14 @@ vec3 mx_latlong_map_lookup(vec3 dir, mat4 transform, float lod, sampler2D envSam vec2 uv = mx_latlong_projection(envDir); return textureLod(envSampler, uv, lod).rgb; } + +// Return the mip level with the appropriate coverage for a filtered importance sample. +// https://developer.nvidia.com/gpugems/GPUGems3/gpugems3_ch20.html +// Section 20.4 Equation 13 +float mx_latlong_compute_lod(vec3 dir, float pdf, float maxMipLevel, int envSamples) +{ + const float MIP_LEVEL_OFFSET = 1.5; + float effectiveMaxMipLevel = maxMipLevel - MIP_LEVEL_OFFSET; + float distortion = sqrt(1.0 - mx_square(dir.y)); + return max(effectiveMaxMipLevel - 0.5 * log2(float(envSamples) * pdf * distortion), 0.0); +} diff --git a/libraries/pbrlib/genglsl/lib/mx_transmission_opacity.glsl b/libraries/pbrlib/genglsl/lib/mx_transmission_opacity.glsl index 2861d06194..54bef92ff4 100644 --- a/libraries/pbrlib/genglsl/lib/mx_transmission_opacity.glsl +++ b/libraries/pbrlib/genglsl/lib/mx_transmission_opacity.glsl @@ -4,3 +4,5 @@ vec3 mx_surface_transmission(vec3 N, vec3 V, vec3 X, vec2 alpha, int distributio { return tint; } + +#define MX39_USING_TRANSMISSION_OPACITY diff --git a/libraries/pbrlib/genglsl/lib/mx_transmission_refract.glsl b/libraries/pbrlib/genglsl/lib/mx_transmission_refract.glsl index 64e496a384..4493321b4b 100644 --- a/libraries/pbrlib/genglsl/lib/mx_transmission_refract.glsl +++ b/libraries/pbrlib/genglsl/lib/mx_transmission_refract.glsl @@ -12,3 +12,5 @@ vec3 mx_surface_transmission(vec3 N, vec3 V, vec3 X, vec2 alpha, int distributio } return mx_environment_radiance(N, V, X, alpha, distribution, fd) * tint; } + +#define MX39_USING_TRANSMISSION_REFRACT diff --git a/libraries/pbrlib/genglsl/mx39_compensating_oren_nayar_diffuse_bsdf.glsl b/libraries/pbrlib/genglsl/mx39_compensating_oren_nayar_diffuse_bsdf.glsl new file mode 100644 index 0000000000..b93b5b8cd0 --- /dev/null +++ b/libraries/pbrlib/genglsl/mx39_compensating_oren_nayar_diffuse_bsdf.glsl @@ -0,0 +1,42 @@ +#include "lib/mx39_microfacet_diffuse.glsl" + +void mx39_compensating_oren_nayar_diffuse_bsdf_reflection(vec3 L, vec3 V, vec3 P, float occlusion, float weight, vec3 color, float roughness, vec3 normal, bool energy_compensation, inout BSDF bsdf) +{ + bsdf.throughput = vec3(0.0); + + if (weight < M_FLOAT_EPS) + { + return; + } + + normal = mx_forward_facing_normal(normal, V); + + float NdotV = clamp(dot(normal, V), M_FLOAT_EPS, 1.0); + float NdotL = clamp(dot(normal, L), M_FLOAT_EPS, 1.0); + float LdotV = clamp(dot(L, V), M_FLOAT_EPS, 1.0); + + vec3 diffuse = energy_compensation ? + mx39_oren_nayar_compensated_diffuse(NdotV, NdotL, LdotV, roughness, color) : + mx39_oren_nayar_diffuse(NdotV, NdotL, LdotV, roughness) * color; + bsdf.response = diffuse * occlusion * weight * NdotL * M_PI_INV; +} + +void mx39_compensating_oren_nayar_diffuse_bsdf_indirect(vec3 V, float weight, vec3 color, float roughness, vec3 normal, bool energy_compensation, inout BSDF bsdf) +{ + bsdf.throughput = vec3(0.0); + + if (weight < M_FLOAT_EPS) + { + return; + } + + normal = mx_forward_facing_normal(normal, V); + + float NdotV = clamp(dot(normal, V), M_FLOAT_EPS, 1.0); + + vec3 diffuse = energy_compensation ? + mx39_oren_nayar_compensated_diffuse_dir_albedo(NdotV, roughness, color) : + mx39_oren_nayar_diffuse_dir_albedo(NdotV, roughness) * color; + vec3 Li = mx_environment_irradiance(normal); + bsdf.response = Li * diffuse * weight; +} diff --git a/libraries/pbrlib/genglsl/mx39_dielectric_tf_bsdf.glsl b/libraries/pbrlib/genglsl/mx39_dielectric_tf_bsdf.glsl new file mode 100644 index 0000000000..3dc668c4fa --- /dev/null +++ b/libraries/pbrlib/genglsl/mx39_dielectric_tf_bsdf.glsl @@ -0,0 +1,92 @@ +#include "lib/mx39_microfacet_specular.glsl" + +void mx39_dielectric_tf_bsdf_reflection(vec3 L, vec3 V, vec3 P, float occlusion, float weight, vec3 tint, float ior, vec2 roughness, float thinfilm_thickness, float thinfilm_ior, vec3 N, vec3 X, int distribution, int scatter_mode, inout BSDF bsdf) +{ + if (weight < M_FLOAT_EPS) + { + return; + } + + N = mx_forward_facing_normal(N, V); + + X = normalize(X - dot(X, N) * N); + vec3 Y = cross(N, X); + vec3 H = normalize(L + V); + + float NdotL = clamp(dot(N, L), M_FLOAT_EPS, 1.0); + float NdotV = clamp(dot(N, V), M_FLOAT_EPS, 1.0); + float VdotH = clamp(dot(V, H), M_FLOAT_EPS, 1.0); + + vec2 safeAlpha = clamp(roughness, M_FLOAT_EPS, 1.0); + float avgAlpha = mx_average_alpha(safeAlpha); + vec3 Ht = vec3(dot(H, X), dot(H, Y), dot(H, N)); + + vec3 safeTint = max(tint, 0.0); + Mx39FresnelData fd = mx39_init_fresnel_dielectric(ior, thinfilm_thickness, thinfilm_ior); + vec3 F = mx39_compute_fresnel(VdotH, fd); + float D = mx_ggx_NDF(Ht, safeAlpha); + float G = mx_ggx_smith_G2(NdotL, NdotV, avgAlpha); + + float F0 = mx39_ior_to_f0(ior); + vec3 comp = mx_ggx_energy_compensation(NdotV, avgAlpha, F); + vec3 dirAlbedo = mx_ggx_dir_albedo(NdotV, avgAlpha, F0, 1.0) * comp; + bsdf.throughput = 1.0 - dirAlbedo * weight; + + // Note: NdotL is cancelled out + bsdf.response = D * F * G * comp * safeTint * occlusion * weight / (4.0 * NdotV); +} + +void mx39_dielectric_tf_bsdf_transmission(vec3 V, float weight, vec3 tint, float ior, vec2 roughness, float thinfilm_thickness, float thinfilm_ior, vec3 N, vec3 X, int distribution, int scatter_mode, inout BSDF bsdf) +{ + if (weight < M_FLOAT_EPS) + { + return; + } + + N = mx_forward_facing_normal(N, V); + float NdotV = clamp(dot(N, V), M_FLOAT_EPS, 1.0); + + vec3 safeTint = max(tint, 0.0); + Mx39FresnelData fd = mx39_init_fresnel_dielectric(ior, thinfilm_thickness, thinfilm_ior); + vec3 F = mx39_compute_fresnel(NdotV, fd); + + vec2 safeAlpha = clamp(roughness, M_FLOAT_EPS, 1.0); + float avgAlpha = mx_average_alpha(safeAlpha); + + float F0 = mx39_ior_to_f0(ior); + vec3 comp = mx_ggx_energy_compensation(NdotV, avgAlpha, F); + vec3 dirAlbedo = mx_ggx_dir_albedo(NdotV, avgAlpha, F0, 1.0) * comp; + bsdf.throughput = 1.0 - dirAlbedo * weight; + + if (scatter_mode != 0) + { + bsdf.response = mx39_surface_transmission(N, V, X, safeAlpha, distribution, fd, safeTint) * weight; + } +} + +void mx39_dielectric_tf_bsdf_indirect(vec3 V, float weight, vec3 tint, float ior, vec2 roughness, float thinfilm_thickness, float thinfilm_ior, vec3 N, vec3 X, int distribution, int scatter_mode, inout BSDF bsdf) +{ + if (weight < M_FLOAT_EPS) + { + return; + } + + N = mx_forward_facing_normal(N, V); + + float NdotV = clamp(dot(N, V), M_FLOAT_EPS, 1.0); + + vec3 safeTint = max(tint, 0.0); + Mx39FresnelData fd = mx39_init_fresnel_dielectric(ior, thinfilm_thickness, thinfilm_ior); + vec3 F = mx39_compute_fresnel(NdotV, fd); + + vec2 safeAlpha = clamp(roughness, M_FLOAT_EPS, 1.0); + float avgAlpha = mx_average_alpha(safeAlpha); + + float F0 = mx39_ior_to_f0(ior); + vec3 comp = mx_ggx_energy_compensation(NdotV, avgAlpha, F); + vec3 dirAlbedo = mx_ggx_dir_albedo(NdotV, avgAlpha, F0, 1.0) * comp; + bsdf.throughput = 1.0 - dirAlbedo * weight; + + vec3 Li = mx39_environment_radiance(N, V, X, safeAlpha, distribution, fd); + bsdf.response = Li * safeTint * comp * weight; +} diff --git a/libraries/pbrlib/genglsl/mx39_generalized_schlick_tf_82_bsdf.glsl b/libraries/pbrlib/genglsl/mx39_generalized_schlick_tf_82_bsdf.glsl new file mode 100644 index 0000000000..512245784a --- /dev/null +++ b/libraries/pbrlib/genglsl/mx39_generalized_schlick_tf_82_bsdf.glsl @@ -0,0 +1,98 @@ +#include "lib/mx39_microfacet_specular.glsl" + +void mx39_generalized_schlick_tf_82_bsdf_reflection(vec3 L, vec3 V, vec3 P, float occlusion, float weight, vec3 color0, vec3 color82, vec3 color90, float exponent, vec2 roughness, float thinfilm_thickness, float thinfilm_ior, vec3 N, vec3 X, int distribution, int scatter_mode, inout BSDF bsdf) +{ + if (weight < M_FLOAT_EPS) + { + return; + } + + N = mx_forward_facing_normal(N, V); + + X = normalize(X - dot(X, N) * N); + vec3 Y = cross(N, X); + vec3 H = normalize(L + V); + + float NdotL = clamp(dot(N, L), M_FLOAT_EPS, 1.0); + float NdotV = clamp(dot(N, V), M_FLOAT_EPS, 1.0); + float VdotH = clamp(dot(V, H), M_FLOAT_EPS, 1.0); + + vec2 safeAlpha = clamp(roughness, M_FLOAT_EPS, 1.0); + float avgAlpha = mx_average_alpha(safeAlpha); + vec3 Ht = vec3(dot(H, X), dot(H, Y), dot(H, N)); + + vec3 safeColor0 = max(color0, 0.0); + vec3 safeColor82 = max(color82, 0.0); + vec3 safeColor90 = max(color90, 0.0); + Mx39FresnelData fd = mx39_init_fresnel_schlick(safeColor0, safeColor82, safeColor90, exponent, thinfilm_thickness, thinfilm_ior); + vec3 F = mx39_compute_fresnel(VdotH, fd); + float D = mx_ggx_NDF(Ht, safeAlpha); + float G = mx_ggx_smith_G2(NdotL, NdotV, avgAlpha); + + vec3 comp = mx_ggx_energy_compensation(NdotV, avgAlpha, F); + vec3 dirAlbedo = mx_ggx_dir_albedo(NdotV, avgAlpha, safeColor0, safeColor90) * comp; + float avgDirAlbedo = dot(dirAlbedo, vec3(1.0 / 3.0)); + bsdf.throughput = vec3(1.0 - avgDirAlbedo * weight); + + // Note: NdotL is cancelled out + bsdf.response = D * F * G * comp * occlusion * weight / (4.0 * NdotV); +} + +void mx39_generalized_schlick_tf_82_bsdf_transmission(vec3 V, float weight, vec3 color0, vec3 color82, vec3 color90, float exponent, vec2 roughness, float thinfilm_thickness, float thinfilm_ior, vec3 N, vec3 X, int distribution, int scatter_mode, inout BSDF bsdf) +{ + if (weight < M_FLOAT_EPS) + { + return; + } + + N = mx_forward_facing_normal(N, V); + float NdotV = clamp(dot(N, V), M_FLOAT_EPS, 1.0); + + vec3 safeColor0 = max(color0, 0.0); + vec3 safeColor82 = max(color82, 0.0); + vec3 safeColor90 = max(color90, 0.0); + Mx39FresnelData fd = mx39_init_fresnel_schlick(safeColor0, safeColor82, safeColor90, exponent, thinfilm_thickness, thinfilm_ior); + vec3 F = mx39_compute_fresnel(NdotV, fd); + + vec2 safeAlpha = clamp(roughness, M_FLOAT_EPS, 1.0); + float avgAlpha = mx_average_alpha(safeAlpha); + + vec3 comp = mx_ggx_energy_compensation(NdotV, avgAlpha, F); + vec3 dirAlbedo = mx_ggx_dir_albedo(NdotV, avgAlpha, safeColor0, safeColor90) * comp; + float avgDirAlbedo = dot(dirAlbedo, vec3(1.0 / 3.0)); + bsdf.throughput = vec3(1.0 - avgDirAlbedo * weight); + + if (scatter_mode != 0) + { + float avgF0 = dot(safeColor0, vec3(1.0 / 3.0)); + fd.ior = vec3(mx39_f0_to_ior(avgF0)); + bsdf.response = mx39_surface_transmission(N, V, X, safeAlpha, distribution, fd, safeColor0) * weight; + } +} + +void mx39_generalized_schlick_tf_82_bsdf_indirect(vec3 V, float weight, vec3 color0, vec3 color82, vec3 color90, float exponent, vec2 roughness, float thinfilm_thickness, float thinfilm_ior, vec3 N, vec3 X, int distribution, int scatter_mode, inout BSDF bsdf) +{ + if (weight < M_FLOAT_EPS) + { + return; + } + + N = mx_forward_facing_normal(N, V); + float NdotV = clamp(dot(N, V), M_FLOAT_EPS, 1.0); + + vec3 safeColor0 = max(color0, 0.0); + vec3 safeColor82 = max(color82, 0.0); + vec3 safeColor90 = max(color90, 0.0); + Mx39FresnelData fd = mx39_init_fresnel_schlick(safeColor0, safeColor82, safeColor90, exponent, thinfilm_thickness, thinfilm_ior); + vec3 F = mx39_compute_fresnel(NdotV, fd); + + vec2 safeAlpha = clamp(roughness, M_FLOAT_EPS, 1.0); + float avgAlpha = mx_average_alpha(safeAlpha); + vec3 comp = mx_ggx_energy_compensation(NdotV, avgAlpha, F); + vec3 dirAlbedo = mx_ggx_dir_albedo(NdotV, avgAlpha, safeColor0, safeColor90) * comp; + float avgDirAlbedo = dot(dirAlbedo, vec3(1.0 / 3.0)); + bsdf.throughput = vec3(1.0 - avgDirAlbedo * weight); + + vec3 Li = mx39_environment_radiance(N, V, X, safeAlpha, distribution, fd); + bsdf.response = Li * comp * weight; +} diff --git a/libraries/pbrlib/genglsl/mx39_pbrlib_genglsl_impl.mtlx b/libraries/pbrlib/genglsl/mx39_pbrlib_genglsl_impl.mtlx new file mode 100644 index 0000000000..3626896222 --- /dev/null +++ b/libraries/pbrlib/genglsl/mx39_pbrlib_genglsl_impl.mtlx @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + diff --git a/libraries/pbrlib/genglsl/mx39_sheen_zeltner_bsdf.glsl b/libraries/pbrlib/genglsl/mx39_sheen_zeltner_bsdf.glsl new file mode 100644 index 0000000000..c6a874a5da --- /dev/null +++ b/libraries/pbrlib/genglsl/mx39_sheen_zeltner_bsdf.glsl @@ -0,0 +1,38 @@ +#include "lib/mx39_microfacet_sheen.glsl" + +void mx39_sheen_zeltner_bsdf_reflection(vec3 L, vec3 V, vec3 P, float occlusion, float weight, vec3 color, float roughness, vec3 N, inout BSDF bsdf) +{ + if (weight < M_FLOAT_EPS) + { + return; + } + + N = mx_forward_facing_normal(N, V); + float NdotV = clamp(dot(N, V), M_FLOAT_EPS, 1.0); + + roughness = clamp(roughness, 0.01, 1.0); // Clamp to range of original impl. + + vec3 fr = color * mx39_zeltner_sheen_brdf(L, V, N, NdotV, roughness); + float dirAlbedo = mx39_zeltner_sheen_dir_albedo(NdotV, roughness); + bsdf.throughput = vec3(1.0 - dirAlbedo * weight); + bsdf.response = dirAlbedo * fr * occlusion * weight; +} + +void mx39_sheen_zeltner_bsdf_indirect(vec3 V, float weight, vec3 color, float roughness, vec3 N, inout BSDF bsdf) +{ + if (weight < M_FLOAT_EPS) + { + return; + } + + N = mx_forward_facing_normal(N, V); + float NdotV = clamp(dot(N, V), M_FLOAT_EPS, 1.0); + + float dirAlbedo; + roughness = clamp(roughness, 0.01, 1.0); // Clamp to range of original impl. + dirAlbedo = mx39_zeltner_sheen_dir_albedo(NdotV, roughness); + + vec3 Li = mx_environment_irradiance(N); + bsdf.throughput = vec3(1.0 - dirAlbedo * weight); + bsdf.response = Li * color * dirAlbedo * weight; +} diff --git a/libraries/pbrlib/genglsl/mx_dielectric_bsdf.glsl b/libraries/pbrlib/genglsl/mx_dielectric_bsdf.glsl index dcaaadf1fa..d8bc1ba637 100644 --- a/libraries/pbrlib/genglsl/mx_dielectric_bsdf.glsl +++ b/libraries/pbrlib/genglsl/mx_dielectric_bsdf.glsl @@ -22,6 +22,7 @@ void mx_dielectric_bsdf_reflection(vec3 L, vec3 V, vec3 P, float occlusion, floa vec3 Ht = vec3(dot(H, X), dot(H, Y), dot(H, N)); FresnelData fd; + vec3 safeTint = max(tint, 0.0); if (bsdf.thickness > 0.0) { fd = mx_init_fresnel_dielectric_airy(ior, bsdf.thickness, bsdf.ior); @@ -40,7 +41,7 @@ void mx_dielectric_bsdf_reflection(vec3 L, vec3 V, vec3 P, float occlusion, floa bsdf.throughput = 1.0 - dirAlbedo * weight; // Note: NdotL is cancelled out - bsdf.response = D * F * G * comp * tint * occlusion * weight / (4.0 * NdotV); + bsdf.response = D * F * G * comp * safeTint * occlusion * weight / (4.0 * NdotV); } void mx_dielectric_bsdf_transmission(vec3 V, float weight, vec3 tint, float ior, vec2 roughness, vec3 N, vec3 X, int distribution, int scatter_mode, inout BSDF bsdf) @@ -54,6 +55,7 @@ void mx_dielectric_bsdf_transmission(vec3 V, float weight, vec3 tint, float ior, float NdotV = clamp(dot(N, V), M_FLOAT_EPS, 1.0); FresnelData fd; + vec3 safeTint = max(tint, 0.0); if (bsdf.thickness > 0.0) { fd = mx_init_fresnel_dielectric_airy(ior, bsdf.thickness, bsdf.ior); @@ -74,7 +76,7 @@ void mx_dielectric_bsdf_transmission(vec3 V, float weight, vec3 tint, float ior, if (scatter_mode != 0) { - bsdf.response = mx_surface_transmission(N, V, X, safeAlpha, distribution, fd, tint) * weight; + bsdf.response = mx_surface_transmission(N, V, X, safeAlpha, distribution, fd, safeTint) * weight; } } @@ -90,6 +92,7 @@ void mx_dielectric_bsdf_indirect(vec3 V, float weight, vec3 tint, float ior, vec float NdotV = clamp(dot(N, V), M_FLOAT_EPS, 1.0); FresnelData fd; + vec3 safeTint = max(tint, 0.0); if (bsdf.thickness > 0.0) { fd = mx_init_fresnel_dielectric_airy(ior, bsdf.thickness, bsdf.ior); @@ -109,5 +112,5 @@ void mx_dielectric_bsdf_indirect(vec3 V, float weight, vec3 tint, float ior, vec bsdf.throughput = 1.0 - dirAlbedo * weight; vec3 Li = mx_environment_radiance(N, V, X, safeAlpha, distribution, fd); - bsdf.response = Li * tint * comp * weight; + bsdf.response = Li * safeTint * comp * weight; } diff --git a/libraries/pbrlib/genglsl/mx_generalized_schlick_bsdf.glsl b/libraries/pbrlib/genglsl/mx_generalized_schlick_bsdf.glsl index ebeaa66f7a..544e479faa 100644 --- a/libraries/pbrlib/genglsl/mx_generalized_schlick_bsdf.glsl +++ b/libraries/pbrlib/genglsl/mx_generalized_schlick_bsdf.glsl @@ -22,20 +22,22 @@ void mx_generalized_schlick_bsdf_reflection(vec3 L, vec3 V, vec3 P, float occlus vec3 Ht = vec3(dot(H, X), dot(H, Y), dot(H, N)); FresnelData fd; + vec3 safeColor0 = max(color0, 0.0); + vec3 safeColor90 = max(color90, 0.0); if (bsdf.thickness > 0.0) { - fd = mx_init_fresnel_schlick_airy(color0, color90, exponent, bsdf.thickness, bsdf.ior); + fd = mx_init_fresnel_schlick_airy(safeColor0, safeColor90, exponent, bsdf.thickness, bsdf.ior); } else { - fd = mx_init_fresnel_schlick(color0, color90, exponent); + fd = mx_init_fresnel_schlick(safeColor0, safeColor90, exponent); } vec3 F = mx_compute_fresnel(VdotH, fd); float D = mx_ggx_NDF(Ht, safeAlpha); float G = mx_ggx_smith_G2(NdotL, NdotV, avgAlpha); vec3 comp = mx_ggx_energy_compensation(NdotV, avgAlpha, F); - vec3 dirAlbedo = mx_ggx_dir_albedo(NdotV, avgAlpha, color0, color90) * comp; + vec3 dirAlbedo = mx_ggx_dir_albedo(NdotV, avgAlpha, safeColor0, safeColor90) * comp; float avgDirAlbedo = dot(dirAlbedo, vec3(1.0 / 3.0)); bsdf.throughput = vec3(1.0 - avgDirAlbedo * weight); @@ -54,13 +56,15 @@ void mx_generalized_schlick_bsdf_transmission(vec3 V, float weight, vec3 color0, float NdotV = clamp(dot(N, V), M_FLOAT_EPS, 1.0); FresnelData fd; + vec3 safeColor0 = max(color0, 0.0); + vec3 safeColor90 = max(color90, 0.0); if (bsdf.thickness > 0.0) { - fd = mx_init_fresnel_schlick_airy(color0, color90, exponent, bsdf.thickness, bsdf.ior); + fd = mx_init_fresnel_schlick_airy(safeColor0, safeColor90, exponent, bsdf.thickness, bsdf.ior); } else { - fd = mx_init_fresnel_schlick(color0, color90, exponent); + fd = mx_init_fresnel_schlick(safeColor0, safeColor90, exponent); } vec3 F = mx_compute_fresnel(NdotV, fd); @@ -68,15 +72,15 @@ void mx_generalized_schlick_bsdf_transmission(vec3 V, float weight, vec3 color0, float avgAlpha = mx_average_alpha(safeAlpha); vec3 comp = mx_ggx_energy_compensation(NdotV, avgAlpha, F); - vec3 dirAlbedo = mx_ggx_dir_albedo(NdotV, avgAlpha, color0, color90) * comp; + vec3 dirAlbedo = mx_ggx_dir_albedo(NdotV, avgAlpha, safeColor0, safeColor90) * comp; float avgDirAlbedo = dot(dirAlbedo, vec3(1.0 / 3.0)); bsdf.throughput = vec3(1.0 - avgDirAlbedo * weight); if (scatter_mode != 0) { - float avgF0 = dot(color0, vec3(1.0 / 3.0)); + float avgF0 = dot(safeColor0, vec3(1.0 / 3.0)); fd.ior = vec3(mx_f0_to_ior(avgF0)); - bsdf.response = mx_surface_transmission(N, V, X, safeAlpha, distribution, fd, color0) * weight; + bsdf.response = mx_surface_transmission(N, V, X, safeAlpha, distribution, fd, safeColor0) * weight; } } @@ -91,20 +95,22 @@ void mx_generalized_schlick_bsdf_indirect(vec3 V, float weight, vec3 color0, vec float NdotV = clamp(dot(N, V), M_FLOAT_EPS, 1.0); FresnelData fd; + vec3 safeColor0 = max(color0, 0.0); + vec3 safeColor90 = max(color90, 0.0); if (bsdf.thickness > 0.0) { - fd = mx_init_fresnel_schlick_airy(color0, color90, exponent, bsdf.thickness, bsdf.ior); + fd = mx_init_fresnel_schlick_airy(safeColor0, safeColor90, exponent, bsdf.thickness, bsdf.ior); } else { - fd = mx_init_fresnel_schlick(color0, color90, exponent); + fd = mx_init_fresnel_schlick(safeColor0, safeColor90, exponent); } vec3 F = mx_compute_fresnel(NdotV, fd); vec2 safeAlpha = clamp(roughness, M_FLOAT_EPS, 1.0); float avgAlpha = mx_average_alpha(safeAlpha); vec3 comp = mx_ggx_energy_compensation(NdotV, avgAlpha, F); - vec3 dirAlbedo = mx_ggx_dir_albedo(NdotV, avgAlpha, color0, color90) * comp; + vec3 dirAlbedo = mx_ggx_dir_albedo(NdotV, avgAlpha, safeColor0, safeColor90) * comp; float avgDirAlbedo = dot(dirAlbedo, vec3(1.0 / 3.0)); bsdf.throughput = vec3(1.0 - avgDirAlbedo * weight); diff --git a/libraries/pbrlib/genmdl/mx39_pbrlib_genmdl_impl.mtlx b/libraries/pbrlib/genmdl/mx39_pbrlib_genmdl_impl.mtlx new file mode 100644 index 0000000000..f2dc8c184d --- /dev/null +++ b/libraries/pbrlib/genmdl/mx39_pbrlib_genmdl_impl.mtlx @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + diff --git a/libraries/pbrlib/genmdl/pbrlib_genmdl_impl.mtlx b/libraries/pbrlib/genmdl/pbrlib_genmdl_impl.mtlx index 800e32edd0..a4277bf675 100644 --- a/libraries/pbrlib/genmdl/pbrlib_genmdl_impl.mtlx +++ b/libraries/pbrlib/genmdl/pbrlib_genmdl_impl.mtlx @@ -2,98 +2,98 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - - - + + + - - - + + + - - - - - - + + + + + + - + - + - + - + diff --git a/libraries/pbrlib/genmsl/mx39_pbrlib_genmsl_impl.mtlx b/libraries/pbrlib/genmsl/mx39_pbrlib_genmsl_impl.mtlx new file mode 100644 index 0000000000..93fe12e647 --- /dev/null +++ b/libraries/pbrlib/genmsl/mx39_pbrlib_genmsl_impl.mtlx @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + diff --git a/libraries/pbrlib/genosl/legacy/mx39_compensating_oren_nayar_diffuse_bsdf.osl b/libraries/pbrlib/genosl/legacy/mx39_compensating_oren_nayar_diffuse_bsdf.osl new file mode 100644 index 0000000000..2ce4dd07b1 --- /dev/null +++ b/libraries/pbrlib/genosl/legacy/mx39_compensating_oren_nayar_diffuse_bsdf.osl @@ -0,0 +1,5 @@ +void mx39_compensating_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/mx39_dielectric_tf_bsdf.osl b/libraries/pbrlib/genosl/legacy/mx39_dielectric_tf_bsdf.osl new file mode 100644 index 0000000000..5d6c81fd36 --- /dev/null +++ b/libraries/pbrlib/genosl/legacy/mx39_dielectric_tf_bsdf.osl @@ -0,0 +1,36 @@ +#include "../lib/mx_microfacet_specular.osl" + +void mx39_dielectric_tf_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/mx39_generalized_schlick_tf_82_bsdf.osl b/libraries/pbrlib/genosl/legacy/mx39_generalized_schlick_tf_82_bsdf.osl new file mode 100644 index 0000000000..ac0e3928e5 --- /dev/null +++ b/libraries/pbrlib/genosl/legacy/mx39_generalized_schlick_tf_82_bsdf.osl @@ -0,0 +1,38 @@ +#include "../lib/mx_microfacet_specular.osl" + +void mx39_generalized_schlick_tf_82_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/mx39_dielectric_tf_bsdf.osl b/libraries/pbrlib/genosl/mx39_dielectric_tf_bsdf.osl new file mode 100644 index 0000000000..5b4243506c --- /dev/null +++ b/libraries/pbrlib/genosl/mx39_dielectric_tf_bsdf.osl @@ -0,0 +1,15 @@ +void mx39_dielectric_tf_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 == "R") + { + bsdf = weight * dielectric_bsdf(N, U, tint, color(0.0), roughness.x, roughness.y, ior, distribution, "thinfilm_thickness", thinfilm_thickness, "thinfilm_ior", thinfilm_ior); + } + else if (scatter_mode == "T") + { + bsdf = weight * dielectric_bsdf(N, U, color(0.0), tint, roughness.x, roughness.y, ior, distribution, "thinfilm_thickness", thinfilm_thickness, "thinfilm_ior", thinfilm_ior); + } + else + { + bsdf = weight * dielectric_bsdf(N, U, tint, tint, roughness.x, roughness.y, ior, distribution, "thinfilm_thickness", thinfilm_thickness, "thinfilm_ior", thinfilm_ior); + } +} diff --git a/libraries/pbrlib/genosl/mx39_generalized_schlick_tf_82_bsdf.osl b/libraries/pbrlib/genosl/mx39_generalized_schlick_tf_82_bsdf.osl new file mode 100644 index 0000000000..4fb9eac0c3 --- /dev/null +++ b/libraries/pbrlib/genosl/mx39_generalized_schlick_tf_82_bsdf.osl @@ -0,0 +1,15 @@ +void mx39_generalized_schlick_tf_82_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) +{ + if (scatter_mode == "R") + { + bsdf = weight * generalized_schlick_bsdf(N, U, color(1.0), color(0.0), roughness.x, roughness.y, color0, color90, exponent, distribution, "thinfilm_thickness", thinfilm_thickness, "thinfilm_ior", thinfilm_ior); + } + else if (scatter_mode == "T") + { + bsdf = weight * generalized_schlick_bsdf(N, U, color(0.0), color(1.0), roughness.x, roughness.y, color0, color90, exponent, distribution, "thinfilm_thickness", thinfilm_thickness, "thinfilm_ior", thinfilm_ior); + } + else + { + bsdf = weight * generalized_schlick_bsdf(N, U, color(1.0), color(1.0), roughness.x, roughness.y, color0, color90, exponent, distribution, "thinfilm_thickness", thinfilm_thickness, "thinfilm_ior", thinfilm_ior); + } +} diff --git a/libraries/pbrlib/genosl/mx39_pbrlib_genosl_impl.legacy b/libraries/pbrlib/genosl/mx39_pbrlib_genosl_impl.legacy new file mode 100644 index 0000000000..95af5056f4 --- /dev/null +++ b/libraries/pbrlib/genosl/mx39_pbrlib_genosl_impl.legacy @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + diff --git a/libraries/pbrlib/genosl/mx39_pbrlib_genosl_impl.mtlx b/libraries/pbrlib/genosl/mx39_pbrlib_genosl_impl.mtlx new file mode 100644 index 0000000000..df8d6a59e9 --- /dev/null +++ b/libraries/pbrlib/genosl/mx39_pbrlib_genosl_impl.mtlx @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + diff --git a/libraries/pbrlib/pbrlib_defs.mtlx b/libraries/pbrlib/pbrlib_defs.mtlx index e63625a45d..5fe6a6a773 100644 --- a/libraries/pbrlib/pbrlib_defs.mtlx +++ b/libraries/pbrlib/pbrlib_defs.mtlx @@ -417,4 +417,78 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/libraries/stdlib/genglsl/mx_creatematrix_vector3_matrix33.glsl b/libraries/stdlib/genglsl/mx_creatematrix_vector3_matrix33.glsl new file mode 100644 index 0000000000..aa10ef5b98 --- /dev/null +++ b/libraries/stdlib/genglsl/mx_creatematrix_vector3_matrix33.glsl @@ -0,0 +1,6 @@ +void mx_creatematrix_vector3_matrix33(vec3 in1, vec3 in2, vec3 in3, out mat3 result) +{ + result = mat3(in1.x, in1.y, in1.z, + in2.x, in2.y, in2.z, + in3.x, in3.y, in3.z); +} diff --git a/libraries/stdlib/genglsl/mx_creatematrix_vector3_matrix44.glsl b/libraries/stdlib/genglsl/mx_creatematrix_vector3_matrix44.glsl new file mode 100644 index 0000000000..194fad421a --- /dev/null +++ b/libraries/stdlib/genglsl/mx_creatematrix_vector3_matrix44.glsl @@ -0,0 +1,7 @@ +void mx_creatematrix_vector3_matrix44(vec3 in1, vec3 in2, vec3 in3, vec3 in4, out mat4 result) +{ + result = mat4(in1.x, in1.y, in1.z, 0.0, + in2.x, in2.y, in2.z, 0.0, + in3.x, in3.y, in3.z, 0.0, + in4.x, in4.y, in4.z, 1.0); +} diff --git a/libraries/stdlib/genglsl/mx_creatematrix_vector4_matrix44.glsl b/libraries/stdlib/genglsl/mx_creatematrix_vector4_matrix44.glsl new file mode 100644 index 0000000000..665a22212b --- /dev/null +++ b/libraries/stdlib/genglsl/mx_creatematrix_vector4_matrix44.glsl @@ -0,0 +1,7 @@ +void mx_creatematrix_vector4_matrix44(vec4 in1, vec4 in2, vec4 in3, vec4 in4, out mat4 result) +{ + result = mat4(in1.x, in1.y, in1.z, in1.w, + in2.x, in2.y, in2.z, in2.w, + in3.x, in3.y, in3.z, in3.w, + in4.x, in4.y, in4.z, in4.w); +} diff --git a/libraries/stdlib/genglsl/mx_fractal3d_fa_vector2.glsl b/libraries/stdlib/genglsl/mx_fractal3d_fa_vector2.glsl deleted file mode 100644 index 59dbbee127..0000000000 --- a/libraries/stdlib/genglsl/mx_fractal3d_fa_vector2.glsl +++ /dev/null @@ -1,7 +0,0 @@ -#include "lib/mx_noise.glsl" - -void mx_fractal3d_fa_vector2(float amplitude, int octaves, float lacunarity, float diminish, vec3 position, out vec2 result) -{ - vec2 value = mx_fractal_noise_vec2(position, octaves, lacunarity, diminish); - result = value * amplitude; -} diff --git a/libraries/stdlib/genglsl/mx_fractal3d_fa_vector3.glsl b/libraries/stdlib/genglsl/mx_fractal3d_fa_vector3.glsl deleted file mode 100644 index d0f30defd4..0000000000 --- a/libraries/stdlib/genglsl/mx_fractal3d_fa_vector3.glsl +++ /dev/null @@ -1,7 +0,0 @@ -#include "lib/mx_noise.glsl" - -void mx_fractal3d_fa_vector3(float amplitude, int octaves, float lacunarity, float diminish, vec3 position, out vec3 result) -{ - vec3 value = mx_fractal_noise_vec3(position, octaves, lacunarity, diminish); - result = value * amplitude; -} diff --git a/libraries/stdlib/genglsl/mx_fractal3d_fa_vector4.glsl b/libraries/stdlib/genglsl/mx_fractal3d_fa_vector4.glsl deleted file mode 100644 index b9c66c4465..0000000000 --- a/libraries/stdlib/genglsl/mx_fractal3d_fa_vector4.glsl +++ /dev/null @@ -1,7 +0,0 @@ -#include "lib/mx_noise.glsl" - -void mx_fractal3d_fa_vector4(float amplitude, int octaves, float lacunarity, float diminish, vec3 position, out vec4 result) -{ - vec4 value = mx_fractal_noise_vec4(position, octaves, lacunarity, diminish); - result = value * amplitude; -} diff --git a/libraries/stdlib/genglsl/mx_noise2d_fa_vector2.glsl b/libraries/stdlib/genglsl/mx_noise2d_fa_vector2.glsl deleted file mode 100644 index f5a81565d7..0000000000 --- a/libraries/stdlib/genglsl/mx_noise2d_fa_vector2.glsl +++ /dev/null @@ -1,7 +0,0 @@ -#include "lib/mx_noise.glsl" - -void mx_noise2d_fa_vector2(float amplitude, float pivot, vec2 texcoord, out vec2 result) -{ - vec3 value = mx_perlin_noise_vec3(texcoord); - result = value.xy * amplitude + pivot; -} diff --git a/libraries/stdlib/genglsl/mx_noise2d_fa_vector3.glsl b/libraries/stdlib/genglsl/mx_noise2d_fa_vector3.glsl deleted file mode 100644 index 0735965ca0..0000000000 --- a/libraries/stdlib/genglsl/mx_noise2d_fa_vector3.glsl +++ /dev/null @@ -1,7 +0,0 @@ -#include "lib/mx_noise.glsl" - -void mx_noise2d_fa_vector3(float amplitude, float pivot, vec2 texcoord, out vec3 result) -{ - vec3 value = mx_perlin_noise_vec3(texcoord); - result = value * amplitude + pivot; -} diff --git a/libraries/stdlib/genglsl/mx_noise2d_fa_vector4.glsl b/libraries/stdlib/genglsl/mx_noise2d_fa_vector4.glsl deleted file mode 100644 index 6d51a59e4a..0000000000 --- a/libraries/stdlib/genglsl/mx_noise2d_fa_vector4.glsl +++ /dev/null @@ -1,8 +0,0 @@ -#include "lib/mx_noise.glsl" - -void mx_noise2d_fa_vector4(float amplitude, float pivot, vec2 texcoord, out vec4 result) -{ - vec3 xyz = mx_perlin_noise_vec3(texcoord); - float w = mx_perlin_noise_float(texcoord + vec2(19, 73)); - result = vec4(xyz, w) * amplitude + pivot; -} diff --git a/libraries/stdlib/genglsl/mx_noise3d_fa_vector2.glsl b/libraries/stdlib/genglsl/mx_noise3d_fa_vector2.glsl deleted file mode 100644 index 06d91f9135..0000000000 --- a/libraries/stdlib/genglsl/mx_noise3d_fa_vector2.glsl +++ /dev/null @@ -1,7 +0,0 @@ -#include "lib/mx_noise.glsl" - -void mx_noise3d_fa_vector2(float amplitude, float pivot, vec3 position, out vec2 result) -{ - vec3 value = mx_perlin_noise_vec3(position); - result = value.xy * amplitude + pivot; -} diff --git a/libraries/stdlib/genglsl/mx_noise3d_fa_vector3.glsl b/libraries/stdlib/genglsl/mx_noise3d_fa_vector3.glsl deleted file mode 100644 index 168bf572f1..0000000000 --- a/libraries/stdlib/genglsl/mx_noise3d_fa_vector3.glsl +++ /dev/null @@ -1,7 +0,0 @@ -#include "lib/mx_noise.glsl" - -void mx_noise3d_fa_vector3(float amplitude, float pivot, vec3 position, out vec3 result) -{ - vec3 value = mx_perlin_noise_vec3(position); - result = value * amplitude + pivot; -} diff --git a/libraries/stdlib/genglsl/mx_noise3d_fa_vector4.glsl b/libraries/stdlib/genglsl/mx_noise3d_fa_vector4.glsl deleted file mode 100644 index 680410f9d3..0000000000 --- a/libraries/stdlib/genglsl/mx_noise3d_fa_vector4.glsl +++ /dev/null @@ -1,8 +0,0 @@ -#include "lib/mx_noise.glsl" - -void mx_noise3d_fa_vector4(float amplitude, float pivot, vec3 position, out vec4 result) -{ - vec3 xyz = mx_perlin_noise_vec3(position); - float w = mx_perlin_noise_float(position + vec3(19, 73, 29)); - result = vec4(xyz, w) * amplitude + pivot; -} diff --git a/libraries/stdlib/genglsl/mx_normalmap.glsl b/libraries/stdlib/genglsl/mx_normalmap.glsl index 86d5610fea..19e0797c4f 100644 --- a/libraries/stdlib/genglsl/mx_normalmap.glsl +++ b/libraries/stdlib/genglsl/mx_normalmap.glsl @@ -1,4 +1,4 @@ -void mx_normalmap(vec3 value, int map_space, float normal_scale, vec3 N, vec3 T, out vec3 result) +void mx_normalmap_vector2(vec3 value, int map_space, vec2 normal_scale, vec3 N, vec3 T, out vec3 result) { // Decode the normal map. value = (value == vec3(0.0f)) ? vec3(0.0, 0.0, 1.0) : value * 2.0 - 1.0; @@ -14,3 +14,8 @@ void mx_normalmap(vec3 value, int map_space, float normal_scale, vec3 N, vec3 T, // Normalize the result. result = normalize(value); } + +void mx_normalmap_float(vec3 value, int map_space, float normal_scale, vec3 N, vec3 T, out vec3 result) +{ + mx_normalmap_vector2(value, map_space, vec2(normal_scale), N, T, result); +} diff --git a/libraries/stdlib/genglsl/mx_overlay.glsl b/libraries/stdlib/genglsl/mx_overlay.glsl deleted file mode 100644 index e1bec8ac44..0000000000 --- a/libraries/stdlib/genglsl/mx_overlay.glsl +++ /dev/null @@ -1,25 +0,0 @@ -float mx_overlay(float fg, float bg) -{ - return (fg < 0.5) ? (2.0 * fg * bg) : (1.0 - (1.0 - fg) * (1.0 - bg)); -} - -vec2 mx_overlay(vec2 fg, vec2 bg) -{ - return vec2(mx_overlay(fg.r, bg.r), - mx_overlay(fg.g, bg.g)); -} - -vec3 mx_overlay(vec3 fg, vec3 bg) -{ - return vec3(mx_overlay(fg.r, bg.r), - mx_overlay(fg.g, bg.g), - mx_overlay(fg.b, bg.b)); -} - -vec4 mx_overlay(vec4 fg, vec4 bg) -{ - return vec4(mx_overlay(fg.r, bg.r), - mx_overlay(fg.g, bg.g), - mx_overlay(fg.b, bg.b), - mx_overlay(fg.a, bg.a)); -} diff --git a/libraries/stdlib/genglsl/mx_overlay_color3.glsl b/libraries/stdlib/genglsl/mx_overlay_color3.glsl deleted file mode 100644 index 3b6ae67804..0000000000 --- a/libraries/stdlib/genglsl/mx_overlay_color3.glsl +++ /dev/null @@ -1,6 +0,0 @@ -#include "mx_overlay.glsl" - -void mx_overlay_color3(vec3 fg, vec3 bg, float mix, out vec3 result) -{ - result = mix * mx_overlay(fg, bg) + (1.0-mix) * bg; -} diff --git a/libraries/stdlib/genglsl/mx_overlay_color4.glsl b/libraries/stdlib/genglsl/mx_overlay_color4.glsl deleted file mode 100644 index 411e0da372..0000000000 --- a/libraries/stdlib/genglsl/mx_overlay_color4.glsl +++ /dev/null @@ -1,6 +0,0 @@ -#include "mx_overlay.glsl" - -void mx_overlay_color4(vec4 fg, vec4 bg, float mix, out vec4 result) -{ - result = mix * mx_overlay(fg, bg) + (1.0-mix) * bg; -} diff --git a/libraries/stdlib/genglsl/mx_smoothstep_vec2FA.glsl b/libraries/stdlib/genglsl/mx_smoothstep_vec2FA.glsl deleted file mode 100644 index 0b16d99e19..0000000000 --- a/libraries/stdlib/genglsl/mx_smoothstep_vec2FA.glsl +++ /dev/null @@ -1,7 +0,0 @@ -#include "mx_smoothstep_float.glsl" - -void mx_smoothstep_vec2FA(vec2 val, float low, float high, out vec2 result) -{ - mx_smoothstep_float(val.x, low, high, result.x); - mx_smoothstep_float(val.y, low, high, result.y); -} diff --git a/libraries/stdlib/genglsl/mx_smoothstep_vec3FA.glsl b/libraries/stdlib/genglsl/mx_smoothstep_vec3FA.glsl deleted file mode 100644 index ffc913e682..0000000000 --- a/libraries/stdlib/genglsl/mx_smoothstep_vec3FA.glsl +++ /dev/null @@ -1,8 +0,0 @@ -#include "mx_smoothstep_float.glsl" - -void mx_smoothstep_vec3FA(vec3 val, float low, float high, out vec3 result) -{ - mx_smoothstep_float(val.x, low, high, result.x); - mx_smoothstep_float(val.y, low, high, result.y); - mx_smoothstep_float(val.z, low, high, result.z); -} diff --git a/libraries/stdlib/genglsl/mx_smoothstep_vec4FA.glsl b/libraries/stdlib/genglsl/mx_smoothstep_vec4FA.glsl deleted file mode 100644 index e001efd86a..0000000000 --- a/libraries/stdlib/genglsl/mx_smoothstep_vec4FA.glsl +++ /dev/null @@ -1,9 +0,0 @@ -#include "mx_smoothstep_float.glsl" - -void mx_smoothstep_vec4FA(vec4 val, float low, float high, out vec4 result) -{ - mx_smoothstep_float(val.x, low, high, result.x); - mx_smoothstep_float(val.y, low, high, result.y); - mx_smoothstep_float(val.z, low, high, result.z); - mx_smoothstep_float(val.w, low, high, result.w); -} diff --git a/libraries/stdlib/genglsl/mx_smoothstep_vec2.glsl b/libraries/stdlib/genglsl/mx_smoothstep_vector2.glsl similarity index 67% rename from libraries/stdlib/genglsl/mx_smoothstep_vec2.glsl rename to libraries/stdlib/genglsl/mx_smoothstep_vector2.glsl index c46152e3fd..f0e630af20 100644 --- a/libraries/stdlib/genglsl/mx_smoothstep_vec2.glsl +++ b/libraries/stdlib/genglsl/mx_smoothstep_vector2.glsl @@ -1,6 +1,6 @@ #include "mx_smoothstep_float.glsl" -void mx_smoothstep_vec2(vec2 val, vec2 low, vec2 high, out vec2 result) +void mx_smoothstep_vector2(vec2 val, vec2 low, vec2 high, out vec2 result) { mx_smoothstep_float(val.x, low.x, high.x, result.x); mx_smoothstep_float(val.y, low.y, high.y, result.y); diff --git a/libraries/stdlib/genglsl/mx_smoothstep_vec3.glsl b/libraries/stdlib/genglsl/mx_smoothstep_vector3.glsl similarity index 73% rename from libraries/stdlib/genglsl/mx_smoothstep_vec3.glsl rename to libraries/stdlib/genglsl/mx_smoothstep_vector3.glsl index ce15fcddfd..b6094785a8 100644 --- a/libraries/stdlib/genglsl/mx_smoothstep_vec3.glsl +++ b/libraries/stdlib/genglsl/mx_smoothstep_vector3.glsl @@ -1,6 +1,6 @@ #include "mx_smoothstep_float.glsl" -void mx_smoothstep_vec3(vec3 val, vec3 low, vec3 high, out vec3 result) +void mx_smoothstep_vector3(vec3 val, vec3 low, vec3 high, out vec3 result) { mx_smoothstep_float(val.x, low.x, high.x, result.x); mx_smoothstep_float(val.y, low.y, high.y, result.y); diff --git a/libraries/stdlib/genglsl/mx_smoothstep_vec4.glsl b/libraries/stdlib/genglsl/mx_smoothstep_vector4.glsl similarity index 78% rename from libraries/stdlib/genglsl/mx_smoothstep_vec4.glsl rename to libraries/stdlib/genglsl/mx_smoothstep_vector4.glsl index 04609b6073..1a2d4a986b 100644 --- a/libraries/stdlib/genglsl/mx_smoothstep_vec4.glsl +++ b/libraries/stdlib/genglsl/mx_smoothstep_vector4.glsl @@ -1,6 +1,6 @@ #include "mx_smoothstep_float.glsl" -void mx_smoothstep_vec4(vec4 val, vec4 low, vec4 high, out vec4 result) +void mx_smoothstep_vector4(vec4 val, vec4 low, vec4 high, out vec4 result) { mx_smoothstep_float(val.x, low.x, high.x, result.x); mx_smoothstep_float(val.y, low.y, high.y, result.y); diff --git a/libraries/stdlib/genglsl/stdlib_genglsl_impl.mtlx b/libraries/stdlib/genglsl/stdlib_genglsl_impl.mtlx index 90d3120bd7..243a264763 100644 --- a/libraries/stdlib/genglsl/stdlib_genglsl_impl.mtlx +++ b/libraries/stdlib/genglsl/stdlib_genglsl_impl.mtlx @@ -42,7 +42,9 @@
- + + + @@ -96,42 +98,21 @@ - - - - - - - - - - - - - - - - - - - - - @@ -321,6 +302,15 @@ + + + + + + + + + @@ -497,16 +487,9 @@ - - - - - - - - - - + + + @@ -560,11 +543,6 @@ - - - - - @@ -753,6 +731,11 @@ + + + + + diff --git a/libraries/stdlib/genmdl/stdlib_genmdl_impl.mtlx b/libraries/stdlib/genmdl/stdlib_genmdl_impl.mtlx index ab0d776936..7d80ecb429 100644 --- a/libraries/stdlib/genmdl/stdlib_genmdl_impl.mtlx +++ b/libraries/stdlib/genmdl/stdlib_genmdl_impl.mtlx @@ -15,36 +15,37 @@ - + - + - + - + - + - + - + - + + @@ -65,144 +66,123 @@ - - - - - - + + + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - - - - - - - - + + + + - - - - - - - - - - - + + + + - - - - - - - - - - - + + + + - + - + - - - + + + - - - + + + - + - + - + - + - + - - + + - - - + + + - - - - - - - - - + + + + + + + + + - + - + @@ -274,10 +254,10 @@ - - - - + + + + @@ -289,8 +269,8 @@ - - + + @@ -301,15 +281,15 @@ - + - - + + @@ -317,19 +297,28 @@ - - + + + + + + + + + + + - - + + @@ -386,8 +375,8 @@ - - + + @@ -396,8 +385,8 @@ - - + + @@ -409,8 +398,8 @@ - - + + @@ -422,8 +411,8 @@ - - + + @@ -450,37 +439,37 @@ - + - + - + - - - - + + + + - - + + - - + + - + - + @@ -489,107 +478,95 @@ - - - - - - - - - - - + + + + + + + + + + + - - - - - - - - - - - + + + + - - + + - - + + - - + + - + - + - + - + - + - - - + + + - - - + + + - - - - - - + - + - + - + - + - + - + @@ -605,85 +582,85 @@ - - + + - - - + + + - - - - - - - - - - - - + + + + + + + + + + + + - - - - - - - - - - - - + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + - - - - - - + + + + + + - - - - - - + + + + + + @@ -759,6 +736,11 @@ + + + + + diff --git a/libraries/stdlib/genmsl/mx_normalmap.metal b/libraries/stdlib/genmsl/mx_normalmap.metal index c9c7bd5546..a3ffedaad5 100644 --- a/libraries/stdlib/genmsl/mx_normalmap.metal +++ b/libraries/stdlib/genmsl/mx_normalmap.metal @@ -1,4 +1,4 @@ -void mx_normalmap(vec3 value, int map_space, float normal_scale, vec3 N, vec3 T, out vec3 result) +void mx_normalmap_vector2(vec3 value, int map_space, vec2 normal_scale, vec3 N, vec3 T, out vec3 result) { // Decode the normal map. value = all(value == vec3(0.0f)) ? vec3(0.0, 0.0, 1.0) : value * 2.0 - 1.0; @@ -14,3 +14,8 @@ void mx_normalmap(vec3 value, int map_space, float normal_scale, vec3 N, vec3 T, // Normalize the result. result = normalize(value); } + +void mx_normalmap_float(vec3 value, int map_space, float normal_scale, vec3 N, vec3 T, out vec3 result) +{ + mx_normalmap_vector2(value, map_space, vec2(normal_scale), N, T, result); +} diff --git a/libraries/stdlib/genmsl/mx_smoothstep_vec2FA.metal b/libraries/stdlib/genmsl/mx_smoothstep_vec2FA.metal deleted file mode 100644 index a05a10d746..0000000000 --- a/libraries/stdlib/genmsl/mx_smoothstep_vec2FA.metal +++ /dev/null @@ -1,8 +0,0 @@ -#include "mx_smoothstep_float.metal" - -void mx_smoothstep_vec2FA(vec2 val, float low, float high, out vec2 result) -{ - float f; - mx_smoothstep_float(val.x, low, high, f); result.x = f; - mx_smoothstep_float(val.y, low, high, f); result.y = f; -} diff --git a/libraries/stdlib/genmsl/mx_smoothstep_vec3FA.metal b/libraries/stdlib/genmsl/mx_smoothstep_vec3FA.metal deleted file mode 100644 index 4a1922d5af..0000000000 --- a/libraries/stdlib/genmsl/mx_smoothstep_vec3FA.metal +++ /dev/null @@ -1,9 +0,0 @@ -#include "mx_smoothstep_float.metal" - -void mx_smoothstep_vec3FA(vec3 val, float low, float high, out vec3 result) -{ - float f; - mx_smoothstep_float(val.x, low, high, f); result.x = f; - mx_smoothstep_float(val.y, low, high, f); result.y = f; - mx_smoothstep_float(val.z, low, high, f); result.z = f; -} diff --git a/libraries/stdlib/genmsl/mx_smoothstep_vec4FA.metal b/libraries/stdlib/genmsl/mx_smoothstep_vec4FA.metal deleted file mode 100644 index a7c27cb0e6..0000000000 --- a/libraries/stdlib/genmsl/mx_smoothstep_vec4FA.metal +++ /dev/null @@ -1,10 +0,0 @@ -#include "mx_smoothstep_float.metal" - -void mx_smoothstep_vec4FA(vec4 val, float low, float high, out vec4 result) -{ - float f; - mx_smoothstep_float(val.x, low, high, f); result.x = f; - mx_smoothstep_float(val.y, low, high, f); result.y = f; - mx_smoothstep_float(val.z, low, high, f); result.z = f; - mx_smoothstep_float(val.w, low, high, f); result.w = f; -} diff --git a/libraries/stdlib/genmsl/mx_smoothstep_vec2.metal b/libraries/stdlib/genmsl/mx_smoothstep_vector2.metal similarity index 70% rename from libraries/stdlib/genmsl/mx_smoothstep_vec2.metal rename to libraries/stdlib/genmsl/mx_smoothstep_vector2.metal index 0baa763137..34fec594ee 100644 --- a/libraries/stdlib/genmsl/mx_smoothstep_vec2.metal +++ b/libraries/stdlib/genmsl/mx_smoothstep_vector2.metal @@ -1,6 +1,6 @@ #include "mx_smoothstep_float.metal" -void mx_smoothstep_vec2(vec2 val, vec2 low, vec2 high, out vec2 result) +void mx_smoothstep_vector2(vec2 val, vec2 low, vec2 high, out vec2 result) { float f; mx_smoothstep_float(val.x, low.x, high.x, f); result.x = f; diff --git a/libraries/stdlib/genmsl/mx_smoothstep_vec3.metal b/libraries/stdlib/genmsl/mx_smoothstep_vector3.metal similarity index 77% rename from libraries/stdlib/genmsl/mx_smoothstep_vec3.metal rename to libraries/stdlib/genmsl/mx_smoothstep_vector3.metal index b0f969751b..5b0a9b62cf 100644 --- a/libraries/stdlib/genmsl/mx_smoothstep_vec3.metal +++ b/libraries/stdlib/genmsl/mx_smoothstep_vector3.metal @@ -1,6 +1,6 @@ #include "mx_smoothstep_float.metal" -void mx_smoothstep_vec3(vec3 val, vec3 low, vec3 high, thread vec3& result) +void mx_smoothstep_vector3(vec3 val, vec3 low, vec3 high, thread vec3& result) { float f; mx_smoothstep_float(val.x, low.x, high.x, f); result.x = f; diff --git a/libraries/stdlib/genmsl/mx_smoothstep_vec4.metal b/libraries/stdlib/genmsl/mx_smoothstep_vector4.metal similarity index 80% rename from libraries/stdlib/genmsl/mx_smoothstep_vec4.metal rename to libraries/stdlib/genmsl/mx_smoothstep_vector4.metal index 8bf2f3d025..04dc755149 100644 --- a/libraries/stdlib/genmsl/mx_smoothstep_vec4.metal +++ b/libraries/stdlib/genmsl/mx_smoothstep_vector4.metal @@ -1,6 +1,6 @@ #include "mx_smoothstep_float.metal" -void mx_smoothstep_vec4(vec4 val, vec4 low, vec4 high, out vec4 result) +void mx_smoothstep_vector4(vec4 val, vec4 low, vec4 high, out vec4 result) { float f; mx_smoothstep_float(val.x, low.x, high.x, f); result.x = f; diff --git a/libraries/stdlib/genmsl/stdlib_genmsl_impl.mtlx b/libraries/stdlib/genmsl/stdlib_genmsl_impl.mtlx index fcab8fd69d..e8b6110813 100644 --- a/libraries/stdlib/genmsl/stdlib_genmsl_impl.mtlx +++ b/libraries/stdlib/genmsl/stdlib_genmsl_impl.mtlx @@ -42,7 +42,8 @@ - + + @@ -96,42 +97,21 @@ - - - - - - - - - - - - - - - - - - - - - @@ -322,6 +302,15 @@ + + + + + + + + + @@ -498,16 +487,9 @@ - - - - - - - - - - + + + @@ -560,11 +542,6 @@ - - - - - @@ -753,6 +730,11 @@ + + + + + diff --git a/libraries/stdlib/genosl/include/color4.h b/libraries/stdlib/genosl/include/color4.h index 78b06b24ec..dcee101258 100644 --- a/libraries/stdlib/genosl/include/color4.h +++ b/libraries/stdlib/genosl/include/color4.h @@ -151,6 +151,11 @@ color4 ceil(color4 a) return color4(ceil(a.rgb), ceil(a.a)); } +color4 round(color4 a) +{ + return color4(round(a.rgb), round(a.a)); +} + color4 floor(color4 a) { return color4(floor(a.rgb), floor(a.a)); diff --git a/libraries/stdlib/genosl/include/vector2.h b/libraries/stdlib/genosl/include/vector2.h index f819dd142f..83fad03456 100644 --- a/libraries/stdlib/genosl/include/vector2.h +++ b/libraries/stdlib/genosl/include/vector2.h @@ -151,6 +151,11 @@ vector2 ceil(vector2 a) return vector2 (ceil(a.x), ceil(a.y)); } +vector2 round(vector2 a) +{ + return vector2 (round(a.x), round(a.y)); +} + vector2 floor(vector2 a) { return vector2 (floor(a.x), floor(a.y)); diff --git a/libraries/stdlib/genosl/include/vector4.h b/libraries/stdlib/genosl/include/vector4.h index 56b64b0c6a..6c8b3996dc 100644 --- a/libraries/stdlib/genosl/include/vector4.h +++ b/libraries/stdlib/genosl/include/vector4.h @@ -160,6 +160,14 @@ vector4 ceil(vector4 in) ceil(in.w)); } +vector4 round(vector4 in) +{ + return vector4 (round(in.x), + round(in.y), + round(in.z), + round(in.w)); +} + vector4 floor(vector4 in) { return vector4 (floor(in.x), diff --git a/libraries/stdlib/genosl/mx_creatematrix.osl b/libraries/stdlib/genosl/mx_creatematrix.osl new file mode 100644 index 0000000000..3e567d3b5b --- /dev/null +++ b/libraries/stdlib/genosl/mx_creatematrix.osl @@ -0,0 +1,23 @@ +void mx_creatematrix_vector3_matrix33(vector in1, vector in2, vector in3, output matrix result) +{ + result = matrix(in1.x, in1.y, in1.z, 0.0, + in2.x, in2.y, in2.z, 0.0, + in3.x, in3.y, in3.z, 0.0, + 0.0, 0.0, 0.0, 1.0); +} + +void mx_creatematrix_vector3_matrix44(vector in1, vector in2, vector in3, vector in4, output matrix result) +{ + result = matrix(in1.x, in1.y, in1.z, 0.0, + in2.x, in2.y, in2.z, 0.0, + in3.x, in3.y, in3.z, 0.0, + in4.x, in4.y, in4.z, 1.0); +} + +void mx_creatematrix_vector4_matrix44(vector4 in1, vector4 in2, vector4 in3, vector4 in4, output matrix result) +{ + result = matrix(in1.x, in1.y, in1.z, in1.w, + in2.x, in2.y, in2.z, in2.w, + in3.x, in3.y, in3.z, in3.w, + in4.x, in4.y, in4.z, in4.w); +} diff --git a/libraries/stdlib/genosl/mx_fractal3d_color3.osl b/libraries/stdlib/genosl/mx_fractal3d_color3.osl deleted file mode 100644 index bf1744890b..0000000000 --- a/libraries/stdlib/genosl/mx_fractal3d_color3.osl +++ /dev/null @@ -1,5 +0,0 @@ -void mx_fractal3d_color3(vector amplitude, int octaves, float lacunarity, float diminish, vector position, output color result) -{ - color f = mx_fbm(position, octaves, lacunarity, diminish, "snoise"); - result = f * amplitude; -} diff --git a/libraries/stdlib/genosl/mx_fractal3d_color4.osl b/libraries/stdlib/genosl/mx_fractal3d_color4.osl deleted file mode 100644 index 9943a92dfd..0000000000 --- a/libraries/stdlib/genosl/mx_fractal3d_color4.osl +++ /dev/null @@ -1,5 +0,0 @@ -void mx_fractal3d_color4(vector4 amplitude, int octaves, float lacunarity, float diminish, vector position, output color4 result) -{ - color4 f = mx_fbm(position, octaves, lacunarity, diminish, "snoise"); - result = f * color4(color(amplitude.x, amplitude.y, amplitude.z), amplitude.w); -} diff --git a/libraries/stdlib/genosl/mx_fractal3d_fa_color3.osl b/libraries/stdlib/genosl/mx_fractal3d_fa_color3.osl deleted file mode 100644 index 889848c692..0000000000 --- a/libraries/stdlib/genosl/mx_fractal3d_fa_color3.osl +++ /dev/null @@ -1,5 +0,0 @@ -void mx_fractal3d_fa_color3(float amplitude, int octaves, float lacunarity, float diminish, vector position, output color result) -{ - color f = mx_fbm(position, octaves, lacunarity, diminish, "snoise"); - result = f * amplitude; -} diff --git a/libraries/stdlib/genosl/mx_fractal3d_fa_color4.osl b/libraries/stdlib/genosl/mx_fractal3d_fa_color4.osl deleted file mode 100644 index d2a8f49291..0000000000 --- a/libraries/stdlib/genosl/mx_fractal3d_fa_color4.osl +++ /dev/null @@ -1,5 +0,0 @@ -void mx_fractal3d_fa_color4(float amplitude, int octaves, float lacunarity, float diminish, vector position, output color4 result) -{ - color4 f = mx_fbm(position, octaves, lacunarity, diminish, "snoise"); - result = f * amplitude; -} diff --git a/libraries/stdlib/genosl/mx_fractal3d_fa_vector2.osl b/libraries/stdlib/genosl/mx_fractal3d_fa_vector2.osl deleted file mode 100644 index c1266d473c..0000000000 --- a/libraries/stdlib/genosl/mx_fractal3d_fa_vector2.osl +++ /dev/null @@ -1,5 +0,0 @@ -void mx_fractal3d_fa_vector2(float amplitude, int octaves, float lacunarity, float diminish, vector position, output vector2 result) -{ - vector2 f = mx_fbm(position, octaves, lacunarity, diminish, "snoise"); - result = f * amplitude; -} diff --git a/libraries/stdlib/genosl/mx_fractal3d_fa_vector3.osl b/libraries/stdlib/genosl/mx_fractal3d_fa_vector3.osl deleted file mode 100644 index 34f6515ca8..0000000000 --- a/libraries/stdlib/genosl/mx_fractal3d_fa_vector3.osl +++ /dev/null @@ -1,5 +0,0 @@ -void mx_fractal3d_fa_vector3(float amplitude, int octaves, float lacunarity, float diminish, vector position, output vector result) -{ - vector f = mx_fbm(position, octaves, lacunarity, diminish, "snoise"); - result = f * amplitude; -} diff --git a/libraries/stdlib/genosl/mx_fractal3d_fa_vector4.osl b/libraries/stdlib/genosl/mx_fractal3d_fa_vector4.osl deleted file mode 100644 index fb5a8c73d6..0000000000 --- a/libraries/stdlib/genosl/mx_fractal3d_fa_vector4.osl +++ /dev/null @@ -1,5 +0,0 @@ -void mx_fractal3d_fa_vector4(float amplitude, int octaves, float lacunarity, float diminish, vector position, output vector4 result) -{ - vector4 f = mx_fbm(position, octaves, lacunarity, diminish, "snoise"); - result = f * amplitude; -} diff --git a/libraries/stdlib/genosl/mx_image_color3.osl b/libraries/stdlib/genosl/mx_image_color3.osl index 15b594e885..89ba94f376 100644 --- a/libraries/stdlib/genosl/mx_image_color3.osl +++ b/libraries/stdlib/genosl/mx_image_color3.osl @@ -12,6 +12,5 @@ void mx_image_color3(textureresource file, string layer, color default_value, ve color missingColor = default_value; vector2 st = mx_transform_uv(texcoord); - out = texture(file.filename, st.x, st.y, "subimage", layer, "missingcolor", missingColor, "swrap", uaddressmode, "twrap", vaddressmode $extraTextureLookupArguments); + out = texture(file.filename, st.x, st.y, "subimage", layer, "missingcolor", missingColor, "swrap", uaddressmode, "twrap", vaddressmode, "colorspace", file.colorspace); } - diff --git a/libraries/stdlib/genosl/mx_image_color4.osl b/libraries/stdlib/genosl/mx_image_color4.osl index 3bde1a5047..261108b5b4 100644 --- a/libraries/stdlib/genosl/mx_image_color4.osl +++ b/libraries/stdlib/genosl/mx_image_color4.osl @@ -15,7 +15,7 @@ void mx_image_color4(textureresource file, string layer, color4 default_value, v vector2 st = mx_transform_uv(texcoord); float alpha; color rgb = texture(file.filename, st.x, st.y, "alpha", alpha, "subimage", layer, - "missingcolor", missingColor, "missingalpha", missingAlpha, "swrap", uaddressmode, "twrap", vaddressmode $extraTextureLookupArguments ); + "missingcolor", missingColor, "missingalpha", missingAlpha, "swrap", uaddressmode, "twrap", vaddressmode, "colorspace", file.colorspace); out = color4(rgb, alpha); } diff --git a/libraries/stdlib/genosl/mx_noise2d_color3.osl b/libraries/stdlib/genosl/mx_noise2d_color3.osl deleted file mode 100644 index 37421ee810..0000000000 --- a/libraries/stdlib/genosl/mx_noise2d_color3.osl +++ /dev/null @@ -1,5 +0,0 @@ -void mx_noise2d_color3(vector amplitude, float pivot, vector2 texcoord, output color result) -{ - color value = noise("snoise", texcoord.x, texcoord.y); - result = value * amplitude + pivot; -} diff --git a/libraries/stdlib/genosl/mx_noise2d_color4.osl b/libraries/stdlib/genosl/mx_noise2d_color4.osl deleted file mode 100644 index ec8064c577..0000000000 --- a/libraries/stdlib/genosl/mx_noise2d_color4.osl +++ /dev/null @@ -1,5 +0,0 @@ -void mx_noise2d_color4(vector4 amplitude, float pivot, vector2 texcoord, output color4 result) -{ - color4 value = mx_noise("snoise", texcoord.x, texcoord.y); - result = value * color4(color(amplitude.x, amplitude.y, amplitude.z), amplitude.w) + pivot; -} diff --git a/libraries/stdlib/genosl/mx_noise2d_fa_color3.osl b/libraries/stdlib/genosl/mx_noise2d_fa_color3.osl deleted file mode 100644 index 29c09c1ae2..0000000000 --- a/libraries/stdlib/genosl/mx_noise2d_fa_color3.osl +++ /dev/null @@ -1,5 +0,0 @@ -void mx_noise2d_fa_color3(float amplitude, float pivot, vector2 texcoord, output color result) -{ - color value = noise("snoise", texcoord.x, texcoord.y); - result = value * amplitude + pivot; -} diff --git a/libraries/stdlib/genosl/mx_noise2d_fa_color4.osl b/libraries/stdlib/genosl/mx_noise2d_fa_color4.osl deleted file mode 100644 index 35d3463ff7..0000000000 --- a/libraries/stdlib/genosl/mx_noise2d_fa_color4.osl +++ /dev/null @@ -1,5 +0,0 @@ -void mx_noise2d_fa_color4(float amplitude, float pivot, vector2 texcoord, output color4 result) -{ - color4 value = mx_noise("snoise", texcoord.x, texcoord.y); - result = value * amplitude + pivot; -} diff --git a/libraries/stdlib/genosl/mx_noise2d_fa_vector2.osl b/libraries/stdlib/genosl/mx_noise2d_fa_vector2.osl deleted file mode 100644 index b64dc6de7a..0000000000 --- a/libraries/stdlib/genosl/mx_noise2d_fa_vector2.osl +++ /dev/null @@ -1,5 +0,0 @@ -void mx_noise2d_fa_vector2(float amplitude, float pivot, vector2 texcoord, output vector2 result) -{ - vector2 value = mx_noise("snoise", texcoord.x, texcoord.y); - result = value * amplitude + pivot; -} diff --git a/libraries/stdlib/genosl/mx_noise2d_fa_vector3.osl b/libraries/stdlib/genosl/mx_noise2d_fa_vector3.osl deleted file mode 100644 index c1f060a265..0000000000 --- a/libraries/stdlib/genosl/mx_noise2d_fa_vector3.osl +++ /dev/null @@ -1,5 +0,0 @@ -void mx_noise2d_fa_vector3(float amplitude, float pivot, vector2 texcoord, output vector result) -{ - vector value = noise("snoise", texcoord.x, texcoord.y); - result = value * amplitude + pivot; -} diff --git a/libraries/stdlib/genosl/mx_noise2d_fa_vector4.osl b/libraries/stdlib/genosl/mx_noise2d_fa_vector4.osl deleted file mode 100644 index 9cb9f57c7c..0000000000 --- a/libraries/stdlib/genosl/mx_noise2d_fa_vector4.osl +++ /dev/null @@ -1,5 +0,0 @@ -void mx_noise2d_fa_vector4(float amplitude, float pivot, vector2 texcoord, output vector4 result) -{ - vector4 value = mx_noise("snoise", texcoord.x, texcoord.y); - result = value * amplitude + pivot; -} diff --git a/libraries/stdlib/genosl/mx_noise3d_color3.osl b/libraries/stdlib/genosl/mx_noise3d_color3.osl deleted file mode 100644 index f4649a598a..0000000000 --- a/libraries/stdlib/genosl/mx_noise3d_color3.osl +++ /dev/null @@ -1,5 +0,0 @@ -void mx_noise3d_color3(vector amplitude, float pivot, vector position, output color result) -{ - color value = noise("snoise", position); - result = value * amplitude + pivot; -} diff --git a/libraries/stdlib/genosl/mx_noise3d_color4.osl b/libraries/stdlib/genosl/mx_noise3d_color4.osl deleted file mode 100644 index c522f81493..0000000000 --- a/libraries/stdlib/genosl/mx_noise3d_color4.osl +++ /dev/null @@ -1,5 +0,0 @@ -void mx_noise3d_color4(vector4 amplitude, float pivot, vector position, output color4 result) -{ - color4 value = mx_noise("snoise", position); - result = value * color4(color(amplitude.x, amplitude.y, amplitude.z), amplitude.w) + pivot; -} diff --git a/libraries/stdlib/genosl/mx_noise3d_fa_color3.osl b/libraries/stdlib/genosl/mx_noise3d_fa_color3.osl deleted file mode 100644 index 83b777b2f2..0000000000 --- a/libraries/stdlib/genosl/mx_noise3d_fa_color3.osl +++ /dev/null @@ -1,5 +0,0 @@ -void mx_noise3d_fa_color3(float amplitude, float pivot, vector position, output color result) -{ - color value = noise("snoise", position); - result = value * amplitude + pivot; -} diff --git a/libraries/stdlib/genosl/mx_noise3d_fa_color4.osl b/libraries/stdlib/genosl/mx_noise3d_fa_color4.osl deleted file mode 100644 index ee1a48ea0c..0000000000 --- a/libraries/stdlib/genosl/mx_noise3d_fa_color4.osl +++ /dev/null @@ -1,5 +0,0 @@ -void mx_noise3d_fa_color4(float amplitude, float pivot, vector position, output color4 result) -{ - color4 value = mx_noise("snoise", position); - result = value * amplitude + pivot; -} diff --git a/libraries/stdlib/genosl/mx_noise3d_fa_vector2.osl b/libraries/stdlib/genosl/mx_noise3d_fa_vector2.osl deleted file mode 100644 index 9317d8933b..0000000000 --- a/libraries/stdlib/genosl/mx_noise3d_fa_vector2.osl +++ /dev/null @@ -1,5 +0,0 @@ -void mx_noise3d_fa_vector2(float amplitude, float pivot, vector position, output vector2 result) -{ - vector2 value = mx_noise("snoise", position); - result = value * amplitude + pivot; -} diff --git a/libraries/stdlib/genosl/mx_noise3d_fa_vector3.osl b/libraries/stdlib/genosl/mx_noise3d_fa_vector3.osl deleted file mode 100644 index 4e235febce..0000000000 --- a/libraries/stdlib/genosl/mx_noise3d_fa_vector3.osl +++ /dev/null @@ -1,5 +0,0 @@ -void mx_noise3d_fa_vector3(float amplitude, float pivot, vector position, output vector result) -{ - vector value = noise("snoise", position); - result = value * amplitude + pivot; -} diff --git a/libraries/stdlib/genosl/mx_noise3d_fa_vector4.osl b/libraries/stdlib/genosl/mx_noise3d_fa_vector4.osl deleted file mode 100644 index 177fc3f286..0000000000 --- a/libraries/stdlib/genosl/mx_noise3d_fa_vector4.osl +++ /dev/null @@ -1,5 +0,0 @@ -void mx_noise3d_fa_vector4(float amplitude, float pivot, vector position, output vector4 result) -{ - vector4 value = mx_noise("snoise", position); - result = value * amplitude + pivot; -} diff --git a/libraries/stdlib/genosl/mx_normalmap.osl b/libraries/stdlib/genosl/mx_normalmap.osl index a1f276faf1..79b31df69d 100644 --- a/libraries/stdlib/genosl/mx_normalmap.osl +++ b/libraries/stdlib/genosl/mx_normalmap.osl @@ -1,4 +1,4 @@ -void mx_normalmap(vector value, string map_space, float normal_scale, vector N, vector U, output vector result) +void mx_normalmap_vector2(vector value, string map_space, vector2 normal_scale, vector N, vector U, output vector result) { // Tangent space if (map_space == "tangent") @@ -6,7 +6,7 @@ void mx_normalmap(vector value, string map_space, float normal_scale, vector N, vector v = value * 2.0 - 1.0; vector T = normalize(U - dot(U, N) * N); vector B = normalize(cross(N, T)); - result = normalize(T * v[0] * normal_scale + B * v[1] * normal_scale + N * v[2]); + result = normalize(T * v[0] * normal_scale.x + B * v[1] * normal_scale.y + N * v[2]); } // Object space else @@ -15,3 +15,8 @@ void mx_normalmap(vector value, string map_space, float normal_scale, vector N, result = normalize(n); } } + +void mx_normalmap_float(vector value, string map_space, float normal_scale, vector N, vector U, output vector result) +{ + mx_normalmap_vector2(value, map_space, vector2(normal_scale, normal_scale), N, U, result); +} diff --git a/libraries/stdlib/genosl/mx_overlay_color3.osl b/libraries/stdlib/genosl/mx_overlay_color3.osl deleted file mode 100644 index 387653fe05..0000000000 --- a/libraries/stdlib/genosl/mx_overlay_color3.osl +++ /dev/null @@ -1,16 +0,0 @@ -float overlay(float fg, float bg) -{ - return (fg < 0.5) ? (2 * fg * bg) : (1 - (1 - fg) * (1 - bg)); -} - -color overlay(color fg, color bg) -{ - return color(overlay(fg[0], bg[0]), - overlay(fg[1], bg[1]), - overlay(fg[2], bg[2])); -} - -void mx_overlay_color3(color fg, color bg, float mix, output color out) -{ - out = mix * overlay(fg, bg) + (1-mix) * bg; -} diff --git a/libraries/stdlib/genosl/mx_overlay_color4.osl b/libraries/stdlib/genosl/mx_overlay_color4.osl deleted file mode 100644 index 1ae6a72c15..0000000000 --- a/libraries/stdlib/genosl/mx_overlay_color4.osl +++ /dev/null @@ -1,22 +0,0 @@ -float overlay(float fg, float bg) -{ - return (fg < 0.5) ? (2 * fg * bg) : (1 - (1 - fg) * (1 - bg)); -} - -color overlay(color fg, color bg) -{ - return color(overlay(fg[0], bg[0]), - overlay(fg[1], bg[1]), - overlay(fg[2], bg[2])); -} - -color4 overlay(color4 fg, color4 bg) -{ - return color4(overlay(fg.rgb, bg.rgb), - overlay(fg.a, bg.a)); -} - -void mx_overlay_color4(color4 fg, color4 bg, float mix, output color4 out) -{ - out = mix * overlay(fg, bg) + (1-mix) * bg; -} diff --git a/libraries/stdlib/genosl/stdlib_genosl_impl.mtlx b/libraries/stdlib/genosl/stdlib_genosl_impl.mtlx index 1ba22ef6a3..c916eb3052 100644 --- a/libraries/stdlib/genosl/stdlib_genosl_impl.mtlx +++ b/libraries/stdlib/genosl/stdlib_genosl_impl.mtlx @@ -44,7 +44,8 @@ - + + @@ -98,42 +99,21 @@ - - - - - - - - - - - - - - - - - - - - - @@ -324,6 +304,15 @@ + + + + + + + + + @@ -498,16 +487,9 @@ - - - - - - - @@ -561,11 +543,6 @@ - - - - - @@ -756,6 +733,11 @@ + + + + + diff --git a/libraries/stdlib/stdlib_defs.mtlx b/libraries/stdlib/stdlib_defs.mtlx index bb5e8edd1f..7433b0a2f7 100644 --- a/libraries/stdlib/stdlib_defs.mtlx +++ b/libraries/stdlib/stdlib_defs.mtlx @@ -1914,6 +1914,39 @@
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -3343,8 +3467,8 @@ @@ -4359,6 +4483,33 @@ + + + + + + + + + + + + + + + + + + + + + + + + - + @@ -196,7 +196,7 @@ @@ -1309,6 +1309,200 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -1576,7 +1770,7 @@ @@ -1669,7 +1863,7 @@ - + @@ -2361,11 +2555,14 @@ - + + @@ -2479,7 +2676,7 @@ - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -3391,6 +3929,118 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/python/Scripts/baketextures.py b/python/Scripts/baketextures.py index caf2aaed3e..ce132036a6 100644 --- a/python/Scripts/baketextures.py +++ b/python/Scripts/baketextures.py @@ -5,9 +5,8 @@ import sys, os, argparse from sys import platform + import MaterialX as mx -from MaterialX import PyMaterialXGenShader -from MaterialX import PyMaterialXGenGlsl from MaterialX import PyMaterialXRender as mx_render from MaterialX import PyMaterialXRenderGlsl as mx_render_glsl if platform == "darwin": diff --git a/python/Scripts/generateshader.py b/python/Scripts/generateshader.py index 8329f7231e..65b628d733 100644 --- a/python/Scripts/generateshader.py +++ b/python/Scripts/generateshader.py @@ -5,12 +5,13 @@ ''' import sys, os, argparse, subprocess + import MaterialX as mx -import MaterialX.PyMaterialXGenShader as mx_gen_shader import MaterialX.PyMaterialXGenGlsl as mx_gen_glsl -import MaterialX.PyMaterialXGenOsl as mx_gen_osl import MaterialX.PyMaterialXGenMdl as mx_gen_mdl import MaterialX.PyMaterialXGenMsl as mx_gen_msl +import MaterialX.PyMaterialXGenOsl as mx_gen_osl +import MaterialX.PyMaterialXGenShader as mx_gen_shader def validateCode(sourceCodeFile, codevalidator, codevalidatorArgs): if codevalidator: @@ -24,7 +25,7 @@ def validateCode(sourceCodeFile, codevalidator, codevalidatorArgs): print(cmd_flatten) try: output = subprocess.check_output(cmd, stderr=subprocess.STDOUT) - result = output.decode(encoding='utf-8') + return output.decode(encoding='utf-8') except subprocess.CalledProcessError as out: return (out.output.decode(encoding='utf-8')) return "" @@ -82,7 +83,7 @@ def main(): try: mx.loadLibraries(libraryFolders, searchPath, stdlib) doc.importLibrary(stdlib) - except err: + except Exception as err: print('Generation failed: "', err, '"') sys.exit(-1) @@ -142,8 +143,6 @@ def main(): nodes = mx_gen_shader.findRenderableElements(doc) if not nodes: nodes = doc.getMaterialNodes() - if not nodes: - nodes = doc.getNodesOfType(mx.SURFACE_SHADER_TYPE_STRING) pathPrefix = '' if opts.outputPath and os.path.exists(opts.outputPath): diff --git a/python/Scripts/genmdl.py b/python/Scripts/genmdl.py index f42add0425..24d8b518f2 100644 --- a/python/Scripts/genmdl.py +++ b/python/Scripts/genmdl.py @@ -3,9 +3,11 @@ Generate MDL implementation directory based on MaterialX nodedefs ''' -import sys import os -import string; os.environ['PYTHONIOENCODING'] = 'utf-8' +import sys + +os.environ['PYTHONIOENCODING'] = 'utf-8' + import MaterialX as mx def usage(): @@ -345,7 +347,7 @@ def main(): doc = mx.createDocument() searchPath = os.path.join(_startPath, 'libraries') - libraryPath = os.path.join(searchPath, 'stdlib') + libraryPath = os.path.join(searchPath, LIBRARY) _loadLibraries(doc, searchPath, libraryPath) DEFINITION_PREFIX = 'ND_' @@ -522,7 +524,7 @@ def main(): if isinstance(elem, mx.Output): outputValue = elem.getAttribute('default') if outputValue == '[]': - outputvalue = '' + outputValue = '' if not outputValue: outputValue = elem.getAttribute('defaultinput') if outputValue: @@ -642,6 +644,9 @@ def main(): elif nodeCategory == 'ceil': _writeOneArgumentFunc(file, outputType, '::math::'+nodeCategory) wroteImplementation = True + elif nodeCategory == 'round': + _writeOneArgumentFunc(file, outputType, '::math::'+nodeCategory) + wroteImplementation = True elif nodeCategory == 'floor': _writeOneArgumentFunc(file, outputType, '::math::'+nodeCategory) wroteImplementation = True diff --git a/python/Scripts/mxdoc.py b/python/Scripts/mxdoc.py index 7ee21eb8e5..7c9ba09a07 100644 --- a/python/Scripts/mxdoc.py +++ b/python/Scripts/mxdoc.py @@ -3,7 +3,9 @@ Print markdown documentation for each nodedef in the given document. ''' -import sys, os, argparse +import argparse +import sys + import MaterialX as mx HEADERS = ('Name', 'Type', 'Default Value', diff --git a/python/Scripts/mxformat.py b/python/Scripts/mxformat.py index 8f6ad731e1..0b327883bd 100644 --- a/python/Scripts/mxformat.py +++ b/python/Scripts/mxformat.py @@ -4,7 +4,9 @@ the documents to the latest version of the standard. ''' -import sys, os, argparse +import argparse +import os + import MaterialX as mx def main(): diff --git a/python/Scripts/mxvalidate.py b/python/Scripts/mxvalidate.py index e251b4599b..8b5271e9ed 100755 --- a/python/Scripts/mxvalidate.py +++ b/python/Scripts/mxvalidate.py @@ -3,7 +3,9 @@ Verify that the given file is a valid MaterialX document. ''' -import sys, os, argparse +import argparse +import sys + import MaterialX as mx def main(): @@ -25,7 +27,7 @@ def main(): stdlib = mx.createDocument() try: mx.loadLibraries(mx.getDefaultDataLibraryFolders(), mx.getDefaultDataSearchPath(), stdlib) - except err: + except Exception as err: print(err) sys.exit(0) doc.importLibrary(stdlib) diff --git a/python/Scripts/translateshader.py b/python/Scripts/translateshader.py index 71d7a480b5..f7c5686211 100644 --- a/python/Scripts/translateshader.py +++ b/python/Scripts/translateshader.py @@ -5,15 +5,13 @@ ''' import sys, os, argparse -import MaterialX as mx - from sys import platform + +import MaterialX as mx from MaterialX import PyMaterialXGenShader as mx_gen_shader -from MaterialX import PyMaterialXGenGlsl as ms_gen_glsl from MaterialX import PyMaterialXRender as mx_render from MaterialX import PyMaterialXRenderGlsl as mx_render_glsl if platform == "darwin": - from MaterialX import PyMaterialXGenMsl as ms_gen_msl from MaterialX import PyMaterialXRenderMsl as mx_render_msl def main(): diff --git a/resources/Lights/envmap_shader.mtlx b/resources/Lights/environment_map.mtlx similarity index 67% rename from resources/Lights/envmap_shader.mtlx rename to resources/Lights/environment_map.mtlx index 8c9c6ec0f5..8aef3c11a5 100644 --- a/resources/Lights/envmap_shader.mtlx +++ b/resources/Lights/environment_map.mtlx @@ -1,17 +1,10 @@ - + - - - - - - - - + - + @@ -46,14 +39,19 @@ - + - - - + + + + + + + + - + diff --git a/resources/Materials/Examples/OpenPbr/open_pbr_aluminum_brushed.mtlx b/resources/Materials/Examples/OpenPbr/open_pbr_aluminum_brushed.mtlx new file mode 100644 index 0000000000..7f7072d416 --- /dev/null +++ b/resources/Materials/Examples/OpenPbr/open_pbr_aluminum_brushed.mtlx @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/resources/Materials/Examples/OpenPbr/open_pbr_carpaint.mtlx b/resources/Materials/Examples/OpenPbr/open_pbr_carpaint.mtlx new file mode 100644 index 0000000000..fd42fdf48d --- /dev/null +++ b/resources/Materials/Examples/OpenPbr/open_pbr_carpaint.mtlx @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/resources/Materials/Examples/OpenPbr/open_pbr_default.mtlx b/resources/Materials/Examples/OpenPbr/open_pbr_default.mtlx new file mode 100644 index 0000000000..8125541a99 --- /dev/null +++ b/resources/Materials/Examples/OpenPbr/open_pbr_default.mtlx @@ -0,0 +1,46 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/resources/Materials/Examples/OpenPbr/open_pbr_glass.mtlx b/resources/Materials/Examples/OpenPbr/open_pbr_glass.mtlx new file mode 100644 index 0000000000..a661b9d1f6 --- /dev/null +++ b/resources/Materials/Examples/OpenPbr/open_pbr_glass.mtlx @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/resources/Materials/Examples/OpenPbr/open_pbr_honey.mtlx b/resources/Materials/Examples/OpenPbr/open_pbr_honey.mtlx new file mode 100644 index 0000000000..41e076d231 --- /dev/null +++ b/resources/Materials/Examples/OpenPbr/open_pbr_honey.mtlx @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/resources/Materials/Examples/OpenPbr/open_pbr_ketchup.mtlx b/resources/Materials/Examples/OpenPbr/open_pbr_ketchup.mtlx new file mode 100644 index 0000000000..cda2ebdf7e --- /dev/null +++ b/resources/Materials/Examples/OpenPbr/open_pbr_ketchup.mtlx @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/resources/Materials/Examples/OpenPbr/open_pbr_lightbulb.mtlx b/resources/Materials/Examples/OpenPbr/open_pbr_lightbulb.mtlx new file mode 100644 index 0000000000..a915f842a4 --- /dev/null +++ b/resources/Materials/Examples/OpenPbr/open_pbr_lightbulb.mtlx @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/resources/Materials/Examples/OpenPbr/open_pbr_pearl.mtlx b/resources/Materials/Examples/OpenPbr/open_pbr_pearl.mtlx new file mode 100644 index 0000000000..83db774b8e --- /dev/null +++ b/resources/Materials/Examples/OpenPbr/open_pbr_pearl.mtlx @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/resources/Materials/Examples/OpenPbr/open_pbr_soapbubble.mtlx b/resources/Materials/Examples/OpenPbr/open_pbr_soapbubble.mtlx new file mode 100644 index 0000000000..af0faccb2a --- /dev/null +++ b/resources/Materials/Examples/OpenPbr/open_pbr_soapbubble.mtlx @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/resources/Materials/Examples/OpenPbr/open_pbr_velvet.mtlx b/resources/Materials/Examples/OpenPbr/open_pbr_velvet.mtlx new file mode 100644 index 0000000000..6fbc907f3d --- /dev/null +++ b/resources/Materials/Examples/OpenPbr/open_pbr_velvet.mtlx @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/resources/Materials/TestSuite/_options.mtlx b/resources/Materials/TestSuite/_options.mtlx index 8716cba5f0..e12a5b564b 100644 --- a/resources/Materials/TestSuite/_options.mtlx +++ b/resources/Materials/TestSuite/_options.mtlx @@ -11,23 +11,6 @@ can also be performed depending on the options enabled. --> - - - - - - - - - - - - - - - - - @@ -87,48 +70,13 @@ - - - - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/resources/Materials/TestSuite/nprlib/edge_brighten.mtlx b/resources/Materials/TestSuite/nprlib/edge_brighten.mtlx new file mode 100644 index 0000000000..8ce3affd40 --- /dev/null +++ b/resources/Materials/TestSuite/nprlib/edge_brighten.mtlx @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + + + + diff --git a/resources/Materials/TestSuite/nprlib/gooch_shade.mtlx b/resources/Materials/TestSuite/nprlib/gooch_shade.mtlx new file mode 100644 index 0000000000..9e723e2de6 --- /dev/null +++ b/resources/Materials/TestSuite/nprlib/gooch_shade.mtlx @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/resources/Materials/TestSuite/nprlib/starfield.mtlx b/resources/Materials/TestSuite/nprlib/starfield.mtlx new file mode 100644 index 0000000000..6898054a6d --- /dev/null +++ b/resources/Materials/TestSuite/nprlib/starfield.mtlx @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/resources/Materials/TestSuite/nprlib/toon_shade.mtlx b/resources/Materials/TestSuite/nprlib/toon_shade.mtlx new file mode 100644 index 0000000000..1c93cad62d --- /dev/null +++ b/resources/Materials/TestSuite/nprlib/toon_shade.mtlx @@ -0,0 +1,151 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/resources/Materials/TestSuite/pbrlib/bsdf/generalized_schlick.mtlx b/resources/Materials/TestSuite/pbrlib/bsdf/generalized_schlick.mtlx index cb36a8957d..a320dcda9a 100644 --- a/resources/Materials/TestSuite/pbrlib/bsdf/generalized_schlick.mtlx +++ b/resources/Materials/TestSuite/pbrlib/bsdf/generalized_schlick.mtlx @@ -1,6 +1,6 @@ - + diff --git a/resources/Materials/TestSuite/pbrlib/bsdf/wedge_conductor.mtlx b/resources/Materials/TestSuite/pbrlib/bsdf/wedge_conductor.mtlx deleted file mode 100644 index 4e34fdc4a1..0000000000 --- a/resources/Materials/TestSuite/pbrlib/bsdf/wedge_conductor.mtlx +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/resources/Materials/TestSuite/pbrlib/displacement/displacement.mtlx b/resources/Materials/TestSuite/pbrlib/displacement/displacement.mtlx index 6ea8b7e90d..d0ef073583 100644 --- a/resources/Materials/TestSuite/pbrlib/displacement/displacement.mtlx +++ b/resources/Materials/TestSuite/pbrlib/displacement/displacement.mtlx @@ -1,6 +1,6 @@ - + @@ -21,7 +21,7 @@ - + diff --git a/resources/Materials/TestSuite/pbrlib/multioutput/multishaderoutput.mtlx b/resources/Materials/TestSuite/pbrlib/multioutput/multishaderoutput.mtlx index 7456b088d9..f6dacf6ed5 100644 --- a/resources/Materials/TestSuite/pbrlib/multioutput/multishaderoutput.mtlx +++ b/resources/Materials/TestSuite/pbrlib/multioutput/multishaderoutput.mtlx @@ -1,6 +1,6 @@ - + @@ -16,7 +16,7 @@ - + diff --git a/resources/Materials/TestSuite/pbrlib/surfaceshader/network_surfaceshader.mtlx b/resources/Materials/TestSuite/pbrlib/surfaceshader/network_surfaceshader.mtlx new file mode 100644 index 0000000000..fb5202b37c --- /dev/null +++ b/resources/Materials/TestSuite/pbrlib/surfaceshader/network_surfaceshader.mtlx @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/resources/Materials/TestSuite/pbrlib/surfaceshader/normalmapped_surfaceshader.mtlx b/resources/Materials/TestSuite/pbrlib/surfaceshader/normalmapped_surfaceshader.mtlx index 8a92848783..460f8a8998 100644 --- a/resources/Materials/TestSuite/pbrlib/surfaceshader/normalmapped_surfaceshader.mtlx +++ b/resources/Materials/TestSuite/pbrlib/surfaceshader/normalmapped_surfaceshader.mtlx @@ -25,4 +25,29 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/resources/Materials/TestSuite/pbrlib/surfaceshader/surfacematerial_with_graph.mtlx b/resources/Materials/TestSuite/pbrlib/surfaceshader/surfacematerial_with_graph.mtlx index 203aae6be4..1ea487a503 100644 --- a/resources/Materials/TestSuite/pbrlib/surfaceshader/surfacematerial_with_graph.mtlx +++ b/resources/Materials/TestSuite/pbrlib/surfaceshader/surfacematerial_with_graph.mtlx @@ -1,10 +1,6 @@ - - - - - + @@ -12,42 +8,46 @@ - - - + + + - + + - - - - - - + + + + + + + + + + + + - + + + + + - - - - - - - - + + - - + diff --git a/resources/Materials/TestSuite/stdlib/adjustment/smoothstep.mtlx b/resources/Materials/TestSuite/stdlib/adjustment/smoothstep.mtlx index 90510df2f1..e1fb76113b 100644 --- a/resources/Materials/TestSuite/stdlib/adjustment/smoothstep.mtlx +++ b/resources/Materials/TestSuite/stdlib/adjustment/smoothstep.mtlx @@ -1,8 +1,8 @@ @@ -20,38 +20,6 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -60,14 +28,6 @@ - - - - - - - - @@ -76,14 +36,6 @@ - - - - - - - - @@ -92,12 +44,4 @@ - - - - - - - - diff --git a/resources/Materials/TestSuite/stdlib/compositing/compositing.mtlx b/resources/Materials/TestSuite/stdlib/compositing/compositing.mtlx index e7a742c581..b125e70dca 100644 --- a/resources/Materials/TestSuite/stdlib/compositing/compositing.mtlx +++ b/resources/Materials/TestSuite/stdlib/compositing/compositing.mtlx @@ -183,24 +183,24 @@ - - + + - - + + - - + + diff --git a/resources/Materials/TestSuite/stdlib/math/math.mtlx b/resources/Materials/TestSuite/stdlib/math/math.mtlx index 5a4f0b214f..0969618369 100644 --- a/resources/Materials/TestSuite/stdlib/math/math.mtlx +++ b/resources/Materials/TestSuite/stdlib/math/math.mtlx @@ -234,6 +234,69 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/resources/Materials/TestSuite/stdlib/math/math_operators.mtlx b/resources/Materials/TestSuite/stdlib/math/math_operators.mtlx index fd48cd275a..f22181409d 100644 --- a/resources/Materials/TestSuite/stdlib/math/math_operators.mtlx +++ b/resources/Materials/TestSuite/stdlib/math/math_operators.mtlx @@ -462,6 +462,83 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/resources/Materials/TestSuite/stdlib/math/matrix.mtlx b/resources/Materials/TestSuite/stdlib/math/matrix.mtlx new file mode 100644 index 0000000000..4bcb555739 --- /dev/null +++ b/resources/Materials/TestSuite/stdlib/math/matrix.mtlx @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/resources/Materials/TestSuite/stdlib/noise/noise.mtlx b/resources/Materials/TestSuite/stdlib/noise/noise.mtlx index 14ab1b9702..9a43223c60 100644 --- a/resources/Materials/TestSuite/stdlib/noise/noise.mtlx +++ b/resources/Materials/TestSuite/stdlib/noise/noise.mtlx @@ -1,208 +1,127 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/resources/Materials/TestSuite/stdlib/procedural/tiledshape.mtlx b/resources/Materials/TestSuite/stdlib/procedural/tiledshape.mtlx index 69fd225f2c..fe6e414535 100644 --- a/resources/Materials/TestSuite/stdlib/procedural/tiledshape.mtlx +++ b/resources/Materials/TestSuite/stdlib/procedural/tiledshape.mtlx @@ -24,7 +24,7 @@ - + diff --git a/resources/Materials/TestSuite/stdlib/texture/noise.mtlx b/resources/Materials/TestSuite/stdlib/texture/noise.mtlx deleted file mode 100644 index 760e508896..0000000000 --- a/resources/Materials/TestSuite/stdlib/texture/noise.mtlx +++ /dev/null @@ -1,228 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/resources/Materials/TestSuite/stdlib/texture/texcoord.mtlx b/resources/Materials/TestSuite/stdlib/texture/texcoord.mtlx new file mode 100644 index 0000000000..4fbf6d12d9 --- /dev/null +++ b/resources/Materials/TestSuite/stdlib/texture/texcoord.mtlx @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/resources/Materials/TestSuite/stdlib/upgrade/1_37_to_1_38.mtlx b/resources/Materials/TestSuite/stdlib/upgrade/1_37_to_1_38.mtlx deleted file mode 100644 index 28b9ae8ad2..0000000000 --- a/resources/Materials/TestSuite/stdlib/upgrade/1_37_to_1_38.mtlx +++ /dev/null @@ -1,40 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/resources/Materials/TestSuite/stdlib/upgrade/1_38_parameter_to_input.mtlx b/resources/Materials/TestSuite/stdlib/upgrade/1_38_parameter_to_input.mtlx deleted file mode 100644 index 220836d354..0000000000 --- a/resources/Materials/TestSuite/stdlib/upgrade/1_38_parameter_to_input.mtlx +++ /dev/null @@ -1,71 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/resources/Materials/TestSuite/stdlib/upgrade/material_element_to_surface_material.mtlx b/resources/Materials/TestSuite/stdlib/upgrade/material_element_to_surface_material.mtlx deleted file mode 100644 index 4979f7a6da..0000000000 --- a/resources/Materials/TestSuite/stdlib/upgrade/material_element_to_surface_material.mtlx +++ /dev/null @@ -1,22 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - diff --git a/resources/Materials/TestSuite/stdlib/upgrade/syntax_1_22.mtlx b/resources/Materials/TestSuite/stdlib/upgrade/syntax_1_22.mtlx new file mode 100644 index 0000000000..a9eff392d3 --- /dev/null +++ b/resources/Materials/TestSuite/stdlib/upgrade/syntax_1_22.mtlx @@ -0,0 +1,70 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/resources/Materials/TestSuite/stdlib/upgrade/syntax_1_25.mtlx b/resources/Materials/TestSuite/stdlib/upgrade/syntax_1_25.mtlx new file mode 100644 index 0000000000..df723e7054 --- /dev/null +++ b/resources/Materials/TestSuite/stdlib/upgrade/syntax_1_25.mtlx @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/resources/Materials/TestSuite/stdlib/upgrade/1_36_to_1_37.mtlx b/resources/Materials/TestSuite/stdlib/upgrade/syntax_1_36.mtlx similarity index 99% rename from resources/Materials/TestSuite/stdlib/upgrade/1_36_to_1_37.mtlx rename to resources/Materials/TestSuite/stdlib/upgrade/syntax_1_36.mtlx index 84db1c6101..08a049435f 100644 --- a/resources/Materials/TestSuite/stdlib/upgrade/1_36_to_1_37.mtlx +++ b/resources/Materials/TestSuite/stdlib/upgrade/syntax_1_36.mtlx @@ -1,9 +1,7 @@ diff --git a/resources/Materials/TestSuite/stdlib/upgrade/syntax_1_37.mtlx b/resources/Materials/TestSuite/stdlib/upgrade/syntax_1_37.mtlx new file mode 100644 index 0000000000..7404b75575 --- /dev/null +++ b/resources/Materials/TestSuite/stdlib/upgrade/syntax_1_37.mtlx @@ -0,0 +1,113 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/source/JsMaterialX/JsMaterialXCore/JsNode.cpp b/source/JsMaterialX/JsMaterialXCore/JsNode.cpp index 8878a219f5..fae1bcba5d 100644 --- a/source/JsMaterialX/JsMaterialXCore/JsNode.cpp +++ b/source/JsMaterialX/JsMaterialXCore/JsNode.cpp @@ -57,6 +57,7 @@ EMSCRIPTEN_BINDINGS(node) .function("setNodeDef", &mx::NodeGraph::setNodeDef) .function("getNodeDef", &mx::NodeGraph::getNodeDef) .function("getImplementation", &mx::NodeGraph::getImplementation) + .function("getDownstreamPorts", &mx::NodeGraph::getDownstreamPorts) .function("addInterfaceName", &mx::NodeGraph::addInterfaceName) .function("removeInterfaceName", &mx::NodeGraph::removeInterfaceName) .function("modifyInterfaceName", &mx::NodeGraph::modifyInterfaceName) diff --git a/source/JsMaterialX/JsMaterialXGenShader/JsGenOptions.cpp b/source/JsMaterialX/JsMaterialXGenShader/JsGenOptions.cpp index 7e3313cdf7..9b28a6f534 100644 --- a/source/JsMaterialX/JsMaterialXGenShader/JsGenOptions.cpp +++ b/source/JsMaterialX/JsMaterialXGenShader/JsGenOptions.cpp @@ -42,5 +42,6 @@ EMSCRIPTEN_BINDINGS(GenOptions) .property("hwMaxActiveLightSources", &mx::GenOptions::hwMaxActiveLightSources) .property("hwNormalizeUdimTexCoords", &mx::GenOptions::hwNormalizeUdimTexCoords) .property("hwWriteAlbedoTable", &mx::GenOptions::hwWriteAlbedoTable) + .property("hwWriteEnvPrefilter", &mx::GenOptions::hwWriteEnvPrefilter) ; } diff --git a/source/MaterialXCore/Definition.cpp b/source/MaterialXCore/Definition.cpp index cf9587ecda..c3150e2a87 100644 --- a/source/MaterialXCore/Definition.cpp +++ b/source/MaterialXCore/Definition.cpp @@ -84,7 +84,7 @@ InterfaceElementPtr NodeDef::getImplementation(const string& target) const } } } - + // Then search for a generic match. for (InterfaceElementPtr interface : interfaces) { diff --git a/source/MaterialXCore/Document.cpp b/source/MaterialXCore/Document.cpp index d37c4b2e12..228c182601 100644 --- a/source/MaterialXCore/Document.cpp +++ b/source/MaterialXCore/Document.cpp @@ -95,7 +95,7 @@ class Document::Cache PortElementPtr portElem = elem->asA(); if (portElem) { - portElementMap.emplace(portElem->getQualifiedName(nodeName), portElem); + portElementMap[portElem->getQualifiedName(nodeName)].push_back(portElem); } } else @@ -105,7 +105,7 @@ class Document::Cache PortElementPtr portElem = elem->asA(); if (portElem) { - portElementMap.emplace(portElem->getQualifiedName(nodeGraphName), portElem); + portElementMap[portElem->getQualifiedName(nodeGraphName)].push_back(portElem); } } } @@ -114,7 +114,7 @@ class Document::Cache NodeDefPtr nodeDef = elem->asA(); if (nodeDef) { - nodeDefMap.emplace(nodeDef->getQualifiedName(nodeString), nodeDef); + nodeDefMap[nodeDef->getQualifiedName(nodeString)].push_back(nodeDef); } } if (!nodeDefString.empty()) @@ -124,7 +124,7 @@ class Document::Cache { if (interface->isA()) { - implementationMap.emplace(interface->getQualifiedName(nodeDefString), interface); + implementationMap[interface->getQualifiedName(nodeDefString)].push_back(interface); } ImplementationPtr impl = interface->asA(); if (impl) @@ -135,11 +135,11 @@ class Document::Cache { NodeGraphPtr nodeGraph = impl->getDocument()->getNodeGraph(nodeGraphString); if (nodeGraph) - implementationMap.emplace(interface->getQualifiedName(nodeDefString), nodeGraph); + implementationMap[interface->getQualifiedName(nodeDefString)].push_back(nodeGraph); } else { - implementationMap.emplace(interface->getQualifiedName(nodeDefString), interface); + implementationMap[interface->getQualifiedName(nodeDefString)].push_back(interface); } } } @@ -154,9 +154,9 @@ class Document::Cache weak_ptr doc; std::mutex mutex; bool valid; - std::unordered_multimap portElementMap; - std::unordered_multimap nodeDefMap; - std::unordered_multimap implementationMap; + std::unordered_map> portElementMap; + std::unordered_map> nodeDefMap; + std::unordered_map> implementationMap; }; // @@ -304,16 +304,15 @@ vector Document::getMatchingPorts(const string& nodeName) const // Refresh the cache. _cache->refresh(); - // Find all port elements matching the given node name. - vector ports; - auto keyRange = _cache->portElementMap.equal_range(nodeName); - for (auto it = keyRange.first; it != keyRange.second; ++it) + // Return all port elements matching the given node name. + if (_cache->portElementMap.count(nodeName)) { - ports.push_back(it->second); + return _cache->portElementMap.at(nodeName); + } + else + { + return vector(); } - - // Return the matches. - return ports; } ValuePtr Document::getGeomPropValue(const string& geomPropName, const string& geom) const @@ -362,16 +361,15 @@ vector Document::getMatchingNodeDefs(const string& nodeName) const // Refresh the cache. _cache->refresh(); - // Find all nodedefs matching the given node name. - vector nodeDefs; - auto keyRange = _cache->nodeDefMap.equal_range(nodeName); - for (auto it = keyRange.first; it != keyRange.second; ++it) + // Return all nodedefs matching the given node name. + if (_cache->nodeDefMap.count(nodeName)) { - nodeDefs.push_back(it->second); + return _cache->nodeDefMap.at(nodeName); + } + else + { + return vector(); } - - // Return the matches. - return nodeDefs; } vector Document::getMatchingImplementations(const string& nodeDef) const @@ -379,16 +377,15 @@ vector Document::getMatchingImplementations(const string& n // Refresh the cache. _cache->refresh(); - // Find all implementations matching the given nodedef string. - vector implementations; - auto keyRange = _cache->implementationMap.equal_range(nodeDef); - for (auto it = keyRange.first; it != keyRange.second; ++it) + // Return all implementations matching the given nodedef string. + if (_cache->implementationMap.count(nodeDef)) { - implementations.push_back(it->second); + return _cache->implementationMap.at(nodeDef); + } + else + { + return vector(); } - - // Return the matches. - return implementations; } bool Document::validate(string* message) const @@ -492,12 +489,10 @@ void Document::upgradeVersion() if (nodeDef->hasAttribute("shadertype")) { nodeDef->setType(SURFACE_SHADER_TYPE_STRING); - nodeDef->removeAttribute("shadertype"); } if (nodeDef->hasAttribute("shaderprogram")) { nodeDef->setNodeString(nodeDef->getAttribute("shaderprogram")); - nodeDef->removeAttribute("shaderprogram"); } } else if (child->getCategory() == "shaderref") @@ -751,8 +746,18 @@ void Document::upgradeVersion() // Remove legacy shader nodedefs. for (NodeDefPtr nodeDef : getNodeDefs()) { - if (nodeDef->getType() == "surface") + if (nodeDef->hasAttribute("shadertype")) { + for (ElementPtr mat : getChildrenOfType("material")) + { + for (ElementPtr shaderRef : mat->getChildrenOfType("shaderref")) + { + if (shaderRef->getAttribute(InterfaceElement::NODE_DEF_ATTRIBUTE) == nodeDef->getName()) + { + shaderRef->removeAttribute(InterfaceElement::NODE_DEF_ATTRIBUTE); + } + } + } removeNodeDef(nodeDef->getName()); } } @@ -1044,39 +1049,7 @@ void Document::upgradeVersion() } } - // Update atan2 interface and rotate3d interface - const string ATAN2 = "atan2"; - const string IN1 = "in1"; - const string IN2 = "in2"; - const string ROTATE3D = "rotate3d"; - const string AXIS = "axis"; - const string INPUT_ONE = "1.0"; - - // Update nodedefs - bool upgradeAtan2Instances = false; - for (auto nodedef : getMatchingNodeDefs(ATAN2)) - { - InputPtr input = nodedef->getInput(IN1); - InputPtr input2 = nodedef->getInput(IN2); - string inputValue = input->getValueString(); - // Only flip value if nodedef value is the previous versions. - if (inputValue == INPUT_ONE) - { - input->setValueString(input2->getValueString()); - input2->setValueString(inputValue); - upgradeAtan2Instances = true; - } - } - for (auto nodedef : getMatchingNodeDefs(ROTATE3D)) - { - ElementPtr axis = nodedef->getChild(AXIS); - if (axis) - { - nodedef->changeChildCategory(axis, "input"); - } - } - - // Update BSDF interfaces + // Define BSDF node pairs. using StringPair = std::pair; const StringPair DIELECTRIC_BRDF = { "dielectric_brdf", "dielectric_bsdf" }; const StringPair DIELECTRIC_BTDF = { "dielectric_btdf", "dielectric_bsdf" }; @@ -1089,57 +1062,11 @@ void Document::upgradeVersion() const StringPair SUBSURFACE_BRDF = { "subsurface_brdf", "subsurface_bsdf" }; const StringPair THIN_FILM_BRDF = { "thin_film_brdf", "thin_film_bsdf" }; - const string SCATTER_MODE = "scatter_mode"; - const string BSDF = "BSDF"; - const string LAYER = "layer"; - const string TOP = "top"; - const string BASE = "base"; - const string INTERIOR = "interior"; - const string ARTISTIC_IOR = "artistic_ior"; - const string COMPLEX_IOR = "complex_ior"; - const string REFLECTIVITY = "reflectivity"; - const string EDGE_COLOR = "edge_color"; - const string IOR = "ior"; - const string EXTINCTION = "extinction"; - const string COLOR3 = "color3"; - const string VECTOR3 = "vector3"; - const string CONVERT = "convert"; - const string IN = "in"; - - // Function for upgrading BSDF nodedef. - auto upgradeBsdfNodeDef = [SCATTER_MODE](NodeDefPtr nodedef, const string& newCategory, bool addScatterMode = false) - { - if (nodedef) - { - nodedef->setName(newCategory); - if (addScatterMode) - { - InputPtr mode = nodedef->addInput(SCATTER_MODE, STRING_TYPE_STRING); - mode->setIsUniform(true); - mode->setValueString("R"); - mode->setAttribute("enum", "R,T,RT"); - } - } - }; - - // Update nodedefs. - upgradeBsdfNodeDef(getNodeDef(DIELECTRIC_BRDF.first), DIELECTRIC_BRDF.second, true); - upgradeBsdfNodeDef(getNodeDef(GENERALIZED_SCHLICK_BRDF.first), GENERALIZED_SCHLICK_BRDF.second, true); - upgradeBsdfNodeDef(getNodeDef(CONDUCTOR_BRDF.first), CONDUCTOR_BRDF.second); - upgradeBsdfNodeDef(getNodeDef(SHEEN_BRDF.first), SHEEN_BRDF.second); - upgradeBsdfNodeDef(getNodeDef(DIFFUSE_BRDF.first), DIFFUSE_BRDF.second); - upgradeBsdfNodeDef(getNodeDef(BURLEY_DIFFUSE_BRDF.first), BURLEY_DIFFUSE_BRDF.second); - upgradeBsdfNodeDef(getNodeDef(DIFFUSE_BTDF.first), DIFFUSE_BTDF.second); - upgradeBsdfNodeDef(getNodeDef(SUBSURFACE_BRDF.first), SUBSURFACE_BRDF.second); - upgradeBsdfNodeDef(getNodeDef(THIN_FILM_BRDF.first), THIN_FILM_BRDF.second); - removeNodeDef(DIELECTRIC_BTDF.first); - removeNodeDef(COMPLEX_IOR); - // Function for upgrading old nested layering setup // to new setup with layer operators. - auto upgradeBsdfLayering = [TOP, BASE, LAYER, BSDF](NodePtr node) + auto upgradeBsdfLayering = [](NodePtr node) { - InputPtr base = node->getInput(BASE); + InputPtr base = node->getInput("base"); if (base) { NodePtr baseNode = base->getConnectedNode(); @@ -1150,13 +1077,13 @@ void Document::upgradeVersion() // so we don't need to update any connection references. const string oldName = node->getName(); node->setName(oldName + "__layer_top"); - NodePtr layer = parent->addNode(LAYER, oldName, BSDF); - InputPtr layerTop = layer->addInput(TOP, BSDF); - InputPtr layerBase = layer->addInput(BASE, BSDF); + NodePtr layer = parent->addNode("layer", oldName, "BSDF"); + InputPtr layerTop = layer->addInput("top", "BSDF"); + InputPtr layerBase = layer->addInput("base", "BSDF"); layerTop->setConnectedNode(node); layerBase->setConnectedNode(baseNode); } - node->removeInput(BASE); + node->removeInput("base"); } }; @@ -1181,31 +1108,31 @@ void Document::upgradeVersion() continue; } const string& nodeCategory = node->getCategory(); - if (upgradeAtan2Instances && nodeCategory == ATAN2) + if (nodeCategory == "atan2") { - InputPtr input = node->getInput(IN1); - InputPtr input2 = node->getInput(IN2); + InputPtr input = node->getInput("in1"); + InputPtr input2 = node->getInput("in2"); if (input && input2) { input->setName(EMPTY_STRING); - input2->setName(IN1); - input->setName(IN2); + input2->setName("in1"); + input->setName("in2"); } else { if (input) { - input->setName(IN2); + input->setName("in2"); } if (input2) { - input2->setName(IN1); + input2->setName("in1"); } } } - else if (nodeCategory == ROTATE3D) + else if (nodeCategory == "rotate3d") { - ElementPtr axis = node->getChild(AXIS); + ElementPtr axis = node->getChild("axis"); if (axis) { node->changeChildCategory(axis, "input"); @@ -1219,8 +1146,8 @@ void Document::upgradeVersion() else if (nodeCategory == DIELECTRIC_BTDF.first) { node->setCategory(DIELECTRIC_BTDF.second); - node->removeInput(INTERIOR); - InputPtr mode = node->addInput(SCATTER_MODE, STRING_TYPE_STRING); + node->removeInput("interior"); + InputPtr mode = node->addInput("scatter_mode", STRING_TYPE_STRING); mode->setValueString("T"); } else if (nodeCategory == GENERALIZED_SCHLICK_BRDF.first) @@ -1244,32 +1171,32 @@ void Document::upgradeVersion() // Create an artistic_ior node to convert from artistic to physical parameterization. GraphElementPtr parent = node->getParent()->asA(); - NodePtr artisticIor = parent->addNode(ARTISTIC_IOR, node->getName() + "__artistic_ior", "multioutput"); - OutputPtr artisticIor_ior = artisticIor->addOutput(IOR, COLOR3); - OutputPtr artisticIor_extinction = artisticIor->addOutput(EXTINCTION, COLOR3); + NodePtr artisticIor = parent->addNode("artistic_ior", node->getName() + "__artistic_ior", "multioutput"); + OutputPtr artisticIor_ior = artisticIor->addOutput("ior", "color3"); + OutputPtr artisticIor_extinction = artisticIor->addOutput("extinction", "color3"); // Copy values and connections from conductor node to artistic_ior node. - InputPtr reflectivity = node->getInput(REFLECTIVITY); + InputPtr reflectivity = node->getInput("reflectivity"); if (reflectivity) { - InputPtr artisticIor_reflectivity = artisticIor->addInput(REFLECTIVITY, COLOR3); + InputPtr artisticIor_reflectivity = artisticIor->addInput("reflectivity", "color3"); copyAttributes(reflectivity, artisticIor_reflectivity); } - InputPtr edge_color = node->getInput(EDGE_COLOR); + InputPtr edge_color = node->getInput("edge_color"); if (edge_color) { - InputPtr artisticIor_edge_color = artisticIor->addInput(EDGE_COLOR, COLOR3); + InputPtr artisticIor_edge_color = artisticIor->addInput("edge_color", "color3"); copyAttributes(edge_color, artisticIor_edge_color); } // Update the parameterization on the conductor node // and connect it to the artistic_ior node. - node->removeInput(REFLECTIVITY); - node->removeInput(EDGE_COLOR); - InputPtr ior = node->addInput(IOR, COLOR3); + node->removeInput("reflectivity"); + node->removeInput("edge_color"); + InputPtr ior = node->addInput("ior", "color3"); ior->setNodeName(artisticIor->getName()); ior->setOutputString(artisticIor_ior->getName()); - InputPtr extinction = node->addInput(EXTINCTION, COLOR3); + InputPtr extinction = node->addInput("extinction", "color3"); extinction->setNodeName(artisticIor->getName()); extinction->setOutputString(artisticIor_extinction->getName()); } @@ -1289,17 +1216,17 @@ void Document::upgradeVersion() { node->setCategory(SUBSURFACE_BRDF.second); } - else if (nodeCategory == ARTISTIC_IOR) + else if (nodeCategory == "artistic_ior") { - OutputPtr ior = node->getOutput(IOR); + OutputPtr ior = node->getOutput("ior"); if (ior) { - ior->setType(COLOR3); + ior->setType("color3"); } - OutputPtr extinction = node->getOutput(EXTINCTION); + OutputPtr extinction = node->getOutput("extinction"); if (extinction) { - extinction->setType(COLOR3); + extinction->setType("color3"); } } @@ -1310,18 +1237,18 @@ void Document::upgradeVersion() // since we can't modify the graph while traversing it. for (InputPtr input : node->getInputs()) { - if (input->getOutputString() == IOR && input->getType() == VECTOR3) + if (input->getOutputString() == "ior" && input->getType() == "vector3") { NodePtr connectedNode = input->getConnectedNode(); - if (connectedNode && connectedNode->getCategory() == ARTISTIC_IOR) + if (connectedNode && connectedNode->getCategory() == "artistic_ior") { artisticIorConnections.push_back(input); } } - else if (input->getOutputString() == EXTINCTION && input->getType() == VECTOR3) + else if (input->getOutputString() == "extinction" && input->getType() == "vector3") { NodePtr connectedNode = input->getConnectedNode(); - if (connectedNode && connectedNode->getCategory() == ARTISTIC_IOR) + if (connectedNode && connectedNode->getCategory() == "artistic_ior") { artisticExtConnections.push_back(input); } @@ -1335,10 +1262,10 @@ void Document::upgradeVersion() NodePtr artisticIorNode = input->getConnectedNode(); ElementPtr node = input->getParent(); GraphElementPtr parent = node->getParent()->asA(); - NodePtr convert = parent->addNode(CONVERT, node->getName() + "__convert_ior", VECTOR3); - InputPtr convertInput = convert->addInput(IN, COLOR3); + NodePtr convert = parent->addNode("convert", node->getName() + "__convert_ior", "vector3"); + InputPtr convertInput = convert->addInput("in", "color3"); convertInput->setNodeName(artisticIorNode->getName()); - convertInput->setOutputString(IOR); + convertInput->setOutputString("ior"); input->setNodeName(convert->getName()); input->removeAttribute(PortElement::OUTPUT_ATTRIBUTE); } @@ -1347,10 +1274,10 @@ void Document::upgradeVersion() NodePtr artisticIorNode = input->getConnectedNode(); ElementPtr node = input->getParent(); GraphElementPtr parent = node->getParent()->asA(); - NodePtr convert = parent->addNode(CONVERT, node->getName() + "__convert_extinction", VECTOR3); - InputPtr convertInput = convert->addInput(IN, COLOR3); + NodePtr convert = parent->addNode("convert", node->getName() + "__convert_extinction", "vector3"); + InputPtr convertInput = convert->addInput("in", "color3"); convertInput->setNodeName(artisticIorNode->getName()); - convertInput->setOutputString(EXTINCTION); + convertInput->setOutputString("extinction"); input->setNodeName(convert->getName()); input->removeAttribute(PortElement::OUTPUT_ATTRIBUTE); } diff --git a/source/MaterialXCore/Element.cpp b/source/MaterialXCore/Element.cpp index 18d028efd3..5131dc8070 100644 --- a/source/MaterialXCore/Element.cpp +++ b/source/MaterialXCore/Element.cpp @@ -168,7 +168,7 @@ void Element::setChildIndex(const string& name, int index) return; } - if (index < 0 || index > (int) _childOrder.size()) + if (index < 0 || index >= (int) _childOrder.size()) { throw Exception("Invalid child index"); } diff --git a/source/MaterialXCore/Element.h b/source/MaterialXCore/Element.h index 0e00bf596a..2db357e173 100644 --- a/source/MaterialXCore/Element.h +++ b/source/MaterialXCore/Element.h @@ -869,6 +869,12 @@ class MX_CORE_API TypedElement : public Element return getAttribute(TYPE_ATTRIBUTE); } + /// Return true if the element is of color type. + bool isColorType() const + { + return getType() == "color3" || getType() == "color4"; + } + /// Return true if the element is of multi-output type. bool isMultiOutputType() const { diff --git a/source/MaterialXCore/Geom.h b/source/MaterialXCore/Geom.h index c4d7f78060..f008a26419 100644 --- a/source/MaterialXCore/Geom.h +++ b/source/MaterialXCore/Geom.h @@ -90,16 +90,7 @@ class MX_CORE_API GeomPath { return _empty ? EMPTY_STRING : UNIVERSAL_GEOM_NAME; } - string geom; - for (size_t i = 0; i < _vec.size(); i++) - { - geom += _vec[i]; - if (i + 1 < _vec.size()) - { - geom += GEOM_PATH_SEPARATOR; - } - } - return geom; + return GEOM_PATH_SEPARATOR + joinStrings(_vec, GEOM_PATH_SEPARATOR); } /// Return true if there is any geometry in common between the two paths. diff --git a/source/MaterialXCore/Util.cpp b/source/MaterialXCore/Util.cpp index d6001053c5..639b8f343c 100644 --- a/source/MaterialXCore/Util.cpp +++ b/source/MaterialXCore/Util.cpp @@ -24,7 +24,7 @@ const std::tuple LIBRARY_VERSION_TUPLE(MATERIALX_MAJOR_VERSION, bool invalidNameChar(char c) { - return !isalnum(c) && c != '_' && c != ':'; + return !isalnum((unsigned char) c) && c != '_' && c != ':'; } } // anonymous namespace @@ -93,10 +93,10 @@ StringVec splitString(const string& str, const string& sep) string joinStrings(const StringVec& stringVec, const string& sep) { - string res; - for (const string& name : stringVec) + string res = stringVec.empty() ? EMPTY_STRING : stringVec[0]; + for (size_t i = 1; i < stringVec.size(); i++) { - res = res.empty() ? name : res + sep + name; + res += sep + stringVec[i]; } return res; } diff --git a/source/MaterialXCore/Value.cpp b/source/MaterialXCore/Value.cpp index 238473d5ad..3e8c1f4462 100644 --- a/source/MaterialXCore/Value.cpp +++ b/source/MaterialXCore/Value.cpp @@ -242,7 +242,10 @@ ScopedFloatFormatting::ScopedFloatFormatting(Value::FloatFormat format, int prec _precision(Value::getFloatPrecision()) { Value::setFloatFormat(format); - Value::setFloatPrecision(precision); + if (precision >= 0) + { + Value::setFloatPrecision(precision); + } } ScopedFloatFormatting::~ScopedFloatFormatting() diff --git a/source/MaterialXCore/Value.h b/source/MaterialXCore/Value.h index 8e55a97acf..1bd29b1d2b 100644 --- a/source/MaterialXCore/Value.h +++ b/source/MaterialXCore/Value.h @@ -198,7 +198,7 @@ template class MX_CORE_API TypedValue : public Value class MX_CORE_API ScopedFloatFormatting { public: - explicit ScopedFloatFormatting(Value::FloatFormat format, int precision = 6); + explicit ScopedFloatFormatting(Value::FloatFormat format, int precision = -1); ~ScopedFloatFormatting(); private: diff --git a/source/MaterialXFormat/File.cpp b/source/MaterialXFormat/File.cpp index bb40ba54d1..62b7ec39a8 100644 --- a/source/MaterialXFormat/File.cpp +++ b/source/MaterialXFormat/File.cpp @@ -51,7 +51,7 @@ const string MATERIALX_SEARCH_PATH_ENV_VAR = "MATERIALX_SEARCH_PATH"; inline bool hasWindowsDriveSpecifier(const string& val) { - return (val.length() > 1 && std::isalpha(val[0]) && (val[1] == ':')); + return (val.length() > 1 && std::isalpha((unsigned char) val[0]) && (val[1] == ':')); } // diff --git a/source/MaterialXFormat/Util.cpp b/source/MaterialXFormat/Util.cpp index 32feda4d0d..48ded1d6b1 100644 --- a/source/MaterialXFormat/Util.cpp +++ b/source/MaterialXFormat/Util.cpp @@ -234,7 +234,7 @@ FileSearchPath getDefaultDataSearchPath() } currentPath = currentPath.getParentPath(); } - return FileSearchPath(); + return FileSearchPath(); } MATERIALX_NAMESPACE_END diff --git a/source/MaterialXFormat/Util.h b/source/MaterialXFormat/Util.h index 46f55c41ee..c7ef0c6d38 100644 --- a/source/MaterialXFormat/Util.h +++ b/source/MaterialXFormat/Util.h @@ -62,7 +62,7 @@ MX_FORMAT_API FileSearchPath getSourceSearchPath(ConstDocumentPtr doc); /// Return a file search path to the default data library folder. /// The module path and all parent paths are examined to until either there is -/// no parent or the library folder is found. +/// no parent or the library folder is found. MX_FORMAT_API FileSearchPath getDefaultDataSearchPath(); MATERIALX_NAMESPACE_END diff --git a/source/MaterialXFormat/XmlIo.cpp b/source/MaterialXFormat/XmlIo.cpp index 67d41225a4..2bc0908008 100644 --- a/source/MaterialXFormat/XmlIo.cpp +++ b/source/MaterialXFormat/XmlIo.cpp @@ -353,7 +353,7 @@ void readFromXmlFile(DocumentPtr doc, FilePath filename, FileSearchPath searchPa documentFromXml(doc, xmlDoc, searchPath, readOptions); } -void readFromXmlString(DocumentPtr doc, const string& str, FileSearchPath searchPath, const XmlReadOptions* readOptions) +void readFromXmlString(DocumentPtr doc, const string& str, const FileSearchPath& searchPath, const XmlReadOptions* readOptions) { std::istringstream stream(str); readFromXmlStream(doc, stream, searchPath, readOptions); diff --git a/source/MaterialXFormat/XmlIo.h b/source/MaterialXFormat/XmlIo.h index b098c0fb3a..3aa8d41ed5 100644 --- a/source/MaterialXFormat/XmlIo.h +++ b/source/MaterialXFormat/XmlIo.h @@ -146,7 +146,7 @@ MX_FORMAT_API void readFromXmlFile(DocumentPtr doc, /// If provided, then the given options will affect the behavior of the /// read function. Defaults to a null pointer. /// @throws ExceptionParseError if the document cannot be parsed. -MX_FORMAT_API void readFromXmlString(DocumentPtr doc, const string& str, FileSearchPath searchPath = FileSearchPath(), const XmlReadOptions* readOptions = nullptr); +MX_FORMAT_API void readFromXmlString(DocumentPtr doc, const string& str, const FileSearchPath& searchPath = FileSearchPath(), const XmlReadOptions* readOptions = nullptr); /// @} /// @name Write Functions diff --git a/source/MaterialXGenGlsl/GlslResourceBindingContext.cpp b/source/MaterialXGenGlsl/GlslResourceBindingContext.cpp index 3aad355d60..d4496bf154 100644 --- a/source/MaterialXGenGlsl/GlslResourceBindingContext.cpp +++ b/source/MaterialXGenGlsl/GlslResourceBindingContext.cpp @@ -58,7 +58,7 @@ void GlslResourceBindingContext::emitDirectives(GenContext& context, ShaderStage void GlslResourceBindingContext::emitResourceBindings(GenContext& context, const VariableBlock& uniforms, ShaderStage& stage) { - ShaderGenerator& generator = context.getShaderGenerator(); + const ShaderGenerator& generator = context.getShaderGenerator(); const Syntax& syntax = generator.getSyntax(); // First, emit all value uniforms in a block with single layout binding @@ -93,7 +93,7 @@ void GlslResourceBindingContext::emitResourceBindings(GenContext& context, const // Second, emit all sampler uniforms as separate uniforms with separate layout bindings for (auto uniform : uniforms.getVariableOrder()) { - if (uniform->getType() == Type::FILENAME) + if (*uniform->getType() == *Type::FILENAME) { generator.emitString("layout (binding=" + std::to_string(_separateBindingLocation ? _hwUniformBindLocation++ : _hwSamplerBindLocation++) + ") " + syntax.getUniformQualifier() + " ", stage); generator.emitVariableDeclaration(uniform, EMPTY_STRING, context, stage, false); @@ -108,7 +108,7 @@ void GlslResourceBindingContext::emitStructuredResourceBindings(GenContext& cont ShaderStage& stage, const std::string& structInstanceName, const std::string& arraySuffix) { - ShaderGenerator& generator = context.getShaderGenerator(); + const ShaderGenerator& generator = context.getShaderGenerator(); const Syntax& syntax = generator.getSyntax(); // Glsl structures need to be aligned. We make a best effort to base align struct members and add diff --git a/source/MaterialXGenGlsl/GlslShaderGenerator.cpp b/source/MaterialXGenGlsl/GlslShaderGenerator.cpp index 766b61ec05..f8ed1a4892 100644 --- a/source/MaterialXGenGlsl/GlslShaderGenerator.cpp +++ b/source/MaterialXGenGlsl/GlslShaderGenerator.cpp @@ -6,15 +6,8 @@ #include #include -#include -#include -#include -#include -#include #include #include -#include -#include #include #include #include @@ -23,9 +16,6 @@ #include #include #include -#include -#include -#include #include #include @@ -34,6 +24,15 @@ #include #include #include +#include +#include +#include +#include +#include +#include +#include +#include +#include #include #include #include @@ -58,17 +57,17 @@ GlslShaderGenerator::GlslShaderGenerator() : // StringVec elementNames; - + // elementNames = { // - "IM_switch_float_" + GlslShaderGenerator::TARGET, - "IM_switch_color3_" + GlslShaderGenerator::TARGET, - "IM_switch_color4_" + GlslShaderGenerator::TARGET, + "IM_switch_float_" + GlslShaderGenerator::TARGET, + "IM_switch_color3_" + GlslShaderGenerator::TARGET, + "IM_switch_color4_" + GlslShaderGenerator::TARGET, "IM_switch_vector2_" + GlslShaderGenerator::TARGET, "IM_switch_vector3_" + GlslShaderGenerator::TARGET, "IM_switch_vector4_" + GlslShaderGenerator::TARGET, - + // "IM_switch_floatI_" + GlslShaderGenerator::TARGET, "IM_switch_color3I_" + GlslShaderGenerator::TARGET, @@ -87,7 +86,7 @@ GlslShaderGenerator::GlslShaderGenerator() : "IM_swizzle_float_vector2_" + GlslShaderGenerator::TARGET, "IM_swizzle_float_vector3_" + GlslShaderGenerator::TARGET, "IM_swizzle_float_vector4_" + GlslShaderGenerator::TARGET, - + // "IM_swizzle_color3_float_" + GlslShaderGenerator::TARGET, "IM_swizzle_color3_color3_" + GlslShaderGenerator::TARGET, @@ -95,7 +94,7 @@ GlslShaderGenerator::GlslShaderGenerator() : "IM_swizzle_color3_vector2_" + GlslShaderGenerator::TARGET, "IM_swizzle_color3_vector3_" + GlslShaderGenerator::TARGET, "IM_swizzle_color3_vector4_" + GlslShaderGenerator::TARGET, - + // "IM_swizzle_color4_float_" + GlslShaderGenerator::TARGET, "IM_swizzle_color4_color3_" + GlslShaderGenerator::TARGET, @@ -103,7 +102,7 @@ GlslShaderGenerator::GlslShaderGenerator() : "IM_swizzle_color4_vector2_" + GlslShaderGenerator::TARGET, "IM_swizzle_color4_vector3_" + GlslShaderGenerator::TARGET, "IM_swizzle_color4_vector4_" + GlslShaderGenerator::TARGET, - + // "IM_swizzle_vector2_float_" + GlslShaderGenerator::TARGET, "IM_swizzle_vector2_color3_" + GlslShaderGenerator::TARGET, @@ -111,7 +110,7 @@ GlslShaderGenerator::GlslShaderGenerator() : "IM_swizzle_vector2_vector2_" + GlslShaderGenerator::TARGET, "IM_swizzle_vector2_vector3_" + GlslShaderGenerator::TARGET, "IM_swizzle_vector2_vector4_" + GlslShaderGenerator::TARGET, - + // "IM_swizzle_vector3_float_" + GlslShaderGenerator::TARGET, "IM_swizzle_vector3_color3_" + GlslShaderGenerator::TARGET, @@ -119,7 +118,7 @@ GlslShaderGenerator::GlslShaderGenerator() : "IM_swizzle_vector3_vector2_" + GlslShaderGenerator::TARGET, "IM_swizzle_vector3_vector3_" + GlslShaderGenerator::TARGET, "IM_swizzle_vector3_vector4_" + GlslShaderGenerator::TARGET, - + // "IM_swizzle_vector4_float_" + GlslShaderGenerator::TARGET, "IM_swizzle_vector4_color3_" + GlslShaderGenerator::TARGET, @@ -166,16 +165,16 @@ GlslShaderGenerator::GlslShaderGenerator() : registerImplementation(elementNames, CombineNode::create); // - registerImplementation("IM_position_vector3_" + GlslShaderGenerator::TARGET, PositionNodeGlsl::create); + registerImplementation("IM_position_vector3_" + GlslShaderGenerator::TARGET, HwPositionNode::create); // - registerImplementation("IM_normal_vector3_" + GlslShaderGenerator::TARGET, NormalNodeGlsl::create); + registerImplementation("IM_normal_vector3_" + GlslShaderGenerator::TARGET, HwNormalNode::create); // - registerImplementation("IM_tangent_vector3_" + GlslShaderGenerator::TARGET, TangentNodeGlsl::create); + registerImplementation("IM_tangent_vector3_" + GlslShaderGenerator::TARGET, HwTangentNode::create); // - registerImplementation("IM_bitangent_vector3_" + GlslShaderGenerator::TARGET, BitangentNodeGlsl::create); + registerImplementation("IM_bitangent_vector3_" + GlslShaderGenerator::TARGET, HwBitangentNode::create); // - registerImplementation("IM_texcoord_vector2_" + GlslShaderGenerator::TARGET, TexCoordNodeGlsl::create); - registerImplementation("IM_texcoord_vector3_" + GlslShaderGenerator::TARGET, TexCoordNodeGlsl::create); + registerImplementation("IM_texcoord_vector2_" + GlslShaderGenerator::TARGET, HwTexCoordNode::create); + registerImplementation("IM_texcoord_vector3_" + GlslShaderGenerator::TARGET, HwTexCoordNode::create); // registerImplementation("IM_geomcolor_float_" + GlslShaderGenerator::TARGET, GeomColorNodeGlsl::create); registerImplementation("IM_geomcolor_color3_" + GlslShaderGenerator::TARGET, GeomColorNodeGlsl::create); @@ -195,9 +194,11 @@ GlslShaderGenerator::GlslShaderGenerator() : registerImplementation("IM_geompropvalue_string_" + GlslShaderGenerator::TARGET, GeomPropValueNodeGlslAsUniform::create); // - registerImplementation("IM_frame_float_" + GlslShaderGenerator::TARGET, FrameNodeGlsl::create); + registerImplementation("IM_frame_float_" + GlslShaderGenerator::TARGET, HwFrameNode::create); // - registerImplementation("IM_time_float_" + GlslShaderGenerator::TARGET, TimeNodeGlsl::create); + registerImplementation("IM_time_float_" + GlslShaderGenerator::TARGET, HwTimeNode::create); + // + registerImplementation("IM_viewdirection_vector3_" + GlslShaderGenerator::TARGET, HwViewDirectionNode::create); // registerImplementation("IM_surface_" + GlslShaderGenerator::TARGET, SurfaceNodeGlsl::create); @@ -228,13 +229,13 @@ GlslShaderGenerator::GlslShaderGenerator() : registerImplementation(elementNames, BlurNodeGlsl::create); // elementNames = { @@ -279,9 +280,7 @@ ShaderPtr GlslShaderGenerator::generate(const string& name, ElementPtr element, { ShaderPtr shader = createShader(name, element, context); - // Turn on fixed float formatting to make sure float values are - // emitted with a decimal point and not as integers, and to avoid - // any scientific notation which isn't supported by all OpenGL targets. + // Request fixed floating-point notation for consistency across targets. ScopedFloatFormatting fmt(Value::FloatFormatFixed); // Make sure we initialize/reset the binding context before generation. @@ -557,7 +556,7 @@ void GlslShaderGenerator::emitPixelStage(const ShaderGraph& graph, GenContext& c bool lighting = requiresLighting(graph); // Define directional albedo approach - if (lighting || context.getOptions().hwWriteAlbedoTable) + if (lighting || context.getOptions().hwWriteAlbedoTable || context.getOptions().hwWriteEnvPrefilter) { emitLine("#define DIRECTIONAL_ALBEDO_METHOD " + std::to_string(int(context.getOptions().hwDirectionalAlbedoMethod)), stage, false); emitLineBreak(stage); @@ -591,7 +590,14 @@ void GlslShaderGenerator::emitPixelStage(const ShaderGraph& graph, GenContext& c // Emit directional albedo table code. if (context.getOptions().hwWriteAlbedoTable) { - emitLibraryInclude("pbrlib/genglsl/lib/mx_table.glsl", context, stage); + emitLibraryInclude("pbrlib/genglsl/lib/mx_generate_albedo_table.glsl", context, stage); + emitLineBreak(stage); + } + + // Emit environment prefiltering code + if (context.getOptions().hwWriteEnvPrefilter) + { + emitLibraryInclude("pbrlib/genglsl/lib/mx_generate_prefilter_env.glsl", context, stage); emitLineBreak(stage); } @@ -640,6 +646,10 @@ void GlslShaderGenerator::emitPixelStage(const ShaderGraph& graph, GenContext& c { emitLine(outputSocket->getVariable() + " = vec4(mx_generate_dir_albedo_table(), 1.0)", stage); } + else if (context.getOptions().hwWriteEnvPrefilter) + { + emitLine(outputSocket->getVariable() + " = vec4(mx_generate_prefilter_env(), 1.0)", stage); + } else { // Add all function calls. @@ -772,11 +782,11 @@ void GlslShaderGenerator::toVec4(const TypeDesc* type, string& variable) { variable = "vec4(" + variable + ", 0.0, 1.0)"; } - else if (type == Type::FLOAT || type == Type::INTEGER) + else if (*type == *Type::FLOAT || *type == *Type::INTEGER) { variable = "vec4(" + variable + ", " + variable + ", " + variable + ", 1.0)"; } - else if (type == Type::BSDF || type == Type::EDF) + else if (*type == *Type::BSDF || *type == *Type::EDF) { variable = "vec4(" + variable + ", 1.0)"; } @@ -792,7 +802,7 @@ void GlslShaderGenerator::emitVariableDeclaration(const ShaderPort* variable, co bool assignValue) const { // A file texture input needs special handling on GLSL - if (variable->getType() == Type::FILENAME) + if (*variable->getType() == *Type::FILENAME) { // Samplers must always be uniforms string str = qualifier.empty() ? EMPTY_STRING : qualifier + " "; @@ -803,7 +813,7 @@ void GlslShaderGenerator::emitVariableDeclaration(const ShaderPort* variable, co string str = qualifier.empty() ? EMPTY_STRING : qualifier + " "; // Varying parameters of type int must be flat qualified on output from vertex stage and // input to pixel stage. The only way to get these is with geompropvalue_integer nodes. - if (qualifier.empty() && variable->getType() == Type::INTEGER && !assignValue && variable->getName().rfind(HW::T_IN_GEOMPROP, 0) == 0) + if (qualifier.empty() && *variable->getType() == *Type::INTEGER && !assignValue && variable->getName().rfind(HW::T_IN_GEOMPROP, 0) == 0) { str += GlslSyntax::FLAT_QUALIFIER + " "; } @@ -860,7 +870,7 @@ ShaderNodeImplPtr GlslShaderGenerator::getImplementation(const NodeDef& nodedef, if (implElement->isA()) { // Use a compound implementation. - if (outputType == Type::LIGHTSHADER) + if (*outputType == *Type::LIGHTSHADER) { impl = LightCompoundNodeGlsl::create(); } @@ -903,36 +913,9 @@ ShaderNodeImplPtr GlslShaderGenerator::getImplementation(const NodeDef& nodedef, return impl; } -const string GlslImplementation::SPACE = "space"; -const string GlslImplementation::TO_SPACE = "tospace"; -const string GlslImplementation::FROM_SPACE = "fromspace"; -const string GlslImplementation::WORLD = "world"; -const string GlslImplementation::OBJECT = "object"; -const string GlslImplementation::MODEL = "model"; -const string GlslImplementation::INDEX = "index"; -const string GlslImplementation::GEOMPROP = "geomprop"; - -namespace -{ - -// List name of inputs that are not to be editable and -// published as shader uniforms in GLSL. -const std::set IMMUTABLE_INPUTS = -{ - // Geometric node inputs are immutable since a shader needs regeneration if they change. - "index", "space", "attrname" -}; - -} // anonymous namespace - const string& GlslImplementation::getTarget() const { return GlslShaderGenerator::TARGET; } -bool GlslImplementation::isEditable(const ShaderInput& input) const -{ - return IMMUTABLE_INPUTS.count(input.getName()) == 0; -} - MATERIALX_NAMESPACE_END diff --git a/source/MaterialXGenGlsl/GlslShaderGenerator.h b/source/MaterialXGenGlsl/GlslShaderGenerator.h index 1df2ace543..aafd665140 100644 --- a/source/MaterialXGenGlsl/GlslShaderGenerator.h +++ b/source/MaterialXGenGlsl/GlslShaderGenerator.h @@ -45,7 +45,7 @@ class MX_GENGLSL_API GlslShaderGenerator : public HwShaderGenerator ShaderNodeImplPtr getImplementation(const NodeDef& nodedef, GenContext& context) const override; /// Determine the prefix of vertex data variables. - virtual string getVertexDataPrefix(const VariableBlock& vertexData) const; + string getVertexDataPrefix(const VariableBlock& vertexData) const override; public: /// Unique identifier for this generator target @@ -88,35 +88,13 @@ class MX_GENGLSL_API GlslShaderGenerator : public HwShaderGenerator }; /// Base class for common GLSL node implementations -class MX_GENGLSL_API GlslImplementation : public ShaderNodeImpl +class MX_GENGLSL_API GlslImplementation : public HwImplementation { public: const string& getTarget() const override; - bool isEditable(const ShaderInput& input) const override; - protected: GlslImplementation() { } - - // Integer identifiers for coordinate spaces. - // The order must match the order given for - // the space enum string in stdlib. - enum Space - { - MODEL_SPACE = 0, - OBJECT_SPACE = 1, - WORLD_SPACE = 2 - }; - - /// Internal string constants - static const string SPACE; - static const string TO_SPACE; - static const string FROM_SPACE; - static const string WORLD; - static const string OBJECT; - static const string MODEL; - static const string INDEX; - static const string GEOMPROP; }; MATERIALX_NAMESPACE_END diff --git a/source/MaterialXGenGlsl/GlslSyntax.cpp b/source/MaterialXGenGlsl/GlslSyntax.cpp index afd6f033dc..2f82250394 100644 --- a/source/MaterialXGenGlsl/GlslSyntax.cpp +++ b/source/MaterialXGenGlsl/GlslSyntax.cpp @@ -364,7 +364,7 @@ bool GlslSyntax::remapEnumeration(const string& value, const TypeDesc* type, con // Don't convert already supported types // or filenames and arrays. if (typeSupported(type) || - type == Type::FILENAME || (type && type->isArray())) + *type == *Type::FILENAME || (type && type->isArray())) { return false; } diff --git a/source/MaterialXGenGlsl/Nodes/BitangentNodeGlsl.cpp b/source/MaterialXGenGlsl/Nodes/BitangentNodeGlsl.cpp deleted file mode 100644 index 6f515824e7..0000000000 --- a/source/MaterialXGenGlsl/Nodes/BitangentNodeGlsl.cpp +++ /dev/null @@ -1,135 +0,0 @@ -// -// Copyright Contributors to the MaterialX Project -// SPDX-License-Identifier: Apache-2.0 -// - -#include - -#include - -MATERIALX_NAMESPACE_BEGIN - -ShaderNodeImplPtr BitangentNodeGlsl::create() -{ - return std::make_shared(); -} - -void BitangentNodeGlsl::createVariables(const ShaderNode& node, GenContext& context, Shader& shader) const -{ - const GenOptions& options = context.getOptions(); - - ShaderStage& vs = shader.getStage(Stage::VERTEX); - ShaderStage& ps = shader.getStage(Stage::PIXEL); - - if (options.hwImplicitBitangents) - { - addStageInput(HW::VERTEX_INPUTS, Type::VECTOR3, HW::T_IN_NORMAL, vs); - addStageInput(HW::VERTEX_INPUTS, Type::VECTOR3, HW::T_IN_TANGENT, vs); - } - else - { - addStageInput(HW::VERTEX_INPUTS, Type::VECTOR3, HW::T_IN_BITANGENT, vs); - } - - const ShaderInput* spaceInput = node.getInput(SPACE); - const int space = spaceInput ? spaceInput->getValue()->asA() : OBJECT_SPACE; - if (space == WORLD_SPACE) - { - addStageConnector(HW::VERTEX_DATA, Type::VECTOR3, HW::T_BITANGENT_WORLD, vs, ps); - addStageUniform(HW::PRIVATE_UNIFORMS, Type::MATRIX44, HW::T_WORLD_MATRIX, vs); - - if (options.hwImplicitBitangents) - { - addStageConnector(HW::VERTEX_DATA, Type::VECTOR3, HW::T_NORMAL_WORLD, vs, ps); - addStageConnector(HW::VERTEX_DATA, Type::VECTOR3, HW::T_TANGENT_WORLD, vs, ps); - addStageUniform(HW::PRIVATE_UNIFORMS, Type::MATRIX44, HW::T_WORLD_INVERSE_TRANSPOSE_MATRIX, vs); - } - } - else - { - addStageConnector(HW::VERTEX_DATA, Type::VECTOR3, HW::T_BITANGENT_OBJECT, vs, ps); - } -} - -void BitangentNodeGlsl::emitFunctionCall(const ShaderNode& node, GenContext& context, ShaderStage& stage) const -{ - const GlslShaderGenerator& shadergen = static_cast(context.getShaderGenerator()); - const GenOptions& options = context.getOptions(); - - const ShaderInput* spaceInput = node.getInput(SPACE); - const int space = spaceInput ? spaceInput->getValue()->asA() : OBJECT_SPACE; - - DEFINE_SHADER_STAGE(stage, Stage::VERTEX) - { - VariableBlock& vertexData = stage.getOutputBlock(HW::VERTEX_DATA); - const string prefix = shadergen.getVertexDataPrefix(vertexData); - if (space == WORLD_SPACE) - { - ShaderPort* bitangent = vertexData[HW::T_BITANGENT_WORLD]; - - if (!bitangent->isEmitted()) - { - bitangent->setEmitted(); - - if (options.hwImplicitBitangents) - { - ShaderPort* normal = vertexData[HW::T_NORMAL_WORLD]; - if (!normal->isEmitted()) - { - normal->setEmitted(); - shadergen.emitLine(prefix + normal->getVariable() + " = normalize((" + HW::T_WORLD_INVERSE_TRANSPOSE_MATRIX + " * vec4(" + HW::T_IN_NORMAL + ", 0.0)).xyz)", stage); - } - ShaderPort* tangent = vertexData[HW::T_TANGENT_WORLD]; - if (!tangent->isEmitted()) - { - tangent->setEmitted(); - shadergen.emitLine(prefix + tangent->getVariable() + " = normalize((" + HW::T_WORLD_MATRIX + " * vec4(" + HW::T_IN_TANGENT + ", 0.0)).xyz)", stage); - } - shadergen.emitLine(prefix + bitangent->getVariable() + " = cross(" + prefix + normal->getVariable() + ", " + prefix + tangent->getVariable() + ")", stage); - } - else - { - shadergen.emitLine(prefix + bitangent->getVariable() + " = normalize((" + HW::T_WORLD_MATRIX + " * vec4(" + HW::T_IN_BITANGENT + ", 0.0)).xyz)", stage); - } - } - } - else - { - ShaderPort* bitangent = vertexData[HW::T_BITANGENT_OBJECT]; - if (!bitangent->isEmitted()) - { - bitangent->setEmitted(); - - if (options.hwImplicitBitangents) - { - shadergen.emitLine(prefix + bitangent->getVariable() + " = cross(" + HW::T_IN_NORMAL + ", " + HW::T_IN_TANGENT + ")", stage); - } - else - { - shadergen.emitLine(prefix + bitangent->getVariable() + " = " + HW::T_IN_BITANGENT, stage); - } - } - } - } - - DEFINE_SHADER_STAGE(stage, Stage::PIXEL) - { - VariableBlock& vertexData = stage.getInputBlock(HW::VERTEX_DATA); - const string prefix = shadergen.getVertexDataPrefix(vertexData); - shadergen.emitLineBegin(stage); - shadergen.emitOutput(node.getOutput(), true, false, context, stage); - if (space == WORLD_SPACE) - { - const ShaderPort* bitangent = vertexData[HW::T_BITANGENT_WORLD]; - shadergen.emitString(" = normalize(" + prefix + bitangent->getVariable() + ")", stage); - } - else - { - const ShaderPort* bitangent = vertexData[HW::T_BITANGENT_OBJECT]; - shadergen.emitString(" = normalize(" + prefix + bitangent->getVariable() + ")", stage); - } - shadergen.emitLineEnd(stage); - } -} - -MATERIALX_NAMESPACE_END diff --git a/source/MaterialXGenGlsl/Nodes/FrameNodeGlsl.cpp b/source/MaterialXGenGlsl/Nodes/FrameNodeGlsl.cpp deleted file mode 100644 index b6dbb2002b..0000000000 --- a/source/MaterialXGenGlsl/Nodes/FrameNodeGlsl.cpp +++ /dev/null @@ -1,35 +0,0 @@ -// -// Copyright Contributors to the MaterialX Project -// SPDX-License-Identifier: Apache-2.0 -// - -#include - -#include - -MATERIALX_NAMESPACE_BEGIN - -ShaderNodeImplPtr FrameNodeGlsl::create() -{ - return std::make_shared(); -} - -void FrameNodeGlsl::createVariables(const ShaderNode&, GenContext&, Shader& shader) const -{ - ShaderStage& ps = shader.getStage(Stage::PIXEL); - addStageUniform(HW::PRIVATE_UNIFORMS, Type::FLOAT, HW::T_FRAME, ps); -} - -void FrameNodeGlsl::emitFunctionCall(const ShaderNode& node, GenContext& context, ShaderStage& stage) const -{ - DEFINE_SHADER_STAGE(stage, Stage::PIXEL) - { - const ShaderGenerator& shadergen = context.getShaderGenerator(); - shadergen.emitLineBegin(stage); - shadergen.emitOutput(node.getOutput(), true, false, context, stage); - shadergen.emitString(" = " + HW::T_FRAME, stage); - shadergen.emitLineEnd(stage); - } -} - -MATERIALX_NAMESPACE_END diff --git a/source/MaterialXGenGlsl/Nodes/GeomColorNodeGlsl.cpp b/source/MaterialXGenGlsl/Nodes/GeomColorNodeGlsl.cpp index 7e24331f93..bdcb4c0fac 100644 --- a/source/MaterialXGenGlsl/Nodes/GeomColorNodeGlsl.cpp +++ b/source/MaterialXGenGlsl/Nodes/GeomColorNodeGlsl.cpp @@ -49,11 +49,11 @@ void GeomColorNodeGlsl::emitFunctionCall(const ShaderNode& node, GenContext& con DEFINE_SHADER_STAGE(stage, Stage::PIXEL) { string suffix = ""; - if (output->getType() == Type::FLOAT) + if (*output->getType() == *Type::FLOAT) { suffix = ".r"; } - else if (output->getType() == Type::COLOR3) + else if (*output->getType() == *Type::COLOR3) { suffix = ".rgb"; } diff --git a/source/MaterialXGenGlsl/Nodes/HeightToNormalNodeGlsl.cpp b/source/MaterialXGenGlsl/Nodes/HeightToNormalNodeGlsl.cpp index 157cd5be04..14716eee1e 100644 --- a/source/MaterialXGenGlsl/Nodes/HeightToNormalNodeGlsl.cpp +++ b/source/MaterialXGenGlsl/Nodes/HeightToNormalNodeGlsl.cpp @@ -33,6 +33,11 @@ ShaderNodeImplPtr HeightToNormalNodeGlsl::create() return std::make_shared(); } +void HeightToNormalNodeGlsl::createVariables(const ShaderNode&, GenContext&, Shader&) const +{ + // Default filter kernels from ConvolutionNode are not used by this derived class. +} + void HeightToNormalNodeGlsl::computeSampleOffsetStrings(const string& sampleSizeName, const string& offsetTypeString, unsigned int, StringVec& offsetStrings) const { @@ -49,7 +54,7 @@ void HeightToNormalNodeGlsl::computeSampleOffsetStrings(const string& sampleSize bool HeightToNormalNodeGlsl::acceptsInputType(const TypeDesc* type) const { // Only support inputs which are float scalar - return (type == Type::FLOAT && type->isScalar()); + return (*type == *Type::FLOAT && type->isScalar()); } void HeightToNormalNodeGlsl::emitFunctionDefinition(const ShaderNode&, GenContext& context, ShaderStage& stage) const diff --git a/source/MaterialXGenGlsl/Nodes/HeightToNormalNodeGlsl.h b/source/MaterialXGenGlsl/Nodes/HeightToNormalNodeGlsl.h index 638623ea43..fc6e6b421f 100644 --- a/source/MaterialXGenGlsl/Nodes/HeightToNormalNodeGlsl.h +++ b/source/MaterialXGenGlsl/Nodes/HeightToNormalNodeGlsl.h @@ -18,6 +18,8 @@ class MX_GENGLSL_API HeightToNormalNodeGlsl : public ConvolutionNode public: static ShaderNodeImplPtr create(); + void createVariables(const ShaderNode&, GenContext&, Shader& shader) const override; + void emitFunctionDefinition(const ShaderNode& node, GenContext& context, ShaderStage& stage) const override; void emitFunctionCall(const ShaderNode& node, GenContext& context, ShaderStage& stage) const override; diff --git a/source/MaterialXGenGlsl/Nodes/PositionNodeGlsl.cpp b/source/MaterialXGenGlsl/Nodes/PositionNodeGlsl.cpp deleted file mode 100644 index d37af520b2..0000000000 --- a/source/MaterialXGenGlsl/Nodes/PositionNodeGlsl.cpp +++ /dev/null @@ -1,87 +0,0 @@ -// -// Copyright Contributors to the MaterialX Project -// SPDX-License-Identifier: Apache-2.0 -// - -#include - -#include - -MATERIALX_NAMESPACE_BEGIN - -ShaderNodeImplPtr PositionNodeGlsl::create() -{ - return std::make_shared(); -} - -void PositionNodeGlsl::createVariables(const ShaderNode& node, GenContext&, Shader& shader) const -{ - ShaderStage vs = shader.getStage(Stage::VERTEX); - ShaderStage ps = shader.getStage(Stage::PIXEL); - - addStageInput(HW::VERTEX_INPUTS, Type::VECTOR3, HW::T_IN_POSITION, vs); - - const ShaderInput* spaceInput = node.getInput(SPACE); - const int space = spaceInput ? spaceInput->getValue()->asA() : OBJECT_SPACE; - if (space == WORLD_SPACE) - { - addStageConnector(HW::VERTEX_DATA, Type::VECTOR3, HW::T_POSITION_WORLD, vs, ps); - } - else - { - addStageConnector(HW::VERTEX_DATA, Type::VECTOR3, HW::T_POSITION_OBJECT, vs, ps); - } -} - -void PositionNodeGlsl::emitFunctionCall(const ShaderNode& node, GenContext& context, ShaderStage& stage) const -{ - const GlslShaderGenerator& shadergen = static_cast(context.getShaderGenerator()); - - const ShaderInput* spaceInput = node.getInput(SPACE); - const int space = spaceInput ? spaceInput->getValue()->asA() : OBJECT_SPACE; - - DEFINE_SHADER_STAGE(stage, Stage::VERTEX) - { - VariableBlock& vertexData = stage.getOutputBlock(HW::VERTEX_DATA); - const string prefix = shadergen.getVertexDataPrefix(vertexData); - if (space == WORLD_SPACE) - { - ShaderPort* position = vertexData[HW::T_POSITION_WORLD]; - if (!position->isEmitted()) - { - position->setEmitted(); - shadergen.emitLine(prefix + position->getVariable() + " = hPositionWorld.xyz", stage); - } - } - else - { - ShaderPort* position = vertexData[HW::T_POSITION_OBJECT]; - if (!position->isEmitted()) - { - position->setEmitted(); - shadergen.emitLine(prefix + position->getVariable() + " = " + HW::T_IN_POSITION, stage); - } - } - } - - DEFINE_SHADER_STAGE(stage, Stage::PIXEL) - { - VariableBlock& vertexData = stage.getInputBlock(HW::VERTEX_DATA); - const string prefix = shadergen.getVertexDataPrefix(vertexData); - shadergen.emitLineBegin(stage); - shadergen.emitOutput(node.getOutput(), true, false, context, stage); - if (space == WORLD_SPACE) - { - const ShaderPort* position = vertexData[HW::T_POSITION_WORLD]; - shadergen.emitString(" = " + prefix + position->getVariable(), stage); - } - else - { - const ShaderPort* position = vertexData[HW::T_POSITION_OBJECT]; - shadergen.emitString(" = " + prefix + position->getVariable(), stage); - } - shadergen.emitLineEnd(stage); - } -} - -MATERIALX_NAMESPACE_END diff --git a/source/MaterialXGenGlsl/Nodes/SurfaceNodeGlsl.cpp b/source/MaterialXGenGlsl/Nodes/SurfaceNodeGlsl.cpp index c83fbe1d78..2e222f6bcc 100644 --- a/source/MaterialXGenGlsl/Nodes/SurfaceNodeGlsl.cpp +++ b/source/MaterialXGenGlsl/Nodes/SurfaceNodeGlsl.cpp @@ -45,8 +45,8 @@ void SurfaceNodeGlsl::createVariables(const ShaderNode&, GenContext& context, Sh { // TODO: // The surface shader needs position, normal, view position and light sources. We should solve this by adding some - // dependency mechanism so this implementation can be set to depend on the PositionNodeGlsl, NormalNodeGlsl - // ViewDirectionNodeGlsl and LightNodeGlsl nodes instead? This is where the MaterialX attribute "internalgeomprops" + // dependency mechanism so this implementation can be set to depend on the HwPositionNode, HwNormalNode + // HwViewDirectionNode and LightNodeGlsl nodes instead? This is where the MaterialX attribute "internalgeomprops" // is needed. // ShaderStage& vs = shader.getStage(Stage::VERTEX); diff --git a/source/MaterialXGenGlsl/Nodes/SurfaceShaderNodeGlsl.cpp b/source/MaterialXGenGlsl/Nodes/SurfaceShaderNodeGlsl.cpp index 00362b1cab..5e97b8ffc6 100644 --- a/source/MaterialXGenGlsl/Nodes/SurfaceShaderNodeGlsl.cpp +++ b/source/MaterialXGenGlsl/Nodes/SurfaceShaderNodeGlsl.cpp @@ -24,8 +24,8 @@ void SurfaceShaderNodeGlsl::createVariables(const ShaderNode&, GenContext& conte { // TODO: // The surface shader needs position, view position and light sources. We should solve this by adding some - // dependency mechanism so this implementation can be set to depend on the PositionNodeGlsl, - // ViewDirectionNodeGlsl and LightNodeGlsl nodes instead? This is where the MaterialX attribute "internalgeomprops" + // dependency mechanism so this implementation can be set to depend on the HwPositionNode, + // HwViewDirectionNode and LightNodeGlsl nodes instead? This is where the MaterialX attribute "internalgeomprops" // is needed. // ShaderStage& vs = shader.getStage(Stage::VERTEX); diff --git a/source/MaterialXGenGlsl/Nodes/TexCoordNodeGlsl.cpp b/source/MaterialXGenGlsl/Nodes/TexCoordNodeGlsl.cpp deleted file mode 100644 index 846c77f5b7..0000000000 --- a/source/MaterialXGenGlsl/Nodes/TexCoordNodeGlsl.cpp +++ /dev/null @@ -1,62 +0,0 @@ -// -// Copyright Contributors to the MaterialX Project -// SPDX-License-Identifier: Apache-2.0 -// - -#include - -#include - -MATERIALX_NAMESPACE_BEGIN - -ShaderNodeImplPtr TexCoordNodeGlsl::create() -{ - return std::make_shared(); -} - -void TexCoordNodeGlsl::createVariables(const ShaderNode& node, GenContext&, Shader& shader) const -{ - const ShaderOutput* output = node.getOutput(); - const ShaderInput* indexInput = node.getInput(INDEX); - const string index = indexInput ? indexInput->getValue()->getValueString() : "0"; - - ShaderStage& vs = shader.getStage(Stage::VERTEX); - ShaderStage& ps = shader.getStage(Stage::PIXEL); - - addStageInput(HW::VERTEX_INPUTS, output->getType(), HW::T_IN_TEXCOORD + "_" + index, vs); - addStageConnector(HW::VERTEX_DATA, output->getType(), HW::T_TEXCOORD + "_" + index, vs, ps); -} - -void TexCoordNodeGlsl::emitFunctionCall(const ShaderNode& node, GenContext& context, ShaderStage& stage) const -{ - const GlslShaderGenerator& shadergen = static_cast(context.getShaderGenerator()); - - const ShaderInput* indexInput = node.getInput(INDEX); - const string index = indexInput ? indexInput->getValue()->getValueString() : "0"; - const string variable = HW::T_TEXCOORD + "_" + index; - - DEFINE_SHADER_STAGE(stage, Stage::VERTEX) - { - VariableBlock& vertexData = stage.getOutputBlock(HW::VERTEX_DATA); - const string prefix = shadergen.getVertexDataPrefix(vertexData); - ShaderPort* texcoord = vertexData[variable]; - if (!texcoord->isEmitted()) - { - shadergen.emitLine(prefix + texcoord->getVariable() + " = " + HW::T_IN_TEXCOORD + "_" + index, stage); - texcoord->setEmitted(); - } - } - - DEFINE_SHADER_STAGE(stage, Stage::PIXEL) - { - VariableBlock& vertexData = stage.getInputBlock(HW::VERTEX_DATA); - const string prefix = shadergen.getVertexDataPrefix(vertexData); - ShaderPort* texcoord = vertexData[variable]; - shadergen.emitLineBegin(stage); - shadergen.emitOutput(node.getOutput(), true, false, context, stage); - shadergen.emitString(" = " + prefix + texcoord->getVariable(), stage); - shadergen.emitLineEnd(stage); - } -} - -MATERIALX_NAMESPACE_END diff --git a/source/MaterialXGenGlsl/Nodes/TexCoordNodeGlsl.h b/source/MaterialXGenGlsl/Nodes/TexCoordNodeGlsl.h deleted file mode 100644 index c15a86fd9c..0000000000 --- a/source/MaterialXGenGlsl/Nodes/TexCoordNodeGlsl.h +++ /dev/null @@ -1,26 +0,0 @@ -// -// Copyright Contributors to the MaterialX Project -// SPDX-License-Identifier: Apache-2.0 -// - -#ifndef MATERIALX_TEXCOORDNODEGLSL_H -#define MATERIALX_TEXCOORDNODEGLSL_H - -#include - -MATERIALX_NAMESPACE_BEGIN - -/// TexCoord node implementation for GLSL -class MX_GENGLSL_API TexCoordNodeGlsl : public GlslImplementation -{ - public: - static ShaderNodeImplPtr create(); - - void createVariables(const ShaderNode& node, GenContext& context, Shader& shader) const override; - - void emitFunctionCall(const ShaderNode& node, GenContext& context, ShaderStage& stage) const override; -}; - -MATERIALX_NAMESPACE_END - -#endif diff --git a/source/MaterialXGenGlsl/Nodes/TimeNodeGlsl.cpp b/source/MaterialXGenGlsl/Nodes/TimeNodeGlsl.cpp deleted file mode 100644 index e508391141..0000000000 --- a/source/MaterialXGenGlsl/Nodes/TimeNodeGlsl.cpp +++ /dev/null @@ -1,38 +0,0 @@ -// -// Copyright Contributors to the MaterialX Project -// SPDX-License-Identifier: Apache-2.0 -// - -#include - -#include - -MATERIALX_NAMESPACE_BEGIN - -ShaderNodeImplPtr TimeNodeGlsl::create() -{ - return std::make_shared(); -} - -void TimeNodeGlsl::createVariables(const ShaderNode&, GenContext&, Shader& shader) const -{ - ShaderStage& ps = shader.getStage(Stage::PIXEL); - addStageUniform(HW::PRIVATE_UNIFORMS, Type::FLOAT, HW::T_FRAME, ps); -} - -void TimeNodeGlsl::emitFunctionCall(const ShaderNode& node, GenContext& context, ShaderStage& stage) const -{ - DEFINE_SHADER_STAGE(stage, Stage::PIXEL) - { - const ShaderGenerator& shadergen = context.getShaderGenerator(); - shadergen.emitLineBegin(stage); - shadergen.emitOutput(node.getOutput(), true, false, context, stage); - shadergen.emitString(" = " + HW::T_FRAME + " / ", stage); - const ShaderInput* fpsInput = node.getInput("fps"); - const string fps = fpsInput->getValue()->getValueString(); - shadergen.emitString(fps, stage); - shadergen.emitLineEnd(stage); - } -} - -MATERIALX_NAMESPACE_END diff --git a/source/MaterialXGenGlsl/Nodes/TransformNormalNodeGlsl.cpp b/source/MaterialXGenGlsl/Nodes/TransformNormalNodeGlsl.cpp deleted file mode 100644 index 0800fb4bf3..0000000000 --- a/source/MaterialXGenGlsl/Nodes/TransformNormalNodeGlsl.cpp +++ /dev/null @@ -1,43 +0,0 @@ -// -// Copyright Contributors to the MaterialX Project -// SPDX-License-Identifier: Apache-2.0 -// - -#include - -MATERIALX_NAMESPACE_BEGIN - -ShaderNodeImplPtr TransformNormalNodeGlsl::create() -{ - return std::make_shared(); -} - -void TransformNormalNodeGlsl::emitFunctionCall(const ShaderNode& node, GenContext& context, ShaderStage& stage) const -{ - TransformVectorNodeGlsl::emitFunctionCall(node, context, stage); - - DEFINE_SHADER_STAGE(stage, Stage::PIXEL) - { - const ShaderGenerator& shadergen = context.getShaderGenerator(); - const ShaderOutput* output = node.getOutput(); - shadergen.emitLineBegin(stage); - shadergen.emitOutput(output, false, false, context, stage); - shadergen.emitString(" = normalize(" + output->getVariable() + ")", stage); - shadergen.emitLineEnd(stage); - } -} - -const string& TransformNormalNodeGlsl::getMatrix(const string& fromSpace, const string& toSpace) const -{ - if ((fromSpace == MODEL || fromSpace == OBJECT) && toSpace == WORLD) - { - return HW::T_WORLD_INVERSE_TRANSPOSE_MATRIX; - } - else if (fromSpace == WORLD && (toSpace == MODEL || toSpace == OBJECT)) - { - return HW::T_WORLD_TRANSPOSE_MATRIX; - } - return EMPTY_STRING; -} - -MATERIALX_NAMESPACE_END diff --git a/source/MaterialXGenGlsl/Nodes/TransformNormalNodeGlsl.h b/source/MaterialXGenGlsl/Nodes/TransformNormalNodeGlsl.h deleted file mode 100644 index f08ec564d9..0000000000 --- a/source/MaterialXGenGlsl/Nodes/TransformNormalNodeGlsl.h +++ /dev/null @@ -1,27 +0,0 @@ -// -// Copyright Contributors to the MaterialX Project -// SPDX-License-Identifier: Apache-2.0 -// - -#ifndef MATERIALX_TRANSFORMNORMALNODEGLSL_H -#define MATERIALX_TRANSFORMNORMALNODEGLSL_H - -#include - -MATERIALX_NAMESPACE_BEGIN - -/// TransformNormal node implementation for GLSL -class MX_GENGLSL_API TransformNormalNodeGlsl : public TransformVectorNodeGlsl -{ - public: - static ShaderNodeImplPtr create(); - - protected: - void emitFunctionCall(const ShaderNode& node, GenContext& context, ShaderStage& stage) const override; - - const string& getMatrix(const string& fromSpace, const string& toSpace) const override; -}; - -MATERIALX_NAMESPACE_END - -#endif diff --git a/source/MaterialXGenGlsl/Nodes/TransformPointNodeGlsl.cpp b/source/MaterialXGenGlsl/Nodes/TransformPointNodeGlsl.cpp deleted file mode 100644 index 1570939bfe..0000000000 --- a/source/MaterialXGenGlsl/Nodes/TransformPointNodeGlsl.cpp +++ /dev/null @@ -1,23 +0,0 @@ -// -// Copyright Contributors to the MaterialX Project -// SPDX-License-Identifier: Apache-2.0 -// - -#include - -#include - -MATERIALX_NAMESPACE_BEGIN - -ShaderNodeImplPtr TransformPointNodeGlsl::create() -{ - return std::make_shared(); -} - -string TransformPointNodeGlsl::getHomogeneousCoordinate(const ShaderInput* in, GenContext& context) const -{ - const ShaderGenerator& shadergen = context.getShaderGenerator(); - return "vec4(" + shadergen.getUpstreamResult(in, context) + ", 1.0)"; -} - -MATERIALX_NAMESPACE_END diff --git a/source/MaterialXGenGlsl/Nodes/TransformPointNodeGlsl.h b/source/MaterialXGenGlsl/Nodes/TransformPointNodeGlsl.h deleted file mode 100644 index eb366d8190..0000000000 --- a/source/MaterialXGenGlsl/Nodes/TransformPointNodeGlsl.h +++ /dev/null @@ -1,25 +0,0 @@ -// -// Copyright Contributors to the MaterialX Project -// SPDX-License-Identifier: Apache-2.0 -// - -#ifndef MATERIALX_TRANSFORMPOINTNODEGLSL_H -#define MATERIALX_TRANSFORMPOINTNODEGLSL_H - -#include - -MATERIALX_NAMESPACE_BEGIN - -/// TransformPoint node implementation for GLSL -class MX_GENGLSL_API TransformPointNodeGlsl : public TransformVectorNodeGlsl -{ - public: - static ShaderNodeImplPtr create(); - - protected: - virtual string getHomogeneousCoordinate(const ShaderInput* in, GenContext& context) const override; -}; - -MATERIALX_NAMESPACE_END - -#endif diff --git a/source/MaterialXGenGlsl/Nodes/TransformVectorNodeGlsl.cpp b/source/MaterialXGenGlsl/Nodes/TransformVectorNodeGlsl.cpp deleted file mode 100644 index df1e921497..0000000000 --- a/source/MaterialXGenGlsl/Nodes/TransformVectorNodeGlsl.cpp +++ /dev/null @@ -1,84 +0,0 @@ -// -// Copyright Contributors to the MaterialX Project -// SPDX-License-Identifier: Apache-2.0 -// - -#include - -#include - -MATERIALX_NAMESPACE_BEGIN - -ShaderNodeImplPtr TransformVectorNodeGlsl::create() -{ - return std::make_shared(); -} - -void TransformVectorNodeGlsl::createVariables(const ShaderNode& node, GenContext&, Shader& shader) const -{ - const ShaderInput* toSpaceInput = node.getInput(TO_SPACE); - string toSpace = toSpaceInput ? toSpaceInput->getValue()->getValueString() : EMPTY_STRING; - - const ShaderInput* fromSpaceInput = node.getInput(FROM_SPACE); - string fromSpace = fromSpaceInput ? fromSpaceInput->getValue()->getValueString() : EMPTY_STRING; - - const string& matrix = getMatrix(fromSpace, toSpace); - if (!matrix.empty()) - { - ShaderStage& ps = shader.getStage(Stage::PIXEL); - addStageUniform(HW::PRIVATE_UNIFORMS, Type::MATRIX44, matrix, ps); - } -} - -void TransformVectorNodeGlsl::emitFunctionCall(const ShaderNode& node, GenContext& context, ShaderStage& stage) const -{ - DEFINE_SHADER_STAGE(stage, Stage::PIXEL) - { - const ShaderGenerator& shadergen = context.getShaderGenerator(); - - const ShaderInput* inInput = node.getInput("in"); - if (inInput->getType() != Type::VECTOR3 && inInput->getType() != Type::VECTOR4) - { - throw ExceptionShaderGenError("Transform node must have 'in' type of vector3 or vector4."); - } - - const ShaderInput* toSpaceInput = node.getInput(TO_SPACE); - string toSpace = toSpaceInput ? toSpaceInput->getValue()->getValueString() : EMPTY_STRING; - - const ShaderInput* fromSpaceInput = node.getInput(FROM_SPACE); - string fromSpace = fromSpaceInput ? fromSpaceInput->getValue()->getValueString() : EMPTY_STRING; - - shadergen.emitLineBegin(stage); - shadergen.emitOutput(node.getOutput(), true, false, context, stage); - shadergen.emitString(" = (", stage); - const string& matrix = getMatrix(fromSpace, toSpace); - if (!matrix.empty()) - { - shadergen.emitString(matrix + " * ", stage); - } - shadergen.emitString(getHomogeneousCoordinate(inInput, context), stage); - shadergen.emitString(").xyz", stage); - shadergen.emitLineEnd(stage); - } -} - -const string& TransformVectorNodeGlsl::getMatrix(const string& fromSpace, const string& toSpace) const -{ - if ((fromSpace == MODEL || fromSpace == OBJECT) && toSpace == WORLD) - { - return HW::T_WORLD_MATRIX; - } - else if (fromSpace == WORLD && (toSpace == MODEL || toSpace == OBJECT)) - { - return HW::T_WORLD_INVERSE_MATRIX; - } - return EMPTY_STRING; -} - -string TransformVectorNodeGlsl::getHomogeneousCoordinate(const ShaderInput* in, GenContext& context) const -{ - const ShaderGenerator& shadergen = context.getShaderGenerator(); - return "vec4(" + shadergen.getUpstreamResult(in, context) + ", 0.0)"; -} - -MATERIALX_NAMESPACE_END diff --git a/source/MaterialXGenGlsl/Nodes/TransformVectorNodeGlsl.h b/source/MaterialXGenGlsl/Nodes/TransformVectorNodeGlsl.h deleted file mode 100644 index e9861650b3..0000000000 --- a/source/MaterialXGenGlsl/Nodes/TransformVectorNodeGlsl.h +++ /dev/null @@ -1,30 +0,0 @@ -// -// Copyright Contributors to the MaterialX Project -// SPDX-License-Identifier: Apache-2.0 -// - -#ifndef MATERIALX_TRANSFORMVECTORNODEGLSL_H -#define MATERIALX_TRANSFORMVECTORNODEGLSL_H - -#include - -MATERIALX_NAMESPACE_BEGIN - -/// TransformVector node implementation for GLSL -class MX_GENGLSL_API TransformVectorNodeGlsl : public GlslImplementation -{ - public: - static ShaderNodeImplPtr create(); - - void createVariables(const ShaderNode& node, GenContext& context, Shader& shader) const override; - - void emitFunctionCall(const ShaderNode& node, GenContext& context, ShaderStage& stage) const override; - - protected: - virtual const string& getMatrix(const string& fromSpace, const string& toSpace) const; - virtual string getHomogeneousCoordinate(const ShaderInput* in, GenContext& context) const; -}; - -MATERIALX_NAMESPACE_END - -#endif diff --git a/source/MaterialXGenGlsl/VkResourceBindingContext.cpp b/source/MaterialXGenGlsl/VkResourceBindingContext.cpp index 38e7186f4a..89e65f9d07 100644 --- a/source/MaterialXGenGlsl/VkResourceBindingContext.cpp +++ b/source/MaterialXGenGlsl/VkResourceBindingContext.cpp @@ -24,7 +24,7 @@ void VkResourceBindingContext::initialize() void VkResourceBindingContext::emitDirectives(GenContext& context, ShaderStage& stage) { - ShaderGenerator& generator = context.getShaderGenerator(); + const ShaderGenerator& generator = context.getShaderGenerator(); // Write shader stage directives for Vulkan compliance std::string shaderStage; @@ -45,7 +45,7 @@ void VkResourceBindingContext::emitDirectives(GenContext& context, ShaderStage& void VkResourceBindingContext::emitResourceBindings(GenContext& context, const VariableBlock& uniforms, ShaderStage& stage) { - ShaderGenerator& generator = context.getShaderGenerator(); + const ShaderGenerator& generator = context.getShaderGenerator(); const Syntax& syntax = generator.getSyntax(); // First, emit all value uniforms in a block with single layout binding @@ -80,7 +80,7 @@ void VkResourceBindingContext::emitResourceBindings(GenContext& context, const V // Second, emit all sampler uniforms as separate uniforms with separate layout bindings for (auto uniform : uniforms.getVariableOrder()) { - if (uniform->getType() == Type::FILENAME) + if (*uniform->getType() == *Type::FILENAME) { generator.emitString("layout (binding=" + std::to_string(_hwUniformBindLocation++) + ") " + syntax.getUniformQualifier() + " ", stage); generator.emitVariableDeclaration(uniform, EMPTY_STRING, context, stage, false); @@ -95,7 +95,7 @@ void VkResourceBindingContext::emitStructuredResourceBindings(GenContext& contex ShaderStage& stage, const std::string& structInstanceName, const std::string& arraySuffix) { - ShaderGenerator& generator = context.getShaderGenerator(); + const ShaderGenerator& generator = context.getShaderGenerator(); const Syntax& syntax = generator.getSyntax(); // Glsl structures need to be aligned. We make a best effort to base align struct members and add diff --git a/source/MaterialXGenGlsl/VkShaderGenerator.cpp b/source/MaterialXGenGlsl/VkShaderGenerator.cpp index b57a4d2e94..5a91d96ff5 100644 --- a/source/MaterialXGenGlsl/VkShaderGenerator.cpp +++ b/source/MaterialXGenGlsl/VkShaderGenerator.cpp @@ -69,9 +69,9 @@ void VkShaderGenerator::emitInputs(GenContext& context, ShaderStage& stage) cons } } -string VkShaderGenerator::getVertexDataPrefix(const VariableBlock&) const +string VkShaderGenerator::getVertexDataPrefix(const VariableBlock& vertexData) const { - return EMPTY_STRING; + return vertexData.getInstance() + "."; } void VkShaderGenerator::emitOutputs(GenContext& context, ShaderStage& stage) const diff --git a/source/MaterialXGenMdl/MdlShaderGenerator.cpp b/source/MaterialXGenMdl/MdlShaderGenerator.cpp index dddf1f2f13..57c653bc83 100644 --- a/source/MaterialXGenMdl/MdlShaderGenerator.cpp +++ b/source/MaterialXGenMdl/MdlShaderGenerator.cpp @@ -17,6 +17,7 @@ #include #include #include +#include #include #include @@ -25,14 +26,13 @@ #include #include #include +#include MATERIALX_NAMESPACE_BEGIN namespace { -const string MDL_VERSION = "1.6"; - const vector DEFAULT_IMPORTS = { "import ::df::*", @@ -41,16 +41,30 @@ const vector DEFAULT_IMPORTS = "import ::state::*", "import ::anno::*", "import ::tex::*", - "import ::mx::swizzle::*", - "using ::mx::core import *", - "using ::mx::stdlib import *", - "using ::mx::pbrlib import *", - "using ::mx::sampling import *", + "import ::materialx::swizzle::*", + "using ::materialx::core import *", + "using ::materialx::sampling import *", +}; + +const vector DEFAULT_VERSIONED_IMPORTS = { + "using ::materialx::stdlib_", + "using ::materialx::pbrlib_", }; +const string IMPORT_ALL = " import *"; + + +const string MDL_VERSION_1_6 = "1.6"; +const string MDL_VERSION_1_7 = "1.7"; +const string MDL_VERSION_1_8 = "1.8"; +const string MDL_VERSION_SUFFIX_1_6 = "1_6"; +const string MDL_VERSION_SUFFIX_1_7 = "1_7"; +const string MDL_VERSION_SUFFIX_1_8 = "1_8"; + } // anonymous namespace const string MdlShaderGenerator::TARGET = "genmdl"; +const string GenMdlOptions::GEN_CONTEXT_USER_DATA_KEY = "genmdloptions"; const std::unordered_map MdlShaderGenerator::GEOMPROP_DEFINITIONS = { @@ -178,15 +192,26 @@ MdlShaderGenerator::MdlShaderGenerator() : // registerImplementation("IM_dielectric_bsdf_" + MdlShaderGenerator::TARGET, ThinFilmReceiverNodeMdl::create); + registerImplementation("IM_dielectric_tf_bsdf_" + MdlShaderGenerator::TARGET, LayerableNodeMdl::create); // registerImplementation("IM_conductor_bsdf_" + MdlShaderGenerator::TARGET, ThinFilmReceiverNodeMdl::create); // registerImplementation("IM_generalized_schlick_bsdf_" + MdlShaderGenerator::TARGET, ThinFilmReceiverNodeMdl::create); + registerImplementation("IM_generalized_schlick_tf_82_bsdf_" + MdlShaderGenerator::TARGET, LayerableNodeMdl::create); // registerImplementation("IM_sheen_bsdf_" + MdlShaderGenerator::TARGET, LayerableNodeMdl::create); + registerImplementation("IM_sheen_zeltner_bsdf_" + MdlShaderGenerator::TARGET, LayerableNodeMdl::create); + + // + registerImplementation("IM_image_float_" + MdlShaderGenerator::TARGET, ImageNodeMdl::create); + registerImplementation("IM_image_color3_" + MdlShaderGenerator::TARGET, ImageNodeMdl::create); + registerImplementation("IM_image_color4_" + MdlShaderGenerator::TARGET, ImageNodeMdl::create); + registerImplementation("IM_image_vector2_" + MdlShaderGenerator::TARGET, ImageNodeMdl::create); + registerImplementation("IM_image_vector3_" + MdlShaderGenerator::TARGET, ImageNodeMdl::create); + registerImplementation("IM_image_vector4_" + MdlShaderGenerator::TARGET, ImageNodeMdl::create); } ShaderPtr MdlShaderGenerator::generate(const string& name, ElementPtr element, GenContext& context) const @@ -198,20 +223,28 @@ ShaderPtr MdlShaderGenerator::generate(const string& name, ElementPtr element, G ShaderPtr shader = createShader(name, element, context); + // Request fixed floating-point notation for consistency across targets. + ScopedFloatFormatting fmt(Value::FloatFormatFixed); + ShaderGraph& graph = shader->getGraph(); ShaderStage& stage = shader->getStage(Stage::PIXEL); // Emit version - emitLine("mdl " + MDL_VERSION, stage); + emitMdlVersionNumber(context, stage); emitLineBreak(stage); - emitLine("using mx = materialx", stage); - // Emit module imports for (const string& module : DEFAULT_IMPORTS) { emitLine(module, stage); } + for (const string& module : DEFAULT_VERSIONED_IMPORTS) + { + emitString(module, stage); + emitMdlVersionFilenameSuffix(context, stage); + emitString(IMPORT_ALL, stage); + emitLineEnd(stage, true); + } // Add global constants and type definitions emitTypeDefinitions(context, stage); @@ -232,7 +265,7 @@ ShaderPtr MdlShaderGenerator::generate(const string& name, ElementPtr element, G emitScopeBegin(stage, Syntax::PARENTHESES); // Emit shader inputs - emitShaderInputs(stage.getInputBlock(MDL::INPUTS), stage); + emitShaderInputs(element->getDocument(), stage.getInputBlock(MDL::INPUTS), stage); // End shader signature emitScopeEnd(stage); @@ -275,13 +308,13 @@ ShaderPtr MdlShaderGenerator::generate(const string& name, ElementPtr element, G const TypeDesc* outputType = outputSocket->getType(); if (graph.hasClassification(ShaderNode::Classification::TEXTURE)) { - if (outputType == Type::DISPLACEMENTSHADER) + if (*outputType == *Type::DISPLACEMENTSHADER) { emitLine("float3 displacement__ = " + result + ".geometry.displacement", stage); emitLine("color finalOutput__ = mk_color3(" - "r: math::dot(displacement__, state::texture_tangent_u(0))," - "g: math::dot(displacement__, state::texture_tangent_v(0))," - "b: math::dot(displacement__, state::normal()))", stage); + "r: math::dot(displacement__, state::texture_tangent_u(0))," + "g: math::dot(displacement__, state::texture_tangent_v(0))," + "b: math::dot(displacement__, state::normal()))", stage); } else { @@ -648,14 +681,32 @@ ShaderPtr MdlShaderGenerator::createShader(const string& name, ElementPtr elemen return shader; } -void MdlShaderGenerator::emitShaderInputs(const VariableBlock& inputs, ShaderStage& stage) const +namespace +{ + +void emitInputAnnotations(const MdlShaderGenerator& _this, const DocumentPtr doc, const ShaderPort* variable, ShaderStage& stage) +{ + // allows to relate between MaterialX and MDL parameters when looking at the MDL code. + const std::string mtlxParameterPathAnno = "materialx::core::origin(\"" + variable->getPath() + "\")"; + + _this.emitLineEnd(stage, false); + _this.emitLine("[[", stage, false); + _this.emitLine("\t" + mtlxParameterPathAnno, stage, false); + _this.emitLineBegin(stage); + _this.emitString("]]", stage); // line ending follows by caller +} + +} // anonymous namespace + + +void MdlShaderGenerator::emitShaderInputs(const DocumentPtr doc, const VariableBlock& inputs, ShaderStage& stage) const { const string uniformPrefix = _syntax->getUniformQualifier() + " "; for (size_t i = 0; i < inputs.size(); ++i) { const ShaderPort* input = inputs[i]; - const string& qualifier = input->isUniform() || input->getType() == Type::FILENAME ? uniformPrefix : EMPTY_STRING; + const string& qualifier = input->isUniform() || *input->getType() == *Type::FILENAME ? uniformPrefix : EMPTY_STRING; const string& type = _syntax->getTypeName(input->getType()); string value = input->getValue() ? _syntax->getValue(input->getType(), *input->getValue(), true) : EMPTY_STRING; @@ -675,6 +726,7 @@ void MdlShaderGenerator::emitShaderInputs(const VariableBlock& inputs, ShaderSta emitLineBegin(stage); emitString(qualifier + type + " " + input->getVariable() + " = " + value, stage); + emitInputAnnotations(*this, doc, input, stage); if (i < inputs.size() - 1) { @@ -685,6 +737,55 @@ void MdlShaderGenerator::emitShaderInputs(const VariableBlock& inputs, ShaderSta } } + +void MdlShaderGenerator::emitMdlVersionNumber(GenContext& context, ShaderStage& stage) const +{ + GenMdlOptionsPtr options = context.getUserData(GenMdlOptions::GEN_CONTEXT_USER_DATA_KEY); + GenMdlOptions::MdlVersion version = options ? options->targetVersion : GenMdlOptions::MdlVersion::MDL_LATEST; + + emitLineBegin(stage); + emitString("mdl ", stage); + switch (version) + { + case GenMdlOptions::MdlVersion::MDL_1_6: + emitString(MDL_VERSION_1_6, stage); + break; + case GenMdlOptions::MdlVersion::MDL_1_7: + emitString(MDL_VERSION_1_7, stage); + break; + default: + // GenMdlOptions::MdlVersion::MDL_1_8 + // GenMdlOptions::MdlVersion::MDL_LATEST + emitString(MDL_VERSION_1_8, stage); + break; + } + emitLineEnd(stage, true); +} + +const string& MdlShaderGenerator::getMdlVersionFilenameSuffix(GenContext& context) const +{ + GenMdlOptionsPtr options = context.getUserData(GenMdlOptions::GEN_CONTEXT_USER_DATA_KEY); + GenMdlOptions::MdlVersion version = options ? options->targetVersion : GenMdlOptions::MdlVersion::MDL_LATEST; + + switch (version) + { + case GenMdlOptions::MdlVersion::MDL_1_6: + return MDL_VERSION_SUFFIX_1_6; + case GenMdlOptions::MdlVersion::MDL_1_7: + return MDL_VERSION_SUFFIX_1_7; + default: + // GenMdlOptions::MdlVersion::MDL_1_8 + // GenMdlOptions::MdlVersion::MDL_LATEST + return MDL_VERSION_SUFFIX_1_8; + } +} + + +void MdlShaderGenerator::emitMdlVersionFilenameSuffix(GenContext& context, ShaderStage& stage) const +{ + emitString(getMdlVersionFilenameSuffix(context), stage); +} + namespace MDL { // Identifiers for MDL variable blocks diff --git a/source/MaterialXGenMdl/MdlShaderGenerator.h b/source/MaterialXGenMdl/MdlShaderGenerator.h index f1431b8916..3a24bcf87d 100644 --- a/source/MaterialXGenMdl/MdlShaderGenerator.h +++ b/source/MaterialXGenMdl/MdlShaderGenerator.h @@ -15,6 +15,35 @@ MATERIALX_NAMESPACE_BEGIN +/// Generator context data class to pass strings. +class MX_GENMDL_API GenMdlOptions : public GenUserData +{ + public: + /// MDL Versions supported by the Code Generator + enum class MdlVersion + { + MDL_1_6, + MDL_1_7, + MDL_1_8, + MDL_LATEST = MDL_1_8 + }; + + /// Create MDL code generator options with default values. + GenMdlOptions() : + targetVersion(MdlVersion::MDL_LATEST) { } + + /// Unique identifier for the MDL options on the GenContext object. + static const string GEN_CONTEXT_USER_DATA_KEY; + + /// The MDL version number the generated module will have. + /// Allows to generate MDL for older applications by limiting support according + /// to the corresponding specification. By default this option is MDL_LATEST. + MdlVersion targetVersion; +}; + +/// Shared pointer to GenMdlOptions +using GenMdlOptionsPtr = shared_ptr; + /// Shared pointer to an MdlShaderGenerator using MdlShaderGeneratorPtr = shared_ptr; @@ -47,12 +76,21 @@ class MX_GENMDL_API MdlShaderGenerator : public ShaderGenerator /// Map of code snippets for geomprops in MDL. static const std::unordered_map GEOMPROP_DEFINITIONS; + /// Add the MDL file header containing the version number of the generated module.. + void emitMdlVersionNumber(GenContext& context, ShaderStage& stage) const; + + /// Add the version number suffix appended to MDL modules that use versions. + void emitMdlVersionFilenameSuffix(GenContext& context, ShaderStage& stage) const; + + /// Get the version number suffix appended to MDL modules that use versions. + const string& getMdlVersionFilenameSuffix(GenContext& context) const; + protected: // Create and initialize a new MDL shader for shader generation. ShaderPtr createShader(const string& name, ElementPtr element, GenContext& context) const; // Emit a block of shader inputs. - void emitShaderInputs(const VariableBlock& inputs, ShaderStage& stage) const; + void emitShaderInputs(const DocumentPtr doc, const VariableBlock& inputs, ShaderStage& stage) const; }; namespace MDL diff --git a/source/MaterialXGenMdl/MdlSyntax.cpp b/source/MaterialXGenMdl/MdlSyntax.cpp index 9d5483bcca..f32fe6c60f 100644 --- a/source/MaterialXGenMdl/MdlSyntax.cpp +++ b/source/MaterialXGenMdl/MdlSyntax.cpp @@ -48,7 +48,7 @@ class MdlFilenameTypeSyntax : public ScalarTypeSyntax // assuming it ends with a slash ... if (outputValue.back() == '/') { - return getDefaultValue(true); + return getDefaultValue(true); } // ... or the last segment does not have an extension suffix size_t idx_s = outputValue.find_last_of('/'); @@ -492,7 +492,7 @@ const std::unordered_map CHANNELS_TO_XYZW = string MdlSyntax::getSwizzledVariable(const string& srcName, const TypeDesc* srcType, const string& channels, const TypeDesc* dstType) const { - if (srcType == Type::COLOR3 || srcType == Type::COLOR4) + if (*srcType == *Type::COLOR3 || *srcType == *Type::COLOR4) { const TypeSyntax& srcSyntax = getTypeSyntax(srcType); const TypeSyntax& dstSyntax = getTypeSyntax(dstType); @@ -523,7 +523,7 @@ string MdlSyntax::getSwizzledVariable(const string& srcName, const TypeDesc* src } string variable = srcName; - if (srcType == Type::COLOR3) + if (*srcType == *Type::COLOR3) { variable = "float3(" + srcName + ")"; } @@ -567,7 +567,7 @@ bool MdlSyntax::remapEnumeration(const string& value, const TypeDesc* type, cons } // Don't convert filenames or arrays. - if (type == Type::FILENAME || (type && type->isArray())) + if (*type == *Type::FILENAME || (type && type->isArray())) { return false; } diff --git a/source/MaterialXGenMdl/Nodes/ClosureCompoundNodeMdl.cpp b/source/MaterialXGenMdl/Nodes/ClosureCompoundNodeMdl.cpp index e175696d55..0a2004cd71 100644 --- a/source/MaterialXGenMdl/Nodes/ClosureCompoundNodeMdl.cpp +++ b/source/MaterialXGenMdl/Nodes/ClosureCompoundNodeMdl.cpp @@ -41,7 +41,7 @@ void ClosureCompoundNodeMdl::emitFunctionDefinition(const ShaderNode& node, GenC { if (!outputSocket->getConnection()) continue; - + const ShaderNode* upstream = outputSocket->getConnection()->getNode(); const bool isMaterialExpr = (upstream->hasClassification(ShaderNode::Classification::CLOSURE) || upstream->hasClassification(ShaderNode::Classification::SHADER)); diff --git a/source/MaterialXGenMdl/Nodes/ClosureLayerNodeMdl.cpp b/source/MaterialXGenMdl/Nodes/ClosureLayerNodeMdl.cpp index fd27d5e547..41dfa54111 100644 --- a/source/MaterialXGenMdl/Nodes/ClosureLayerNodeMdl.cpp +++ b/source/MaterialXGenMdl/Nodes/ClosureLayerNodeMdl.cpp @@ -46,7 +46,7 @@ void ClosureLayerNodeMdl::emitFunctionCall(const ShaderNode& _node, GenContext& // // 1. Handle the BSDF-over-VDF case // - if (baseInput->getType() == Type::VDF) + if (*baseInput->getType() == *Type::VDF) { // Make sure we have a top BSDF connected. if (!topInput->getConnection()) @@ -368,12 +368,12 @@ const string& MixBsdfNodeMdl::getOperatorName(size_t index) const { switch (index) { - case 0: - return StringConstantsMdl::FG; - case 1: - return StringConstantsMdl::BG; - default: - return StringConstantsMdl::EMPTY; + case 0: + return StringConstantsMdl::FG; + case 1: + return StringConstantsMdl::BG; + default: + return StringConstantsMdl::EMPTY; } } @@ -386,12 +386,12 @@ const string& AddOrMultiplyBsdfNodeMdl::getOperatorName(size_t index) const { switch (index) { - case 0: - return StringConstantsMdl::IN1; - case 1: - return StringConstantsMdl::IN2; - default: - return StringConstantsMdl::EMPTY; + case 0: + return StringConstantsMdl::IN1; + case 1: + return StringConstantsMdl::IN2; + default: + return StringConstantsMdl::EMPTY; } } diff --git a/source/MaterialXGenMdl/Nodes/ClosureLayerNodeMdl.h b/source/MaterialXGenMdl/Nodes/ClosureLayerNodeMdl.h index 75ea46046c..95c51198f8 100644 --- a/source/MaterialXGenMdl/Nodes/ClosureLayerNodeMdl.h +++ b/source/MaterialXGenMdl/Nodes/ClosureLayerNodeMdl.h @@ -21,18 +21,18 @@ class MX_GENMDL_API StringConstantsMdl public: /// String constants - static const string TOP; ///< layer parameter name of the top component + static const string TOP; ///< layer parameter name of the top component static const string BASE; ///< layer parameter name of the base component - static const string FG; ///< parameter of the mix node - static const string BG; ///< parameter of the mix node - static const string IN1; ///< parameter of the add and multiply nodes - static const string IN2; ///< parameter of the add and multiply nodes + static const string FG; ///< parameter of the mix node + static const string BG; ///< parameter of the mix node + static const string IN1; ///< parameter of the add and multiply nodes + static const string IN2; ///< parameter of the add and multiply nodes static const string THICKNESS; ///< thickness parameter name of the thin_film_bsdf - static const string IOR; ///< ior parameter name of the thin_film_bsdf + static const string IOR; ///< ior parameter name of the thin_film_bsdf static const string THIN_FILM_THICKNESS; ///< helper parameter name for transporting thickness - static const string THIN_FILM_IOR; ///< helper parameter name for transporting ior + static const string THIN_FILM_IOR; ///< helper parameter name for transporting ior static const string EMPTY; ///< the empty string "" }; @@ -41,7 +41,7 @@ class MX_GENMDL_API StringConstantsMdl /// thin_film_bsdf through layers and mixers, etc., to the elemental bsdfs that support thin film. /// Because thin-film can not be layered on any BSDF in MDL, we try to push down the parameters to /// the nodes that support thin-film. -template class CarryThinFilmParameters : public TBase +template class CarryThinFilmParameters : public TBase { public: /// Add the thin film inputs for transporting the parameter. diff --git a/source/MaterialXGenMdl/Nodes/CombineNodeMdl.cpp b/source/MaterialXGenMdl/Nodes/CombineNodeMdl.cpp index 9d6789c94c..83dc755b7a 100644 --- a/source/MaterialXGenMdl/Nodes/CombineNodeMdl.cpp +++ b/source/MaterialXGenMdl/Nodes/CombineNodeMdl.cpp @@ -33,10 +33,10 @@ void CombineNodeMdl::emitFunctionCall(const ShaderNode& node, GenContext& contex throw ExceptionShaderGenError("Node '" + node.getName() + "' is not a valid convert node"); } - if (in1->getType() == Type::COLOR3) + if (*in1->getType() == *Type::COLOR3) { const ShaderInput* in2 = node.getInput(1); - if (!in2 || in2->getType() != Type::FLOAT) + if (!in2 || *in2->getType() != *Type::FLOAT) { throw ExceptionShaderGenError("Node '" + node.getName() + "' is not a valid convert node"); } diff --git a/source/MaterialXGenMdl/Nodes/CompoundNodeMdl.cpp b/source/MaterialXGenMdl/Nodes/CompoundNodeMdl.cpp index 03c8bc172f..b7b81e5d30 100644 --- a/source/MaterialXGenMdl/Nodes/CompoundNodeMdl.cpp +++ b/source/MaterialXGenMdl/Nodes/CompoundNodeMdl.cpp @@ -233,7 +233,7 @@ void CompoundNodeMdl::emitFunctionSignature(const ShaderNode&, GenContext& conte int count = int(_rootGraph->numInputSockets()); for (ShaderGraphInputSocket* input : _rootGraph->getInputSockets()) { - const string& qualifier = input->isUniform() || input->getType() == Type::FILENAME ? uniformPrefix : EMPTY_STRING; + const string& qualifier = input->isUniform() || *input->getType() == *Type::FILENAME ? uniformPrefix : EMPTY_STRING; const string& type = syntax.getTypeName(input->getType()); string value = input->getValue() ? syntax.getValue(input->getType(), *input->getValue(), true) : EMPTY_STRING; diff --git a/source/MaterialXGenMdl/Nodes/HeightToNormalNodeMdl.cpp b/source/MaterialXGenMdl/Nodes/HeightToNormalNodeMdl.cpp index 186c88be88..b52ebc8ab2 100644 --- a/source/MaterialXGenMdl/Nodes/HeightToNormalNodeMdl.cpp +++ b/source/MaterialXGenMdl/Nodes/HeightToNormalNodeMdl.cpp @@ -50,7 +50,7 @@ void HeightToNormalNodeMdl::computeSampleOffsetStrings(const string& sampleSizeN bool HeightToNormalNodeMdl::acceptsInputType(const TypeDesc* type) const { // Only support inputs which are float scalar - return (type == Type::FLOAT && type->isScalar()); + return (*type == *Type::FLOAT && type->isScalar()); } void HeightToNormalNodeMdl::emitFunctionCall(const ShaderNode& node, GenContext& context, ShaderStage& stage) const diff --git a/source/MaterialXGenMdl/Nodes/ImageNodeMdl.cpp b/source/MaterialXGenMdl/Nodes/ImageNodeMdl.cpp new file mode 100644 index 0000000000..502711fe01 --- /dev/null +++ b/source/MaterialXGenMdl/Nodes/ImageNodeMdl.cpp @@ -0,0 +1,50 @@ +// +// Copyright Contributors to the MaterialX Project +// SPDX-License-Identifier: Apache-2.0 +// + +#include +#include +#include +#include + +MATERIALX_NAMESPACE_BEGIN + +const string ImageNodeMdl::FLIP_V = "flip_v"; + +ShaderNodeImplPtr ImageNodeMdl::create() +{ + return std::make_shared(); +} + +void ImageNodeMdl::addInputs(ShaderNode& node, GenContext& context) const +{ + BASE::addInputs(node, context); + node.addInput(ImageNodeMdl::FLIP_V, Type::BOOLEAN)->setUniform(); +} + +bool ImageNodeMdl::isEditable(const ShaderInput& input) const +{ + if (input.getName() == ImageNodeMdl::FLIP_V) + { + return false; + } + return BASE::isEditable(input); +} + +void ImageNodeMdl::emitFunctionCall(const ShaderNode& _node, GenContext& context, ShaderStage& stage) const +{ + DEFINE_SHADER_STAGE(stage, Stage::PIXEL) + { + ShaderNode& node = const_cast(_node); + ShaderInput* flipUInput = node.getInput(ImageNodeMdl::FLIP_V); + ValuePtr value = TypedValue::createValue(context.getOptions().fileTextureVerticalFlip); + if (flipUInput) + { + flipUInput->setValue(value); + } + BASE::emitFunctionCall(_node, context, stage); + } +} + +MATERIALX_NAMESPACE_END diff --git a/source/MaterialXGenMdl/Nodes/ImageNodeMdl.h b/source/MaterialXGenMdl/Nodes/ImageNodeMdl.h new file mode 100644 index 0000000000..fe88b2ce09 --- /dev/null +++ b/source/MaterialXGenMdl/Nodes/ImageNodeMdl.h @@ -0,0 +1,34 @@ +// +// Copyright Contributors to the MaterialX Project +// SPDX-License-Identifier: Apache-2.0 +// + +#ifndef MATERIALX_IMAGENODEMDL_H +#define MATERIALX_IMAGENODEMDL_H + +#include + +#include "SourceCodeNodeMdl.h" + +MATERIALX_NAMESPACE_BEGIN + +/// Image node implementation for MDL +class MX_GENMDL_API ImageNodeMdl : public SourceCodeNodeMdl +{ + using BASE = SourceCodeNodeMdl; + + public: + static const string FLIP_V; ///< the empty string "" + + static ShaderNodeImplPtr create(); + + void addInputs(ShaderNode& node, GenContext& context) const override; + + bool isEditable(const ShaderInput& input) const override; + + void emitFunctionCall(const ShaderNode& node, GenContext& context, ShaderStage& stage) const override; +}; + +MATERIALX_NAMESPACE_END + +#endif diff --git a/source/MaterialXGenMdl/Nodes/MaterialNodeMdl.cpp b/source/MaterialXGenMdl/Nodes/MaterialNodeMdl.cpp index 936526d59d..d13aa2871f 100644 --- a/source/MaterialXGenMdl/Nodes/MaterialNodeMdl.cpp +++ b/source/MaterialXGenMdl/Nodes/MaterialNodeMdl.cpp @@ -4,6 +4,7 @@ // #include +#include #include #include #include @@ -30,6 +31,7 @@ void MaterialNodeMdl::emitFunctionCall(const ShaderNode& _node, GenContext& cont } const ShaderGenerator& shadergen = context.getShaderGenerator(); + const MdlShaderGenerator& shadergenMdl = static_cast(shadergen); // Emit the function call for upstream surface shader. const ShaderNode* surfaceshaderNode = surfaceshaderInput->getConnection()->getNode(); @@ -39,7 +41,9 @@ void MaterialNodeMdl::emitFunctionCall(const ShaderNode& _node, GenContext& cont // Emit the output and funtion name. shadergen.emitOutput(node.getOutput(), true, false, context, stage); - shadergen.emitString(" = mx::stdlib::mx_surfacematerial(", stage); + shadergen.emitString(" = materialx::stdlib_", stage); + shadergenMdl.emitMdlVersionFilenameSuffix(context, stage); + shadergen.emitString("::mx_surfacematerial(", stage); // Emit all inputs on the node. string delim = ""; diff --git a/source/MaterialXGenMdl/Nodes/SourceCodeNodeMdl.cpp b/source/MaterialXGenMdl/Nodes/SourceCodeNodeMdl.cpp index fde22bf1fc..8ce86263d4 100644 --- a/source/MaterialXGenMdl/Nodes/SourceCodeNodeMdl.cpp +++ b/source/MaterialXGenMdl/Nodes/SourceCodeNodeMdl.cpp @@ -4,6 +4,8 @@ // #include +#include +#include #include #include @@ -11,8 +13,43 @@ #include #include +#include + MATERIALX_NAMESPACE_BEGIN +namespace // anonymous +{ +const string MARKER_MDL_VERSION_SUFFIX = "MDL_VERSION_SUFFIX"; + +StringVec replaceSourceCodeMarkers(const string& nodeName, const string& soureCode, std::function lambda) +{ + // An inline function call + // Replace tokens of the format "{{}}" + static const string prefix("{{"); + static const string postfix("}}"); + + size_t pos = 0; + size_t i = soureCode.find_first_of(prefix); + StringVec code; + while (i != string::npos) + { + code.push_back(soureCode.substr(pos, i - pos)); + size_t j = soureCode.find_first_of(postfix, i + 2); + if (j == string::npos) + { + throw ExceptionShaderGenError("Malformed inline expression in implementation for node " + nodeName); + } + const string marker = soureCode.substr(i + 2, j - i - 2); + code.push_back(lambda(marker)); + pos = j + 2; + i = soureCode.find_first_of(prefix, pos); + } + code.push_back(soureCode.substr(pos)); + return code; +} + +} // anonymous namespace + ShaderNodeImplPtr SourceCodeNodeMdl::create() { return std::make_shared(); @@ -36,6 +73,15 @@ void SourceCodeNodeMdl::initialize(const InterfaceElement& element, GenContext& { size_t pos = _functionSource.find_first_of('('); string functionName = _functionSource.substr(0, pos); + + const ShaderGenerator& shadergen = context.getShaderGenerator(); + const MdlShaderGenerator& shadergenMdl = static_cast(shadergen); + const string versionSuffix = shadergenMdl.getMdlVersionFilenameSuffix(context); + StringVec code = replaceSourceCodeMarkers(getName(), functionName, [&versionSuffix](const string& marker) + { + return marker == MARKER_MDL_VERSION_SUFFIX ? versionSuffix : EMPTY_STRING; + }); + functionName = std::accumulate(code.begin(), code.end(), EMPTY_STRING); _returnStruct = functionName + "__result"; } else @@ -54,39 +100,31 @@ void SourceCodeNodeMdl::emitFunctionCall(const ShaderNode& node, GenContext& con DEFINE_SHADER_STAGE(stage, Stage::PIXEL) { const ShaderGenerator& shadergen = context.getShaderGenerator(); + const MdlShaderGenerator& shadergenMdl = static_cast(shadergen); if (_inlined) { - // An inline function call - - static const string prefix("{{"); - static const string postfix("}}"); - - size_t pos = 0; - size_t i = _functionSource.find_first_of(prefix); - StringVec code; - while (i != string::npos) - { - code.push_back(_functionSource.substr(pos, i - pos)); - size_t j = _functionSource.find_first_of(postfix, i + 2); - if (j == string::npos) + const string versionSuffix = shadergenMdl.getMdlVersionFilenameSuffix(context); + StringVec code = replaceSourceCodeMarkers(node.getName(), _functionSource, + [&shadergenMdl, &context, &node, &versionSuffix](const string& marker) { - throw ExceptionShaderGenError("Malformed inline expression in implementation for node " + node.getName()); - } - - const string variable = _functionSource.substr(i + 2, j - i - 2); - const ShaderInput* input = node.getInput(variable); - if (!input) - { - throw ExceptionShaderGenError("Could not find an input named '" + variable + - "' on node '" + node.getName() + "'"); - } - - code.push_back(shadergen.getUpstreamResult(input, context)); - - pos = j + 2; - i = _functionSource.find_first_of(prefix, pos); - } - code.push_back(_functionSource.substr(pos)); + // Special handling for the version suffix of MDL source code modules. + if (marker == MARKER_MDL_VERSION_SUFFIX) + { + return versionSuffix; + } + // Insert inputs based on parameter names. + else + { + const ShaderInput* input = node.getInput(marker); + if (!input) + { + throw ExceptionShaderGenError("Could not find an input named '" + marker + + "' on node '" + node.getName() + "'"); + } + + return shadergenMdl.getUpstreamResult(input, context); + } + }); if (!_returnStruct.empty()) { diff --git a/source/MaterialXGenMdl/Nodes/SurfaceNodeMdl.cpp b/source/MaterialXGenMdl/Nodes/SurfaceNodeMdl.cpp index 8ce4bf0f33..305f2ad814 100644 --- a/source/MaterialXGenMdl/Nodes/SurfaceNodeMdl.cpp +++ b/source/MaterialXGenMdl/Nodes/SurfaceNodeMdl.cpp @@ -38,7 +38,7 @@ const ShaderInput* findTransmissionIOR(const ShaderNode& node) } for (const ShaderInput* input : node.getInputs()) { - if (input->getType() == Type::BSDF && input->getConnection()) + if (*input->getType() == *Type::BSDF && input->getConnection()) { const ShaderInput* ior = findTransmissionIOR(*input->getConnection()->getNode()); if (ior) @@ -70,7 +70,9 @@ void SurfaceNodeMdl::emitFunctionCall(const ShaderNode& node, GenContext& contex // Emit the output and funtion name. shadergen.emitOutput(node.getOutput(), true, false, context, stage); - shadergen.emitString(" = mx::pbrlib::mx_surface(", stage); + shadergen.emitString(" = materialx::pbrlib_", stage); + shadergen.emitMdlVersionFilenameSuffix(context, stage); + shadergen.emitString("::mx_surface(", stage); // Emit all inputs on the node. string delim = ""; diff --git a/source/MaterialXGenMdl/mdl/materialx/core.mdl b/source/MaterialXGenMdl/mdl/materialx/core.mdl index ddcea572e4..f9fe427b3e 100644 --- a/source/MaterialXGenMdl/mdl/materialx/core.mdl +++ b/source/MaterialXGenMdl/mdl/materialx/core.mdl @@ -27,11 +27,11 @@ // Document version 1.7.2, January 17, 2022 // www.nvidia.com/mdl -mdl 1.7; +mdl 1.6; import ::math::*; -import ::tex::*; import ::state::*; +import ::tex::*; // Epsilon value used in float calculations. export const float FLOAT_EPS = 0.000001; @@ -193,4 +193,7 @@ export enum mx_distribution_type { mx_distribution_type_ggx }; - +// Custom annotation for MDL function parameters to map between MDL and the original MaterialX graph. +// * When added to a paramater, the "name" will contain the path in the MaterialX graph starting +// from the root up to the input using `/` as separator. +export annotation origin(string name); diff --git a/source/MaterialXGenMdl/mdl/materialx/hsv.mdl b/source/MaterialXGenMdl/mdl/materialx/hsv.mdl index 888d4ada86..3c7753a96f 100644 --- a/source/MaterialXGenMdl/mdl/materialx/hsv.mdl +++ b/source/MaterialXGenMdl/mdl/materialx/hsv.mdl @@ -16,25 +16,25 @@ // Support functions for HSV <--> RGB color conversions -mdl 1.0; +mdl 1.6; -import ::math::*; import ::limits::*; +import ::math::*; // Convert from the HSV color model to the RGB color model export float3 mx_hsvtorgb(float3 hsv) { // from "Color Imaging, Fundamentals and Applications", Reinhard et al., p. 442 - // A hue of 1.0 is questionably valid, and needs to be interpreted as 0.0f - float h_prime = (hsv.x < 1.0f) ? hsv.x * 6.0f : 0.0f; // H * 360.0/60.0 - float h_floor = math::floor(h_prime); - float f = h_prime - h_floor; + float h = 6.0 * (hsv.x - math::floor(hsv.x)); + int hi = int(h); // truncate + float f = h - float(hi); + float zy = hsv.z*hsv.y; float a = hsv.z - zy; float b = hsv.z - zy*f; float c = a + zy*f; - switch(int(h_floor)) { + switch(hi) { default: // hue out of [0,1] range... // fall through... diff --git a/source/MaterialXGenMdl/mdl/materialx/noise.mdl b/source/MaterialXGenMdl/mdl/materialx/noise.mdl index bcbc2fcd1b..a6c1658b74 100644 --- a/source/MaterialXGenMdl/mdl/materialx/noise.mdl +++ b/source/MaterialXGenMdl/mdl/materialx/noise.mdl @@ -46,11 +46,12 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. mdl 1.6; -using core import *; -import swizzle::*; +import ::anno::*; import ::math::*; import ::state::*; -import ::anno::*; + +import .::core::*; +import .::swizzle::*; float mx_bilerp_float(float v0, float v1, float v2, float v3, float s, float t) { diff --git a/source/MaterialXGenMdl/mdl/materialx/pbrlib.mdl b/source/MaterialXGenMdl/mdl/materialx/pbrlib.mdl index 61234c4037..0c11ce3744 100644 --- a/source/MaterialXGenMdl/mdl/materialx/pbrlib.mdl +++ b/source/MaterialXGenMdl/mdl/materialx/pbrlib.mdl @@ -14,997 +14,17 @@ * limitations under the License. */ -// Implementation of all types and nodes of +// MDL implementation of all types and nodes of // MaterialX Physically-Based Shading Nodes // Document v1.37 REV2, July 16, 2019 (Revised October 17, 2019) // see www.materialx.org // in -// NVIDIA Material Definition Language 1.7 +// NVIDIA Material Definition Language 1.8 // Language Specification -// Document version 1.7.2, January 17, 2022 +// Document version 1.8.2, May 24, 2023 // www.nvidia.com/mdl -mdl 1.7; +mdl 1.8; -using .::core import *; -import .::swizzle::*; - -import ::df::*; -import ::math::*; -import ::state::*; -import ::anno::*; - -// NOTE: We use the MDL material type to represent all PBS nodes of -// BSDF, EDF, VDF and other MaterialX material related types. -// To document, and possibly also support tool diagnostics, we -// use the ::anno::usage(string) annotation to document the -// true MaterialX type, only connections with equal usage -// annotations are correct MaterialX connections. - -// NOTE: Geometric parameters like surface normal are specified in MDL internal -// space, which is the efficient and natural way for MDL. -// TODO: Check that the generator emits proper space transform conversion -// calls where needed -// TODO: Check how MaterialX unit handling works with this -// TODO: Check if scene_units_per_meter() is applicable as well, like for displacement - -// NOTE: Some PBR nodes require multiple implementations with different -// parameter types. If those require a material type as result, we -// cannot use overlaods and must use different names. Examples are -// mix, add, multiply, and we include displacement for orthogonality. - -// NOTE: Because of the BTDFs and the VDF below them, we have to take care -// of volumetric properties in the BSDF components as well. Since IOR -// is uniform in MDL, some nodes have a limitation on how IOR works. - - -// Enum selecting scatter mode, instead of string -export enum mx_scatter_mode { - mx_scatter_mode_R, - mx_scatter_mode_T, - mx_scatter_mode_RT -}; - -// Helper function mapping MaterialX scatter mode to MDL scatter_mode enum -export df::scatter_mode mx_map_scatter_mode( mx_scatter_mode mode) { - switch (mode) { - case mx_scatter_mode_R: - return df::scatter_reflect; - case mx_scatter_mode_T: - return df::scatter_transmit; - default: - return df::scatter_reflect_transmit; - } -} - -export material mx_oren_nayar_diffuse_bsdf( - float mxp_weight = 1.0, - color mxp_color = color(0.18), - float mxp_roughness = 0.0, - float3 mxp_normal = state::normal() -) [[ - anno::usage( "materialx:bsdf") -]] -= material( - surface: material_surface( - scattering: df::weighted_layer( - weight: mxp_weight, - layer: df::diffuse_reflection_bsdf( - tint: mxp_color, - roughness: mxp_roughness - ), - normal: mxp_normal - ) - ) -); - -// NOTE: Approximate Burley with df::diffuse_reflection_bsdf, the difference isn't big -export material mx_burley_diffuse_bsdf( - float mxp_weight = 1.0, - color mxp_color = color(0.18), - float mxp_roughness = 0.0, - float3 mxp_normal = state::normal() -) [[ - anno::usage( "materialx:bsdf") -]] -= material( - surface: material_surface( - scattering: df::weighted_layer( - weight: mxp_weight, - layer: df::diffuse_reflection_bsdf( - tint: mxp_color, - roughness: mxp_roughness - ), - normal: mxp_normal - ) - ) -); - -export material mx_translucent_bsdf( - float mxp_weight = 1.0, - color mxp_color = color(1.0), - float3 mxp_normal = state::normal() -) [[ - anno::usage( "materialx:bsdf") -]] -= material( - surface: material_surface( - scattering: df::weighted_layer( - weight: mxp_weight, - layer: df::diffuse_transmission_bsdf( - tint: mxp_color - ), - normal: mxp_normal - ) - ) -); - -// TODO MDL 1.8 -// * will add support for thin film above a color_custom_curve_layer node until then, thin_film will have no effect -// * thin_film(thickness: 0.0, ior: < 1.0) will be handled properly -export material mx_dielectric_bsdf( - float mxp_weight = 1.0, - color mxp_tint = color(1.0), - float mxp_ior = 1.5, - float2 mxp_roughness = float2(0.0), - float3 mxp_normal = state::normal(), - float3 mxp_tangent = state::texture_tangent_u(0), - uniform mx_distribution_type mxp_distribution = mx_distribution_type_ggx [[ anno::unused() ]], - uniform mx_scatter_mode mxp_scatter_mode = mx_scatter_mode_R, - material mxp_base = material() [[ anno::usage( "materialx:bsdf") ]], - float mxp_thinfilm_thickness = 0.0, - float mxp_thinfilm_ior = 1.0 -) [[ - anno::usage( "materialx:bsdf") -]] -= let { - float coatIor = mxp_thinfilm_ior <= 0.0 ? 1.0 : mxp_thinfilm_ior; - float grazing_refl = math::max((1.0 - math::average(mxp_roughness)), 0.0); - float root_r = (mxp_ior-1)/(mxp_ior+1); - bsdf bsdf_R = df::thin_film( - thickness: mxp_thinfilm_thickness, - ior: color(coatIor), - // fresnel layer has issues if base is a diffuse transmission, use custom curve for now - // this will break thin_film but improves standard_surface with diffuse transmission - base: df::custom_curve_layer( - normal_reflectivity: root_r*root_r, - grazing_reflectivity: grazing_refl, - weight: mxp_weight, - layer: df::microfacet_ggx_smith_bsdf( - roughness_u: mxp_roughness.x, - roughness_v: mxp_roughness.y, - tint: mxp_tint, - tangent_u: mxp_tangent, - mode: df::scatter_reflect), - base: mxp_base.surface.scattering, - normal: mxp_normal)); - - bsdf bsdf_T = df::weighted_layer( - weight: mxp_weight, - layer: df::microfacet_ggx_smith_bsdf( - roughness_u: mxp_roughness.x, - roughness_v: mxp_roughness.y, - tint: mxp_tint, - tangent_u: mxp_tangent, - mode: df::scatter_transmit), - normal: mxp_normal); - - bsdf bsdf_RT = df::weighted_layer( - weight: mxp_weight, - layer: df::thin_film( - thickness: mxp_thinfilm_thickness, - ior: color(coatIor), - base: df::microfacet_ggx_smith_bsdf( - roughness_u: mxp_roughness.x, - roughness_v: mxp_roughness.y, - tint: mxp_tint, - tangent_u: mxp_tangent, - mode: df::scatter_reflect_transmit)), - normal: mxp_normal); - - bsdf bsdf_selected = (mxp_scatter_mode == mx_scatter_mode_R) ? bsdf_R : - ((mxp_scatter_mode == mx_scatter_mode_T) ? bsdf_T : bsdf_RT); -} in material( - surface: material_surface( - scattering: bsdf_selected - ), - // we need to carry volume properties along for SSS - ior: mxp_base.ior, - volume: mxp_base.volume -); - -// TODO MDL 1.8 -// * thin_film(thickness: 0.0, ior: < 1.0) will be handled properly -export material mx_conductor_bsdf( - float mxp_weight = 1.0, - color mxp_ior = color(0.18, 0.42, 1.37), - color mxp_extinction = color(3.42, 2.35, 1.77), - float2 mxp_roughness = float2(0.0), - float3 mxp_normal = state::normal(), - float3 mxp_tangent = state::texture_tangent_u(0), - uniform mx_distribution_type mxp_distribution = mx_distribution_type_ggx [[ anno::unused() ]], - float mxp_thinfilm_thickness = 0.0, - float mxp_thinfilm_ior = 1.0 -) [[ - anno::usage( "materialx:bsdf") -]] -= let { - float coatIor = mxp_thinfilm_ior <= 0.0 ? 1.0 : mxp_thinfilm_ior; - bsdf ggx_model = df::microfacet_ggx_smith_bsdf( - roughness_u: mxp_roughness.x, - roughness_v: mxp_roughness.y, - tangent_u: mxp_tangent); - bsdf conductor = df::fresnel_factor( - ior: mxp_ior, - extinction_coefficient: mxp_extinction, - base: ggx_model); - bsdf thin_film_conductor = df::thin_film( - thickness: mxp_thinfilm_thickness, - ior: color(coatIor), - base: conductor); -} in material( - surface: material_surface( - scattering: df::weighted_layer( - weight: mxp_weight, - layer: thin_film_conductor, - normal: mxp_normal - ) - ) -); - -// TODO MDL 1.8 -// * will add support for thin film above a color_custom_curve_layer node until then, thin_film will have no effect -// * thin_film(thickness: 0.0, ior: < 1.0) will be handled properly -export material mx_generalized_schlick_bsdf( - float mxp_weight = 1.0, - color mxp_color0 = color(1.0), - color mxp_color90 = color(1.0), - float mxp_exponent = 5.0, - float2 mxp_roughness = float2(0.05), - float3 mxp_normal = state::normal(), - float3 mxp_tangent = state::texture_tangent_u(0), - uniform mx_distribution_type mxp_distribution = mx_distribution_type_ggx [[ anno::unused() ]], - uniform mx_scatter_mode mxp_scatter_mode = mx_scatter_mode_R, - material mxp_base = material() [[ anno::usage( "materialx:bsdf") ]], - float mxp_thinfilm_thickness = 0.0, - float mxp_thinfilm_ior = 1.0 -) [[ - anno::usage( "materialx:bsdf") -]] -= let { - float coatIor = mxp_thinfilm_ior <= 0.0 ? 1.0 : mxp_thinfilm_ior; - float avgF0 = math::average(float3(mxp_color0)); - bsdf ggx_model_R = df::microfacet_ggx_smith_bsdf( - roughness_u: mxp_roughness.x, - roughness_v: mxp_roughness.y, - tint: color(1.0), - tangent_u: mxp_tangent, - mode: df::scatter_reflect); - - bsdf ggx_model_T = df::microfacet_ggx_smith_bsdf( - roughness_u: mxp_roughness.x, - roughness_v: mxp_roughness.y, - tint: color(1.0), - tangent_u: mxp_tangent, - mode: df::scatter_transmit); -} in material( - surface: material_surface( - scattering: df::weighted_layer( - weight: mxp_weight, - layer: mxp_scatter_mode == mx_scatter_mode_T - ? df::color_custom_curve_layer( - normal_reflectivity: mxp_color0, - grazing_reflectivity: mxp_color90, - exponent: mxp_exponent, - layer: bsdf(), - base: ggx_model_T) - : df::thin_film( - thickness: mxp_thinfilm_thickness, - ior: color(coatIor), - base: df::color_custom_curve_layer( - normal_reflectivity: mxp_color0, - grazing_reflectivity: mxp_color90, - exponent: mxp_exponent, - layer: ggx_model_R, - base: mxp_scatter_mode == mx_scatter_mode_R - ? mxp_base.surface.scattering - : ggx_model_T)), - base: mxp_base.surface.scattering, - normal: mxp_normal - ) - ), - // we can't use the computed ior here because it's varying - // assuming that we have something glass like when transmission is used - ior: color(1.5), // color(mx_f0_to_ior(avgF0)) - - // we need to carry volume properties along for SSS - volume: mxp_base.volume -); - -export material mx_subsurface_bsdf( - float mxp_weight = 1.0 [[ anno::unused() ]], - color mxp_color = color(0.18), - float3 mxp_radius = float3(1.0), // TODO: should probably be a color in MTLX Spec - float mxp_anisotropy = 0.0, - float3 mxp_normal = state::normal() [[ anno::unused() ]] -) [[ - anno::usage( "materialx:bsdf") -]] -= let { - // https://blog.selfshadow.com/publications/s2017-shading-course/imageworks/s2017_pbs_imageworks_slides_v2.pdf - // Phase function eccentricity 'g' has been omitted here since we pass that directly - // to anisotropic_vdf(directional_bias: g). - color albedo = color(4.09712) + - (4.20863f * mxp_color) - - math::sqrt( - 9.59217f + - 41.6808f * mxp_color + - 17.7126f * mxp_color * mxp_color); - - color albedo_sq = albedo * albedo; - - color white = color(1.0, 1.0, 1.0); - - color alpha = - (white - albedo_sq) / (white - mxp_anisotropy * albedo_sq); - - color radius_inv = white/color(mxp_radius); - - color sigma_s = alpha * radius_inv; - color sigma_a = radius_inv - sigma_s; - -} in material( - volume: material_volume( - scattering: df::anisotropic_vdf ( - directional_bias: mxp_anisotropy - ), - scattering_coefficient: sigma_s, - absorption_coefficient: sigma_a - ), - - surface: material_surface( - scattering: df::diffuse_transmission_bsdf(tint: white) - ) -); - -// To match with OSL, the sheen weight is scaled with average color as approximation of albedo. -// OSL uses the layer operator which mixes based on albedo. -export material mx_sheen_bsdf( - float mxp_weight = 1.0, - color mxp_color = color(1.0), - float mxp_roughness = 0.2, - float3 mxp_normal = state::normal(), - material mxp_base = material( - surface: material_surface( - scattering: df::diffuse_reflection_bsdf( - ))) [[ anno::usage( "materialx:bsdf") ]] -) [[ - anno::usage( "materialx:bsdf") -]] -= material( - surface: material_surface( - // using the mix seems to fit OSL best, at least in the test cases - scattering: df::weighted_layer( - weight: math::average(mxp_color) * mxp_weight, - layer: df::sheen_bsdf( - roughness: mxp_roughness, - tint: mxp_color, - multiscatter_tint: color(1.0), - multiscatter: mxp_base.surface.scattering - ), - base: mxp_base.surface.scattering, - normal: mxp_normal)), - // we need to carry volume properties along for SSS - ior: mxp_base.ior, - volume: mxp_base.volume -); - -export material mx_thin_film_bsdf( - float mxp_thickness = 1000.0, - float mxp_ior = 1.5, - material mxp_base = material() [[ anno::usage( "materialx:bsdf") ]] -) [[ - anno::usage( "materialx:bsdf") -]] -= material( - surface: material_surface( - scattering: df::thin_film( - thickness: mxp_thickness, - ior: color(mxp_ior), - base: mxp_base.surface.scattering - ) - ), - // we need to carry volume properties along for SSS - ior: mxp_base.ior, - volume: mxp_base.volume -); - -// EDF Nodes - -export material mx_uniform_edf( - color mxp_color = color(1.0) -) [[ - anno::usage( "materialx:edf") -]] -= material( - surface: material_surface( - emission: material_emission( emission: df::diffuse_edf(), intensity: mxp_color * math::PI) - ) -); - -export material mx_conical_edf( - color mxp_color = color(1.0), - float3 mxp_normal = state::normal() - [[ - anno::unused() - ]], - uniform float mxp_inner_angle = 60.0, - uniform float mxp_outer_angle = 0.0 -) [[ - anno::usage( "materialx:edf") -]] -= material( - surface: material_surface( - emission: material_emission( - emission: df::spot_edf( // TODO: refine exact math of the mapping here - spread: math::radians( math::max(mxp_inner_angle, mxp_outer_angle)), - exponent: (mxp_outer_angle <= mxp_inner_angle) ? 0.0 : 1.0 - ), - intensity: mxp_color * math::PI - ) - ) -); - -export material mx_measured_edf( - color mxp_color = color(1.0), - float3 mxp_normal = state::normal() - [[ - anno::unused() - ]], - uniform light_profile mxp_file = light_profile() -) [[ - anno::usage( "materialx:edf") -]] -= material( - surface: material_surface( - emission: material_emission( - emission: df::measured_edf( profile: mxp_file), - intensity: mxp_color * math::PI - ) - ) -); - -export material mx_generalized_schlick_edf( - color mxp_color0 = color(1.0), - color mxp_color90 = color(1.0), - float mxp_exponent = 5.0, - material mxp_base = material() [[ anno::usage( "materialx:bsdf") ]] -) [[ - anno::usage( "materialx:edf") -]] -= material( - thin_walled: mxp_base.thin_walled, - surface: material_surface( - scattering: mxp_base.surface.scattering, - emission: material_emission( - emission: df::directional_factor(mxp_color0, mxp_color90, mxp_exponent, mxp_base.surface.emission.emission), - intensity: mxp_base.surface.emission.intensity, - mode: mxp_base.surface.emission.mode) - ), - backface: mxp_base.backface, - ior: mxp_base.ior, - volume: mxp_base.volume, - geometry: mxp_base.geometry, - hair: mxp_base.hair -); - -// VDF Nodes - -export material mx_absorption_vdf( - // TODO: should probably become color3 in the MaterialX spec - float3 mxp_absorption = float3(0.0) -) [[ - anno::usage( "materialx:vdf") -]] -= material( - volume: material_volume( - absorption_coefficient: color( mxp_absorption) - ) -); - -export material mx_anisotropic_vdf( - // TODO: should probably become color3 in the MaterialX spec - float3 mxp_absorption = float3(0.0), - // TODO: should probably become color3 in the MaterialX spec - float3 mxp_scattering = float3(0.0), - float mxp_anisotropy = 0.0 -) [[ - anno::usage( "materialx:vdf") -]] -= material( - volume: material_volume( - scattering: df::anisotropic_vdf( directional_bias: mxp_anisotropy), - absorption_coefficient: color( mxp_absorption), - scattering_coefficient: color( mxp_scattering) - ) -); - -// Shader Nodes - -// NOTE: The MDL material with thin_walled == false uses the same material_surface -// properties for the front- and backface, the material will not be black -// from the backside as mandated by the MaterialX spec. -export material mx_surface( - material mxp_bsdf = material() [[ anno::usage( "materialx:bsdf") ]], - material mxp_edf = material() [[ anno::usage( "materialx:edf") ]], - float mxp_opacity = 1.0, - uniform float mxp_transmission_ior = 0.0 // extra parameter for setting transmission IOR -) [[ - anno::usage( "materialx:surfaceshader") -]] -= let { - bsdf bsdf_node = mxp_bsdf.surface.scattering; - material_emission edf_node = mxp_edf.surface.emission; - // we need to carry volume properties along for SSS - material_volume bsdf_volume = mxp_bsdf.volume; -} in material( - thin_walled: false, - surface: material_surface( - scattering: bsdf_node, - emission: edf_node - ), - ior: mxp_transmission_ior > 0.0 ? color(mxp_transmission_ior) : mxp_bsdf.ior, - volume: bsdf_volume, - geometry: material_geometry( - cutout_opacity: mxp_opacity - ) -); - -export material mx_thin_surface( - material mxp_front_bsdf = material() [[ anno::usage( "materialx:bsdf") ]], - material mxp_front_edf = material() [[ anno::usage( "materialx:edf") ]], - material mxp_back_bsdf = material() [[ anno::usage( "materialx:bsdf") ]], - material mxp_back_edf = material() [[ anno::usage( "materialx:edf") ]], - float mxp_opacity = 1.0 -) [[ - anno::usage( "materialx:surfaceshader") -]] -= let { - bsdf front_bsdf_node = mxp_front_bsdf.surface.scattering; - material_emission front_edf_node = mxp_front_edf.surface.emission; - bsdf back_bsdf_node = mxp_back_bsdf.surface.scattering; - material_emission back_edf_node = mxp_back_edf.surface.emission; - // we need to carry volume properties along for SSS - // TODO: clarify SSS behavior in MaterialX for thin-walled surfaces, - // in MDL there is only one volume property - material_volume bsdf_volume = mxp_front_bsdf.volume; -} in material( - thin_walled: true, - surface: material_surface( - scattering: front_bsdf_node, - emission: front_edf_node - ), - backface: material_surface( - scattering: back_bsdf_node, - emission: back_edf_node - ), - ior: color(1.0), - volume: bsdf_volume, - geometry: material_geometry( - cutout_opacity: mxp_opacity - ) -); - -// MDL 1.7, Volumes do support emssion, but not as EDF, just emission intensity. -// A uniform emission DF is the only practical DF here. -export material mx_volume( - material mxp_vdf = material() [[ anno::usage( "materialx:vdf") ]], - material mxp_edf = material() [[ anno::usage( "materialx:edf") ]] -) [[ - anno::usage( "materialx:volumeshader") -]] -= material( - volume: material_volume( - absorption_coefficient: mxp_vdf.volume.absorption_coefficient, - scattering_coefficient: mxp_vdf.volume.scattering_coefficient, - emission_intensity: mxp_edf.surface.emission.intensity - ) -); - -export material mx_light( - material mxp_edf = material() [[ anno::usage( "materialx:edf") ]], - color mxp_intensity = color(1.0), - float mxp_exposure = 0.0 -) [[ - anno::usage( "materialx:lightshader") -]] -= let { - edf emission = mxp_edf.surface.emission.emission; - color intensity = mxp_edf.surface.emission.intensity; - color scale = (mxp_exposure == 0.0) - ? mxp_intensity - : mxp_intensity * math::pow(2, mxp_exposure); -} in material( - // TODO: check MTLX spec if we need emission on front- end backface - surface: material_surface( - emission: material_emission( - emission: emission, - intensity: intensity * scale - ) - ) -); - -// NOTE: MDL provides function overloading, but not material definition -// overlaoding. We thus try to use float3 as MDL type matching -// the MaterialX displacementshader and allow thus for an overloaded -// implementation of mxp_displacement. -// TODO: Check if this works in the translator and higher level nodes, like -// mxp_material, if not, we have to switch to the material type and -// use two different names for mxp_displacemnnt. -export material mx_displacement_float( - float mxp_displacement = 0.0, - float mxp_scale = 1.0 -) [[ - anno::usage( "materialx:displacementshader") -]] = material( - geometry: material_geometry( - displacement: mxp_displacement * mxp_scale * state::scene_units_per_meter() * state::normal() - ) -); - -export material mx_displacement_vector3( - float3 mxp_displacement = float3(0.0), - float mxp_scale = 1.0 -) [[ - anno::usage( "materialx:displacementshader") -]] = let -{ - float3 vec = (mxp_displacement.x * state::texture_tangent_u(0) - + mxp_displacement.y * state::texture_tangent_v(0) - + mxp_displacement.z * state::normal()); -} in material( - geometry: material_geometry( - displacement: vec * mxp_scale * state::scene_units_per_meter() - ) -); - - -// helper function to mix two scattering volumes: -// - combined scattering coefficient is just the sum of the two -// - VDF mixer weight is the relative probability of encountering the corresponding -// particle type -// NOTE: mixer weight should be a color, but due to a bug in current MDL compilers -// the color mixers don't accept non-uniform weights yet -struct volume_mix_return { - color scattering_coefficient; - float mix_weight1; // mix_weight2 = 1.0 - mix_weight1, can use any mixer -}; -volume_mix_return volume_mix( - color scattering_coefficient1, - float weight1, - color scattering_coefficient2, - float weight2) -{ - color s1 = weight1 * scattering_coefficient1; - color s = s1 + weight2 * scattering_coefficient2; - return volume_mix_return(scattering_coefficient: s, mix_weight1: math::average(s1 / s)); -} - -export material mx_mix_bsdf( - material mxp_fg = material() [[ anno::usage( "materialx:bsdf") ]], - material mxp_bg = material() [[ anno::usage( "materialx:bsdf") ]], - float mxp_mix = 0.0 -) [[ - anno::usage( "materialx:bsdf") -]] -= let { - volume_mix_return v = volume_mix( - mxp_fg.volume.scattering_coefficient, mxp_mix, - mxp_bg.volume.scattering_coefficient, (1.0f - mxp_mix)); -} in material( - surface: material_surface( - scattering: df::weighted_layer( - weight: mxp_mix, - layer: mxp_fg.surface.scattering, - base: mxp_bg.surface.scattering - ) - ), - // we need to carry volume properties along for SSS - ior: mxp_fg.ior, // NOTE: IOR is uniform, cannot mix here - volume: material_volume( - scattering: df::unbounded_mix( - df::vdf_component[]( - df::vdf_component(v.mix_weight1, mxp_fg.volume.scattering), - df::vdf_component(1.0 - v.mix_weight1, mxp_bg.volume.scattering)) - ), - absorption_coefficient: mxp_mix * mxp_fg.volume.absorption_coefficient + - (1.0 - mxp_mix) * mxp_bg.volume.absorption_coefficient, - scattering_coefficient: v.scattering_coefficient - ) -); - -export material mx_mix_edf( - material mxp_fg = material() [[ anno::usage( "materialx:edf") ]], - material mxp_bg = material() [[ anno::usage( "materialx:edf") ]], - float mxp_mix = 0.0 -) [[ - anno::usage( "materialx:edf") -]] -= material( - surface: material_surface( - emission: material_emission( - emission: df::unbounded_mix( // unbounded_mix is cheaper - df::edf_component[]( - df::edf_component( mxp_mix, mxp_fg.surface.emission.emission), - df::edf_component( 1.0 - mxp_mix, mxp_bg.surface.emission.emission)) - ), - intensity: mxp_mix * mxp_fg.surface.emission.intensity + - (1.0 - mxp_mix) * mxp_bg.surface.emission.intensity - ) - ) -); - -export material mx_mix_vdf( - material mxp_fg = material() [[ anno::usage( "materialx:vdf") ]], - material mxp_bg = material() [[ anno::usage( "materialx:vdf") ]], - float mxp_mix = 0.0 -) [[ - anno::usage( "materialx:vdf") -]] -= let { - volume_mix_return v = volume_mix( - mxp_fg.volume.scattering_coefficient, mxp_mix, - mxp_bg.volume.scattering_coefficient, (1.0f - mxp_mix)); -} in material( - ior: mxp_fg.ior, // NOTE: IOR is uniform, cannot mix here - volume: material_volume( - scattering: df::unbounded_mix( - df::vdf_component[]( - df::vdf_component( v.mix_weight1, mxp_fg.volume.scattering), - df::vdf_component( 1.0 - v.mix_weight1, mxp_bg.volume.scattering)) - ), - absorption_coefficient: mxp_mix * mxp_fg.volume.absorption_coefficient + - (1.0 - mxp_mix) * mxp_bg.volume.absorption_coefficient, - scattering_coefficient: v.scattering_coefficient - ) -); - -// NOTE: Adding two BSDFs is not supported in MDL, the generator would best -// analyze the context for mixing weights and replace the add with a mix. -// The provided implementation just mixes the BSDFs with equal weight. -export material mx_add_bsdf( - material mxp_in1 = material() [[ anno::usage( "materialx:bsdf") ]], - material mxp_in2 = material() [[ anno::usage( "materialx:bsdf") ]] -) [[ - anno::usage( "materialx:bsdf") -]] -= let { - volume_mix_return v = volume_mix( - mxp_in1.volume.scattering_coefficient, 1.0f, - mxp_in2.volume.scattering_coefficient, 1.0f); -} in material( - surface: material_surface( - scattering: df::unbounded_mix( - df::bsdf_component[]( - df::bsdf_component( 1.0, mxp_in1.surface.scattering), - df::bsdf_component( 1.0, mxp_in2.surface.scattering) - ) - ) - ), - // we need to carry volume properties along for SSS - volume: material_volume( - scattering: df::unbounded_mix( - df::vdf_component[]( - df::vdf_component( v.mix_weight1, mxp_in1.volume.scattering), - df::vdf_component( 1.0 - v.mix_weight1, mxp_in2.volume.scattering)) - ), - absorption_coefficient: mxp_in1.volume.absorption_coefficient + - mxp_in2.volume.absorption_coefficient, - scattering_coefficient: v.scattering_coefficient - ) -); - -// NOTE: Adding two EDFs is not supported in MDL, the generator would best -// analyze the context for mixing weights and replace the add with a mix. -// The provided implementation just mixes the EDFs with equal weight -// and adds the intensities. -export material mx_add_edf( - material mxp_in1 = material() [[ anno::usage( "materialx:edf") ]], - material mxp_in2 = material() [[ anno::usage( "materialx:edf") ]] -) [[ - anno::usage( "materialx:edf") -]] -= material( - surface: material_surface( - emission: material_emission( - emission: df::unbounded_mix( - df::edf_component[]( - df::edf_component( 1.0, mxp_in1.surface.emission.emission), - df::edf_component( 1.0, mxp_in2.surface.emission.emission)) - ), - intensity: mxp_in1.surface.emission.intensity + mxp_in2.surface.emission.intensity - ) - ) -); - -// NOTE: Adding two VDFs is not supported in MDL, the generator would best -// analyze the context for mixing weights and replace the add with a mix. -// The provided implementation just mixes the VDFs with equal weight. -export material mx_add_vdf( - material mxp_in1 = material() [[ anno::usage( "materialx:vdf") ]], - material mxp_in2 = material() [[ anno::usage( "materialx:vdf") ]] -) [[ - anno::usage( "materialx:vdf") -]] -= let { - volume_mix_return v = volume_mix( - mxp_in1.volume.scattering_coefficient, 1.0f, - mxp_in2.volume.scattering_coefficient, 1.0f); -} in material( - // assuming mixing the IOR is the best we can do here - ior: 0.5 * mxp_in1.ior + 0.5 * mxp_in2.ior, - volume: material_volume( - scattering: df::unbounded_mix( - df::vdf_component[]( - df::vdf_component( v.mix_weight1, mxp_in1.volume.scattering), - df::vdf_component( 1.0 - v.mix_weight1, mxp_in2.volume.scattering)) - ), - absorption_coefficient: mxp_in1.volume.absorption_coefficient + - mxp_in2.volume.absorption_coefficient, - scattering_coefficient: v.scattering_coefficient - ) -); - -export material mx_multiply_bsdf_color3( - material mxp_in1 = material() [[ anno::usage( "materialx:bsdf") ]], - color mxp_in2 = color(1.0) -) [[ - anno::usage( "materialx:bsdf") -]] -= material( - surface: material_surface( - scattering: df::tint( - tint: mxp_in2, - base: mxp_in1.surface.scattering - ) - ), - // we need to carry volume properties along for SSS - ior: mxp_in1.ior, - volume: mxp_in1.volume -); - -export material mx_multiply_bsdf_float( - material mxp_in1 = material() [[ anno::usage( "materialx:bsdf") ]], - float mxp_in2 = 1.0 -) [[ - anno::usage( "materialx:bsdf") -]] -= material( - surface: material_surface( - scattering: df::tint( - tint: color(mxp_in2), - base: mxp_in1.surface.scattering - ) - ), - // we need to carry volume properties along for SSS - ior: mxp_in1.ior, - volume: mxp_in1.volume -); - -export material mx_multiply_edf_color3( - material mxp_in1 = material() [[ anno::usage( "materialx:edf") ]], - color mxp_in2 = color(1.0) -) [[ - anno::usage( "materialx:edf") -]] -= material( - surface: material_surface( - emission: material_emission( - emission: mxp_in1.surface.emission.emission, - intensity: mxp_in2 * mxp_in1.surface.emission.intensity - ) - ) -); - -export material mx_multiply_edf_float( - material mxp_in1 = material() [[ anno::usage( "materialx:edf") ]], - float mxp_in2 = 1.0 -) [[ - anno::usage( "materialx:edf") -]] -= material( - surface: material_surface( - emission: material_emission( - emission: mxp_in1.surface.emission.emission, - intensity: mxp_in2 * mxp_in1.surface.emission.intensity - ) - ) -); - -export material mx_multiply_vdf_color3( - material mxp_in1 = material() [[ anno::usage( "materialx:vdf") ]], - color mxp_in2 = color(1.0) -) [[ - anno::usage( "materialx:vdf") -]] -= material( - ior: mxp_in1.ior, - volume: material_volume( - scattering: mxp_in1.volume.scattering, - absorption_coefficient: color(1.0) - - mxp_in2 * (color(1.0) - mxp_in1.volume.absorption_coefficient), - scattering_coefficient: mxp_in2 * mxp_in1.volume.scattering_coefficient - ) -); - -export material mx_multiply_vdf_float( - material mxp_in1 = material() [[ anno::usage( "materialx:vdf") ]], - float mxp_in2 = 1.0 -) [[ - anno::usage( "materialx:vdf") -]] -= material( - ior: mxp_in1.ior, - volume: material_volume( - scattering: mxp_in1.volume.scattering, - absorption_coefficient: color(1.0) - - mxp_in2 * (color(1.0) - mxp_in1.volume.absorption_coefficient), - scattering_coefficient: mxp_in2 * mxp_in1.volume.scattering_coefficient - ) -); - -export float2 mx_roughness_anisotropy( - float mxp_roughness = 0.0, - float mxp_anisotropy = 0.0 -) { - float roughness_sqr = math::clamp(mxp_roughness*mxp_roughness, FLOAT_EPS, 1.0); - if (mxp_anisotropy > 0.0) - { - float aspect = math::sqrt(1.0 - math::clamp(mxp_anisotropy, 0.0, 0.98)); - return float2( - math::min(roughness_sqr / aspect, 1.0), - roughness_sqr * aspect); - } - return float2(roughness_sqr); -} - -export float2 mx_roughness_dual( - float2 mxp_roughness = float2(0.0) -) { - if (mxp_roughness.y < 0.0) - mxp_roughness.y = mxp_roughness.x; - return float2( - math::clamp(mxp_roughness.x * mxp_roughness.x, FLOAT_EPS, 1.0), - math::clamp(mxp_roughness.y * mxp_roughness.y, FLOAT_EPS, 1.0)); -} - -export color mx_blackbody( - float mxp_temperature = 5000 -) { - return math::blackbody( mxp_temperature); -} - -// Supportive struct type for the two outputs of mx_artistic_ior -export struct mx_artistic_ior__result { - color mxp_ior; - color mxp_extinction; -}; - -// Converts the artistic parameterization reflectivity and edgecolor -// to complex IOR values; this is the inverse of the ​complex_ior​ node. -export mx_artistic_ior__result mx_artistic_ior( - color mxp_reflectivity = color(0.947, 0.776, 0.371), - color mxp_edge_color = color(1.0, 0.982, 0.753) -) { - color r = math::clamp( mxp_reflectivity, color(0.0), color(0.99)); - color r_sqrt = math::sqrt(r); - color n_min = (1.0 - r) / (1.0 + r); - color n_max = (1.0 + r_sqrt) / (1.0 - r_sqrt); - color n = math::lerp(n_max, n_min, mxp_edge_color); - color np1 = n + 1.0; - color nm1 = n - 1.0; - color k2 = (np1*np1 * r - nm1*nm1) / (1.0 - r); - k2 = math::max(k2, 0.0); - color k = math::sqrt(k2); - return mx_artistic_ior__result(n,k); -} +// forward the latest version +export using .::pbrlib_1_8 import *; diff --git a/source/MaterialXGenMdl/mdl/materialx/pbrlib_1_6.mdl b/source/MaterialXGenMdl/mdl/materialx/pbrlib_1_6.mdl new file mode 100644 index 0000000000..fbd6b5c1dd --- /dev/null +++ b/source/MaterialXGenMdl/mdl/materialx/pbrlib_1_6.mdl @@ -0,0 +1,1009 @@ +/* + * Copyright (c) 2020, NVIDIA CORPORATION. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// MDL implementation of all types and nodes of +// MaterialX Physically-Based Shading Nodes +// Document v1.37 REV2, July 16, 2019 (Revised October 17, 2019) +// see www.materialx.org +// in +// NVIDIA Material Definition Language 1.6 +// Language Specification +// Document version 1.6.1, December 16, 2019 +// www.nvidia.com/mdl + +mdl 1.6; + +import ::anno::*; +import ::df::*; +import ::math::*; +import ::state::*; + +import .::core::*; +import .::swizzle::*; + +// NOTE: We use the MDL material type to represent all PBS nodes of +// BSDF, EDF, VDF and other MaterialX material related types. +// To document, and possibly also support tool diagnostics, we +// use the ::anno::usage(string) annotation to document the +// true MaterialX type, only connections with equal usage +// annotations are correct MaterialX connections. + +// NOTE: Geometric parameters like surface normal are specified in MDL internal +// space, which is the efficient and natural way for MDL. +// TODO: Check that the generator emits proper space transform conversion +// calls where needed +// TODO: Check how MaterialX unit handling works with this +// TODO: Check if scene_units_per_meter() is applicable as well, like for displacement + +// NOTE: Some PBR nodes require multiple implementations with different +// parameter types. If those require a material type as result, we +// cannot use overlaods and must use different names. Examples are +// mix, add, multiply, and we include displacement for orthogonality. + +// NOTE: Because of the BTDFs and the VDF below them, we have to take care +// of volumetric properties in the BSDF components as well. Since IOR +// is uniform in MDL, some nodes have a limitation on how IOR works. + + +// Enum selecting scatter mode, instead of string +export enum mx_scatter_mode { + mx_scatter_mode_R, + mx_scatter_mode_T, + mx_scatter_mode_RT +}; + +// Helper function mapping MaterialX scatter mode to MDL scatter_mode enum +export df::scatter_mode mx_map_scatter_mode( + mx_scatter_mode mode +) { + switch (mode) { + case mx_scatter_mode_R: + return df::scatter_reflect; + case mx_scatter_mode_T: + return df::scatter_transmit; + default: + return df::scatter_reflect_transmit; + } +} + +export material mx_oren_nayar_diffuse_bsdf( + float mxp_weight = 1.0, + color mxp_color = color(0.18), + float mxp_roughness = 0.0, + float3 mxp_normal = state::normal() +) [[ + anno::usage( "materialx:bsdf") +]] += material( + surface: material_surface( + scattering: df::weighted_layer( + weight: mxp_weight, + layer: df::diffuse_reflection_bsdf( + tint: mxp_color, + roughness: mxp_roughness + ), + normal: mxp_normal + ) + ) +); + +// NOTE: Approximate Burley with df::diffuse_reflection_bsdf, the difference isn't big +export material mx_burley_diffuse_bsdf( + float mxp_weight = 1.0, + color mxp_color = color(0.18), + float mxp_roughness = 0.0, + float3 mxp_normal = state::normal() +) [[ + anno::usage( "materialx:bsdf") +]] += material( + surface: material_surface( + scattering: df::weighted_layer( + weight: mxp_weight, + layer: df::diffuse_reflection_bsdf( + tint: mxp_color, + roughness: mxp_roughness + ), + normal: mxp_normal + ) + ) +); + +export material mx_translucent_bsdf( + float mxp_weight = 1.0, + color mxp_color = color(1.0), + float3 mxp_normal = state::normal() +) [[ + anno::usage( "materialx:bsdf") +]] += material( + surface: material_surface( + scattering: df::weighted_layer( + weight: mxp_weight, + layer: df::diffuse_transmission_bsdf( + tint: mxp_color + ), + normal: mxp_normal + ) + ) +); + +// TODO MDL 1.8 +// * will add support for thin film above a color_custom_curve_layer node until then, thin_film will have no effect +// * thin_film(thickness: 0.0, ior: < 1.0) will be handled properly +export material mx_dielectric_bsdf( + float mxp_weight = 1.0, + color mxp_tint = color(1.0), + float mxp_ior = 1.5, + float2 mxp_roughness = float2(0.0), + float3 mxp_normal = state::normal(), + float3 mxp_tangent = state::texture_tangent_u(0), + uniform core::mx_distribution_type mxp_distribution = core::mx_distribution_type_ggx [[ anno::unused() ]], + uniform mx_scatter_mode mxp_scatter_mode = mx_scatter_mode_R, + material mxp_base = material() [[ anno::usage( "materialx:bsdf") ]], + float mxp_thinfilm_thickness = 0.0, + float mxp_thinfilm_ior = 1.0 +) [[ + anno::usage( "materialx:bsdf") +]] += let { + float coatIor = mxp_thinfilm_ior <= 0.0 ? 1.0 : mxp_thinfilm_ior; + float grazing_refl = math::max((1.0 - math::average(mxp_roughness)), 0.0); + float root_r = (mxp_ior-1)/(mxp_ior+1); + bsdf bsdf_R = df::thin_film( + thickness: mxp_thinfilm_thickness, + ior: color(coatIor), + // fresnel layer has issues if base is a diffuse transmission, use custom curve for now + // this will break thin_film but improves standard_surface with diffuse transmission + base: df::custom_curve_layer( + normal_reflectivity: root_r*root_r, + grazing_reflectivity: grazing_refl, + weight: mxp_weight, + layer: df::microfacet_ggx_smith_bsdf( + roughness_u: mxp_roughness.x, + roughness_v: mxp_roughness.y, + tint: mxp_tint, + tangent_u: mxp_tangent, + mode: df::scatter_reflect), + base: mxp_base.surface.scattering, + normal: mxp_normal)); + + bsdf bsdf_T = df::weighted_layer( + weight: mxp_weight, + layer: df::microfacet_ggx_smith_bsdf( + roughness_u: mxp_roughness.x, + roughness_v: mxp_roughness.y, + tint: mxp_tint, + tangent_u: mxp_tangent, + mode: df::scatter_transmit), + normal: mxp_normal); + + bsdf bsdf_RT = df::weighted_layer( + weight: mxp_weight, + layer: df::thin_film( + thickness: mxp_thinfilm_thickness, + ior: color(coatIor), + base: df::microfacet_ggx_smith_bsdf( + roughness_u: mxp_roughness.x, + roughness_v: mxp_roughness.y, + tint: mxp_tint, + tangent_u: mxp_tangent, + mode: df::scatter_reflect_transmit)), + normal: mxp_normal); + + bsdf bsdf_selected = (mxp_scatter_mode == mx_scatter_mode_R) ? bsdf_R : + ((mxp_scatter_mode == mx_scatter_mode_T) ? bsdf_T : bsdf_RT); +} in material( + surface: material_surface( + scattering: bsdf_selected + ), + // we need to carry volume properties along for SSS + ior: mxp_base.ior, + volume: mxp_base.volume +); + +// TODO MDL 1.8 +// * thin_film(thickness: 0.0, ior: < 1.0) will be handled properly +export material mx_conductor_bsdf( + float mxp_weight = 1.0, + color mxp_ior = color(0.18, 0.42, 1.37), + color mxp_extinction = color(3.42, 2.35, 1.77), + float2 mxp_roughness = float2(0.0), + float3 mxp_normal = state::normal(), + float3 mxp_tangent = state::texture_tangent_u(0), + uniform core::mx_distribution_type mxp_distribution = core::mx_distribution_type_ggx [[ anno::unused() ]], + float mxp_thinfilm_thickness = 0.0, + float mxp_thinfilm_ior = 1.0 +) [[ + anno::usage( "materialx:bsdf") +]] += let { + float coatIor = mxp_thinfilm_ior <= 0.0 ? 1.0 : mxp_thinfilm_ior; + bsdf ggx_model = df::microfacet_ggx_smith_bsdf( + roughness_u: mxp_roughness.x, + roughness_v: mxp_roughness.y, + tangent_u: mxp_tangent); + bsdf conductor = df::fresnel_factor( + ior: mxp_ior, + extinction_coefficient: mxp_extinction, + base: ggx_model); + bsdf thin_film_conductor = df::thin_film( + thickness: mxp_thinfilm_thickness, + ior: color(coatIor), + base: conductor); +} in material( + surface: material_surface( + scattering: df::weighted_layer( + weight: mxp_weight, + layer: thin_film_conductor, + normal: mxp_normal + ) + ) +); + +// TODO MDL 1.8 +// * will add support for thin film above a color_custom_curve_layer node until then, thin_film will have no effect +// * thin_film(thickness: 0.0, ior: < 1.0) will be handled properly +export material mx_generalized_schlick_bsdf( + float mxp_weight = 1.0, + color mxp_color0 = color(1.0), + color mxp_color90 = color(1.0), + float mxp_exponent = 5.0, + float2 mxp_roughness = float2(0.05), + float3 mxp_normal = state::normal(), + float3 mxp_tangent = state::texture_tangent_u(0), + uniform core::mx_distribution_type mxp_distribution = core::mx_distribution_type_ggx [[ anno::unused() ]], + uniform mx_scatter_mode mxp_scatter_mode = mx_scatter_mode_R, + material mxp_base = material() [[ anno::usage( "materialx:bsdf") ]], + float mxp_thinfilm_thickness = 0.0, + float mxp_thinfilm_ior = 1.0 +) [[ + anno::usage( "materialx:bsdf") +]] += let { + float coatIor = mxp_thinfilm_ior <= 0.0 ? 1.0 : mxp_thinfilm_ior; + // float avgF0 = math::average(float3(mxp_color0)); + bsdf ggx_model_R = df::microfacet_ggx_smith_bsdf( + roughness_u: mxp_roughness.x, + roughness_v: mxp_roughness.y, + tint: color(1.0), + tangent_u: mxp_tangent, + mode: df::scatter_reflect); + + bsdf ggx_model_T = df::microfacet_ggx_smith_bsdf( + roughness_u: mxp_roughness.x, + roughness_v: mxp_roughness.y, + tint: color(1.0), + tangent_u: mxp_tangent, + mode: df::scatter_transmit); +} in material( + surface: material_surface( + scattering: df::weighted_layer( + weight: mxp_weight, + layer: mxp_scatter_mode == mx_scatter_mode_T + ? df::color_custom_curve_layer( + normal_reflectivity: mxp_color0, + grazing_reflectivity: mxp_color90, + exponent: mxp_exponent, + layer: bsdf(), + base: ggx_model_T) + : df::thin_film( + thickness: mxp_thinfilm_thickness, + ior: color(coatIor), + base: df::color_custom_curve_layer( + normal_reflectivity: mxp_color0, + grazing_reflectivity: mxp_color90, + exponent: mxp_exponent, + layer: ggx_model_R, + base: mxp_scatter_mode == mx_scatter_mode_R + ? mxp_base.surface.scattering + : ggx_model_T)), + base: mxp_base.surface.scattering, + normal: mxp_normal + ) + ), + // we can't use the computed ior here because it's varying + // assuming that we have something glass like when transmission is used + ior: color(1.5), // color(mx_f0_to_ior(avgF0)) + + // we need to carry volume properties along for SSS + volume: mxp_base.volume +); + +export material mx_subsurface_bsdf( + float mxp_weight = 1.0 [[ anno::unused() ]], + color mxp_color = color(0.18), + float3 mxp_radius = float3(1.0), // TODO: should probably be a color in MTLX Spec + float mxp_anisotropy = 0.0, + float3 mxp_normal = state::normal() [[ anno::unused() ]] +) [[ + anno::usage( "materialx:bsdf") +]] += let { + // https://blog.selfshadow.com/publications/s2017-shading-course/imageworks/s2017_pbs_imageworks_slides_v2.pdf + // Phase function eccentricity 'g' has been omitted here since we pass that directly + // to anisotropic_vdf(directional_bias: g). + color albedo = color(4.09712) + + (4.20863f * mxp_color) - + math::sqrt( + 9.59217f + + 41.6808f * mxp_color + + 17.7126f * mxp_color * mxp_color); + + color albedo_sq = albedo * albedo; + + color white = color(1.0, 1.0, 1.0); + + color alpha = + (white - albedo_sq) / (white - mxp_anisotropy * albedo_sq); + + color radius_inv = white/color(mxp_radius); + + color sigma_s = alpha * radius_inv; + color sigma_a = radius_inv - sigma_s; + +} in material( + volume: material_volume( + scattering: df::anisotropic_vdf ( + directional_bias: mxp_anisotropy + ), + scattering_coefficient: sigma_s, + absorption_coefficient: sigma_a + ), + + surface: material_surface( + scattering: df::diffuse_transmission_bsdf(tint: white) + ) +); + +// TODO: MDL's sheen BSDF has no possibility to configure the base BSDF, it is +// always a diffuse BSDF. Its color is configurable through the multiscatter +// tint and can be fed through the extra mxp_diffuse_tint input. A context +// analysis in the generator can map the color of the base to this input. +export material mx_sheen_bsdf( + float mxp_weight = 1.0, + color mxp_color = color(1.0), + float mxp_roughness = 0.2, + float3 mxp_normal = state::normal(), + material mxp_base = material() [[ anno::usage( "materialx:bsdf") ]], + color mxp_diffuse_color = color(1.0) // color of the base layer, MDL supports only diffuse +) [[ + anno::usage( "materialx:bsdf") +]] += material( + surface: material_surface( + scattering: df::weighted_layer( + weight: mxp_weight, + layer: df::sheen_bsdf( + roughness: mxp_roughness, + tint: mxp_color, + multiscatter_tint: mxp_diffuse_color + ), + base: mxp_base.surface.scattering, + normal: mxp_normal + ) + ), + // we need to carry volume properties along for SSS + ior: mxp_base.ior, + volume: mxp_base.volume +); + +export material mx_thin_film_bsdf( + float mxp_thickness = 1000.0, + float mxp_ior = 1.5, + material mxp_base = material() [[ anno::usage( "materialx:bsdf") ]] +) [[ + anno::usage( "materialx:bsdf") +]] += material( + surface: material_surface( + scattering: df::thin_film( + thickness: mxp_thickness, + ior: color(mxp_ior), + base: mxp_base.surface.scattering + ) + ), + // we need to carry volume properties along for SSS + ior: mxp_base.ior, + volume: mxp_base.volume +); + +// EDF Nodes + +export material mx_uniform_edf( + color mxp_color = color(1.0) +) [[ + anno::usage( "materialx:edf") +]] += material( + surface: material_surface( + emission: material_emission( emission: df::diffuse_edf(), intensity: mxp_color * math::PI) + ) +); + +export material mx_conical_edf( + color mxp_color = color(1.0), + float3 mxp_normal = state::normal() + [[ + anno::unused() + ]], + uniform float mxp_inner_angle = 60.0, + uniform float mxp_outer_angle = 0.0 +) [[ + anno::usage( "materialx:edf") +]] += material( + surface: material_surface( + emission: material_emission( + emission: df::spot_edf( // TODO: refine exact math of the mapping here + spread: math::radians( math::max(mxp_inner_angle, mxp_outer_angle)), + exponent: (mxp_outer_angle <= mxp_inner_angle) ? 0.0 : 1.0 + ), + intensity: mxp_color * math::PI + ) + ) +); + +export material mx_measured_edf( + color mxp_color = color(1.0), + float3 mxp_normal = state::normal() + [[ + anno::unused() + ]], + uniform light_profile mxp_file = light_profile() +) [[ + anno::usage( "materialx:edf") +]] += material( + surface: material_surface( + emission: material_emission( + emission: df::measured_edf( profile: mxp_file), + intensity: mxp_color * math::PI + ) + ) +); + +// no directional factor for EDFs in MDL 1.6 +export material mx_generalized_schlick_edf( + color mxp_color0 = color(1.0) [[anno::unused()]], + color mxp_color90 = color(1.0) [[anno::unused()]], + float mxp_exponent = 5.0 [[anno::unused()]], + material mxp_base = material() [[ anno::usage( "materialx:bsdf") ]] +) [[ + anno::usage( "materialx:edf") +]] += material( + thin_walled: mxp_base.thin_walled, + surface: material_surface( + scattering: mxp_base.surface.scattering, + emission: mxp_base.surface.emission + ), + backface: mxp_base.backface, + ior: mxp_base.ior, + volume: mxp_base.volume, + geometry: mxp_base.geometry, + hair: mxp_base.hair +); + +// VDF Nodes + +export material mx_absorption_vdf( + // TODO: should probably become color3 in the MaterialX spec + float3 mxp_absorption = float3(0.0) +) [[ + anno::usage( "materialx:vdf") +]] += material( + volume: material_volume( + absorption_coefficient: color( mxp_absorption) + ) +); + +export material mx_anisotropic_vdf( + // TODO: should probably become color3 in the MaterialX spec + float3 mxp_absorption = float3(0.0), + // TODO: should probably become color3 in the MaterialX spec + float3 mxp_scattering = float3(0.0), + float mxp_anisotropy = 0.0 +) [[ + anno::usage( "materialx:vdf") +]] += material( + volume: material_volume( + scattering: df::anisotropic_vdf( directional_bias: mxp_anisotropy), + absorption_coefficient: color( mxp_absorption), + scattering_coefficient: color( mxp_scattering) + ) +); + +// Shader Nodes + +// NOTE: The MDL material with thin_walled == false uses the same material_surface +// properties for the front- and backface, the material will not be black +// from the backside as mandated by the MaterialX spec. +export material mx_surface( + material mxp_bsdf = material() [[ anno::usage( "materialx:bsdf") ]], + material mxp_edf = material() [[ anno::usage( "materialx:edf") ]], + float mxp_opacity = 1.0, + uniform float mxp_transmission_ior = 0.0 // extra parameter for setting transmission IOR +) [[ + anno::usage( "materialx:surfaceshader") +]] += let { + bsdf bsdf_node = mxp_bsdf.surface.scattering; + material_emission edf_node = mxp_edf.surface.emission; + // we need to carry volume properties along for SSS + material_volume bsdf_volume = mxp_bsdf.volume; +} in material( + thin_walled: false, + surface: material_surface( + scattering: bsdf_node, + emission: edf_node + ), + ior: mxp_transmission_ior > 0.0 ? color(mxp_transmission_ior) : mxp_bsdf.ior, + volume: bsdf_volume, + geometry: material_geometry( + cutout_opacity: mxp_opacity + ) +); + +export material mx_thin_surface( + material mxp_front_bsdf = material() [[ anno::usage( "materialx:bsdf") ]], + material mxp_front_edf = material() [[ anno::usage( "materialx:edf") ]], + material mxp_back_bsdf = material() [[ anno::usage( "materialx:bsdf") ]], + material mxp_back_edf = material() [[ anno::usage( "materialx:edf") ]], + float mxp_opacity = 1.0 +) [[ + anno::usage( "materialx:surfaceshader") +]] += let { + bsdf front_bsdf_node = mxp_front_bsdf.surface.scattering; + material_emission front_edf_node = mxp_front_edf.surface.emission; + bsdf back_bsdf_node = mxp_back_bsdf.surface.scattering; + material_emission back_edf_node = mxp_back_edf.surface.emission; + // we need to carry volume properties along for SSS + // TODO: clarify SSS behavior in MaterialX for thin-walled surfaces, + // in MDL there is only one volume property + material_volume bsdf_volume = mxp_front_bsdf.volume; +} in material( + thin_walled: true, + surface: material_surface( + scattering: front_bsdf_node, + emission: front_edf_node + ), + backface: material_surface( + scattering: back_bsdf_node, + emission: back_edf_node + ), + ior: color(1.0), + volume: bsdf_volume, + geometry: material_geometry( + cutout_opacity: mxp_opacity + ) +); + +// MDL 1.6, Volumes do not support emission. +export material mx_volume( + material mxp_vdf = material() [[ anno::usage( "materialx:vdf") ]], + material mxp_edf = material() [[ anno::usage( "materialx:edf"), anno::unused() ]] +) [[ + anno::usage( "materialx:volumeshader") +]] += material( + volume: material_volume( + absorption_coefficient: mxp_vdf.volume.absorption_coefficient, + scattering_coefficient: mxp_vdf.volume.scattering_coefficient + ) +); + +export material mx_light( + material mxp_edf = material() [[ anno::usage( "materialx:edf") ]], + color mxp_intensity = color(1.0), + float mxp_exposure = 0.0 +) [[ + anno::usage( "materialx:lightshader") +]] += let { + edf emission = mxp_edf.surface.emission.emission; + color intensity = mxp_edf.surface.emission.intensity; + color scale = (mxp_exposure == 0.0) + ? mxp_intensity + : mxp_intensity * math::pow(2, mxp_exposure); +} in material( + // TODO: check MTLX spec if we need emission on front- end backface + surface: material_surface( + emission: material_emission( + emission: emission, + intensity: intensity * scale + ) + ) +); + +// NOTE: MDL provides function overloading, but not material definition +// overlaoding. We thus try to use float3 as MDL type matching +// the MaterialX displacementshader and allow thus for an overloaded +// implementation of mxp_displacement. +// TODO: Check if this works in the translator and higher level nodes, like +// mxp_material, if not, we have to switch to the material type and +// use two different names for mxp_displacemnnt. +export material mx_displacement_float( + float mxp_displacement = 0.0, + float mxp_scale = 1.0 +) [[ + anno::usage( "materialx:displacementshader") +]] = material( + geometry: material_geometry( + displacement: mxp_displacement * mxp_scale * state::scene_units_per_meter() * state::normal() + ) +); + +export material mx_displacement_vector3( + float3 mxp_displacement = float3(0.0), + float mxp_scale = 1.0 +) [[ + anno::usage( "materialx:displacementshader") +]] = let +{ + float3 vec = (mxp_displacement.x * state::texture_tangent_u(0) + + mxp_displacement.y * state::texture_tangent_v(0) + + mxp_displacement.z * state::normal()); +} in material( + geometry: material_geometry( + displacement: vec * mxp_scale * state::scene_units_per_meter() + ) +); + + +// helper function to mix two scattering volumes: +// - combined scattering coefficient is just the sum of the two +// - VDF mixer weight is the relative probability of encountering the corresponding +// particle type +// NOTE: mixer weight should be a color, but due to a bug in current MDL compilers +// the color mixers don't accept non-uniform weights yet +export struct volume_mix_return { + color scattering_coefficient; + float mix_weight1; // mix_weight2 = 1.0 - mix_weight1, can use any mixer +}; +export volume_mix_return volume_mix( + color scattering_coefficient1, + float weight1, + color scattering_coefficient2, + float weight2) +{ + color s1 = weight1 * scattering_coefficient1; + color s = s1 + weight2 * scattering_coefficient2; + return volume_mix_return(scattering_coefficient: s, mix_weight1: math::average(s1 / s)); +} + +export material mx_mix_bsdf( + material mxp_fg = material() [[ anno::usage( "materialx:bsdf") ]], + material mxp_bg = material() [[ anno::usage( "materialx:bsdf") ]], + float mxp_mix = 0.0 +) [[ + anno::usage( "materialx:bsdf") +]] += let { + float mix = math::saturate(mxp_mix); + volume_mix_return v = volume_mix( + mxp_fg.volume.scattering_coefficient, mix, + mxp_bg.volume.scattering_coefficient, (1.0f - mix)); +} in material( + surface: material_surface( + scattering: df::weighted_layer( + weight: mix, + layer: mxp_fg.surface.scattering, + base: mxp_bg.surface.scattering + ) + ), + // we need to carry volume properties along for SSS + ior: mxp_fg.ior, // NOTE: IOR is uniform, cannot mix here + volume: material_volume( + scattering: df::clamped_mix( + df::vdf_component[]( + df::vdf_component(v.mix_weight1, mxp_fg.volume.scattering), + df::vdf_component(1.0 - v.mix_weight1, mxp_bg.volume.scattering)) + ), + absorption_coefficient: mix * mxp_fg.volume.absorption_coefficient + + (1.0 - mix) * mxp_bg.volume.absorption_coefficient, + scattering_coefficient: v.scattering_coefficient + ) +); + +// NOTE: mixing two EDFs fails with the df::clamped_mix since the weights are uniform in MDL 1.6 +export material mx_mix_edf( + material mxp_fg = material() [[ anno::usage( "materialx:edf") ]], + material mxp_bg = material() [[ anno::usage( "materialx:edf") ]], + float mxp_mix = 0.0 +) [[ + anno::usage( "materialx:edf") +]] += let { + float mix = math::saturate(mxp_mix); +} in material( + surface: material_surface( + emission: material_emission( + emission: mxp_fg.surface.emission.emission, + intensity: mix * mxp_fg.surface.emission.intensity + + (1.0 - mix) * mxp_bg.surface.emission.intensity + ) + ) +); + +export material mx_mix_vdf( + material mxp_fg = material() [[ anno::usage( "materialx:vdf") ]], + material mxp_bg = material() [[ anno::usage( "materialx:vdf") ]], + float mxp_mix = 0.0 +) [[ + anno::usage( "materialx:vdf") +]] += let { + float mix = math::saturate(mxp_mix); + volume_mix_return v = volume_mix( + mxp_fg.volume.scattering_coefficient, mix, + mxp_bg.volume.scattering_coefficient, (1.0f - mix)); +} in material( + ior: mxp_fg.ior, // NOTE: IOR is uniform, cannot mix here + volume: material_volume( + scattering: df::clamped_mix( + df::vdf_component[]( + df::vdf_component( v.mix_weight1, mxp_fg.volume.scattering), + df::vdf_component( 1.0 - v.mix_weight1, mxp_bg.volume.scattering)) + ), + absorption_coefficient: mix * mxp_fg.volume.absorption_coefficient + + (1.0 - mix) * mxp_bg.volume.absorption_coefficient, + scattering_coefficient: v.scattering_coefficient + ) +); + +// NOTE: Adding two BSDFs is not supported in MDL, the generator would best +// analyze the context for mixing weights and replace the add with a mix. +// The provided implementation just mixes the BSDFs with equal weight. +export material mx_add_bsdf( + material mxp_in1 = material() [[ anno::usage( "materialx:bsdf") ]], + material mxp_in2 = material() [[ anno::usage( "materialx:bsdf") ]] +) [[ + anno::usage( "materialx:bsdf") +]] += let { + volume_mix_return v = volume_mix( + mxp_in1.volume.scattering_coefficient, 1.0f, + mxp_in2.volume.scattering_coefficient, 1.0f); +} in material( + surface: material_surface( + scattering: df::clamped_mix( + df::bsdf_component[]( + df::bsdf_component( 0.5, mxp_in1.surface.scattering), + df::bsdf_component( 0.5, mxp_in2.surface.scattering) + ) + ) + ), + // we need to carry volume properties along for SSS + volume: material_volume( + scattering: df::clamped_mix( + df::vdf_component[]( + df::vdf_component( v.mix_weight1, mxp_in1.volume.scattering), + df::vdf_component( 1.0 - v.mix_weight1, mxp_in2.volume.scattering)) + ), + absorption_coefficient: mxp_in1.volume.absorption_coefficient + + mxp_in2.volume.absorption_coefficient, + scattering_coefficient: v.scattering_coefficient + ) +); + +// NOTE: Adding two EDFs is not supported in MDL, the generator would best +// analyze the context for mixing weights and replace the add with a mix. +// The provided implementation just mixes the EDFs with equal weight +// and adds the intensities. +export material mx_add_edf( + material mxp_in1 = material() [[ anno::usage( "materialx:edf") ]], + material mxp_in2 = material() [[ anno::usage( "materialx:edf") ]] +) [[ + anno::usage( "materialx:edf") +]] += material( + surface: material_surface( + emission: material_emission( + emission: df::clamped_mix( + df::edf_component[]( + df::edf_component( 0.5, mxp_in1.surface.emission.emission), + df::edf_component( 0.5, mxp_in2.surface.emission.emission)) + ), + intensity: mxp_in1.surface.emission.intensity + mxp_in2.surface.emission.intensity + ) + ) +); + +// NOTE: Adding two VDFs is not supported in MDL, the generator would best +// analyze the context for mixing weights and replace the add with a mix. +// The provided implementation just mixes the VDFs with equal weight. +export material mx_add_vdf( + material mxp_in1 = material() [[ anno::usage( "materialx:vdf") ]], + material mxp_in2 = material() [[ anno::usage( "materialx:vdf") ]] +) [[ + anno::usage( "materialx:vdf") +]] += let { + volume_mix_return v = volume_mix( + mxp_in1.volume.scattering_coefficient, 1.0f, + mxp_in2.volume.scattering_coefficient, 1.0f); +} in material( + // assuming mixing the IOR is the best we can do here + ior: 0.5 * mxp_in1.ior + 0.5 * mxp_in2.ior, + volume: material_volume( + scattering: df::clamped_mix( + df::vdf_component[]( + df::vdf_component( v.mix_weight1, mxp_in1.volume.scattering), + df::vdf_component( 1.0 - v.mix_weight1, mxp_in2.volume.scattering)) + ), + absorption_coefficient: mxp_in1.volume.absorption_coefficient + + mxp_in2.volume.absorption_coefficient, + scattering_coefficient: v.scattering_coefficient + ) +); + +export material mx_multiply_bsdf_color3( + material mxp_in1 = material() [[ anno::usage( "materialx:bsdf") ]], + color mxp_in2 = color(1.0) +) [[ + anno::usage( "materialx:bsdf") +]] += material( + surface: material_surface( + scattering: df::tint( + tint: mxp_in2, + base: mxp_in1.surface.scattering + ) + ), + // we need to carry volume properties along for SSS + ior: mxp_in1.ior, + volume: mxp_in1.volume +); + +export material mx_multiply_bsdf_float( + material mxp_in1 = material() [[ anno::usage( "materialx:bsdf") ]], + float mxp_in2 = 1.0 +) [[ + anno::usage( "materialx:bsdf") +]] += material( + surface: material_surface( + scattering: df::tint( + tint: color(mxp_in2), + base: mxp_in1.surface.scattering + ) + ), + // we need to carry volume properties along for SSS + ior: mxp_in1.ior, + volume: mxp_in1.volume +); + +export material mx_multiply_edf_color3( + material mxp_in1 = material() [[ anno::usage( "materialx:edf") ]], + color mxp_in2 = color(1.0) +) [[ + anno::usage( "materialx:edf") +]] += material( + surface: material_surface( + emission: material_emission( + emission: mxp_in1.surface.emission.emission, + intensity: mxp_in2 * mxp_in1.surface.emission.intensity + ) + ) +); + +export material mx_multiply_edf_float( + material mxp_in1 = material() [[ anno::usage( "materialx:edf") ]], + float mxp_in2 = 1.0 +) [[ + anno::usage( "materialx:edf") +]] += material( + surface: material_surface( + emission: material_emission( + emission: mxp_in1.surface.emission.emission, + intensity: mxp_in2 * mxp_in1.surface.emission.intensity + ) + ) +); + +export material mx_multiply_vdf_color3( + material mxp_in1 = material() [[ anno::usage( "materialx:vdf") ]], + color mxp_in2 = color(1.0) +) [[ + anno::usage( "materialx:vdf") +]] += material( + ior: mxp_in1.ior, + volume: material_volume( + scattering: mxp_in1.volume.scattering, + absorption_coefficient: color(1.0) + - mxp_in2 * (color(1.0) - mxp_in1.volume.absorption_coefficient), + scattering_coefficient: mxp_in2 * mxp_in1.volume.scattering_coefficient + ) +); + +export material mx_multiply_vdf_float( + material mxp_in1 = material() [[ anno::usage( "materialx:vdf") ]], + float mxp_in2 = 1.0 +) [[ + anno::usage( "materialx:vdf") +]] += material( + ior: mxp_in1.ior, + volume: material_volume( + scattering: mxp_in1.volume.scattering, + absorption_coefficient: color(1.0) + - mxp_in2 * (color(1.0) - mxp_in1.volume.absorption_coefficient), + scattering_coefficient: mxp_in2 * mxp_in1.volume.scattering_coefficient + ) +); + +export float2 mx_roughness_anisotropy( + float mxp_roughness = 0.0, + float mxp_anisotropy = 0.0 +) { + float roughness_sqr = math::clamp(mxp_roughness*mxp_roughness, core::FLOAT_EPS, 1.0); + if (mxp_anisotropy > 0.0) + { + float aspect = math::sqrt(1.0 - math::clamp(mxp_anisotropy, 0.0, 0.98)); + return float2( + math::min(roughness_sqr / aspect, 1.0), + roughness_sqr * aspect); + } + return float2(roughness_sqr); +} + +export float2 mx_roughness_dual( + float2 mxp_roughness = float2(0.0) +) { + if (mxp_roughness.y < 0.0) + mxp_roughness.y = mxp_roughness.x; + return float2( + math::clamp(mxp_roughness.x * mxp_roughness.x, core::FLOAT_EPS, 1.0), + math::clamp(mxp_roughness.y * mxp_roughness.y, core::FLOAT_EPS, 1.0)); +} + +export color mx_blackbody( + float mxp_temperature = 5000 +) { + return math::blackbody( mxp_temperature); +} + +// Supportive struct type for the two outputs of mx_artistic_ior +export struct mx_artistic_ior__result { + color mxp_ior; + color mxp_extinction; +}; + +// Converts the artistic parameterization reflectivity and edgecolor +// to complex IOR values; this is the inverse of the ​complex_ior​ node. +export mx_artistic_ior__result mx_artistic_ior( + color mxp_reflectivity = color(0.947, 0.776, 0.371), + color mxp_edge_color = color(1.0, 0.982, 0.753) +) { + color r = math::clamp( mxp_reflectivity, color(0.0), color(0.99)); + color r_sqrt = math::sqrt(r); + color n_min = (1.0 - r) / (1.0 + r); + color n_max = (1.0 + r_sqrt) / (1.0 - r_sqrt); + color n = math::lerp(n_max, n_min, mxp_edge_color); + color np1 = n + 1.0; + color nm1 = n - 1.0; + color k2 = (np1*np1 * r - nm1*nm1) / (1.0 - r); + k2 = math::max(k2, 0.0); + color k = math::sqrt(k2); + return mx_artistic_ior__result(n,k); +} diff --git a/source/MaterialXGenMdl/mdl/materialx/pbrlib_1_7.mdl b/source/MaterialXGenMdl/mdl/materialx/pbrlib_1_7.mdl new file mode 100644 index 0000000000..e7e5526c01 --- /dev/null +++ b/source/MaterialXGenMdl/mdl/materialx/pbrlib_1_7.mdl @@ -0,0 +1,259 @@ +/* + * Copyright (c) 2020, NVIDIA CORPORATION. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// MDL implementation of all types and nodes of +// MaterialX Physically-Based Shading Nodes +// Document v1.37 REV2, July 16, 2019 (Revised October 17, 2019) +// see www.materialx.org +// in +// NVIDIA Material Definition Language 1.7 +// Language Specification +// Document version 1.7.2, January 17, 2022 +// www.nvidia.com/mdl + +mdl 1.7; + +// Changes since MDL 1.6 +// - Support for unbounded_mix to implement add_bsdf, add_edf, and add_vdf +// - Support for df::sheen_bsdf with a custom base BSDF +// - Support for df::directional_factor on EDFs to implement generalized_schlick_edf +// - Support for emission on VDFs + +import ::anno::*; +import ::df::*; +import ::math::*; +import ::state::*; + +// forward all unchanged definitions from the previous version +export using .::pbrlib_1_6 import mx_scatter_mode; +export using .::pbrlib_1_6 import mx_map_scatter_mode; +export using .::pbrlib_1_6 import mx_oren_nayar_diffuse_bsdf; +export using .::pbrlib_1_6 import mx_burley_diffuse_bsdf; +export using .::pbrlib_1_6 import mx_translucent_bsdf; +export using .::pbrlib_1_6 import mx_dielectric_bsdf; +export using .::pbrlib_1_6 import mx_conductor_bsdf; +export using .::pbrlib_1_6 import mx_generalized_schlick_bsdf; +export using .::pbrlib_1_6 import mx_subsurface_bsdf; +export using .::pbrlib_1_6 import mx_thin_film_bsdf; +export using .::pbrlib_1_6 import mx_uniform_edf; +export using .::pbrlib_1_6 import mx_conical_edf; +export using .::pbrlib_1_6 import mx_measured_edf; +export using .::pbrlib_1_6 import mx_absorption_vdf; +export using .::pbrlib_1_6 import mx_anisotropic_vdf; +export using .::pbrlib_1_6 import mx_surface; +export using .::pbrlib_1_6 import mx_thin_surface; +export using .::pbrlib_1_6 import mx_light; +export using .::pbrlib_1_6 import mx_displacement_float; +export using .::pbrlib_1_6 import mx_displacement_vector3; +export using .::pbrlib_1_6 import volume_mix_return; +export using .::pbrlib_1_6 import volume_mix; +export using .::pbrlib_1_6 import mx_mix_bsdf; +export using .::pbrlib_1_6 import mx_mix_vdf; +export using .::pbrlib_1_6 import mx_multiply_bsdf_color3; +export using .::pbrlib_1_6 import mx_multiply_bsdf_float; +export using .::pbrlib_1_6 import mx_multiply_edf_color3; +export using .::pbrlib_1_6 import mx_multiply_edf_float; +export using .::pbrlib_1_6 import mx_multiply_vdf_color3; +export using .::pbrlib_1_6 import mx_multiply_vdf_float; +export using .::pbrlib_1_6 import mx_roughness_anisotropy; +export using .::pbrlib_1_6 import mx_roughness_dual; +export using .::pbrlib_1_6 import mx_blackbody; +export using .::pbrlib_1_6 import mx_artistic_ior__result ; +export using .::pbrlib_1_6 import mx_artistic_ior; + + + +// To match with OSL, the sheen weight is scaled with average color as approximation of albedo. +// OSL uses the layer operator which mixes based on albedo. +export material mx_sheen_bsdf( + float mxp_weight = 1.0, + color mxp_color = color(1.0), + float mxp_roughness = 0.2, + float3 mxp_normal = state::normal(), + material mxp_base = material( + surface: material_surface( + scattering: df::diffuse_reflection_bsdf( + ))) [[ anno::usage( "materialx:bsdf") ]] +) [[ + anno::usage( "materialx:bsdf") +]] += material( + surface: material_surface( + // using the mix seems to fit OSL best, at least in the test cases + scattering: df::weighted_layer( + weight: math::average(mxp_color) * mxp_weight, + layer: df::sheen_bsdf( + roughness: mxp_roughness, + tint: mxp_color, + multiscatter_tint: color(1.0), + multiscatter: mxp_base.surface.scattering + ), + base: mxp_base.surface.scattering, + normal: mxp_normal)), + // we need to carry volume properties along for SSS + ior: mxp_base.ior, + volume: mxp_base.volume +); + + +// NOTE: Adding two BSDFs is not supported in MDL, the generator would best +// analyze the context for mixing weights and replace the add with a mix. +// The provided implementation just mixes the BSDFs with equal weight. +export material mx_add_bsdf( + material mxp_in1 = material() [[ anno::usage( "materialx:bsdf") ]], + material mxp_in2 = material() [[ anno::usage( "materialx:bsdf") ]] +) [[ + anno::usage( "materialx:bsdf") +]] += let { + volume_mix_return v = volume_mix( + mxp_in1.volume.scattering_coefficient, 1.0f, + mxp_in2.volume.scattering_coefficient, 1.0f); +} in material( + surface: material_surface( + scattering: df::unbounded_mix( + df::bsdf_component[]( + df::bsdf_component( 1.0, mxp_in1.surface.scattering), + df::bsdf_component( 1.0, mxp_in2.surface.scattering) + ) + ) + ), + // we need to carry volume properties along for SSS + volume: material_volume( + scattering: df::unbounded_mix( + df::vdf_component[]( + df::vdf_component( v.mix_weight1, mxp_in1.volume.scattering), + df::vdf_component( 1.0 - v.mix_weight1, mxp_in2.volume.scattering)) + ), + absorption_coefficient: mxp_in1.volume.absorption_coefficient + + mxp_in2.volume.absorption_coefficient, + scattering_coefficient: v.scattering_coefficient + ) +); + +// NOTE: Adding two EDFs is not supported in MDL, the generator would best +// analyze the context for mixing weights and replace the add with a mix. +// The provided implementation just mixes the EDFs with equal weight +// and adds the intensities. +export material mx_add_edf( + material mxp_in1 = material() [[ anno::usage( "materialx:edf") ]], + material mxp_in2 = material() [[ anno::usage( "materialx:edf") ]] +) [[ + anno::usage( "materialx:edf") +]] += material( + surface: material_surface( + emission: material_emission( + emission: df::unbounded_mix( + df::edf_component[]( + df::edf_component( 1.0, mxp_in1.surface.emission.emission), + df::edf_component( 1.0, mxp_in2.surface.emission.emission)) + ), + intensity: mxp_in1.surface.emission.intensity + mxp_in2.surface.emission.intensity + ) + ) +); + +export material mx_mix_edf( + material mxp_fg = material() [[ anno::usage( "materialx:edf") ]], + material mxp_bg = material() [[ anno::usage( "materialx:edf") ]], + float mxp_mix = 0.0 +) [[ + anno::usage( "materialx:edf") +]] += let { + float mix = math::saturate(mxp_mix); +} in material( + surface: material_surface( + emission: material_emission( + emission: df::unbounded_mix( + df::edf_component[]( + df::edf_component( mix, mxp_fg.surface.emission.emission), + df::edf_component( 1.0 - mix, mxp_bg.surface.emission.emission)) + ), + intensity: mix * mxp_fg.surface.emission.intensity + + (1.0 - mix) * mxp_bg.surface.emission.intensity + ) + ) +); + +// NOTE: Adding two VDFs is not supported in MDL, the generator would best +// analyze the context for mixing weights and replace the add with a mix. +// The provided implementation just mixes the VDFs with equal weight. +export material mx_add_vdf( + material mxp_in1 = material() [[ anno::usage( "materialx:vdf") ]], + material mxp_in2 = material() [[ anno::usage( "materialx:vdf") ]] +) [[ + anno::usage( "materialx:vdf") +]] += let { + volume_mix_return v = volume_mix( + mxp_in1.volume.scattering_coefficient, 1.0f, + mxp_in2.volume.scattering_coefficient, 1.0f); +} in material( + // assuming mixing the IOR is the best we can do here + ior: 0.5 * mxp_in1.ior + 0.5 * mxp_in2.ior, + volume: material_volume( + scattering: df::unbounded_mix( + df::vdf_component[]( + df::vdf_component( v.mix_weight1, mxp_in1.volume.scattering), + df::vdf_component( 1.0 - v.mix_weight1, mxp_in2.volume.scattering)) + ), + absorption_coefficient: mxp_in1.volume.absorption_coefficient + + mxp_in2.volume.absorption_coefficient, + scattering_coefficient: v.scattering_coefficient + ) +); + +export material mx_generalized_schlick_edf( + color mxp_color0 = color(1.0), + color mxp_color90 = color(1.0), + float mxp_exponent = 5.0, + material mxp_base = material() [[ anno::usage( "materialx:bsdf") ]] +) [[ + anno::usage( "materialx:edf") +]] += material( + thin_walled: mxp_base.thin_walled, + surface: material_surface( + scattering: mxp_base.surface.scattering, + emission: material_emission( + emission: df::directional_factor(mxp_color0, mxp_color90, mxp_exponent, mxp_base.surface.emission.emission), + intensity: mxp_base.surface.emission.intensity, + mode: mxp_base.surface.emission.mode) + ), + backface: mxp_base.backface, + ior: mxp_base.ior, + volume: mxp_base.volume, + geometry: mxp_base.geometry, + hair: mxp_base.hair +); + +// MDL 1.7, Volumes do support emission, but not as EDF, just emission intensity. +// A uniform emission DF is the only practical DF here. +export material mx_volume( + material mxp_vdf = material() [[ anno::usage( "materialx:vdf") ]], + material mxp_edf = material() [[ anno::usage( "materialx:edf") ]] +) [[ + anno::usage( "materialx:volumeshader") +]] += material( + volume: material_volume( + absorption_coefficient: mxp_vdf.volume.absorption_coefficient, + scattering_coefficient: mxp_vdf.volume.scattering_coefficient, + emission_intensity: mxp_edf.surface.emission.intensity + ) +); diff --git a/source/MaterialXGenMdl/mdl/materialx/pbrlib_1_8.mdl b/source/MaterialXGenMdl/mdl/materialx/pbrlib_1_8.mdl new file mode 100644 index 0000000000..fb77e4829b --- /dev/null +++ b/source/MaterialXGenMdl/mdl/materialx/pbrlib_1_8.mdl @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2020, NVIDIA CORPORATION. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// MDL implementation of all types and nodes of +// MaterialX Physically-Based Shading Nodes +// Document v1.37 REV2, July 16, 2019 (Revised October 17, 2019) +// see www.materialx.org +// in +// NVIDIA Material Definition Language 1.8 +// Language Specification +// Document version 1.8.2, May 24, 2023 +// www.nvidia.com/mdl + +mdl 1.8; + +// Changes since MDL 1.7 +// - Support thin-film on custom curve layer to improve generalized_schlick_bsdf, +// no new implementation required + +// forward all unchanged definitions from the previous version +export using .::pbrlib_1_7 import *; + +// without changing any source code diff --git a/source/MaterialXGenMdl/mdl/materialx/sampling.mdl b/source/MaterialXGenMdl/mdl/materialx/sampling.mdl index 89142f8c51..1809503653 100644 --- a/source/MaterialXGenMdl/mdl/materialx/sampling.mdl +++ b/source/MaterialXGenMdl/mdl/materialx/sampling.mdl @@ -5,10 +5,9 @@ mdl 1.6; -import::math::*; +import ::math::*; -using mx = materialx; -using ::mx::core import *; +import .::core::*; // Restrict to 7x7 kernel size for performance reasons export const int MX_MAX_SAMPLE_COUNT = 49; @@ -171,12 +170,12 @@ export color mx_convolution_color(color[MX_MAX_SAMPLE_COUNT] S, float[MX_WEIGHT_ return result; } -export color4 mx_convolution_color4(color4[MX_MAX_SAMPLE_COUNT] S, float[MX_WEIGHT_ARRAY_SIZE] W, int offset, int sampleCount) +export core::color4 mx_convolution_color4(core::color4[MX_MAX_SAMPLE_COUNT] S, float[MX_WEIGHT_ARRAY_SIZE] W, int offset, int sampleCount) { - color4 result = mk_color4(0.0, 0.0, 0.0, 0.0); + core::color4 result = core::mk_color4(0.0, 0.0, 0.0, 0.0); for (int i=0; i 1.0)) - return mxp_default; - if ( mxp_vaddressmode == mx_addressmode_type_constant - && ( mxp_texcoord.y < 0.0 || mxp_texcoord.y > 1.0)) - return mxp_default; - - float returnValue = ::tex::lookup_float(tex: mxp_file, - coord: mxp_texcoord, - wrap_u: map_addressmode(mxp_uaddressmode), - wrap_v: map_addressmode(mxp_vaddressmode)); - return returnValue; -} - -export color mx_image_color3( - uniform texture_2d mxp_file = texture_2d() - [[ - anno::display_name("Filename") - ]], - uniform string mxp_layer = string("") - [[ - anno::display_name("Layer"), anno::unused() - ]], - color mxp_default = color(0.0, 0.0, 0.0) - [[ - anno::display_name("Default Color") - ]], - float2 mxp_texcoord = float2(swizzle::xy(::state::texture_coordinate(0))) - [[ - anno::display_name("Texture Coordinates") - ]], - uniform mx_addressmode_type mxp_uaddressmode = mx_addressmode_type(mx_addressmode_type_periodic) - [[ - anno::description("Enumeration {constant,clamp,periodic,mirror}."), - anno::display_name("Address Mode U") - ]], - uniform mx_addressmode_type mxp_vaddressmode = mx_addressmode_type(mx_addressmode_type_periodic) - [[ - anno::description("Enumeration {constant,clamp,periodic,mirror}."), - anno::display_name("Address Mode V") - ]], - uniform mx_filterlookup_type mxp_filtertype = mx_filterlookup_type(mx_filterlookup_type_linear) - [[ - anno::description("Enumeration {closest,linear,cubic}."), - anno::display_name("Filter Type"), - anno::unused() - ]], - uniform string mxp_framerange = string("") - [[ - anno::display_name("Frame Range"), - anno::unused() - ]], - uniform int mxp_frameoffset = int(0) - [[ - anno::display_name("Frame Offset"), - anno::unused() - ]], - uniform mx_addressmode_type mxp_frameendaction = mx_addressmode_type(mx_addressmode_type_constant) - [[ - anno::description("Enumeration {constant,clamp,periodic,mirror}."), - anno::display_name("Frame End Action"), - anno::unused() - ]] -) - [[ - anno::description("Node Group: texture2d") - ]] -{ - if ( mxp_uaddressmode == mx_addressmode_type_constant - && ( mxp_texcoord.x < 0.0 || mxp_texcoord.x > 1.0)) - return mxp_default; - if ( mxp_vaddressmode == mx_addressmode_type_constant - && ( mxp_texcoord.y < 0.0 || mxp_texcoord.y > 1.0)) - return mxp_default; - - color returnValue = ::tex::lookup_color(tex: mxp_file, - coord: mxp_texcoord, - wrap_u: map_addressmode(mxp_uaddressmode), - wrap_v: map_addressmode(mxp_vaddressmode)); - return returnValue; -} - -export color4 mx_image_color4( - uniform texture_2d mxp_file = texture_2d() - [[ - anno::display_name("Filename") - ]], - uniform string mxp_layer = string("") - [[ - anno::display_name("Layer"), anno::unused() - ]], - color4 mxp_default = mk_color4(0.0, 0.0, 0.0, 0.0) - [[ - anno::display_name("Default Color") - ]], - float2 mxp_texcoord = float2(swizzle::xy(::state::texture_coordinate(0))) - [[ - anno::display_name("Texture Coordinates") - ]], - uniform mx_addressmode_type mxp_uaddressmode = mx_addressmode_type(mx_addressmode_type_periodic) - [[ - anno::description("Enumeration {constant,clamp,periodic,mirror}."), - anno::display_name("Address Mode U") - ]], - uniform mx_addressmode_type mxp_vaddressmode = mx_addressmode_type(mx_addressmode_type_periodic) - [[ - anno::description("Enumeration {constant,clamp,periodic,mirror}."), - anno::display_name("Address Mode V") - ]], - uniform mx_filterlookup_type mxp_filtertype = mx_filterlookup_type(mx_filterlookup_type_linear) - [[ - anno::description("Enumeration {closest,linear,cubic}."), - anno::display_name("Filter Type"), - anno::unused() - ]], - uniform string mxp_framerange = string("") - [[ - anno::display_name("Frame Range"), - anno::unused() - ]], - uniform int mxp_frameoffset = int(0) - [[ - anno::display_name("Frame Offset"), - anno::unused() - ]], - uniform mx_addressmode_type mxp_frameendaction = mx_addressmode_type(mx_addressmode_type_constant) - [[ - anno::description("Enumeration {constant,clamp,periodic,mirror}."), - anno::display_name("Frame End Action"), - anno::unused() - ]] -) - [[ - anno::description("Node Group: texture2d") - ]] -{ - if ( mxp_uaddressmode == mx_addressmode_type_constant - && ( mxp_texcoord.x < 0.0 || mxp_texcoord.x > 1.0)) - return mxp_default; - if ( mxp_vaddressmode == mx_addressmode_type_constant - && ( mxp_texcoord.y < 0.0 || mxp_texcoord.y > 1.0)) - return mxp_default; - - color4 returnValue = mk_color4( ::tex::lookup_float4(tex: mxp_file, - coord: mxp_texcoord, - wrap_u: map_addressmode(mxp_uaddressmode), - wrap_v: map_addressmode(mxp_vaddressmode))); - return returnValue; -} - -export float2 mx_image_vector2( - uniform texture_2d mxp_file = texture_2d() - [[ - anno::display_name("Filename") - ]], - uniform string mxp_layer = string("") - [[ - anno::display_name("Layer"), anno::unused() - ]], - float2 mxp_default = float2(0.0, 0.0) - [[ - anno::display_name("Default Color") - ]], - float2 mxp_texcoord = float2(swizzle::xy(::state::texture_coordinate(0))) - [[ - anno::display_name("Texture Coordinates") - ]], - uniform mx_addressmode_type mxp_uaddressmode = mx_addressmode_type(mx_addressmode_type_periodic) - [[ - anno::description("Enumeration {constant,clamp,periodic,mirror}."), - anno::display_name("Address Mode U") - ]], - uniform mx_addressmode_type mxp_vaddressmode = mx_addressmode_type(mx_addressmode_type_periodic) - [[ - anno::description("Enumeration {constant,clamp,periodic,mirror}."), - anno::display_name("Address Mode V") - ]], - uniform mx_filterlookup_type mxp_filtertype = mx_filterlookup_type(mx_filterlookup_type_linear) - [[ - anno::description("Enumeration {closest,linear,cubic}."), - anno::display_name("Filter Type"), - anno::unused() - ]], - uniform string mxp_framerange = string("") - [[ - anno::display_name("Frame Range"), - anno::unused() - ]], - uniform int mxp_frameoffset = int(0) - [[ - anno::display_name("Frame Offset"), - anno::unused() - ]], - uniform mx_addressmode_type mxp_frameendaction = mx_addressmode_type(mx_addressmode_type_constant) - [[ - anno::description("Enumeration {constant,clamp,periodic,mirror}."), - anno::display_name("Frame End Action"), - anno::unused() - ]] -) - [[ - anno::description("Node Group: texture2d") - ]] -{ - if ( mxp_uaddressmode == mx_addressmode_type_constant - && ( mxp_texcoord.x < 0.0 || mxp_texcoord.x > 1.0)) - return mxp_default; - if ( mxp_vaddressmode == mx_addressmode_type_constant - && ( mxp_texcoord.y < 0.0 || mxp_texcoord.y > 1.0)) - return mxp_default; - - float2 returnValue = ::tex::lookup_float2(tex: mxp_file, - coord: mxp_texcoord, - wrap_u: map_addressmode(mxp_uaddressmode), - wrap_v: map_addressmode(mxp_vaddressmode)); - return returnValue; -} - -export float3 mx_image_vector3( - uniform texture_2d mxp_file = texture_2d() - [[ - anno::display_name("Filename") - ]], - uniform string mxp_layer = string("") - [[ - anno::display_name("Layer"), anno::unused() - ]], - float3 mxp_default = float3(0.0, 0.0, 0.0) - [[ - anno::display_name("Default Color") - ]], - float2 mxp_texcoord = float2(swizzle::xy(::state::texture_coordinate(0))) - [[ - anno::display_name("Texture Coordinates") - ]], - uniform mx_addressmode_type mxp_uaddressmode = mx_addressmode_type(mx_addressmode_type_periodic) - [[ - anno::description("Enumeration {constant,clamp,periodic,mirror}."), - anno::display_name("Address Mode U") - ]], - uniform mx_addressmode_type mxp_vaddressmode = mx_addressmode_type(mx_addressmode_type_periodic) - [[ - anno::description("Enumeration {constant,clamp,periodic,mirror}."), - anno::display_name("Address Mode V") - ]], - uniform mx_filterlookup_type mxp_filtertype = mx_filterlookup_type(mx_filterlookup_type_linear) - [[ - anno::description("Enumeration {closest,linear,cubic}."), - anno::display_name("Filter Type"), - anno::unused() - ]], - uniform string mxp_framerange = string("") - [[ - anno::display_name("Frame Range"), - anno::unused() - ]], - uniform int mxp_frameoffset = int(0) - [[ - anno::display_name("Frame Offset"), - anno::unused() - ]], - uniform mx_addressmode_type mxp_frameendaction = mx_addressmode_type(mx_addressmode_type_constant) - [[ - anno::description("Enumeration {constant,clamp,periodic,mirror}."), - anno::display_name("Frame End Action"), - anno::unused() - ]] -) - [[ - anno::description("Node Group: texture2d") - ]] -{ - if ( mxp_uaddressmode == mx_addressmode_type_constant - && ( mxp_texcoord.x < 0.0 || mxp_texcoord.x > 1.0)) - return mxp_default; - if ( mxp_vaddressmode == mx_addressmode_type_constant - && ( mxp_texcoord.y < 0.0 || mxp_texcoord.y > 1.0)) - return mxp_default; - - float3 returnValue = ::tex::lookup_float3(tex: mxp_file, - coord: mxp_texcoord, - wrap_u: map_addressmode(mxp_uaddressmode), - wrap_v: map_addressmode(mxp_vaddressmode)); - return returnValue; -} - -export float4 mx_image_vector4( - uniform texture_2d mxp_file = texture_2d() - [[ - anno::display_name("Filename") - ]], - uniform string mxp_layer = string("") - [[ - anno::display_name("Layer"), anno::unused() - ]], - float4 mxp_default = float4(0.0, 0.0, 0.0, 0.0) - [[ - anno::display_name("Default Color") - ]], - float2 mxp_texcoord = float2(swizzle::xy(::state::texture_coordinate(0))) - [[ - anno::display_name("Texture Coordinates") - ]], - uniform mx_addressmode_type mxp_uaddressmode = mx_addressmode_type(mx_addressmode_type_periodic) - [[ - anno::description("Enumeration {constant,clamp,periodic,mirror}."), - anno::display_name("Address Mode U") - ]], - uniform mx_addressmode_type mxp_vaddressmode = mx_addressmode_type(mx_addressmode_type_periodic) - [[ - anno::description("Enumeration {constant,clamp,periodic,mirror}."), - anno::display_name("Address Mode V") - ]], - uniform mx_filterlookup_type mxp_filtertype = mx_filterlookup_type(mx_filterlookup_type_linear) - [[ - anno::description("Enumeration {closest,linear,cubic}."), - anno::display_name("Filter Type"), - anno::unused() - ]], - uniform string mxp_framerange = string("") - [[ - anno::display_name("Frame Range"), - anno::unused() - ]], - uniform int mxp_frameoffset = int(0) - [[ - anno::display_name("Frame Offset"), - anno::unused() - ]], - uniform mx_addressmode_type mxp_frameendaction = mx_addressmode_type(mx_addressmode_type_constant) - [[ - anno::description("Enumeration {constant,clamp,periodic,mirror}."), - anno::display_name("Frame End Action"), - anno::unused() - ]] -) - [[ - anno::description("Node Group: texture2d") - ]] -{ - if ( mxp_uaddressmode == mx_addressmode_type_constant - && ( mxp_texcoord.x < 0.0 || mxp_texcoord.x > 1.0)) - return mxp_default; - if ( mxp_vaddressmode == mx_addressmode_type_constant - && ( mxp_texcoord.y < 0.0 || mxp_texcoord.y > 1.0)) - return mxp_default; - - float4 returnValue = ::tex::lookup_float4(tex: mxp_file, - coord: mxp_texcoord, - wrap_u: map_addressmode(mxp_uaddressmode), - wrap_v: map_addressmode(mxp_vaddressmode)); - return returnValue; -} - -// Nodedef: ND_tiledimage_float is represented by a nodegraph: NG_tiledimage_float -// Nodedef: ND_tiledimage_color3 is represented by a nodegraph: NG_tiledimage_color3 -// Nodedef: ND_tiledimage_color4 is represented by a nodegraph: NG_tiledimage_color4 -// Nodedef: ND_tiledimage_vector2 is represented by a nodegraph: NG_tiledimage_vector2 -// Nodedef: ND_tiledimage_vector3 is represented by a nodegraph: NG_tiledimage_vector3 -// Nodedef: ND_tiledimage_vector4 is represented by a nodegraph: NG_tiledimage_vector4 -// Nodedef: ND_triplanarprojection_float is represented by a nodegraph: NG_triplanarprojection_float -// Nodedef: ND_triplanarprojection_color3 is represented by a nodegraph: NG_triplanarprojection_color3 -// Nodedef: ND_triplanarprojection_color4 is represented by a nodegraph: NG_triplanarprojection_color4 -// Nodedef: ND_triplanarprojection_vector2 is represented by a nodegraph: NG_triplanarprojection_vector2 -// Nodedef: ND_triplanarprojection_vector3 is represented by a nodegraph: NG_triplanarprojection_vector3 -// Nodedef: ND_triplanarprojection_vector4 is represented by a nodegraph: NG_triplanarprojection_vector4 - -export float mx_constant_float( - float mxp_value = float(0.0) -) - [[ - anno::description("Node Group: procedural") - ]] -{ - return mxp_value; -} - -export color mx_constant_color3( - color mxp_value = color(0.0, 0.0, 0.0) -) - [[ - anno::description("Node Group: procedural") - ]] -{ - return mxp_value; -} - -export color4 mx_constant_color4( - color4 mxp_value = mk_color4(0.0, 0.0, 0.0, 0.0) -) - [[ - anno::description("Node Group: procedural") - ]] -{ - return mxp_value; -} - -export float2 mx_constant_vector2( - float2 mxp_value = float2(0.0, 0.0) -) - [[ - anno::description("Node Group: procedural") - ]] -{ - return mxp_value; -} - -export float3 mx_constant_vector3( - float3 mxp_value = float3(0.0, 0.0, 0.0) -) - [[ - anno::description("Node Group: procedural") - ]] -{ - return mxp_value; -} - -export float4 mx_constant_vector4( - float4 mxp_value = float4(0.0, 0.0, 0.0, 0.0) -) - [[ - anno::description("Node Group: procedural") - ]] -{ - return mxp_value; -} - -export bool mx_constant_boolean( - bool mxp_value = bool(false) -) - [[ - anno::description("Node Group: procedural") - ]] -{ - return mxp_value; -} - -export int mx_constant_integer( - int mxp_value = int(0) -) - [[ - anno::description("Node Group: procedural") - ]] -{ - return mxp_value; -} - -export float3x3 mx_constant_matrix33( - float3x3 mxp_value = float3x3(1.0,0.0,0.0, 0.0,1.0,0.0, 0.0,0.0,1.0) -) - [[ - anno::description("Node Group: procedural") - ]] -{ - return mxp_value; -} - -export float4x4 mx_constant_matrix44( - float4x4 mxp_value = float4x4(1.0,0.0,0.0,0.0, 0.0,1.0,0.0,0.0, 0.0,0.0,1.0,0.0, 0.0,0.0,0.0,1.0) -) - [[ - anno::description("Node Group: procedural") - ]] -{ - return mxp_value; -} - -export string mx_constant_string( - uniform string mxp_value = string("") -) - [[ - anno::description("Node Group: procedural") - ]] -{ - return mxp_value; -} - -export string mx_constant_filename( - uniform string mxp_value = string("") -) - [[ - anno::description("Node Group: procedural") - ]] -{ - return mxp_value; -} - -export float mx_ramplr_float( - float mxp_valuel = float(0.0), - float mxp_valuer = float(0.0), - float2 mxp_texcoord = float2(swizzle::xy(::state::texture_coordinate(0))) -) - [[ - anno::description("Node Group: procedural2d") - ]] -{ - return math::lerp(mxp_valuel, mxp_valuer, math::clamp(mxp_texcoord.x, 0.0, 1.0)); -} - -export color mx_ramplr_color3( - color mxp_valuel = color(0.0, 0.0, 0.0), - color mxp_valuer = color(0.0, 0.0, 0.0), - float2 mxp_texcoord = float2(swizzle::xy(::state::texture_coordinate(0))) -) - [[ - anno::description("Node Group: procedural2d") - ]] -{ - return math::lerp(mxp_valuel, mxp_valuer, math::clamp(mxp_texcoord.x, 0.0, 1.0)); -} - -export color4 mx_ramplr_color4( - color4 mxp_valuel = mk_color4(0.0, 0.0, 0.0, 0.0), - color4 mxp_valuer = mk_color4(0.0, 0.0, 0.0, 0.0), - float2 mxp_texcoord = float2(swizzle::xy(::state::texture_coordinate(0))) -) - [[ - anno::description("Node Group: procedural2d") - ]] -{ - color rgb = math::lerp(mxp_valuel.rgb, mxp_valuer.rgb, math::clamp(mxp_texcoord.x, 0.0, 1.0)); - float a = math::lerp(mxp_valuel.a, mxp_valuer.a, math::clamp(mxp_texcoord.x, 0.0, 1.0)); - return color4(rgb, a);} - -export float2 mx_ramplr_vector2( - float2 mxp_valuel = float2(0.0, 0.0), - float2 mxp_valuer = float2(0.0, 0.0), - float2 mxp_texcoord = float2(swizzle::xy(::state::texture_coordinate(0))) -) - [[ - anno::description("Node Group: procedural2d") - ]] -{ - return math::lerp(mxp_valuel, mxp_valuer, math::clamp(mxp_texcoord.x, 0.0, 1.0)); -} - -export float3 mx_ramplr_vector3( - float3 mxp_valuel = float3(0.0, 0.0, 0.0), - float3 mxp_valuer = float3(0.0, 0.0, 0.0), - float2 mxp_texcoord = float2(swizzle::xy(::state::texture_coordinate(0))) -) - [[ - anno::description("Node Group: procedural2d") - ]] -{ - return math::lerp(mxp_valuel, mxp_valuer, math::clamp(mxp_texcoord.x, 0.0, 1.0)); -} - -export float4 mx_ramplr_vector4( - float4 mxp_valuel = float4(0.0, 0.0, 0.0, 0.0), - float4 mxp_valuer = float4(0.0, 0.0, 0.0, 0.0), - float2 mxp_texcoord = float2(swizzle::xy(::state::texture_coordinate(0))) -) - [[ - anno::description("Node Group: procedural2d") - ]] -{ - return math::lerp(mxp_valuel, mxp_valuer, math::clamp(mxp_texcoord.x, 0.0, 1.0)); -} - -export float mx_ramptb_float( - float mxp_valuet = float(0.0), - float mxp_valueb = float(0.0), - float2 mxp_texcoord = float2(swizzle::xy(::state::texture_coordinate(0))) -) - [[ - anno::description("Node Group: procedural2d") - ]] -{ - return math::lerp(mxp_valuet, mxp_valueb, math::clamp(mxp_texcoord.y, 0.0, 1.0)); -} - -export color mx_ramptb_color3( - color mxp_valuet = color(0.0, 0.0, 0.0), - color mxp_valueb = color(0.0, 0.0, 0.0), - float2 mxp_texcoord = float2(swizzle::xy(::state::texture_coordinate(0))) -) - [[ - anno::description("Node Group: procedural2d") - ]] -{ - return math::lerp(mxp_valuet, mxp_valueb, math::clamp(mxp_texcoord.y, 0.0, 1.0)); -} - -export color4 mx_ramptb_color4( - color4 mxp_valuet = mk_color4(0.0, 0.0, 0.0, 0.0), - color4 mxp_valueb = mk_color4(0.0, 0.0, 0.0, 0.0), - float2 mxp_texcoord = float2(swizzle::xy(::state::texture_coordinate(0))) -) - [[ - anno::description("Node Group: procedural2d") - ]] -{ - color rgb = math::lerp(mxp_valuet.rgb, mxp_valueb.rgb, math::clamp(mxp_texcoord.y, 0.0, 1.0)); - float a = math::lerp(mxp_valuet.a, mxp_valueb.a, math::clamp(mxp_texcoord.y, 0.0, 1.0)); - return color4(rgb, a);} - -export float2 mx_ramptb_vector2( - float2 mxp_valuet = float2(0.0, 0.0), - float2 mxp_valueb = float2(0.0, 0.0), - float2 mxp_texcoord = float2(swizzle::xy(::state::texture_coordinate(0))) -) - [[ - anno::description("Node Group: procedural2d") - ]] -{ - return math::lerp(mxp_valuet, mxp_valueb, math::clamp(mxp_texcoord.y, 0.0, 1.0)); -} - -export float3 mx_ramptb_vector3( - float3 mxp_valuet = float3(0.0, 0.0, 0.0), - float3 mxp_valueb = float3(0.0, 0.0, 0.0), - float2 mxp_texcoord = float2(swizzle::xy(::state::texture_coordinate(0))) -) - [[ - anno::description("Node Group: procedural2d") - ]] -{ - return math::lerp(mxp_valuet, mxp_valueb, math::clamp(mxp_texcoord.y, 0.0, 1.0)); -} - -export float4 mx_ramptb_vector4( - float4 mxp_valuet = float4(0.0, 0.0, 0.0, 0.0), - float4 mxp_valueb = float4(0.0, 0.0, 0.0, 0.0), - float2 mxp_texcoord = float2(swizzle::xy(::state::texture_coordinate(0))) -) - [[ - anno::description("Node Group: procedural2d") - ]] -{ - return math::lerp(mxp_valuet, mxp_valueb, math::clamp(mxp_texcoord.y, 0.0, 1.0)); -} - -// Nodedef: ND_ramp4_float is represented by a nodegraph: NG_ramp4_float -// Nodedef: ND_ramp4_color3 is represented by a nodegraph: NG_ramp4_color3 -// Nodedef: ND_ramp4_color4 is represented by a nodegraph: NG_ramp4_color4 -// Nodedef: ND_ramp4_vector2 is represented by a nodegraph: NG_ramp4_vector2 -// Nodedef: ND_ramp4_vector3 is represented by a nodegraph: NG_ramp4_vector3 -// Nodedef: ND_ramp4_vector4 is represented by a nodegraph: NG_ramp4_vector4 - -export float mx_splitlr_float( - float mxp_valuel = float(0.0) - [[ - anno::display_name("Left") - ]], - float mxp_valuer = float(0.0) - [[ - anno::display_name("Right") - ]], - float mxp_center = float(0.5) - [[ - anno::display_name("Center") - ]], - float2 mxp_texcoord = float2(swizzle::xy(::state::texture_coordinate(0))) -) - [[ - anno::description("Node Group: procedural2d") - ]] -{ - return math::lerp(mxp_valuel, mxp_valuer, math::step(mxp_center, math::clamp(mxp_texcoord.x,0,1))); -} - -export color mx_splitlr_color3( - color mxp_valuel = color(0.0, 0.0, 0.0) - [[ - anno::display_name("Left") - ]], - color mxp_valuer = color(0.0, 0.0, 0.0) - [[ - anno::display_name("Right") - ]], - float mxp_center = float(0.5) - [[ - anno::display_name("Center") - ]], - float2 mxp_texcoord = float2(swizzle::xy(::state::texture_coordinate(0))) -) - [[ - anno::description("Node Group: procedural2d") - ]] -{ - return math::lerp(mxp_valuel, mxp_valuer, math::step(mxp_center, math::clamp(mxp_texcoord.x,0,1))); -} - -export color4 mx_splitlr_color4( - color4 mxp_valuel = mk_color4(0.0, 0.0, 0.0, 0.0) - [[ - anno::display_name("Left") - ]], - color4 mxp_valuer = mk_color4(0.0, 0.0, 0.0, 0.0) - [[ - anno::display_name("Right") - ]], - float mxp_center = float(0.5) - [[ - anno::display_name("Center") - ]], - float2 mxp_texcoord = float2(swizzle::xy(::state::texture_coordinate(0))) -) - [[ - anno::description("Node Group: procedural2d") - ]] -{ - color rgb = math::lerp(mxp_valuel.rgb, mxp_valuer.rgb, math::step(mxp_center, math::clamp(mxp_texcoord.x,0,1))); - float a = math::lerp(mxp_valuel.a, mxp_valuer.a, math::step(mxp_center, math::clamp(mxp_texcoord.x,0,1))); - return color4(rgb, a); -} - -export float2 mx_splitlr_vector2( - float2 mxp_valuel = float2(0.0, 0.0) - [[ - anno::display_name("Left") - ]], - float2 mxp_valuer = float2(0.0, 0.0) - [[ - anno::display_name("Right") - ]], - float mxp_center = float(0.5) - [[ - anno::display_name("Center") - ]], - float2 mxp_texcoord = float2(swizzle::xy(::state::texture_coordinate(0))) -) - [[ - anno::description("Node Group: procedural2d") - ]] -{ - return math::lerp(mxp_valuel, mxp_valuer, math::step(mxp_center, math::clamp(mxp_texcoord.x,0,1))); -} - -export float3 mx_splitlr_vector3( - float3 mxp_valuel = float3(0.0, 0.0, 0.0) - [[ - anno::display_name("Left") - ]], - float3 mxp_valuer = float3(0.0, 0.0, 0.0) - [[ - anno::display_name("Right") - ]], - float mxp_center = float(0.5) - [[ - anno::display_name("Center") - ]], - float2 mxp_texcoord = float2(swizzle::xy(::state::texture_coordinate(0))) -) - [[ - anno::description("Node Group: procedural2d") - ]] -{ - return math::lerp(mxp_valuel, mxp_valuer, math::step(mxp_center, math::clamp(mxp_texcoord.x,0,1))); -} - -export float4 mx_splitlr_vector4( - float4 mxp_valuel = float4(0.0, 0.0, 0.0, 0.0) - [[ - anno::display_name("Left") - ]], - float4 mxp_valuer = float4(0.0, 0.0, 0.0, 0.0) - [[ - anno::display_name("Right") - ]], - float mxp_center = float(0.5) - [[ - anno::display_name("Center") - ]], - float2 mxp_texcoord = float2(swizzle::xy(::state::texture_coordinate(0))) -) - [[ - anno::description("Node Group: procedural2d") - ]] -{ - return math::lerp(mxp_valuel, mxp_valuer, math::step(mxp_center, math::clamp(mxp_texcoord.x,0,1))); -} - -export float mx_splittb_float( - float mxp_valuet = float(0.0) - [[ - anno::display_name("Top") - ]], - float mxp_valueb = float(0.0) - [[ - anno::display_name("Bottom") - ]], - float mxp_center = float(0.5) - [[ - anno::display_name("Center") - ]], - float2 mxp_texcoord = float2(swizzle::xy(::state::texture_coordinate(0))) -) - [[ - anno::description("Node Group: procedural2d") - ]] -{ - return math::lerp(mxp_valuet, mxp_valueb, math::step(mxp_center, math::clamp(mxp_texcoord.x,0,1))); -} - -export color mx_splittb_color3( - color mxp_valuet = color(0.0, 0.0, 0.0) - [[ - anno::display_name("Top") - ]], - color mxp_valueb = color(0.0, 0.0, 0.0) - [[ - anno::display_name("Bottom") - ]], - float mxp_center = float(0.5) - [[ - anno::display_name("Center") - ]], - float2 mxp_texcoord = float2(swizzle::xy(::state::texture_coordinate(0))) -) - [[ - anno::description("Node Group: procedural2d") - ]] -{ - return math::lerp(mxp_valuet, mxp_valueb, math::step(mxp_center, math::clamp(mxp_texcoord.x,0,1))); -} - -export color4 mx_splittb_color4( - color4 mxp_valuet = mk_color4(0.0, 0.0, 0.0, 0.0) - [[ - anno::display_name("Top") - ]], - color4 mxp_valueb = mk_color4(0.0, 0.0, 0.0, 0.0) - [[ - anno::display_name("Bottom") - ]], - float mxp_center = float(0.5) - [[ - anno::display_name("Center") - ]], - float2 mxp_texcoord = float2(swizzle::xy(::state::texture_coordinate(0))) -) - [[ - anno::description("Node Group: procedural2d") - ]] -{ - color rgb = math::lerp(mxp_valuet.rgb, mxp_valueb.rgb, math::step(mxp_center, math::clamp(mxp_texcoord.x,0,1))); float a = math::lerp(mxp_valuet.a, mxp_valueb.a, math::step(mxp_center, math::clamp(mxp_texcoord.x,0,1))); return color4(rgb, a); -} - -export float2 mx_splittb_vector2( - float2 mxp_valuet = float2(0.0, 0.0) - [[ - anno::display_name("Top") - ]], - float2 mxp_valueb = float2(0.0, 0.0) - [[ - anno::display_name("Bottom") - ]], - float mxp_center = float(0.5) - [[ - anno::display_name("Center") - ]], - float2 mxp_texcoord = float2(swizzle::xy(::state::texture_coordinate(0))) -) - [[ - anno::description("Node Group: procedural2d") - ]] -{ - return math::lerp(mxp_valuet, mxp_valueb, math::step(mxp_center, math::clamp(mxp_texcoord.x,0,1))); -} - -export float3 mx_splittb_vector3( - float3 mxp_valuet = float3(0.0, 0.0, 0.0) - [[ - anno::display_name("Top") - ]], - float3 mxp_valueb = float3(0.0, 0.0, 0.0) - [[ - anno::display_name("Bottom") - ]], - float mxp_center = float(0.5) - [[ - anno::display_name("Center") - ]], - float2 mxp_texcoord = float2(swizzle::xy(::state::texture_coordinate(0))) -) - [[ - anno::description("Node Group: procedural2d") - ]] -{ - return math::lerp(mxp_valuet, mxp_valueb, math::step(mxp_center, math::clamp(mxp_texcoord.x,0,1))); -} - -export float4 mx_splittb_vector4( - float4 mxp_valuet = float4(0.0, 0.0, 0.0, 0.0) - [[ - anno::display_name("Top") - ]], - float4 mxp_valueb = float4(0.0, 0.0, 0.0, 0.0) - [[ - anno::display_name("Bottom") - ]], - float mxp_center = float(0.5) - [[ - anno::display_name("Center") - ]], - float2 mxp_texcoord = float2(swizzle::xy(::state::texture_coordinate(0))) -) - [[ - anno::description("Node Group: procedural2d") - ]] -{ - return math::lerp(mxp_valuet, mxp_valueb, math::step(mxp_center, math::clamp(mxp_texcoord.x,0,1))); -} - -export float3 mx_position_vector3( - uniform mx_coordinatespace_type mxp_space = mx_coordinatespace_type(mx_coordinatespace_type_object) - [[ - anno::description("Enumeration {model,object,world}.") - ]] -) - [[ - anno::description("Node Group: geometric") - ]] -{ - state::coordinate_space fromSpace = ::mx_map_space(mx_coordinatespace_type_model); - state::coordinate_space toSpace = ::mx_map_space(mxp_space); - return state::transform_point(fromSpace, toSpace, state::position()); -} - -export float3 mx_normal_vector3( - uniform mx_coordinatespace_type mxp_space = mx_coordinatespace_type(mx_coordinatespace_type_object) - [[ - anno::description("Enumeration {model,object,world}.") - ]] -) - [[ - anno::description("Node Group: geometric") - ]] -{ - state::coordinate_space fromSpace = ::mx_map_space(mx_coordinatespace_type_model); - state::coordinate_space toSpace = ::mx_map_space(mxp_space); - return state::transform_normal(fromSpace, toSpace, state::normal()); -} - -export float3 mx_tangent_vector3( - uniform mx_coordinatespace_type mxp_space = mx_coordinatespace_type(mx_coordinatespace_type_object) - [[ - anno::description("Enumeration {model,object,world}.") - ]], - uniform int mxp_index = int(0) -) - [[ - anno::description("Node Group: geometric") - ]] -{ - state::coordinate_space fromSpace = ::mx_map_space(mx_coordinatespace_type_model); - state::coordinate_space toSpace = ::mx_map_space(mxp_space); - return ::math::normalize(state::transform_vector(fromSpace, toSpace, state::texture_tangent_u(mxp_index))); -} - -export float3 mx_bitangent_vector3( - uniform mx_coordinatespace_type mxp_space = mx_coordinatespace_type(mx_coordinatespace_type_object) - [[ - anno::description("Enumeration {model,object,world}.") - ]], - uniform int mxp_index = int(0) -) - [[ - anno::description("Node Group: geometric") - ]] -{ - state::coordinate_space fromSpace = ::mx_map_space(mx_coordinatespace_type_model); - state::coordinate_space toSpace = ::mx_map_space(mxp_space); - return ::math::normalize(state::transform_vector(fromSpace, toSpace, state::texture_tangent_v(mxp_index))); -} - -export float2 mx_texcoord_vector2( - uniform int mxp_index = int(0) -) - [[ - anno::description("Node Group: geometric") - ]] -{ - return swizzle::xy((state::texture_coordinate(mxp_index))); -} - -export float3 mx_texcoord_vector3( - uniform int mxp_index = int(0) -) - [[ - anno::description("Node Group: geometric") - ]] -{ - return state::texture_coordinate(mxp_index); -} - -export float mx_geomcolor_float( - uniform int mxp_index = int(0) [[ anno::unused() ]] -) - [[ - anno::description("Node Group: geometric") - ]] -{ - // Not implemented: mx_geomcolor_float - float defaultValue = float(0.0); - return defaultValue; -} - -export color mx_geomcolor_color3( - uniform int mxp_index = int(0) [[ anno::unused() ]] -) - [[ - anno::description("Node Group: geometric") - ]] -{ - // Not implemented: mx_geomcolor_color3 - color defaultValue = color(0.0, 0.0, 0.0); - return defaultValue; -} - -export color4 mx_geomcolor_color4( - uniform int mxp_index = int(0) [[ anno::unused() ]] -) - [[ - anno::description("Node Group: geometric") - ]] -{ - // Not implemented: mx_geomcolor_color4 - color4 defaultValue = mk_color4(0.0, 0.0, 0.0, 0.0); - return defaultValue; -} - -export int mx_geompropvalue_integer( - uniform string mxp_geomprop = string("") [[ anno::unused() ]], - int mxp_default = int(0) [[ anno::unused() ]] -) - [[ - anno::description("Node Group: geometric") - ]] -{ - // Not implemented: mx_geompropvalue_integer - int defaultValue = int(0); - return defaultValue; -} - -export bool mx_geompropvalue_boolean( - uniform string mxp_geomprop = string("") [[ anno::unused() ]], - bool mxp_default = bool(false) [[ anno::unused() ]] -) - [[ - anno::description("Node Group: geometric") - ]] -{ - // Not implemented: mx_geompropvalue_boolean - bool defaultValue = bool(false); - return defaultValue; -} - -export string mx_geompropvalue_string( - uniform string mxp_geomprop = string("") [[ anno::unused() ]], - string mxp_default = string("") [[ anno::unused() ]] -) - [[ - anno::description("Node Group: geometric") - ]] -{ - // Not implemented: mx_geompropvalue_string - string defaultValue; - return defaultValue; -} - -export float mx_geompropvalue_float( - uniform string mxp_geomprop = string("") [[ anno::unused() ]], - float mxp_default = float(0.0) [[ anno::unused() ]] -) - [[ - anno::description("Node Group: geometric") - ]] -{ - // Not implemented: mx_geompropvalue_float - float defaultValue = float(0.0); - return defaultValue; -} - -export color mx_geompropvalue_color3( - uniform string mxp_geomprop = string("") [[ anno::unused() ]], - color mxp_default = color(0.0, 0.0, 0.0) [[ anno::unused() ]] -) - [[ - anno::description("Node Group: geometric") - ]] -{ - // Not implemented: mx_geompropvalue_color3 - color defaultValue = color(0.0, 0.0, 0.0); - return defaultValue; -} - -export color4 mx_geompropvalue_color4( - uniform string mxp_geomprop = string("") [[ anno::unused() ]], - color4 mxp_default = mk_color4(0.0, 0.0, 0.0, 0.0) [[ anno::unused() ]] -) - [[ - anno::description("Node Group: geometric") - ]] -{ - // Not implemented: mx_geompropvalue_color4 - color4 defaultValue = mk_color4(0.0, 0.0, 0.0, 0.0); - return defaultValue; -} - -export float2 mx_geompropvalue_vector2( - uniform string mxp_geomprop = string("") [[ anno::unused() ]], - float2 mxp_default = float2(0.0, 0.0) [[ anno::unused() ]] -) - [[ - anno::description("Node Group: geometric") - ]] -{ - // Not implemented: mx_geompropvalue_vector2 - float2 defaultValue = float2(0.0, 0.0); - return defaultValue; -} - -export float3 mx_geompropvalue_vector3( - uniform string mxp_geomprop = string("") [[ anno::unused() ]], - float3 mxp_default = float3(0.0, 0.0, 0.0) [[ anno::unused() ]] -) - [[ - anno::description("Node Group: geometric") - ]] -{ - // Not implemented: mx_geompropvalue_vector3 - float3 defaultValue = float3(0.0, 0.0, 0.0); - return defaultValue; -} - -export float4 mx_geompropvalue_vector4( - uniform string mxp_geomprop = string("") [[ anno::unused() ]], - float4 mxp_default = float4(0.0, 0.0, 0.0, 0.0) [[ anno::unused() ]] -) - [[ - anno::description("Node Group: geometric") - ]] -{ - // Not implemented: mx_geompropvalue_vector4 - float4 defaultValue = float4(0.0, 0.0, 0.0, 0.0); - return defaultValue; -} - -export float mx_ambientocclusion_float( - float mxp_coneangle = float(90.0) - [[ - anno::description("Unit Type:angle. Unit:degrees."), - anno::unused() - ]], - float mxp_maxdistance = float(1e38) [[ anno::unused() ]] -) - [[ - anno::description("Node Group: global") - ]] -{ - // Not implemented: mx_ambientocclusion_float - float defaultValue = float(1.0); - return defaultValue; -} - -export float mx_frame_float( -) - [[ - anno::description("Node Group: application") - ]] -{ - // Not implemented: mx_frame_float - float defaultValue = float(1.0); - return defaultValue; -} - -export float mx_time_float( - uniform float mxp_fps = float(24.0) [[ anno::unused() ]] -) - [[ - anno::description("Node Group: application") - ]] -{ - return ::state::animation_time(); -} - -export color mx_modulo_color3( - color mxp_in1 = color(0.0, 0.0, 0.0), - color mxp_in2 = color(1.0, 1.0, 1.0) -) - [[ - anno::description("Node Group: math") - ]] -{ - return color(mx_mod(float3(mxp_in1), float3(mxp_in2))); -} - -export color4 mx_modulo_color4( - color4 mxp_in1 = mk_color4(0.0, 0.0, 0.0, 0.0), - color4 mxp_in2 = mk_color4(1.0, 1.0, 1.0, 1.0) -) - [[ - anno::description("Node Group: math") - ]] -{ - return mk_color4(mx_mod(mk_float4(mxp_in1), mk_float4(mxp_in2))); -} - -export color mx_modulo_color3FA( - color mxp_in1 = color(0.0, 0.0, 0.0), - float mxp_in2 = float(1.0) -) - [[ - anno::description("Node Group: math") - ]] -{ - return color(mx_mod(float3(mxp_in1), float3(mxp_in2))); -} - -export color4 mx_modulo_color4FA( - color4 mxp_in1 = mk_color4(0.0, 0.0, 0.0, 0.0), - float mxp_in2 = float(1.0) -) - [[ - anno::description("Node Group: math") - ]] -{ - return mk_color4(mx_mod(mk_float4(mxp_in1), float4(mxp_in2))); -} - -export color4 mx_invert_color4( - color4 mxp_in = mk_color4(0.0, 0.0, 0.0, 0.0), - color4 mxp_amount = mk_color4(1.0, 1.0, 1.0, 1.0) -) - [[ - anno::description("Node Group: math") - ]] -{ - return mk_color4(mk_float4(mxp_amount) - mk_float4(mxp_in)); -} - -export color4 mx_invert_color4FA( - color4 mxp_in = mk_color4(0.0, 0.0, 0.0, 0.0), - float mxp_amount = float(1.0) -) - [[ - anno::description("Node Group: math") - ]] -{ - return mk_color4(float4(mxp_amount) - mk_float4(mxp_in)); -} - -export color4 mx_absval_color4( - color4 mxp_in = mk_color4(0.0, 0.0, 0.0, 0.0) -) - [[ - anno::description("Node Group: math") - ]] -{ - return mk_color4(::math::abs(mk_float4(mxp_in))); -} - -export color mx_floor_color3( - color mxp_in = color(0.0, 0.0, 0.0) -) - [[ - anno::description("Node Group: math") - ]] -{ - return color(::math::floor(float3(mxp_in))); -} - -export color4 mx_floor_color4( - color4 mxp_in = mk_color4(0.0, 0.0, 0.0, 0.0) -) - [[ - anno::description("Node Group: math") - ]] -{ - return mk_color4(::math::floor(mk_float4(mxp_in))); -} - -export color mx_ceil_color3( - color mxp_in = color(0.0, 0.0, 0.0) -) - [[ - anno::description("Node Group: math") - ]] -{ - return color(::math::ceil(float3(mxp_in))); -} - -export color4 mx_ceil_color4( - color4 mxp_in = mk_color4(0.0, 0.0, 0.0, 0.0) -) - [[ - anno::description("Node Group: math") - ]] -{ - return mk_color4(::math::ceil(mk_float4(mxp_in))); -} - -export color4 mx_power_color4( - color4 mxp_in1 = mk_color4(0.0, 0.0, 0.0, 0.0), - color4 mxp_in2 = mk_color4(1.0, 1.0, 1.0, 1.0) -) - [[ - anno::description("Node Group: math") - ]] -{ - return mk_color4(::math::pow(mk_float4(mxp_in1), mk_float4(mxp_in2))); -} - -export color4 mx_power_color4FA( - color4 mxp_in1 = mk_color4(0.0, 0.0, 0.0, 0.0), - float mxp_in2 = float(1.0) -) - [[ - anno::description("Node Group: math") - ]] -{ - return mk_color4(::math::pow(mk_float4(mxp_in1), float4(mxp_in2))); -} - -export float mx_sin_float( - float mxp_in = float(0.0) -) - [[ - anno::description("Node Group: math") - ]] -{ - return ::math::sin(mxp_in); -} - -export float mx_cos_float( - float mxp_in = float(0.0) -) - [[ - anno::description("Node Group: math") - ]] -{ - return ::math::cos(mxp_in); -} - -export float mx_tan_float( - float mxp_in = float(0.0) -) - [[ - anno::description("Node Group: math") - ]] -{ - return ::math::tan(mxp_in); -} - -export float mx_asin_float( - float mxp_in = float(0.0) -) - [[ - anno::description("Node Group: math") - ]] -{ - return ::math::asin(mxp_in); -} - -export float mx_acos_float( - float mxp_in = float(0.0) -) - [[ - anno::description("Node Group: math") - ]] -{ - return ::math::acos(mxp_in); -} - -export float mx_atan2_float( - float mxp_in1 = float(1.0), - float mxp_in2 = float(0.0) -) - [[ - anno::description("Node Group: math") - ]] -{ - return ::math::atan2(mxp_in1, mxp_in2); -} - -export float2 mx_sin_vector2( - float2 mxp_in = float2(0.0, 0.0) -) - [[ - anno::description("Node Group: math") - ]] -{ - return ::math::sin(mxp_in); -} - -export float2 mx_cos_vector2( - float2 mxp_in = float2(0.0, 0.0) -) - [[ - anno::description("Node Group: math") - ]] -{ - return ::math::cos(mxp_in); -} - -export float2 mx_tan_vector2( - float2 mxp_in = float2(0.0, 0.0) -) - [[ - anno::description("Node Group: math") - ]] -{ - return ::math::tan(mxp_in); -} - -export float2 mx_asin_vector2( - float2 mxp_in = float2(0.0, 0.0) -) - [[ - anno::description("Node Group: math") - ]] -{ - return ::math::asin(mxp_in); -} - -export float2 mx_acos_vector2( - float2 mxp_in = float2(0.0, 0.0) -) - [[ - anno::description("Node Group: math") - ]] -{ - return ::math::acos(mxp_in); -} - -export float2 mx_atan2_vector2( - float2 mxp_in1 = float2(1.0, 1.0), - float2 mxp_in2 = float2(0.0, 0.0) -) - [[ - anno::description("Node Group: math") - ]] -{ - return ::math::atan2(mxp_in1, mxp_in2); -} - -export float3 mx_sin_vector3( - float3 mxp_in = float3(0.0, 0.0, 0.0) -) - [[ - anno::description("Node Group: math") - ]] -{ - return ::math::sin(mxp_in); -} - -export float3 mx_cos_vector3( - float3 mxp_in = float3(0.0, 0.0, 0.0) -) - [[ - anno::description("Node Group: math") - ]] -{ - return ::math::cos(mxp_in); -} - -export float3 mx_tan_vector3( - float3 mxp_in = float3(0.0, 0.0, 0.0) -) - [[ - anno::description("Node Group: math") - ]] -{ - return ::math::tan(mxp_in); -} - -export float3 mx_asin_vector3( - float3 mxp_in = float3(0.0, 0.0, 0.0) -) - [[ - anno::description("Node Group: math") - ]] -{ - return ::math::asin(mxp_in); -} - -export float3 mx_acos_vector3( - float3 mxp_in = float3(0.0, 0.0, 0.0) -) - [[ - anno::description("Node Group: math") - ]] -{ - return ::math::acos(mxp_in); -} - -export float3 mx_atan2_vector3( - float3 mxp_in1 = float3(1.0, 1.0, 1.0), - float3 mxp_in2 = float3(0.0, 0.0, 0.0) -) - [[ - anno::description("Node Group: math") - ]] -{ - return ::math::atan2(mxp_in1, mxp_in2); -} - -export float4 mx_sin_vector4( - float4 mxp_in = float4(0.0, 0.0, 0.0, 0.0) -) - [[ - anno::description("Node Group: math") - ]] -{ - return ::math::sin(mxp_in); -} - -export float4 mx_cos_vector4( - float4 mxp_in = float4(0.0, 0.0, 0.0, 0.0) -) - [[ - anno::description("Node Group: math") - ]] -{ - return ::math::cos(mxp_in); -} - -export float4 mx_tan_vector4( - float4 mxp_in = float4(0.0, 0.0, 0.0, 0.0) -) - [[ - anno::description("Node Group: math") - ]] -{ - return ::math::tan(mxp_in); -} - -export float4 mx_asin_vector4( - float4 mxp_in = float4(0.0, 0.0, 0.0, 0.0) -) - [[ - anno::description("Node Group: math") - ]] -{ - return ::math::asin(mxp_in); -} - -export float4 mx_acos_vector4( - float4 mxp_in = float4(0.0, 0.0, 0.0, 0.0) -) - [[ - anno::description("Node Group: math") - ]] -{ - return ::math::acos(mxp_in); -} - -export float4 mx_atan2_vector4( - float4 mxp_in1 = float4(1.0, 1.0, 1.0, 1.0), - float4 mxp_in2 = float4(0.0, 0.0, 0.0, 0.0) -) - [[ - anno::description("Node Group: math") - ]] -{ - return ::math::atan2(mxp_in1, mxp_in2); -} - -export float mx_sqrt_float( - float mxp_in = float(0.0) -) - [[ - anno::description("Node Group: math") - ]] -{ - return ::math::sqrt(mxp_in); -} - -export float mx_ln_float( - float mxp_in = float(1.0) -) - [[ - anno::description("Node Group: math") - ]] -{ - return ::math::log(mxp_in); -} - -export float mx_exp_float( - float mxp_in = float(0.0) -) - [[ - anno::description("Node Group: math") - ]] -{ - return ::math::exp(mxp_in); -} - -export float2 mx_sqrt_vector2( - float2 mxp_in = float2(0.0, 0.0) -) - [[ - anno::description("Node Group: math") - ]] -{ - return ::math::sqrt(mxp_in); -} - -export float2 mx_ln_vector2( - float2 mxp_in = float2(1.0, 1.0) -) - [[ - anno::description("Node Group: math") - ]] -{ - return ::math::log(mxp_in); -} - -export float2 mx_exp_vector2( - float2 mxp_in = float2(0.0, 0.0) -) - [[ - anno::description("Node Group: math") - ]] -{ - return ::math::exp(mxp_in); -} - -export float3 mx_sqrt_vector3( - float3 mxp_in = float3(0.0, 0.0, 0.0) -) - [[ - anno::description("Node Group: math") - ]] -{ - return ::math::sqrt(mxp_in); -} - -export float3 mx_ln_vector3( - float3 mxp_in = float3(1.0, 1.0, 1.0) -) - [[ - anno::description("Node Group: math") - ]] -{ - return ::math::log(mxp_in); -} - -export float3 mx_exp_vector3( - float3 mxp_in = float3(0.0, 0.0, 0.0) -) - [[ - anno::description("Node Group: math") - ]] -{ - return ::math::exp(mxp_in); -} - -export float4 mx_sqrt_vector4( - float4 mxp_in = float4(0.0, 0.0, 0.0, 0.0) -) - [[ - anno::description("Node Group: math") - ]] -{ - return ::math::sqrt(mxp_in); -} - -export float4 mx_ln_vector4( - float4 mxp_in = float4(1.0, 1.0, 1.0, 1.0) -) - [[ - anno::description("Node Group: math") - ]] -{ - return ::math::log(mxp_in); -} - -export float4 mx_exp_vector4( - float4 mxp_in = float4(0.0, 0.0, 0.0, 0.0) -) - [[ - anno::description("Node Group: math") - ]] -{ - return ::math::exp(mxp_in); -} - -export color mx_sign_color3( - color mxp_in = color(0.0, 0.0, 0.0) -) - [[ - anno::description("Node Group: math") - ]] -{ - return color(::math::sign(float3(mxp_in))); -} - -export color4 mx_sign_color4( - color4 mxp_in = mk_color4(0.0, 0.0, 0.0, 0.0) -) - [[ - anno::description("Node Group: math") - ]] -{ - return mk_color4(::math::sign(mk_float4(mxp_in))); -} - -export color4 mx_clamp_color4( - color4 mxp_in = mk_color4(0.0, 0.0, 0.0, 0.0), - color4 mxp_low = mk_color4(0.0, 0.0, 0.0, 0.0), - color4 mxp_high = mk_color4(1.0, 1.0, 1.0, 1.0) -) - [[ - anno::description("Node Group: math") - ]] -{ - return mk_color4(::math::clamp(mk_float4(mxp_in), mk_float4(mxp_low), mk_float4(mxp_high))); -} - -export color4 mx_clamp_color4FA( - color4 mxp_in = mk_color4(0.0, 0.0, 0.0, 0.0), - float mxp_low = float(0.0), - float mxp_high = float(1.0) -) - [[ - anno::description("Node Group: math") - ]] -{ - return mk_color4(::math::clamp(mk_float4(mxp_in), float4(mxp_low), float4(mxp_high))); -} - -export color4 mx_min_color4( - color4 mxp_in1 = mk_color4(0.0, 0.0, 0.0, 0.0), - color4 mxp_in2 = mk_color4(0.0, 0.0, 0.0, 0.0) -) - [[ - anno::description("Node Group: math") - ]] -{ - return mk_color4(::math::min(mk_float4(mxp_in1), mk_float4(mxp_in2))); -} - -export color4 mx_min_color4( - color4 mxp_in1 = mk_color4(0.0, 0.0, 0.0, 0.0), - float mxp_in2 = float(0.0) -) - [[ - anno::description("Node Group: math") - ]] -{ - return mk_color4(::math::min(mk_float4(mxp_in1), float4(mxp_in2))); -} - -export color4 mx_max_color4( - color4 mxp_in1 = mk_color4(0.0, 0.0, 0.0, 0.0), - color4 mxp_in2 = mk_color4(0.0, 0.0, 0.0, 0.0) -) - [[ - anno::description("Node Group: math") - ]] -{ - return mk_color4(::math::max(mk_float4(mxp_in1), mk_float4(mxp_in2))); -} - -export color4 mx_max_color4( - color4 mxp_in1 = mk_color4(0.0, 0.0, 0.0, 0.0), - float mxp_in2 = float(0.0) -) - [[ - anno::description("Node Group: math") - ]] -{ - return mk_color4(::math::max(mk_float4(mxp_in1), float4(mxp_in2))); -} - -export float3 mx_transformpoint_vector3( - float3 mxp_in = float3(0.0, 0.0, 0.0), - uniform string mxp_fromspace = "object", - uniform string mxp_tospace = "world" -) - [[ - anno::description("Node Group: math") - ]] -{ - state::coordinate_space fromSpace = ::mx_map_space(mxp_fromspace); - state::coordinate_space toSpace = ::mx_map_space(mxp_tospace); - return state::transform_point(fromSpace, toSpace, mxp_in); -} - -export float3 mx_transformvector_vector3( - float3 mxp_in = float3(0.0, 0.0, 0.0), - uniform string mxp_fromspace = "object", - uniform string mxp_tospace = "world" -) - [[ - anno::description("Node Group: math") - ]] -{ - state::coordinate_space fromSpace = ::mx_map_space(mxp_fromspace); - state::coordinate_space toSpace = ::mx_map_space(mxp_tospace); - return state::transform_vector(fromSpace, toSpace, mxp_in); -} - -export float3 mx_transformnormal_vector3( - float3 mxp_in = float3(0.0, 0.0, 1.0), - uniform string mxp_fromspace = "object", - uniform string mxp_tospace = "world" -) - [[ - anno::description("Node Group: math") - ]] -{ - state::coordinate_space fromSpace = ::mx_map_space(mxp_fromspace); - state::coordinate_space toSpace = ::mx_map_space(mxp_tospace); - return state::transform_normal(fromSpace, toSpace, mxp_in); -} - -export float2 mx_transformmatrix_vector2M3( - float2 mxp_in = float2(0.0, 0.0), - float3x3 mxp_mat = float3x3(1.0,0.0,0.0, 0.0,1.0,0.0, 0.0,0.0,1.0) -) - [[ - anno::description("Node Group: math") - ]] -{ - float3 returnValue = mxp_mat * float3(mxp_in.x, mxp_in.y, 1.0); - return float2(returnValue.x, returnValue.y); -} - -export float3 mx_transformmatrix_vector3( - float3 mxp_in = float3(0.0, 0.0, 0.0), - float3x3 mxp_mat = float3x3(1.0,0.0,0.0, 0.0,1.0,0.0, 0.0,0.0,1.0) -) - [[ - anno::description("Node Group: math") - ]] -{ - return mxp_mat * mxp_in; -} - -export float3 mx_transformmatrix_vector3M4( - float3 mxp_in = float3(0.0, 0.0, 0.0), - float4x4 mxp_mat = float4x4(1.0,0.0,0.0,0.0, 0.0,1.0,0.0,0.0, 0.0,0.0,1.0,0.0, 0.0,0.0,0.0,1.0) -) - [[ - anno::description("Node Group: math") - ]] -{ - float4 returnValue = mxp_mat * float4(mxp_in.x, mxp_in.y, mxp_in.z, 1.0); - return float3(returnValue.x, returnValue.y, returnValue.z); -} - -export float4 mx_transformmatrix_vector4( - float4 mxp_in = float4(0.0, 0.0, 0.0, 0.0), - float4x4 mxp_mat = float4x4(1.0,0.0,0.0,0.0, 0.0,1.0,0.0,0.0, 0.0,0.0,1.0,0.0, 0.0,0.0,0.0,1.0) -) - [[ - anno::description("Node Group: math") - ]] -{ - return mxp_mat * mxp_in; -} - -export float3 mx_normalmap( - float3 mxp_in = float3(0.5, 0.5, 1.0), - uniform string mxp_space = string("tangent") - [[ - anno::description("Enumeration {tangent, object}.") - ]], - float mxp_scale = float(1.0), - float3 mxp_normal = float3(::state::transform_normal(::state::coordinate_internal,::state::coordinate_world,::state::normal())), - float3 mxp_tangent = float3(state::transform_vector(::state::coordinate_internal,::state::coordinate_world,::state::texture_tangent_u(0))) -) - [[ - anno::description("Node Group: math") - ]] -{ - if (mxp_space == "tangent") - { - float3 v = mxp_in * 2.0 - 1.0; - float3 binormal = ::math::normalize(::math::cross(mxp_normal, mxp_tangent)); - return ::math::normalize(mxp_tangent * v.x * mxp_scale + binormal * v.y * mxp_scale + mxp_normal * v.z); - } - else - { - float3 n = mxp_in * 2.0 - 1.0; - return ::math::normalize(n); - } -} - -export float3x3 mx_transpose_matrix33( - float3x3 mxp_in = float3x3(1.0,0.0,0.0, 0.0,1.0,0.0, 0.0,0.0,1.0) -) - [[ - anno::description("Node Group: math") - ]] -{ - return ::math::transpose(mxp_in); -} - -export float4x4 mx_transpose_matrix44( - float4x4 mxp_in = float4x4(1.0,0.0,0.0,0.0, 0.0,1.0,0.0,0.0, 0.0,0.0,1.0,0.0, 0.0,0.0,0.0,1.0) -) - [[ - anno::description("Node Group: math") - ]] -{ - return ::math::transpose(mxp_in); -} - -export float mx_determinant_matrix33(float3x3 mxp_in) -[[ - anno::description("Node Group: math") -]] -{ - return mxp_in[0][0] * (mxp_in[2][2]*mxp_in[1][1] - mxp_in[1][2]*mxp_in[2][1]) - + mxp_in[0][1] * (mxp_in[1][2]*mxp_in[2][0] - mxp_in[2][2]*mxp_in[1][0]) - + mxp_in[0][2] * (mxp_in[2][1]*mxp_in[1][0] - mxp_in[1][1]*mxp_in[2][0]); -} - -export float mx_determinant_matrix44(float4x4 mxp_in) -[[ - anno::description("Node Group: math") -]] -{ - float - b00 = mxp_in[0][0] * mxp_in[1][1] - mxp_in[0][1] * mxp_in[1][0], - b01 = mxp_in[0][0] * mxp_in[1][2] - mxp_in[0][2] * mxp_in[1][0], - b02 = mxp_in[0][0] * mxp_in[1][3] - mxp_in[0][3] * mxp_in[1][0], - b03 = mxp_in[0][1] * mxp_in[1][2] - mxp_in[0][2] * mxp_in[1][1], - b04 = mxp_in[0][1] * mxp_in[1][3] - mxp_in[0][3] * mxp_in[1][1], - b05 = mxp_in[0][2] * mxp_in[1][3] - mxp_in[0][3] * mxp_in[1][2], - b06 = mxp_in[2][0] * mxp_in[3][1] - mxp_in[2][1] * mxp_in[3][0], - b07 = mxp_in[2][0] * mxp_in[3][2] - mxp_in[2][2] * mxp_in[3][0], - b08 = mxp_in[2][0] * mxp_in[3][3] - mxp_in[2][3] * mxp_in[3][0], - b09 = mxp_in[2][1] * mxp_in[3][2] - mxp_in[2][2] * mxp_in[3][1], - b10 = mxp_in[2][1] * mxp_in[3][3] - mxp_in[2][3] * mxp_in[3][1], - b11 = mxp_in[2][2] * mxp_in[3][3] - mxp_in[2][3] * mxp_in[3][2]; - return b00 * b11 - b01 * b10 + b02 * b09 + b03 * b08 - b04 * b07 + b05 * b06; -} - -export float3x3 mx_invertmatrix_matrix33( - float3x3 mxp_in = float3x3(1.0,0.0,0.0, 0.0,1.0,0.0, 0.0,0.0,1.0) -) - [[ - anno::description("Node Group: math") - ]] -{ - // Not implemented: mx_invertmatrix_matrix33 - float3x3 defaultValue = mxp_in; - return defaultValue; -} - -export float4x4 mx_invertmatrix_matrix44( - float4x4 mxp_in = float4x4(1.0,0.0,0.0,0.0, 0.0,1.0,0.0,0.0, 0.0,0.0,1.0,0.0, 0.0,0.0,0.0,1.0) -) - [[ - anno::description("Node Group: math") - ]] -{ - // Not implemented: mx_invertmatrix_matrix44 - float4x4 defaultValue = mxp_in; - return defaultValue; -} - -export float2 mx_rotate2d_vector2( - float2 mxp_in = float2(0.0, 0.0), - float mxp_amount = float(0.0) - [[ - anno::description("Unit Type:angle. Unit:degrees.") - ]] -) -[[ - anno::description("Node Group: math") -]] -{ - float angleRadians = math::radians(mxp_amount); - float sinAngle = math::sin(angleRadians); - float cosAngle = math::cos(angleRadians); - return float2(cosAngle*mxp_in.x + sinAngle*mxp_in.y, -sinAngle*mxp_in.x + cosAngle*mxp_in.y); -} - -float4x4 mx_rotationMatrix(float3 mxp_axis, float mxp_amount) -{ - float sinAngle = math::sin(mxp_amount); - float cosAngle = math::cos(mxp_amount); - float oc = 1.0 - cosAngle; - - return float4x4( - oc * mxp_axis.x * mxp_axis.x + cosAngle, oc * mxp_axis.x * mxp_axis.y - mxp_axis.z * sinAngle, oc * mxp_axis.z * mxp_axis.x + mxp_axis.y * sinAngle, 0.0, - oc * mxp_axis.x * mxp_axis.y + mxp_axis.z * sinAngle, oc * mxp_axis.y * mxp_axis.y + cosAngle, oc * mxp_axis.y * mxp_axis.z - mxp_axis.x * sinAngle, 0.0, - oc * mxp_axis.z * mxp_axis.x - mxp_axis.y * sinAngle, oc * mxp_axis.y * mxp_axis.z + mxp_axis.x * sinAngle, oc * mxp_axis.z * mxp_axis.z + cosAngle, 0.0, - 0.0, 0.0, 0.0, 1.0); -} - -export float3 mx_rotate3d_vector3( - float3 mxp_in = float3(0.0, 0.0, 0.0), - float mxp_amount = float(0.0) - [[ - anno::description("Unit Type:angle. Unit:degrees.") - ]], - float3 mxp_axis = float3(0.0, 1.0, 0.0) -) - [[ - anno::description("Node Group: math") - ]] -{ - float angleRadians = math::radians(mxp_amount); - float4x4 m = mx_rotationMatrix(mxp_axis, angleRadians); - float4 v = m * float4(mxp_in.x, mxp_in.y, mxp_in.z, 1.0); - return float3(v.x, v.y, v.z); -} - -// Nodedef: ND_place2d_vector2 is represented by a nodegraph: NG_place2d_vector2 - -export float mx_remap_float( - float mxp_in = float(0.0), - float mxp_inlow = float(0.0), - float mxp_inhigh = float(1.0), - float mxp_outlow = float(0.0), - float mxp_outhigh = float(1.0) -) - [[ - anno::description("Node Group: adjustment") - ]] -{ - return mxp_outlow + (mxp_in - mxp_inlow) * (mxp_outhigh - mxp_outlow) / (mxp_inhigh - mxp_inlow); -} - -export color mx_remap_color3( - color mxp_in = color(0.0, 0.0, 0.0), - color mxp_inlow = color(0.0, 0.0, 0.0), - color mxp_inhigh = color(1.0, 1.0, 1.0), - color mxp_outlow = color(0.0, 0.0, 0.0), - color mxp_outhigh = color(1.0, 1.0, 1.0) -) - [[ - anno::description("Node Group: adjustment") - ]] -{ - return mxp_outlow + (mxp_in - mxp_inlow) * (mxp_outhigh - mxp_outlow) / (mxp_inhigh - mxp_inlow); -} - -export color4 mx_remap_color4( - color4 mxp_in = mk_color4(0.0, 0.0, 0.0, 0.0), - color4 mxp_inlow = mk_color4(0.0, 0.0, 0.0, 0.0), - color4 mxp_inhigh = mk_color4(1.0, 1.0, 1.0, 1.0), - color4 mxp_outlow = mk_color4(0.0, 0.0, 0.0, 0.0), - color4 mxp_outhigh = mk_color4(1.0, 1.0, 1.0, 1.0) -) - [[ - anno::description("Node Group: adjustment") - ]] -{ - color4 val = mxp_outlow; - color4 val2 = mx_add(val, mx_subtract(mxp_in, mxp_inlow)); - color4 val3 = mx_multiply(val2, mx_subtract(mxp_outhigh, mxp_outlow)); - return mx_divide(val3, mx_subtract(mxp_inhigh, mxp_inlow)); -} - -export float2 mx_remap_vector2( - float2 mxp_in = float2(0.0, 0.0), - float2 mxp_inlow = float2(0.0, 0.0), - float2 mxp_inhigh = float2(1.0, 1.0), - float2 mxp_outlow = float2(0.0, 0.0), - float2 mxp_outhigh = float2(1.0, 1.0) -) - [[ - anno::description("Node Group: adjustment") - ]] -{ - return mxp_outlow + (mxp_in - mxp_inlow) * (mxp_outhigh - mxp_outlow) / (mxp_inhigh - mxp_inlow); -} - -export float3 mx_remap_vector3( - float3 mxp_in = float3(0.0, 0.0, 0.0), - float3 mxp_inlow = float3(0.0, 0.0, 0.0), - float3 mxp_inhigh = float3(1.0, 1.0, 1.0), - float3 mxp_outlow = float3(0.0, 0.0, 0.0), - float3 mxp_outhigh = float3(1.0, 1.0, 1.0) -) - [[ - anno::description("Node Group: adjustment") - ]] -{ - return mxp_outlow + (mxp_in - mxp_inlow) * (mxp_outhigh - mxp_outlow) / (mxp_inhigh - mxp_inlow); -} - -export float4 mx_remap_vector4( - float4 mxp_in = float4(0.0, 0.0, 0.0, 0.0), - float4 mxp_inlow = float4(0.0, 0.0, 0.0, 0.0), - float4 mxp_inhigh = float4(1.0, 1.0, 1.0, 1.0), - float4 mxp_outlow = float4(0.0, 0.0, 0.0, 0.0), - float4 mxp_outhigh = float4(1.0, 1.0, 1.0, 1.0) -) - [[ - anno::description("Node Group: adjustment") - ]] -{ - return mxp_outlow + (mxp_in - mxp_inlow) * (mxp_outhigh - mxp_outlow) / (mxp_inhigh - mxp_inlow); -} - -export color mx_remap_color3FA( - color mxp_in = color(0.0, 0.0, 0.0), - float mxp_inlow = float(0.0), - float mxp_inhigh = float(1.0), - float mxp_outlow = float(0.0), - float mxp_outhigh = float(1.0) -) - [[ - anno::description("Node Group: adjustment") - ]] -{ - return mxp_outlow + (mxp_in - mxp_inlow) * (mxp_outhigh - mxp_outlow) / (mxp_inhigh - mxp_inlow); -} - -export color4 mx_remap_color4FA( - color4 mxp_in = mk_color4(0.0, 0.0, 0.0, 0.0), - float mxp_inlow = float(0.0), - float mxp_inhigh = float(1.0), - float mxp_outlow = float(0.0), - float mxp_outhigh = float(1.0) -) - [[ - anno::description("Node Group: adjustment") - ]] -{ - color4 val = mk_color4(mxp_outlow); - color4 val2 = mx_add(val, mx_subtract(mxp_in, mk_color4(mxp_inlow))); - color4 val3 = mx_multiply(val2, mx_subtract(mk_color4(mxp_outhigh), mk_color4(mxp_outlow))); - return mx_divide(val3, mx_subtract(mk_color4(mxp_inhigh), mk_color4(mxp_inlow))); -} - -export float2 mx_remap_vector2FA( - float2 mxp_in = float2(0.0, 0.0), - float mxp_inlow = float(0.0), - float mxp_inhigh = float(1.0), - float mxp_outlow = float(0.0), - float mxp_outhigh = float(1.0) -) - [[ - anno::description("Node Group: adjustment") - ]] -{ - return mxp_outlow + (mxp_in - mxp_inlow) * (mxp_outhigh - mxp_outlow) / (mxp_inhigh - mxp_inlow); -} - -export float3 mx_remap_vector3FA( - float3 mxp_in = float3(0.0, 0.0, 0.0), - float mxp_inlow = float(0.0), - float mxp_inhigh = float(1.0), - float mxp_outlow = float(0.0), - float mxp_outhigh = float(1.0) -) - [[ - anno::description("Node Group: adjustment") - ]] -{ - return mxp_outlow + (mxp_in - mxp_inlow) * (mxp_outhigh - mxp_outlow) / (mxp_inhigh - mxp_inlow); -} - -export float4 mx_remap_vector4FA( - float4 mxp_in = float4(0.0, 0.0, 0.0, 0.0), - float mxp_inlow = float(0.0), - float mxp_inhigh = float(1.0), - float mxp_outlow = float(0.0), - float mxp_outhigh = float(1.0) -) - [[ - anno::description("Node Group: adjustment") - ]] -{ - return mxp_outlow + (mxp_in - mxp_inlow) * (mxp_outhigh - mxp_outlow) / (mxp_inhigh - mxp_inlow); -} - -export float mx_smoothstep_float( - float mxp_in = float(0.0), - float mxp_low = float(0.0), - float mxp_high = float(1.0) -) - [[ - anno::description("Node Group: adjustment") - ]] -{ - return ::math::smoothstep(float(mxp_low), float(mxp_high), float(mxp_in)); -} - -export color mx_smoothstep_color3( - color mxp_in = color(0.0, 0.0, 0.0), - color mxp_low = color(0.0, 0.0, 0.0), - color mxp_high = color(1.0, 1.0, 1.0) -) - [[ - anno::description("Node Group: adjustment") - ]] -{ - return color(::math::smoothstep(float3(mxp_low), float3(mxp_high), float3(mxp_in))); -} - -export color4 mx_smoothstep_color4( - color4 mxp_in = mk_color4(0.0, 0.0, 0.0, 0.0), - color4 mxp_low = mk_color4(0.0, 0.0, 0.0, 0.0), - color4 mxp_high = mk_color4(1.0, 1.0, 1.0, 1.0) -) - [[ - anno::description("Node Group: adjustment") - ]] -{ - return mk_color4(::math::smoothstep(mk_float4(mxp_low), mk_float4(mxp_high), mk_float4(mxp_in))); -} - -export float2 mx_smoothstep_vector2( - float2 mxp_in = float2(0.0, 0.0), - float2 mxp_low = float2(0.0, 0.0), - float2 mxp_high = float2(1.0, 1.0) -) - [[ - anno::description("Node Group: adjustment") - ]] -{ - return ::math::smoothstep(float2(mxp_low), float2(mxp_high), float2(mxp_in)); -} - -export float3 mx_smoothstep_vector3( - float3 mxp_in = float3(0.0, 0.0, 0.0), - float3 mxp_low = float3(0.0, 0.0, 0.0), - float3 mxp_high = float3(1.0, 1.0, 1.0) -) - [[ - anno::description("Node Group: adjustment") - ]] -{ - return ::math::smoothstep(float3(mxp_low), float3(mxp_high), float3(mxp_in)); -} - -export float4 mx_smoothstep_vector4( - float4 mxp_in = float4(0.0, 0.0, 0.0, 0.0), - float4 mxp_low = float4(0.0, 0.0, 0.0, 0.0), - float4 mxp_high = float4(1.0, 1.0, 1.0, 1.0) -) - [[ - anno::description("Node Group: adjustment") - ]] -{ - return ::math::smoothstep(float4(mxp_low), float4(mxp_high), float4(mxp_in)); -} - -export color mx_smoothstep_color3FA( - color mxp_in = color(0.0, 0.0, 0.0), - float mxp_low = float(0.0), - float mxp_high = float(1.0) -) - [[ - anno::description("Node Group: adjustment") - ]] -{ - return color(::math::smoothstep(float3(mxp_in), float3(mxp_low), float3(mxp_high))); -} - -export color4 mx_smoothstep_color4FA( - color4 mxp_in = mk_color4(0.0, 0.0, 0.0, 0.0), - float mxp_low = float(0.0), - float mxp_high = float(1.0) -) - [[ - anno::description("Node Group: adjustment") - ]] -{ - return mk_color4(::math::smoothstep(mk_float4(mxp_in), float4(mxp_low), float4(mxp_high))); -} - -export float2 mx_smoothstep_vector2FA( - float2 mxp_in = float2(0.0, 0.0), - float mxp_low = float(0.0), - float mxp_high = float(1.0) -) - [[ - anno::description("Node Group: adjustment") - ]] -{ - return ::math::smoothstep(float2(mxp_low), float2(mxp_high), float2(mxp_in)); -} - -export float3 mx_smoothstep_vector3FA( - float3 mxp_in = float3(0.0, 0.0, 0.0), - float mxp_low = float(0.0), - float mxp_high = float(1.0) -) - [[ - anno::description("Node Group: adjustment") - ]] -{ - return ::math::smoothstep(float3(mxp_low), float3(mxp_high), float3(mxp_in)); -} - -export float4 mx_smoothstep_vector4FA( - float4 mxp_in = float4(0.0, 0.0, 0.0, 0.0), - float mxp_low = float(0.0), - float mxp_high = float(1.0) -) - [[ - anno::description("Node Group: adjustment") - ]] -{ - return ::math::smoothstep(float4(mxp_low), float4(mxp_high), float4(mxp_in)); -} - -export float mx_curveadjust_float( - float mxp_in = float(0.0), - float2[] mxp_knots = float2[]() [[ anno::unused() ]] -) - [[ - anno::description("Node Group: adjustment") - ]] -{ - // Not implemented: mx_curveadjust_float - float defaultValue = mxp_in; - return defaultValue; -} - -export color mx_curveadjust_color3( - color mxp_in = color(0.0, 0.0, 0.0), - float2[] mxp_knots = float2[]() [[ anno::unused() ]] -) - [[ - anno::description("Node Group: adjustment") - ]] -{ - // Not implemented: mx_curveadjust_color3 - color defaultValue = mxp_in; - return defaultValue; -} - -export color4 mx_curveadjust_color4( - color4 mxp_in = mk_color4(0.0, 0.0, 0.0, 0.0), - float2[] mxp_knots = float2[]() [[ anno::unused() ]] -) - [[ - anno::description("Node Group: adjustment") - ]] -{ - // Not implemented: mx_curveadjust_color4 - color4 defaultValue = mxp_in; - return defaultValue; -} - -export float2 mx_curveadjust_vector2( - float2 mxp_in = float2(0.0, 0.0), - float2[] mxp_knots = float2[]() [[ anno::unused() ]] -) - [[ - anno::description("Node Group: adjustment") - ]] -{ - // Not implemented: mx_curveadjust_vector2 - float2 defaultValue = mxp_in; - return defaultValue; -} - -export float3 mx_curveadjust_vector3( - float3 mxp_in = float3(0.0, 0.0, 0.0), - float2[] mxp_knots = float2[]() [[ anno::unused() ]] -) - [[ - anno::description("Node Group: adjustment") - ]] -{ - // Not implemented: mx_curveadjust_vector3 - float3 defaultValue = mxp_in; - return defaultValue; -} - -export float4 mx_curveadjust_vector4( - float4 mxp_in = float4(0.0, 0.0, 0.0, 0.0), - float2[] mxp_knots = float2[]() [[ anno::unused() ]] -) - [[ - anno::description("Node Group: adjustment") - ]] -{ - // Not implemented: mx_curveadjust_vector4 - float4 defaultValue = mxp_in; - return defaultValue; -} - -export color mx_luminance_color3( - color mxp_in = color(0.0, 0.0, 0.0), - uniform color mxp_lumacoeffs = color(0.2722287, 0.6740818, 0.0536895) - [[ - anno::description("Enumeration {acescg, rec709, rec2020, rec2100}."), - anno::unused() - ]] -) - [[ - anno::description("Node Group: adjustment") - ]] -{ - return color(::math::luminance(mxp_in)); -} - -export color4 mx_luminance_color4( - color4 mxp_in = mk_color4(0.0, 0.0, 0.0, 0.0), - uniform color mxp_lumacoeffs = color(0.2722287, 0.6740818, 0.0536895) - [[ - anno::description("Enumeration {acescg, rec709, rec2020, rec2100}."), - anno::unused() - ]] -) - [[ - anno::description("Node Group: adjustment") - ]] -{ - color rgb = color(mxp_in.rgb); - color4 returnValue = mk_color4(::math::luminance(rgb)); - returnValue.a = mxp_in.a; - return returnValue; -} - -export color mx_rgbtohsv_color3( - color mxp_in = color(0.0, 0.0, 0.0) -) - [[ - anno::description("Node Group: adjustment") - ]] -{ - return color(::hsv::mx_rgbtohsv(float3(mxp_in))); -} - -export color4 mx_rgbtohsv_color4( - color4 mxp_in = mk_color4(0.0, 0.0, 0.0, 0.0) -) - [[ - anno::description("Node Group: adjustment") - ]] -{ - float3 rgb = hsv::mx_rgbtohsv(float3(mxp_in.rgb)); - return color4(color(rgb), mxp_in.a); -} - -export color mx_hsvtorgb_color3( - color mxp_in = color(0.0, 0.0, 0.0) -) - [[ - anno::description("Node Group: adjustment") - ]] -{ - return color(hsv::mx_hsvtorgb(float3(mxp_in))); -} - -export color4 mx_hsvtorgb_color4( - color4 mxp_in = mk_color4(0.0, 0.0, 0.0, 0.0) -) - [[ - anno::description("Node Group: adjustment") - ]] -{ - float3 rgb = hsv::mx_hsvtorgb(float3(mxp_in.rgb)); - return color4(color(rgb), mxp_in.a); -} - -export color4 mx_premult_color4( - color4 mxp_in = mk_color4(0.0, 0.0, 0.0, 1.0) -) - [[ - anno::description("Node Group: compositing") - ]] -{ - // Not implemented: mx_premult_color4 - color4 defaultValue = mxp_in; - return defaultValue; -} - -export color4 mx_unpremult_color4( - color4 mxp_in = mk_color4(0.0, 0.0, 0.0, 1.0) -) - [[ - anno::description("Node Group: compositing") - ]] -{ - // Not implemented: mx_unpremult_color4 - color4 defaultValue = mxp_in; - return defaultValue; -} - -export color4 mx_plus_color4( - color4 mxp_fg = mk_color4(0.0, 0.0, 0.0, 0.0), - color4 mxp_bg = mk_color4(0.0, 0.0, 0.0, 0.0), - float mxp_mix = float(1.0) -) - [[ - anno::description("Node Group: compositing") - ]] -{ - color rgb = (mxp_mix*(mxp_bg.rgb + mxp_fg.rgb)) + ((1.0-mxp_mix)*mxp_bg.rgb); - float a = (mxp_mix*(mxp_bg.a + mxp_fg.a )) + ((1.0-mxp_mix)*mxp_bg.a ); - return color4(rgb,a); -} - -export color4 mx_minus_color4( - color4 mxp_fg = mk_color4(0.0, 0.0, 0.0, 0.0), - color4 mxp_bg = mk_color4(0.0, 0.0, 0.0, 0.0), - float mxp_mix = float(1.0) -) - [[ - anno::description("Node Group: compositing") - ]] -{ - color rgb = (mxp_mix*(mxp_bg.rgb - mxp_fg.rgb)) + ((1.0-mxp_mix)*mxp_bg.rgb); - float a = (mxp_mix*(mxp_bg.a - mxp_fg.a )) + ((1.0-mxp_mix)*mxp_bg.a ); - return color4(rgb,a); -} - -export color4 mx_difference_color4( - color4 mxp_fg = mk_color4(0.0, 0.0, 0.0, 0.0), - color4 mxp_bg = mk_color4(0.0, 0.0, 0.0, 0.0), - float mxp_mix = float(1.0) -) - [[ - anno::description("Node Group: compositing") - ]] -{ - color rgb = (mxp_mix*math::abs(mxp_bg.rgb - mxp_fg.rgb)) + ((1.0-mxp_mix)*mxp_bg.rgb); - float a = (mxp_mix*math::abs(mxp_bg.a - mxp_fg.a )) + ((1.0-mxp_mix)*mxp_bg.a ); - return color4(rgb,a); -} - -export float mx_burn_float( - float mxp_fg = 0.0, - float mxp_bg = 0.0, - float mxp_mix = 1.0 -) - [[ - anno::description("Node Group: compositing") - ]] -{ - if (math::abs(mxp_fg) < FLOAT_EPS) - { - return 0.0; - } - return mxp_mix*(1.0 - ((1.0 - mxp_bg) / mxp_fg)) + ((1.0 - mxp_mix)*mxp_bg); -} - -export color mx_burn_color3( - color mxp_fg = color(0.0), - color mxp_bg = color(0.0), - float mxp_mix = 1.0 -) - [[ - anno::description("Node Group: compositing") - ]] -{ - float3 fg(mxp_fg); - float3 bg(mxp_bg); - return color( - mx_burn_float(fg.x, bg.x, mxp_mix), - mx_burn_float(fg.y, bg.y, mxp_mix), - mx_burn_float(fg.z, bg.z, mxp_mix) - ); -} - -export color4 mx_burn_color4( - color4 mxp_fg = mk_color4(0.0, 0.0, 0.0, 0.0), - color4 mxp_bg = mk_color4(0.0, 0.0, 0.0, 0.0), - float mxp_mix = 1.0 -) - [[ - anno::description("Node Group: compositing") - ]] -{ - return color4( - mx_burn_color3(mxp_fg.rgb, mxp_bg.rgb, mxp_mix), - mx_burn_float(mxp_fg.a, mxp_bg.a, mxp_mix) - ); -} - -export float mx_dodge_float( - float mxp_fg = float(0.0), - float mxp_bg = float(0.0), - float mxp_mix = 1.0 -) - [[ - anno::description("Node Group: compositing") - ]] -{ - if (math::abs(1.0 - mxp_fg) < FLOAT_EPS) - { - return 0.0; - } - return mxp_mix*(mxp_bg / (1.0 - mxp_fg)) + ((1.0-mxp_mix)*mxp_bg); -} - -export color mx_dodge_color3( - color mxp_fg = color(0.0), - color mxp_bg = color(0.0), - float mxp_mix = 1.0 -) - [[ - anno::description("Node Group: compositing") - ]] -{ - float3 fg(mxp_fg); - float3 bg(mxp_bg); - return color( - mx_dodge_float(fg.x, bg.x, mxp_mix), - mx_dodge_float(fg.y, bg.y, mxp_mix), - mx_dodge_float(fg.z, bg.z, mxp_mix) - ); -} - -export color4 mx_dodge_color4( - color4 mxp_fg = mk_color4(0.0, 0.0, 0.0, 0.0), - color4 mxp_bg = mk_color4(0.0, 0.0, 0.0, 0.0), - float mxp_mix = float(1.0) -) - [[ - anno::description("Node Group: compositing") - ]] -{ - return color4( - mx_dodge_color3(mxp_fg.rgb, mxp_bg.rgb, mxp_mix), - mx_dodge_float(mxp_fg.a, mxp_bg.a, mxp_mix) - ); -} - -export color4 mx_screen_color4( - color4 mxp_fg = mk_color4(0.0, 0.0, 0.0, 0.0), - color4 mxp_bg = mk_color4(0.0, 0.0, 0.0, 0.0), - float mxp_mix = float(1.0) -) - [[ - anno::description("Node Group: compositing") - ]] -{ - color rgb = (mxp_mix*((1.0 - (1.0 - mxp_fg.rgb) * (1 - mxp_bg.rgb)))) + ((1.0-mxp_mix)*mxp_bg.rgb); - float a = (mxp_mix*((1.0 - (1.0 - mxp_fg.a ) * (1 - mxp_bg.a )))) + ((1.0-mxp_mix)*mxp_bg.a ); - return color4(rgb,a); -} - -float mx_overlay(float mxp_fg, float mxp_bg) -{ - return (mxp_fg < 0.5) ? (2 * mxp_fg * mxp_bg) : (1 - (1 - mxp_fg) * (1 - mxp_bg)); -} -float2 mx_overlay(float2 mxp_fg, float2 mxp_bg) [[ anno::unused() ]] -{ - return float2( - mx_overlay(mxp_fg.x, mxp_bg.x), - mx_overlay(mxp_fg.y, mxp_bg.y) - ); -} -color mx_overlay(color mxp_fg, color mxp_bg) -{ - float3 fg(mxp_fg); - float3 bg(mxp_bg); - return color( - mx_overlay(fg.x, bg.x), - mx_overlay(fg.y, bg.y), - mx_overlay(fg.z, bg.z) - ); -} - -export float mx_overlay_float( - float mxp_fg = 0.0, - float mxp_bg = 0.0, - float mxp_mix = 1.0 -) - [[ - anno::description("Node Group: compositing") - ]] -{ - return mxp_mix * mx_overlay(mxp_fg, mxp_bg) + (1-mxp_mix) * mxp_bg; -} - -export color mx_overlay_color3( - color mxp_fg = color(0.0), - color mxp_bg = color(0.0), - float mxp_mix = 1.0 -) - [[ - anno::description("Node Group: compositing") - ]] -{ - return mxp_mix * mx_overlay(mxp_fg, mxp_bg) + (1-mxp_mix) * mxp_bg; -} - -export color4 mx_overlay_color4( - color4 mxp_fg = mk_color4(0.0, 0.0, 0.0, 0.0), - color4 mxp_bg = mk_color4(0.0, 0.0, 0.0, 0.0), - float mxp_mix = float(1.0) -) - [[ - anno::description("Node Group: compositing") - ]] -{ - color rgb = mxp_mix * mx_overlay(mxp_fg.rgb, mxp_bg.rgb) + (1-mxp_mix) * mxp_bg.rgb; - float a = mxp_mix * mx_overlay(mxp_fg.a , mxp_bg.a ) + (1-mxp_mix) * mxp_bg.a; - return color4(rgb,a); -} - -export color4 mx_disjointover_color4( - color4 mxp_fg = mk_color4(0.0, 0.0, 0.0, 0.0), - color4 mxp_bg = mk_color4(0.0, 0.0, 0.0, 0.0), - float mxp_mix = float(1.0) -) - [[ - anno::description("Node Group: compositing") - ]] -{ - color4 result; - float summedAlpha = mxp_fg.a + mxp_bg.a; - if (summedAlpha <= 1) - { - result.rgb = mxp_fg.rgb + mxp_bg.rgb; - } - else - { - if (math::abs(mxp_bg.a) < FLOAT_EPS) - { - result.rgb = color(0.0); - } - else - { - float x = (1 - mxp_fg.a) / mxp_bg.a; - result.rgb = mxp_fg.rgb + mxp_bg.rgb * x; - } - } - result.a = math::min(summedAlpha, 1.0); - result.rgb = result.rgb * mxp_mix + (1.0 - mxp_mix) * mxp_bg.rgb; - result.a = result.a * mxp_mix + (1.0 - mxp_mix) * mxp_bg.a; - return result; -} - -export color4 mx_in_color4( - color4 mxp_fg = mk_color4(0.0, 0.0, 0.0, 0.0), - color4 mxp_bg = mk_color4(0.0, 0.0, 0.0, 0.0), - float mxp_mix = float(1.0) -) - [[ - anno::description("Node Group: compositing") - ]] -{ - color rgb = mxp_fg.rgb*mxp_bg.a * mxp_mix + mxp_bg.rgb * (1.0-mxp_mix); - float a = mxp_fg.a *mxp_bg.a * mxp_mix + mxp_bg.a * (1.0-mxp_mix); - return color4(rgb,a); -} - -export color4 mx_mask_color4( - color4 mxp_fg = mk_color4(0.0, 0.0, 0.0, 0.0), - color4 mxp_bg = mk_color4(0.0, 0.0, 0.0, 0.0), - float mxp_mix = float(1.0) -) - [[ - anno::description("Node Group: compositing") - ]] -{ - color rgb = mxp_bg.rgb*mxp_fg.a * mxp_mix + mxp_bg.rgb * (1.0-mxp_mix); - float a = mxp_bg.a *mxp_fg.a * mxp_mix + mxp_bg.a * (1.0-mxp_mix); - return color4(rgb,a); -} - -export color4 mx_matte_color4( - color4 mxp_fg = mk_color4(0.0, 0.0, 0.0, 0.0), - color4 mxp_bg = mk_color4(0.0, 0.0, 0.0, 0.0), - float mxp_mix = 1.0 -) - [[ - anno::description("Node Group: compositing") - ]] -{ - color rgb = (mxp_fg.rgb*mxp_fg.a + mxp_bg.rgb*(1.0-mxp_fg.a)) * mxp_mix + mxp_bg.rgb * (1.0-mxp_mix); - float a = (mxp_fg.a + mxp_bg.a*(1.0-mxp_fg.a)) * mxp_mix + mxp_bg.a * (1.0-mxp_mix); - return color4(rgb, a); -} - -export color4 mx_out_color4( - color4 mxp_fg = mk_color4(0.0, 0.0, 0.0, 0.0), - color4 mxp_bg = mk_color4(0.0, 0.0, 0.0, 0.0), - float mxp_mix = float(1.0) -) - [[ - anno::description("Node Group: compositing") - ]] -{ - color rgb = (mxp_fg.rgb*(1.0 - mxp_bg.a) * mxp_mix) + (mxp_bg.rgb * (1.0-mxp_mix)); - float a = (mxp_fg.a *(1.0 - mxp_bg.a) * mxp_mix) + (mxp_bg.a * (1.0-mxp_mix)); - return color4(rgb,a); -} - -export color4 mx_over_color4( - color4 mxp_fg = mk_color4(0.0, 0.0, 0.0, 0.0), - color4 mxp_bg = mk_color4(0.0, 0.0, 0.0, 0.0), - float mxp_mix = float(1.0) -) - [[ - anno::description("Node Group: compositing") - ]] -{ - color rgb = (mxp_fg.rgb + (mxp_bg.rgb*(1.0-mxp_fg.a))) * mxp_mix + mxp_bg.rgb * (1.0-mxp_mix); - float a = (mxp_fg.a + (mxp_bg.a *(1.0-mxp_fg.a))) * mxp_mix + mxp_bg.a * (1.0-mxp_mix); - return color4(rgb,a); -} - -export color4 mx_mix_color4( - color4 mxp_fg = mk_color4(0.0, 0.0, 0.0, 0.0), - color4 mxp_bg = mk_color4(0.0, 0.0, 0.0, 0.0), - float mxp_mix = float(0.0) -) - [[ - anno::description("Node Group: compositing") - ]] -{ - return mk_color4(::math::lerp(mk_float4(mxp_bg), mk_float4(mxp_fg), float4(mxp_mix))); -} - -export color4 mx_mix_color4_color4( - color4 mxp_fg = mk_color4(0.0, 0.0, 0.0, 0.0), - color4 mxp_bg = mk_color4(0.0, 0.0, 0.0, 0.0), - color4 mxp_mix = mk_color4(0.0, 0.0, 0.0, 0.0) -) - [[ - anno::description("Node Group: compositing") - ]] -{ - return mk_color4(::math::lerp(mk_float4(mxp_bg), mk_float4(mxp_fg), mk_float4(mxp_mix))); -} - -// mix all parts of the material, bsdf, edf, and vdf, geometry -export material mx_mix_surfaceshader( - material mxp_fg = material() [[ anno::usage( "materialx:surfaceshader") ]], - material mxp_bg = material() [[ anno::usage( "materialx:surfaceshader") ]], - float mxp_mix = 0.0 -) [[ - anno::description("Node Group: compositing"), - anno::usage( "materialx:surfaceshader") -]] -= material( - surface: material_surface( - scattering: df::weighted_layer( - weight: mxp_mix, - layer: mxp_fg.surface.scattering, - base: mxp_bg.surface.scattering - ), - emission: material_emission( - emission: df::unbounded_mix( // unbounded_mix is cheaper - df::edf_component[]( - df::edf_component( mxp_mix, mxp_fg.surface.emission.emission), - df::edf_component( 1.0 - mxp_mix, mxp_bg.surface.emission.emission)) - ), - intensity: mxp_mix * mxp_fg.surface.emission.intensity + - (1.0 - mxp_mix) * mxp_bg.surface.emission.intensity - ) - ), - - // we need to carry volume properties along for SSS - ior: mxp_fg.ior, // NOTE: IOR is uniform, cannot mix here - volume: material_volume( - scattering: df::unbounded_mix( // unbounded_mix is cheaper - df::vdf_component[]( - df::vdf_component( mxp_mix, mxp_fg.volume.scattering), - df::vdf_component( 1.0 - mxp_mix, mxp_bg.volume.scattering)) - ), - absorption_coefficient: mxp_mix * mxp_fg.volume.absorption_coefficient + - (1.0 - mxp_mix) * mxp_bg.volume.absorption_coefficient, - scattering_coefficient: mxp_mix * mxp_fg.volume.scattering_coefficient + - (1.0 - mxp_mix) * mxp_bg.volume.scattering_coefficient - ), - geometry: material_geometry( - displacement: mxp_mix * mxp_fg.geometry.displacement + - (1.0 - mxp_mix) * mxp_bg.geometry.displacement, - cutout_opacity: mxp_mix * mxp_fg.geometry.cutout_opacity + - (1.0 - mxp_mix) * mxp_bg.geometry.cutout_opacity, - normal: mxp_mix * mxp_fg.geometry.normal + - (1.0 - mxp_mix) * mxp_bg.geometry.normal - ) -); - -export material mx_mix_volumeshader( - material mxp_fg = material() [[ anno::usage( "materialx:volumeshader") ]], - material mxp_bg = material() [[ anno::usage( "materialx:volumeshader") ]], - float mxp_mix = 0.0 -) [[ - anno::description("Node Group: compositing"), - anno::usage( "materialx:volumeshader") -]] -= mx_mix_surfaceshader( - mxp_fg: mxp_fg, - mxp_bg: mxp_bg, - mxp_mix: mxp_mix); - -export material mx_mix_displacementshader( - material mxp_fg = material() [[ anno::usage( "materialx:displacementshader") ]], - material mxp_bg = material() [[ anno::usage( "materialx:displacementshader") ]], - float mxp_mix = 0.0 -) [[ - anno::description("Node Group: compositing"), - anno::usage( "materialx:displacementshader") -]] -= mx_mix_surfaceshader( - mxp_fg: mxp_fg, - mxp_bg: mxp_bg, - mxp_mix: mxp_mix); - -export float mx_ifgreater_float( - float mxp_value1 = float(1.0), - float mxp_value2 = float(0.0), - float mxp_in1 = float(0.0), - float mxp_in2 = float(0.0) -) - [[ - anno::description("Node Group: conditional") - ]] -{ - if (mxp_value1 > mxp_value2) { return mxp_in1; } return mxp_in2; -} - -export color mx_ifgreater_color3( - float mxp_value1 = float(1.0), - float mxp_value2 = float(0.0), - color mxp_in1 = color(0.0, 0.0, 0.0), - color mxp_in2 = color(0.0, 0.0, 0.0) -) - [[ - anno::description("Node Group: conditional") - ]] -{ - if (mxp_value1 > mxp_value2) { return mxp_in1; } return mxp_in2; -} - -export color4 mx_ifgreater_color4( - float mxp_value1 = float(1.0), - float mxp_value2 = float(0.0), - color4 mxp_in1 = mk_color4(0.0, 0.0, 0.0, 0.0), - color4 mxp_in2 = mk_color4(0.0, 0.0, 0.0, 0.0) -) - [[ - anno::description("Node Group: conditional") - ]] -{ - if (mxp_value1 > mxp_value2) { return mxp_in1; } return mxp_in2; -} - -export float2 mx_ifgreater_vector2( - float mxp_value1 = float(1.0), - float mxp_value2 = float(0.0), - float2 mxp_in1 = float2(0.0, 0.0), - float2 mxp_in2 = float2(0.0, 0.0) -) - [[ - anno::description("Node Group: conditional") - ]] -{ - if (mxp_value1 > mxp_value2) { return mxp_in1; } return mxp_in2; -} - -export float3 mx_ifgreater_vector3( - float mxp_value1 = float(1.0), - float mxp_value2 = float(0.0), - float3 mxp_in1 = float3(0.0, 0.0, 0.0), - float3 mxp_in2 = float3(0.0, 0.0, 0.0) -) - [[ - anno::description("Node Group: conditional") - ]] -{ - if (mxp_value1 > mxp_value2) { return mxp_in1; } return mxp_in2; -} - -export float4 mx_ifgreater_vector4( - float mxp_value1 = float(1.0), - float mxp_value2 = float(0.0), - float4 mxp_in1 = float4(0.0, 0.0, 0.0, 0.0), - float4 mxp_in2 = float4(0.0, 0.0, 0.0, 0.0) -) - [[ - anno::description("Node Group: conditional") - ]] -{ - if (mxp_value1 > mxp_value2) { return mxp_in1; } return mxp_in2; -} - -export float mx_ifgreater_floatI( - int mxp_value1 = int(1), - int mxp_value2 = int(0), - float mxp_in1 = float(0.0), - float mxp_in2 = float(0.0) -) - [[ - anno::description("Node Group: conditional") - ]] -{ - if (mxp_value1 > mxp_value2) { return mxp_in1; } return mxp_in2; -} - -export color mx_ifgreater_color3I( - int mxp_value1 = int(1), - int mxp_value2 = int(0), - color mxp_in1 = color(0.0, 0.0, 0.0), - color mxp_in2 = color(0.0, 0.0, 0.0) -) - [[ - anno::description("Node Group: conditional") - ]] -{ - if (mxp_value1 > mxp_value2) { return mxp_in1; } return mxp_in2; -} - -export color4 mx_ifgreater_color4I( - int mxp_value1 = int(1), - int mxp_value2 = int(0), - color4 mxp_in1 = mk_color4(0.0, 0.0, 0.0, 0.0), - color4 mxp_in2 = mk_color4(0.0, 0.0, 0.0, 0.0) -) - [[ - anno::description("Node Group: conditional") - ]] -{ - if (mxp_value1 > mxp_value2) { return mxp_in1; } return mxp_in2; -} - -export float2 mx_ifgreater_vector2I( - int mxp_value1 = int(1), - int mxp_value2 = int(0), - float2 mxp_in1 = float2(0.0, 0.0), - float2 mxp_in2 = float2(0.0, 0.0) -) - [[ - anno::description("Node Group: conditional") - ]] -{ - if (mxp_value1 > mxp_value2) { return mxp_in1; } return mxp_in2; -} - -export float3 mx_ifgreater_vector3I( - int mxp_value1 = int(1), - int mxp_value2 = int(0), - float3 mxp_in1 = float3(0.0, 0.0, 0.0), - float3 mxp_in2 = float3(0.0, 0.0, 0.0) -) - [[ - anno::description("Node Group: conditional") - ]] -{ - if (mxp_value1 > mxp_value2) { return mxp_in1; } return mxp_in2; -} - -export float4 mx_ifgreater_vector4I( - int mxp_value1 = int(1), - int mxp_value2 = int(0), - float4 mxp_in1 = float4(0.0, 0.0, 0.0, 0.0), - float4 mxp_in2 = float4(0.0, 0.0, 0.0, 0.0) -) - [[ - anno::description("Node Group: conditional") - ]] -{ - if (mxp_value1 > mxp_value2) { return mxp_in1; } return mxp_in2; -} - -export float mx_ifgreatereq_float( - float mxp_value1 = float(1.0), - float mxp_value2 = float(0.0), - float mxp_in1 = float(0.0), - float mxp_in2 = float(0.0) -) - [[ - anno::description("Node Group: conditional") - ]] -{ - if (mxp_value1 >= mxp_value2) { return mxp_in1; } return mxp_in2; -} - -export color mx_ifgreatereq_color3( - float mxp_value1 = float(1.0), - float mxp_value2 = float(0.0), - color mxp_in1 = color(0.0, 0.0, 0.0), - color mxp_in2 = color(0.0, 0.0, 0.0) -) - [[ - anno::description("Node Group: conditional") - ]] -{ - if (mxp_value1 >= mxp_value2) { return mxp_in1; } return mxp_in2; -} - -export color4 mx_ifgreatereq_color4( - float mxp_value1 = float(1.0), - float mxp_value2 = float(0.0), - color4 mxp_in1 = mk_color4(0.0, 0.0, 0.0, 0.0), - color4 mxp_in2 = mk_color4(0.0, 0.0, 0.0, 0.0) -) - [[ - anno::description("Node Group: conditional") - ]] -{ - if (mxp_value1 >= mxp_value2) { return mxp_in1; } return mxp_in2; -} - -export float2 mx_ifgreatereq_vector2( - float mxp_value1 = float(1.0), - float mxp_value2 = float(0.0), - float2 mxp_in1 = float2(0.0, 0.0), - float2 mxp_in2 = float2(0.0, 0.0) -) - [[ - anno::description("Node Group: conditional") - ]] -{ - if (mxp_value1 >= mxp_value2) { return mxp_in1; } return mxp_in2; -} - -export float3 mx_ifgreatereq_vector3( - float mxp_value1 = float(1.0), - float mxp_value2 = float(0.0), - float3 mxp_in1 = float3(0.0, 0.0, 0.0), - float3 mxp_in2 = float3(0.0, 0.0, 0.0) -) - [[ - anno::description("Node Group: conditional") - ]] -{ - if (mxp_value1 >= mxp_value2) { return mxp_in1; } return mxp_in2; -} - -export float4 mx_ifgreatereq_vector4( - float mxp_value1 = float(1.0), - float mxp_value2 = float(0.0), - float4 mxp_in1 = float4(0.0, 0.0, 0.0, 0.0), - float4 mxp_in2 = float4(0.0, 0.0, 0.0, 0.0) -) - [[ - anno::description("Node Group: conditional") - ]] -{ - if (mxp_value1 >= mxp_value2) { return mxp_in1; } return mxp_in2; -} - -export float mx_ifgreatereq_floatI( - int mxp_value1 = int(1), - int mxp_value2 = int(0), - float mxp_in1 = float(0.0), - float mxp_in2 = float(0.0) -) - [[ - anno::description("Node Group: conditional") - ]] -{ - if (mxp_value1 >= mxp_value2) { return mxp_in1; } return mxp_in2; -} - -export color mx_ifgreatereq_color3I( - int mxp_value1 = int(1), - int mxp_value2 = int(0), - color mxp_in1 = color(0.0, 0.0, 0.0), - color mxp_in2 = color(0.0, 0.0, 0.0) -) - [[ - anno::description("Node Group: conditional") - ]] -{ - if (mxp_value1 >= mxp_value2) { return mxp_in1; } return mxp_in2; -} - -export color4 mx_ifgreatereq_color4I( - int mxp_value1 = int(1), - int mxp_value2 = int(0), - color4 mxp_in1 = mk_color4(0.0, 0.0, 0.0, 0.0), - color4 mxp_in2 = mk_color4(0.0, 0.0, 0.0, 0.0) -) - [[ - anno::description("Node Group: conditional") - ]] -{ - if (mxp_value1 >= mxp_value2) { return mxp_in1; } return mxp_in2; -} - -export float2 mx_ifgreatereq_vector2I( - int mxp_value1 = int(1), - int mxp_value2 = int(0), - float2 mxp_in1 = float2(0.0, 0.0), - float2 mxp_in2 = float2(0.0, 0.0) -) - [[ - anno::description("Node Group: conditional") - ]] -{ - if (mxp_value1 >= mxp_value2) { return mxp_in1; } return mxp_in2; -} - -export float3 mx_ifgreatereq_vector3I( - int mxp_value1 = int(1), - int mxp_value2 = int(0), - float3 mxp_in1 = float3(0.0, 0.0, 0.0), - float3 mxp_in2 = float3(0.0, 0.0, 0.0) -) - [[ - anno::description("Node Group: conditional") - ]] -{ - if (mxp_value1 >= mxp_value2) { return mxp_in1; } return mxp_in2; -} - -export float4 mx_ifgreatereq_vector4I( - int mxp_value1 = int(1), - int mxp_value2 = int(0), - float4 mxp_in1 = float4(0.0, 0.0, 0.0, 0.0), - float4 mxp_in2 = float4(0.0, 0.0, 0.0, 0.0) -) - [[ - anno::description("Node Group: conditional") - ]] -{ - if (mxp_value1 >= mxp_value2) { return mxp_in1; } return mxp_in2; -} - -export float mx_ifequal_float( - float mxp_value1 = float(0.0), - float mxp_value2 = float(0.0), - float mxp_in1 = float(0.0), - float mxp_in2 = float(0.0) -) - [[ - anno::description("Node Group: conditional") - ]] -{ - if (mxp_value1 == mxp_value2) { return mxp_in1; } return mxp_in2; -} - -export color mx_ifequal_color3( - float mxp_value1 = float(0.0), - float mxp_value2 = float(0.0), - color mxp_in1 = color(0.0, 0.0, 0.0), - color mxp_in2 = color(0.0, 0.0, 0.0) -) - [[ - anno::description("Node Group: conditional") - ]] -{ - if (mxp_value1 == mxp_value2) { return mxp_in1; } return mxp_in2; -} - -export color4 mx_ifequal_color4( - float mxp_value1 = float(0.0), - float mxp_value2 = float(0.0), - color4 mxp_in1 = mk_color4(0.0, 0.0, 0.0, 0.0), - color4 mxp_in2 = mk_color4(0.0, 0.0, 0.0, 0.0) -) - [[ - anno::description("Node Group: conditional") - ]] -{ - if (mxp_value1 == mxp_value2) { return mxp_in1; } return mxp_in2; -} - -export float2 mx_ifequal_vector2( - float mxp_value1 = float(0.0), - float mxp_value2 = float(0.0), - float2 mxp_in1 = float2(0.0, 0.0), - float2 mxp_in2 = float2(0.0, 0.0) -) - [[ - anno::description("Node Group: conditional") - ]] -{ - if (mxp_value1 == mxp_value2) { return mxp_in1; } return mxp_in2; -} - -export float3 mx_ifequal_vector3( - float mxp_value1 = float(0.0), - float mxp_value2 = float(0.0), - float3 mxp_in1 = float3(0.0, 0.0, 0.0), - float3 mxp_in2 = float3(0.0, 0.0, 0.0) -) - [[ - anno::description("Node Group: conditional") - ]] -{ - if (mxp_value1 == mxp_value2) { return mxp_in1; } return mxp_in2; -} - -export float4 mx_ifequal_vector4( - float mxp_value1 = float(0.0), - float mxp_value2 = float(0.0), - float4 mxp_in1 = float4(0.0, 0.0, 0.0, 0.0), - float4 mxp_in2 = float4(0.0, 0.0, 0.0, 0.0) -) - [[ - anno::description("Node Group: conditional") - ]] -{ - if (mxp_value1 == mxp_value2) { return mxp_in1; } return mxp_in2; -} - -export float mx_ifequal_floatI( - int mxp_value1 = int(0), - int mxp_value2 = int(0), - float mxp_in1 = float(0.0), - float mxp_in2 = float(0.0) -) - [[ - anno::description("Node Group: conditional") - ]] -{ - if (mxp_value1 == mxp_value2) { return mxp_in1; } return mxp_in2; -} - -export color mx_ifequal_color3I( - int mxp_value1 = int(0), - int mxp_value2 = int(0), - color mxp_in1 = color(0.0, 0.0, 0.0), - color mxp_in2 = color(0.0, 0.0, 0.0) -) - [[ - anno::description("Node Group: conditional") - ]] -{ - if (mxp_value1 == mxp_value2) { return mxp_in1; } return mxp_in2; -} - -export color4 mx_ifequal_color4I( - int mxp_value1 = int(0), - int mxp_value2 = int(0), - color4 mxp_in1 = mk_color4(0.0, 0.0, 0.0, 0.0), - color4 mxp_in2 = mk_color4(0.0, 0.0, 0.0, 0.0) -) - [[ - anno::description("Node Group: conditional") - ]] -{ - if (mxp_value1 == mxp_value2) { return mxp_in1; } return mxp_in2; -} - -export float2 mx_ifequal_vector2I( - int mxp_value1 = int(0), - int mxp_value2 = int(0), - float2 mxp_in1 = float2(0.0, 0.0), - float2 mxp_in2 = float2(0.0, 0.0) -) - [[ - anno::description("Node Group: conditional") - ]] -{ - if (mxp_value1 == mxp_value2) { return mxp_in1; } return mxp_in2; -} - -export float3 mx_ifequal_vector3I( - int mxp_value1 = int(0), - int mxp_value2 = int(0), - float3 mxp_in1 = float3(0.0, 0.0, 0.0), - float3 mxp_in2 = float3(0.0, 0.0, 0.0) -) - [[ - anno::description("Node Group: conditional") - ]] -{ - if (mxp_value1 == mxp_value2) { return mxp_in1; } return mxp_in2; -} - -export float4 mx_ifequal_vector4I( - int mxp_value1 = int(0), - int mxp_value2 = int(0), - float4 mxp_in1 = float4(0.0, 0.0, 0.0, 0.0), - float4 mxp_in2 = float4(0.0, 0.0, 0.0, 0.0) -) - [[ - anno::description("Node Group: conditional") - ]] -{ - if (mxp_value1 == mxp_value2) { return mxp_in1; } return mxp_in2; -} - -export float mx_ifequal_floatB( - bool mxp_value1 = bool(false), - bool mxp_value2 = bool(false), - float mxp_in1 = float(0.0), - float mxp_in2 = float(0.0) -) - [[ - anno::description("Node Group: conditional") - ]] -{ - if (mxp_value1 == mxp_value2) { return mxp_in1; } return mxp_in2; -} - -export color mx_ifequal_color3B( - bool mxp_value1 = bool(false), - bool mxp_value2 = bool(false), - color mxp_in1 = color(0.0, 0.0, 0.0), - color mxp_in2 = color(0.0, 0.0, 0.0) -) - [[ - anno::description("Node Group: conditional") - ]] -{ - if (mxp_value1 == mxp_value2) { return mxp_in1; } return mxp_in2; -} - -export color4 mx_ifequal_color4B( - bool mxp_value1 = bool(false), - bool mxp_value2 = bool(false), - color4 mxp_in1 = mk_color4(0.0, 0.0, 0.0, 0.0), - color4 mxp_in2 = mk_color4(0.0, 0.0, 0.0, 0.0) -) - [[ - anno::description("Node Group: conditional") - ]] -{ - if (mxp_value1 == mxp_value2) { return mxp_in1; } return mxp_in2; -} - -export float2 mx_ifequal_vector2B( - bool mxp_value1 = bool(false), - bool mxp_value2 = bool(false), - float2 mxp_in1 = float2(0.0, 0.0), - float2 mxp_in2 = float2(0.0, 0.0) -) - [[ - anno::description("Node Group: conditional") - ]] -{ - if (mxp_value1 == mxp_value2) { return mxp_in1; } return mxp_in2; -} - -export float3 mx_ifequal_vector3B( - bool mxp_value1 = bool(false), - bool mxp_value2 = bool(false), - float3 mxp_in1 = float3(0.0, 0.0, 0.0), - float3 mxp_in2 = float3(0.0, 0.0, 0.0) -) - [[ - anno::description("Node Group: conditional") - ]] -{ - if (mxp_value1 == mxp_value2) { return mxp_in1; } return mxp_in2; -} - -export float4 mx_ifequal_vector4B( - bool mxp_value1 = bool(false), - bool mxp_value2 = bool(false), - float4 mxp_in1 = float4(0.0, 0.0, 0.0, 0.0), - float4 mxp_in2 = float4(0.0, 0.0, 0.0, 0.0) -) - [[ - anno::description("Node Group: conditional") - ]] -{ - if (mxp_value1 == mxp_value2) { return mxp_in1; } return mxp_in2; -} - -export float mx_switch_float( - float mxp_in1 = float(0.0), - float mxp_in2 = float(0.0), - float mxp_in3 = float(0.0), - float mxp_in4 = float(0.0), - float mxp_in5 = float(0.0), - float mxp_which = float(0.0) -) - [[ - anno::description("Node Group: conditional") - ]] -{ - float returnValue; - switch (int(mxp_which)) { - case 0: returnValue=mxp_in1; break; - case 1: returnValue=mxp_in2; break; - case 2: returnValue=mxp_in3; break; - case 3: returnValue=mxp_in4; break; - case 4: returnValue=mxp_in5; break; - default: returnValue=mxp_in1; break; - } - return returnValue; -} - -export color mx_switch_color3( - color mxp_in1 = color(0.0, 0.0, 0.0), - color mxp_in2 = color(0.0, 0.0, 0.0), - color mxp_in3 = color(0.0, 0.0, 0.0), - color mxp_in4 = color(0.0, 0.0, 0.0), - color mxp_in5 = color(0.0, 0.0, 0.0), - float mxp_which = float(0.0) -) - [[ - anno::description("Node Group: conditional") - ]] -{ - color returnValue; - switch (int(mxp_which)) { - case 0: returnValue=mxp_in1; break; - case 1: returnValue=mxp_in2; break; - case 2: returnValue=mxp_in3; break; - case 3: returnValue=mxp_in4; break; - case 4: returnValue=mxp_in5; break; - default: returnValue=mxp_in1; break; - } - return returnValue; -} - -export color4 mx_switch_color4( - color4 mxp_in1 = mk_color4(0.0, 0.0, 0.0, 0.0), - color4 mxp_in2 = mk_color4(0.0, 0.0, 0.0, 0.0), - color4 mxp_in3 = mk_color4(0.0, 0.0, 0.0, 0.0), - color4 mxp_in4 = mk_color4(0.0, 0.0, 0.0, 0.0), - color4 mxp_in5 = mk_color4(0.0, 0.0, 0.0, 0.0), - float mxp_which = float(0.0) -) - [[ - anno::description("Node Group: conditional") - ]] -{ - color4 returnValue; - switch (int(mxp_which)) { - case 0: returnValue=mxp_in1; break; - case 1: returnValue=mxp_in2; break; - case 2: returnValue=mxp_in3; break; - case 3: returnValue=mxp_in4; break; - case 4: returnValue=mxp_in5; break; - default: returnValue=mxp_in1; break; - } - return returnValue; -} - -export float2 mx_switch_vector2( - float2 mxp_in1 = float2(0.0, 0.0), - float2 mxp_in2 = float2(0.0, 0.0), - float2 mxp_in3 = float2(0.0, 0.0), - float2 mxp_in4 = float2(0.0, 0.0), - float2 mxp_in5 = float2(0.0, 0.0), - float mxp_which = float(0.0) -) - [[ - anno::description("Node Group: conditional") - ]] -{ - float2 returnValue; - switch (int(mxp_which)) { - case 0: returnValue=mxp_in1; break; - case 1: returnValue=mxp_in2; break; - case 2: returnValue=mxp_in3; break; - case 3: returnValue=mxp_in4; break; - case 4: returnValue=mxp_in5; break; - default: returnValue=mxp_in1; break; - } - return returnValue; -} - -export float3 mx_switch_vector3( - float3 mxp_in1 = float3(0.0, 0.0, 0.0), - float3 mxp_in2 = float3(0.0, 0.0, 0.0), - float3 mxp_in3 = float3(0.0, 0.0, 0.0), - float3 mxp_in4 = float3(0.0, 0.0, 0.0), - float3 mxp_in5 = float3(0.0, 0.0, 0.0), - float mxp_which = float(0.0) -) - [[ - anno::description("Node Group: conditional") - ]] -{ - float3 returnValue; - switch (int(mxp_which)) { - case 0: returnValue=mxp_in1; break; - case 1: returnValue=mxp_in2; break; - case 2: returnValue=mxp_in3; break; - case 3: returnValue=mxp_in4; break; - case 4: returnValue=mxp_in5; break; - default: returnValue=mxp_in1; break; - } - return returnValue; -} - -export float4 mx_switch_vector4( - float4 mxp_in1 = float4(0.0, 0.0, 0.0, 0.0), - float4 mxp_in2 = float4(0.0, 0.0, 0.0, 0.0), - float4 mxp_in3 = float4(0.0, 0.0, 0.0, 0.0), - float4 mxp_in4 = float4(0.0, 0.0, 0.0, 0.0), - float4 mxp_in5 = float4(0.0, 0.0, 0.0, 0.0), - float mxp_which = float(0.0) -) - [[ - anno::description("Node Group: conditional") - ]] -{ - float4 returnValue; - switch (int(mxp_which)) { - case 0: returnValue=mxp_in1; break; - case 1: returnValue=mxp_in2; break; - case 2: returnValue=mxp_in3; break; - case 3: returnValue=mxp_in4; break; - case 4: returnValue=mxp_in5; break; - default: returnValue=mxp_in1; break; - } - return returnValue; -} - -export float mx_switch_floatI( - float mxp_in1 = float(0.0), - float mxp_in2 = float(0.0), - float mxp_in3 = float(0.0), - float mxp_in4 = float(0.0), - float mxp_in5 = float(0.0), - int mxp_which = int(0) -) - [[ - anno::description("Node Group: conditional") - ]] -{ - float returnValue; - switch (int(mxp_which)) { - case 0: returnValue=mxp_in1; break; - case 1: returnValue=mxp_in2; break; - case 2: returnValue=mxp_in3; break; - case 3: returnValue=mxp_in4; break; - case 4: returnValue=mxp_in5; break; - default: returnValue=mxp_in1; break; - } - return returnValue; -} - -export color mx_switch_color3I( - color mxp_in1 = color(0.0, 0.0, 0.0), - color mxp_in2 = color(0.0, 0.0, 0.0), - color mxp_in3 = color(0.0, 0.0, 0.0), - color mxp_in4 = color(0.0, 0.0, 0.0), - color mxp_in5 = color(0.0, 0.0, 0.0), - int mxp_which = int(0) -) - [[ - anno::description("Node Group: conditional") - ]] -{ - color returnValue; - switch (int(mxp_which)) { - case 0: returnValue=mxp_in1; break; - case 1: returnValue=mxp_in2; break; - case 2: returnValue=mxp_in3; break; - case 3: returnValue=mxp_in4; break; - case 4: returnValue=mxp_in5; break; - default: returnValue=mxp_in1; break; - } - return returnValue; -} - -export color4 mx_switch_color4I( - color4 mxp_in1 = mk_color4(0.0, 0.0, 0.0, 0.0), - color4 mxp_in2 = mk_color4(0.0, 0.0, 0.0, 0.0), - color4 mxp_in3 = mk_color4(0.0, 0.0, 0.0, 0.0), - color4 mxp_in4 = mk_color4(0.0, 0.0, 0.0, 0.0), - color4 mxp_in5 = mk_color4(0.0, 0.0, 0.0, 0.0), - int mxp_which = int(0) -) - [[ - anno::description("Node Group: conditional") - ]] -{ - color4 returnValue; - switch (int(mxp_which)) { - case 0: returnValue=mxp_in1; break; - case 1: returnValue=mxp_in2; break; - case 2: returnValue=mxp_in3; break; - case 3: returnValue=mxp_in4; break; - case 4: returnValue=mxp_in5; break; - default: returnValue=mxp_in1; break; - } - return returnValue; -} - -export float2 mx_switch_vector2I( - float2 mxp_in1 = float2(0.0, 0.0), - float2 mxp_in2 = float2(0.0, 0.0), - float2 mxp_in3 = float2(0.0, 0.0), - float2 mxp_in4 = float2(0.0, 0.0), - float2 mxp_in5 = float2(0.0, 0.0), - int mxp_which = int(0) -) - [[ - anno::description("Node Group: conditional") - ]] -{ - float2 returnValue; - switch (int(mxp_which)) { - case 0: returnValue=mxp_in1; break; - case 1: returnValue=mxp_in2; break; - case 2: returnValue=mxp_in3; break; - case 3: returnValue=mxp_in4; break; - case 4: returnValue=mxp_in5; break; - default: returnValue=mxp_in1; break; - } - return returnValue; -} - -export float3 mx_switch_vector3I( - float3 mxp_in1 = float3(0.0, 0.0, 0.0), - float3 mxp_in2 = float3(0.0, 0.0, 0.0), - float3 mxp_in3 = float3(0.0, 0.0, 0.0), - float3 mxp_in4 = float3(0.0, 0.0, 0.0), - float3 mxp_in5 = float3(0.0, 0.0, 0.0), - int mxp_which = int(0) -) - [[ - anno::description("Node Group: conditional") - ]] -{ - float3 returnValue; - switch (int(mxp_which)) { - case 0: returnValue=mxp_in1; break; - case 1: returnValue=mxp_in2; break; - case 2: returnValue=mxp_in3; break; - case 3: returnValue=mxp_in4; break; - case 4: returnValue=mxp_in5; break; - default: returnValue=mxp_in1; break; - } - return returnValue; -} - -export float4 mx_switch_vector4I( - float4 mxp_in1 = float4(0.0, 0.0, 0.0, 0.0), - float4 mxp_in2 = float4(0.0, 0.0, 0.0, 0.0), - float4 mxp_in3 = float4(0.0, 0.0, 0.0, 0.0), - float4 mxp_in4 = float4(0.0, 0.0, 0.0, 0.0), - float4 mxp_in5 = float4(0.0, 0.0, 0.0, 0.0), - int mxp_which = int(0) -) - [[ - anno::description("Node Group: conditional") - ]] -{ - float4 returnValue; - switch (int(mxp_which)) { - case 0: returnValue=mxp_in1; break; - case 1: returnValue=mxp_in2; break; - case 2: returnValue=mxp_in3; break; - case 3: returnValue=mxp_in4; break; - case 4: returnValue=mxp_in5; break; - default: returnValue=mxp_in1; break; - } - return returnValue; -} - -export color mx_convert_float_color3( - float mxp_in = float(0.0) -) - [[ - anno::description("Node Group: channel") - ]] -{ - return color(mxp_in); -} - -export color4 mx_convert_float_color4( - float mxp_in = float(0.0) -) - [[ - anno::description("Node Group: channel") - ]] -{ - return mk_color4(mxp_in); -} - -export float2 mx_convert_float_vector2( - float mxp_in = float(0.0) -) - [[ - anno::description("Node Group: channel") - ]] -{ - return float2(mxp_in); -} - -export float3 mx_convert_float_vector3( - float mxp_in = float(0.0) -) - [[ - anno::description("Node Group: channel") - ]] -{ - return float3(mxp_in); -} - -export float4 mx_convert_float_vector4( - float mxp_in = float(0.0) -) - [[ - anno::description("Node Group: channel") - ]] -{ - return float4(mxp_in); -} - -export float3 mx_convert_vector2_vector3( - float2 mxp_in = float2(0.0, 0.0) -) - [[ - anno::description("Node Group: channel") - ]] -{ - return float3(mxp_in.x, mxp_in.y, 0.0); -} - -export color mx_convert_vector3_color3( - float3 mxp_in = float3(0.0, 0.0, 0.0) -) - [[ - anno::description("Node Group: channel") - ]] -{ - return color(mxp_in); -} - -export float2 mx_convert_vector3_vector2( - float3 mxp_in = float3(0.0, 0.0, 0.0) -) - [[ - anno::description("Node Group: channel") - ]] -{ - return float2(mxp_in.x, mxp_in.y); -} - -export float4 mx_convert_vector3_vector4( - float3 mxp_in = float3(0.0, 0.0, 0.0) -) - [[ - anno::description("Node Group: channel") - ]] -{ - return float4(mxp_in.x, mxp_in.y, mxp_in.z, 0.0); -} - -export color4 mx_convert_vector4_color4( - float4 mxp_in = float4(0.0, 0.0, 0.0, 0.0) -) - [[ - anno::description("Node Group: channel") - ]] -{ - return mk_color4(mxp_in); -} - -export float3 mx_convert_vector4_vector3( - float4 mxp_in = float4(0.0, 0.0, 0.0, 0.0) -) - [[ - anno::description("Node Group: channel") - ]] -{ - return float3(mxp_in.x, mxp_in.y, mxp_in.z); -} - -export float3 mx_convert_color3_vector3( - color mxp_in = color(0.0, 0.0, 0.0) -) - [[ - anno::description("Node Group: channel") - ]] -{ - return float3(mxp_in); -} - -export float4 mx_convert_color4_vector4( - color4 mxp_in = mk_color4(0.0, 0.0, 0.0, 0.0) -) - [[ - anno::description("Node Group: channel") - ]] -{ - return mk_float4(mxp_in); -} - -export color4 mx_convert_color3_color4( - color mxp_in = color(0.0, 0.0, 0.0) -) - [[ - anno::description("Node Group: channel") - ]] -{ - return mk_color4(mxp_in); -} - -export color mx_convert_color4_color3( - color4 mxp_in = mk_color4(0.0, 0.0, 0.0, 0.0) -) - [[ - anno::description("Node Group: channel") - ]] -{ - return mxp_in.rgb; -} - -export float mx_convert_boolean_float( - bool mxp_in = bool(false) -) - [[ - anno::description("Node Group: channel") - ]] -{ - return float(mxp_in); -} - -export float mx_convert_integer_float( - int mxp_in = int(0) -) - [[ - anno::description("Node Group: channel") - ]] -{ - return float(mxp_in); -} - -export float2 mx_combine2_vector2( - float mxp_in1 = float(0.0), - float mxp_in2 = float(0.0) -) - [[ - anno::description("Node Group: channel") - ]] -{ - return float2(mxp_in1, mxp_in2); -} - -export color4 mx_combine2_color4CF( - color mxp_in1 = color(0.0, 0.0, 0.0), - float mxp_in2 = float(0.0) -) - [[ - anno::description("Node Group: channel") - ]] -{ - return color4(mxp_in1, mxp_in2); -} - -export float4 mx_combine2_vector4VF( - float3 mxp_in1 = float3(0.0, 0.0, 0.0), - float mxp_in2 = float(0.0) -) - [[ - anno::description("Node Group: channel") - ]] -{ - return float4(mxp_in1.x, mxp_in1.y, mxp_in1.z, mxp_in2); -} - -export color4 mx_combine2_color4CC( - float2 mxp_in1 = float2(0.0, 0.0), - float2 mxp_in2 = float2(0.0, 0.0) -) - [[ - anno::description("Node Group: channel") - ]] -{ - return color4(color(mxp_in1.x, mxp_in1.y, mxp_in2.x), mxp_in2.y); -} - -export float4 mx_combine2_vector4VV( - float2 mxp_in1 = float2(0.0, 0.0), - float2 mxp_in2 = float2(0.0, 0.0) -) - [[ - anno::description("Node Group: channel") - ]] -{ - return float4(mxp_in1.x, mxp_in1.y, mxp_in2.x, mxp_in2.y); -} - -export color mx_combine3_color3( - float mxp_in1 = float(0.0), - float mxp_in2 = float(0.0), - float mxp_in3 = float(0.0) -) - [[ - anno::description("Node Group: channel") - ]] -{ - return color(mxp_in1, mxp_in2, mxp_in3); -} - -export float3 mx_combine3_vector3( - float mxp_in1 = float(0.0), - float mxp_in2 = float(0.0), - float mxp_in3 = float(0.0) -) - [[ - anno::description("Node Group: channel") - ]] -{ - return float3(mxp_in1, mxp_in2, mxp_in3); -} - -export color4 mx_combine4_color4( - float mxp_in1 = float(0.0), - float mxp_in2 = float(0.0), - float mxp_in3 = float(0.0), - float mxp_in4 = float(0.0) -) - [[ - anno::description("Node Group: channel") - ]] -{ - return mk_color4(mxp_in1, mxp_in2, mxp_in3, mxp_in4); -} - -export float4 mx_combine4_vector4( - float mxp_in1 = float(0.0), - float mxp_in2 = float(0.0), - float mxp_in3 = float(0.0), - float mxp_in4 = float(0.0) -) - [[ - anno::description("Node Group: channel") - ]] -{ - return float4(mxp_in1, mxp_in2, mxp_in3, mxp_in4); -} - -// Nodedef: ND_extract_color3 is represented by a nodegraph: NG_extract_color3 -// Nodedef: ND_extract_color4 is represented by a nodegraph: NG_extract_color4 -// Nodedef: ND_extract_vector2 is represented by a nodegraph: NG_extract_vector2 -// Nodedef: ND_extract_vector3 is represented by a nodegraph: NG_extract_vector3 -// Nodedef: ND_extract_vector4 is represented by a nodegraph: NG_extract_vector4 -// Nodedef: ND_separate2_vector2 is represented by a nodegraph: NG_separate2_vector2 -// Nodedef: ND_separate3_color3 is represented by a nodegraph: NG_separate3_color3 -// Nodedef: ND_separate3_vector3 is represented by a nodegraph: NG_separate3_vector3 -// Nodedef: ND_separate4_color4 is represented by a nodegraph: NG_separate4_color4 -// Nodedef: ND_separate4_vector4 is represented by a nodegraph: NG_separate4_vector4 - -export float mx_blur_float( - float mxp_in = float(0.0), - float mxp_size = float(0.0) - [[ - anno::unused() - ]], - uniform mx_filter_type mxp_filtertype = mx_filter_type(mx_filter_type_box) - [[ - anno::description("Enumeration {box,gaussian}."), - anno::unused() - ]] -) - [[ - anno::description("Node Group: convolution2d") - ]] -{ - // Not implemented: mx_blur_float - float defaultValue = mxp_in; - return defaultValue; -} - -export color mx_blur_color3( - color mxp_in = color(0.0, 0.0, 0.0), - float mxp_size = float(0.0) - [[ - anno::unused() - ]], - uniform mx_filter_type mxp_filtertype = mx_filter_type(mx_filter_type_box) - [[ - anno::description("Enumeration {box,gaussian}."), - anno::unused() - ]] -) - [[ - anno::description("Node Group: convolution2d") - ]] -{ - // Not implemented: mx_blur_color3 - color defaultValue = mxp_in; - return defaultValue; -} - -export color4 mx_blur_color4( - color4 mxp_in = mk_color4(0.0, 0.0, 0.0, 0.0), - float mxp_size = float(0.0) - [[ - anno::unused() - ]], - uniform mx_filter_type mxp_filtertype = mx_filter_type(mx_filter_type_box) - [[ - anno::description("Enumeration {box,gaussian}."), - anno::unused() - ]] -) - [[ - anno::description("Node Group: convolution2d") - ]] -{ - // Not implemented: mx_blur_color4 - color4 defaultValue = mxp_in; - return defaultValue; -} - -export float2 mx_blur_vector2( - float2 mxp_in = float2(0.0, 0.0), - float mxp_size = float(0.0) - [[ - anno::unused() - ]], - uniform mx_filter_type mxp_filtertype = mx_filter_type(mx_filter_type_box) - [[ - anno::description("Enumeration {box,gaussian}."), - anno::unused() - ]] -) - [[ - anno::description("Node Group: convolution2d") - ]] -{ - // Not implemented: mx_blur_vector2 - float2 defaultValue = mxp_in; - return defaultValue; -} - -export float3 mx_blur_vector3( - float3 mxp_in = float3(0.0, 0.0, 0.0), - float mxp_size = float(0.0) - [[ - anno::unused() - ]], - uniform mx_filter_type mxp_filtertype = mx_filter_type(mx_filter_type_box) - [[ - anno::description("Enumeration {box,gaussian}."), - anno::unused() - ]] -) - [[ - anno::description("Node Group: convolution2d") - ]] -{ - // Not implemented: mx_blur_vector3 - float3 defaultValue = mxp_in; - return defaultValue; -} - -export float4 mx_blur_vector4( - float4 mxp_in = float4(0.0, 0.0, 0.0, 0.0), - float mxp_size = float(0.0) - [[ - anno::unused() - ]], - uniform mx_filter_type mxp_filtertype = mx_filter_type(mx_filter_type_box) - [[ - anno::description("Enumeration {box,gaussian}."), - anno::unused() - ]] -) - [[ - anno::description("Node Group: convolution2d") - ]] -{ - // Not implemented: mx_blur_vector4 - float4 defaultValue = mxp_in; - return defaultValue; -} - -export float3 mx_heighttonormal_vector3( - float mxp_in = float(0.0) [[ anno::unused() ]], - float mxp_scale = float(1.0) [[ anno::unused() ]] -) - [[ - anno::description("Node Group: convolution2d") - ]] -{ - // Not implemented: mx_heighttonormal_vector3 - float3 defaultValue = float3(0.0, 1.0, 0.0); - return defaultValue; -} - -export float mx_noise2d_float( - float mxp_amplitude = 1.0, - float mxp_pivot = 0.0, - float2 mxp_texcoord = swizzle::xy( ::state::texture_coordinate(0)) -) -{ - float value = noise::mx_perlin_noise_float(mxp_texcoord); - return value * mxp_amplitude + mxp_pivot; -} - -export float2 mx_noise2d_float2( - float2 mxp_amplitude = float2(1.0), - float mxp_pivot = 0.0, - float2 mxp_texcoord = swizzle::xy( ::state::texture_coordinate(0)) -) -{ - float3 value = noise::mx_perlin_noise_float3(mxp_texcoord); - return swizzle::xy(value) * mxp_amplitude + mxp_pivot; -} - -export float3 mx_noise2d_float3( - float3 mxp_amplitude = float3(1.0), - float mxp_pivot = 0.0, - float2 mxp_texcoord = swizzle::xy( ::state::texture_coordinate(0)) -) -{ - float3 value = noise::mx_perlin_noise_float3(mxp_texcoord); - return value * mxp_amplitude + mxp_pivot; -} - -export float4 mx_noise2d_float4( - float4 mxp_amplitude = float4(1.0), - float mxp_pivot = 0.0, - float2 mxp_texcoord = swizzle::xy( ::state::texture_coordinate(0)) -) -{ - float3 v = noise::mx_perlin_noise_float3(mxp_texcoord); - float w = noise::mx_perlin_noise_float(mxp_texcoord + float2(19, 73)); - return float4(v.x, v.y, v.z, w) * mxp_amplitude + mxp_pivot; -} - -export color mx_noise2d_color3( - float3 mxp_amplitude = float3(1.0), - float mxp_pivot = 0.0, - float2 mxp_texcoord = swizzle::xy( ::state::texture_coordinate(0)) -) -{ - return color(mx_noise2d_float3(mxp_amplitude, mxp_pivot, mxp_texcoord)); -} - -export color4 mx_noise2d_color4( - float4 mxp_amplitude = float4(1.0), - float mxp_pivot = 0.0, - float2 mxp_texcoord = swizzle::xy( ::state::texture_coordinate(0)) -) -{ - float3 v = noise::mx_perlin_noise_float3(mxp_texcoord); - float w = noise::mx_perlin_noise_float(mxp_texcoord + float2(19, 73)); - return mk_color4(float4(v.x, v.y, v.z, w) * mxp_amplitude + float4(mxp_pivot)); -} - -export float2 mx_noise2d_float2FA( - float mxp_amplitude = 1.0, - float mxp_pivot = 0.0, - float2 mxp_texcoord = swizzle::xy( ::state::texture_coordinate(0)) -) -{ - return mx_noise2d_float2(float2(mxp_amplitude), mxp_pivot, mxp_texcoord); -} - -export float3 mx_noise2d_float3FA( - float mxp_amplitude = 1.0, - float mxp_pivot = 0.0, - float2 mxp_texcoord = swizzle::xy( ::state::texture_coordinate(0)) -) -{ - return mx_noise2d_float3(float3(mxp_amplitude), mxp_pivot, mxp_texcoord); -} - -export float4 mx_noise2d_float4FA( - float mxp_amplitude = 1.0, - float mxp_pivot = 0.0, - float2 mxp_texcoord = swizzle::xy( ::state::texture_coordinate(0)) -) -{ - return mx_noise2d_float4(float4(mxp_amplitude), mxp_pivot, mxp_texcoord); -} - -export color mx_noise2d_color3FA( - float mxp_amplitude = 1.0, - float mxp_pivot = 0.0, - float2 mxp_texcoord = swizzle::xy( ::state::texture_coordinate(0)) -) -{ - return mx_noise2d_color3(float3(mxp_amplitude), mxp_pivot, mxp_texcoord); -} - -export color4 mx_noise2d_color4FA( - float mxp_amplitude = 1.0, - float mxp_pivot = 0.0, - float2 mxp_texcoord = swizzle::xy( ::state::texture_coordinate(0)) -) -{ - return mx_noise2d_color4(float4(mxp_amplitude), mxp_pivot, mxp_texcoord); -} - -export float mx_noise3d_float( - float mxp_amplitude = 1.0, - float mxp_pivot = 0.0, - float3 mxp_position = state::transform_point(state::coordinate_internal, state::coordinate_object, state::position()) -) -{ - float value = noise::mx_perlin_noise_float(mxp_position); - return value * mxp_amplitude + mxp_pivot; -} - -export float2 mx_noise3d_float2( - float2 mxp_amplitude = float2(1.0), - float mxp_pivot = 0.0, - float3 mxp_position = state::transform_point(state::coordinate_internal, state::coordinate_object, state::position()) -) -{ - float3 value = noise::mx_perlin_noise_float3(mxp_position); - return swizzle::xy(value) * mxp_amplitude + mxp_pivot; -} - -export float3 mx_noise3d_float3( - float3 mxp_amplitude = float3(1.0), - float mxp_pivot = 0.0, - float3 mxp_position = state::transform_point(state::coordinate_internal, state::coordinate_object, state::position()) -) -{ - float3 value = noise::mx_perlin_noise_float3(mxp_position); - return value * mxp_amplitude + mxp_pivot; -} - -export float4 mx_noise3d_float4( - float4 mxp_amplitude = float4(1.0), - float mxp_pivot = 0.0, - float3 mxp_position = state::transform_point(state::coordinate_internal, state::coordinate_object, state::position()) -) -{ - float3 v = noise::mx_perlin_noise_float3(mxp_position); - float w = noise::mx_perlin_noise_float(mxp_position + float3(19, 73, 29)); - return float4(v.x, v.y, v.z, w) * mxp_amplitude + mxp_pivot; -} - -export color mx_noise3d_color3( - float3 mxp_amplitude = float3(1.0), - float mxp_pivot = 0.0, - float3 mxp_position = state::transform_point(state::coordinate_internal, state::coordinate_object, state::position()) -) -{ - return color(mx_noise3d_float3(mxp_amplitude, mxp_pivot, mxp_position)); -} - -export color4 mx_noise3d_color4( - float4 mxp_amplitude = float4(1.0), - float mxp_pivot = 0.0, - float3 mxp_position = state::transform_point(state::coordinate_internal, state::coordinate_object, state::position()) -) -{ - return mk_color4(mx_noise3d_float4(mxp_amplitude, mxp_pivot, mxp_position)); -} - -export float2 mx_noise3d_float2FA( - float mxp_amplitude = 1.0, - float mxp_pivot = 0.0, - float3 mxp_position = state::transform_point(state::coordinate_internal, state::coordinate_object, state::position()) -) -{ - return mx_noise3d_float2(float2(mxp_amplitude), mxp_pivot, mxp_position); -} - -export float3 mx_noise3d_float3FA( - float mxp_amplitude = 1.0, - float mxp_pivot = 0.0, - float3 mxp_position = state::transform_point(state::coordinate_internal, state::coordinate_object, state::position()) -) -{ - return mx_noise3d_float3(float3(mxp_amplitude), mxp_pivot, mxp_position); -} - -export float4 mx_noise3d_float4FA( - float mxp_amplitude = 1.0, - float mxp_pivot = 0.0, - float3 mxp_position = state::transform_point(state::coordinate_internal, state::coordinate_object, state::position()) -) -{ - return mx_noise3d_float4(float4(mxp_amplitude), mxp_pivot, mxp_position); -} - -export color mx_noise3d_color3FA( - float mxp_amplitude = 1.0, - float mxp_pivot = 0.0, - float3 mxp_position = state::transform_point(state::coordinate_internal, state::coordinate_object, state::position()) -) -{ - return color(mx_noise3d_float3(float3(mxp_amplitude), mxp_pivot, mxp_position)); -} - -export color4 mx_noise3d_color4FA( - float mxp_amplitude = 1.0, - float mxp_pivot = 0.0, - float3 mxp_position = state::transform_point(state::coordinate_internal, state::coordinate_object, state::position()) -) -{ - return mk_color4(mx_noise3d_float4FA(mxp_amplitude, mxp_pivot, mxp_position)); -} - -export float mx_fractal3d_float( - float mxp_amplitude = 1.0, - int mxp_octaves = 3, - float mxp_lacunarity = 2.0, - float mxp_diminish= 0.5, - float3 mxp_position = state::transform_point(state::coordinate_internal, state::coordinate_object, state::position()) -) -{ - float v = noise::mx_fractal_noise_float(mxp_position, mxp_octaves, mxp_lacunarity, mxp_diminish); - return v * mxp_amplitude; -} - -export float2 mx_fractal3d_float2( - float2 mxp_amplitude = float2(1.0), - int mxp_octaves = 3, - float mxp_lacunarity = 2.0, - float mxp_diminish= 0.5, - float3 mxp_position = state::transform_point(state::coordinate_internal, state::coordinate_object, state::position()) -) -{ - float2 v = noise::mx_fractal_noise_float2(mxp_position, mxp_octaves, mxp_lacunarity, mxp_diminish); - return v * mxp_amplitude; -} - -export float3 mx_fractal3d_float3( - float3 mxp_amplitude = float3(1.0), - int mxp_octaves = 3, - float mxp_lacunarity = 2.0, - float mxp_diminish= 0.5, - float3 mxp_position = state::transform_point(state::coordinate_internal, state::coordinate_object, state::position()) -) -{ - float3 v = noise::mx_fractal_noise_float3(mxp_position, mxp_octaves, mxp_lacunarity, mxp_diminish); - return v * mxp_amplitude; -} - -export float4 mx_fractal3d_float4( - float4 mxp_amplitude = float4(1.0), - int mxp_octaves = 3, - float mxp_lacunarity = 2.0, - float mxp_diminish= 0.5, - float3 mxp_position = state::transform_point(state::coordinate_internal, state::coordinate_object, state::position()) -) -{ - float4 v = noise::mx_fractal_noise_float4(mxp_position, mxp_octaves, mxp_lacunarity, mxp_diminish); - return v * mxp_amplitude; -} - -export color mx_fractal3d_color3( - float3 mxp_amplitude = float3(1.0), - int mxp_octaves = 3, - float mxp_lacunarity = 2.0, - float mxp_diminish= 0.5, - float3 mxp_position = state::transform_point(state::coordinate_internal, state::coordinate_object, state::position()) -) -{ - float3 v = noise::mx_fractal_noise_float3(mxp_position, mxp_octaves, mxp_lacunarity, mxp_diminish); - return color(v * mxp_amplitude); -} - -export color4 mx_fractal3d_color4( - float4 mxp_amplitude = float4(1.0), - int mxp_octaves = 3, - float mxp_lacunarity = 2.0, - float mxp_diminish= 0.5, - float3 mxp_position = state::transform_point(state::coordinate_internal, state::coordinate_object, state::position()) -) -{ - return mk_color4(mx_fractal3d_float4(mxp_amplitude, mxp_octaves, mxp_lacunarity, mxp_diminish, mxp_position)); -} - -export float2 mx_fractal3d_float2FA( - float mxp_amplitude = 1.0, - int mxp_octaves = 3, - float mxp_lacunarity = 2.0, - float mxp_diminish= 0.5, - float3 mxp_position = state::transform_point(state::coordinate_internal, state::coordinate_object, state::position()) -) -{ - return mx_fractal3d_float2(float2(mxp_amplitude), mxp_octaves, mxp_lacunarity, mxp_diminish, mxp_position); -} - -export float3 mx_fractal3d_float3FA( - float mxp_amplitude = 1.0, - int mxp_octaves = 3, - float mxp_lacunarity = 2.0, - float mxp_diminish= 0.5, - float3 mxp_position = state::transform_point(state::coordinate_internal, state::coordinate_object, state::position()) -) -{ - return mx_fractal3d_float3(float3(mxp_amplitude), mxp_octaves, mxp_lacunarity, mxp_diminish, mxp_position); -} - -export float4 mx_fractal3d_float4FA( - float mxp_amplitude = 1.0, - int mxp_octaves = 3, - float mxp_lacunarity = 2.0, - float mxp_diminish= 0.5, - float3 mxp_position = state::transform_point(state::coordinate_internal, state::coordinate_object, state::position()) -) -{ - return mx_fractal3d_float4(float4(mxp_amplitude), mxp_octaves, mxp_lacunarity, mxp_diminish, mxp_position); -} - -export color mx_fractal3d_color3FA( - float mxp_amplitude = 1.0, - int mxp_octaves = 3, - float mxp_lacunarity = 2.0, - float mxp_diminish= 0.5, - float3 mxp_position = state::transform_point(state::coordinate_internal, state::coordinate_object, state::position()) -) -{ - return mx_fractal3d_color3(float3(mxp_amplitude), mxp_octaves, mxp_lacunarity, mxp_diminish, mxp_position); -} - -export color4 mx_fractal3d_color4FA( - float mxp_amplitude = 1.0, - int mxp_octaves = 3, - float mxp_lacunarity = 2.0, - float mxp_diminish= 0.5, - float3 mxp_position = state::transform_point(state::coordinate_internal, state::coordinate_object, state::position()) -) -{ - return mx_fractal3d_color4(float4(mxp_amplitude), mxp_octaves, mxp_lacunarity, mxp_diminish, mxp_position); -} - -export float mx_cellnoise2d_float( - float2 mxp_texcoord = swizzle::xy( ::state::texture_coordinate(0)) -) -{ - return noise::mx_cell_noise_float(mxp_texcoord); -} - -export float mx_cellnoise3d_float( - float3 mxp_position = state::transform_point(state::coordinate_internal, state::coordinate_object, state::position()) -) -{ - return noise::mx_cell_noise_float(mxp_position); -} - -export float mx_worleynoise2d_float( - float2 mxp_texcoord = swizzle::xy( ::state::texture_coordinate(0)), - float mxp_jitter = 1.0 -) -{ - return noise::mx_worley_noise_float(mxp_texcoord, mxp_jitter, 0); -} - -export float2 mx_worleynoise2d_float2( - float2 mxp_texcoord = swizzle::xy( ::state::texture_coordinate(0)), - float mxp_jitter = 1.0 -) -{ - return noise::mx_worley_noise_float2(mxp_texcoord, mxp_jitter, 0); -} - -export float3 mx_worleynoise2d_float3( - float2 mxp_texcoord = swizzle::xy( ::state::texture_coordinate(0)), - float mxp_jitter = 1.0 -) -{ - return noise::mx_worley_noise_float3(mxp_texcoord, mxp_jitter, 0); -} - -export float mx_worleynoise3d_float( - float3 mxp_position = state::transform_point(state::coordinate_internal, state::coordinate_object, state::position()), - float mxp_jitter = 1.0 -) -{ - return noise::mx_worley_noise_float(mxp_position, mxp_jitter, 0); -} - -export float2 mx_worleynoise3d_float2( - float3 mxp_position = state::transform_point(state::coordinate_internal, state::coordinate_object, state::position()), - float mxp_jitter = 1.0 -) -{ - return noise::mx_worley_noise_float2(mxp_position, mxp_jitter, 0); -} - -export float3 mx_worleynoise3d_float3( - float3 mxp_position = state::transform_point(state::coordinate_internal, state::coordinate_object, state::position()), - float mxp_jitter = 1.0 -) -{ - return noise::mx_worley_noise_float3(mxp_position, mxp_jitter, 0); -} +// forward the latest version +export using .::stdlib_1_8 import *; diff --git a/source/MaterialXGenMdl/mdl/materialx/stdlib_1_6.mdl b/source/MaterialXGenMdl/mdl/materialx/stdlib_1_6.mdl new file mode 100644 index 0000000000..8b948bb605 --- /dev/null +++ b/source/MaterialXGenMdl/mdl/materialx/stdlib_1_6.mdl @@ -0,0 +1,4578 @@ +// +// Copyright Contributors to the MaterialX Project +// SPDX-License-Identifier: Apache-2.0 +// +// MDL Implementation of all types and nodes of +// MaterialX Physically-Based Shading Nodes +// Document v1.37 REV2, July 16, 2019 (Revised October 17, 2019) +// see www.materialx.org +// in +// NVIDIA Material Definition Language 1.6 +// Language Specification +// Document version 1.6.1, December 16, 2019 +// www.nvidia.com/mdl + +mdl 1.6; + +import ::df::*; +import ::anno::*; +import ::math::*; +import ::state::*; +import ::tex::*; + +import .::core::*; +import .::noise::*; +import .::swizzle::*; +import .::hsv::*; + +// NOTE: To insulate MaterialX names from MDL names, in particular +// conflicts with MDL reserved names, all node names, type names +// and enumeration names are prefixed with 'mx_', while all +// node input parameter names are prefixed with 'mxp_' + +// NOTE: We use the ::anno::unused() annotation to mark unsupported parameters + + +// Shader Nodes + +export material mx_surfacematerial( + material mxp_surfaceshader = material() [[ anno::usage( "materialx:surfaceshader") ]], + material mxp_displacementshader = material() [[ anno::usage( "materialx:displacementshader") ]] +) += material( + thin_walled: false, + surface: mxp_surfaceshader.surface, + backface: mxp_surfaceshader.backface, + geometry: material_geometry( + cutout_opacity: mxp_surfaceshader.geometry.cutout_opacity, + displacement : mxp_displacementshader.geometry.displacement, + normal: mxp_surfaceshader.geometry.normal + ), + ior: mxp_surfaceshader.ior, + volume: mxp_surfaceshader.volume +); + +export material mx_surface_unlit( + float mxp_emission = 0.0, + color mxp_emission_color = color(1.0, 1.0, 1.0), + float mxp_transmission = 0.0, + color mxp_transmission_color = color(1.0, 1.0, 1.0), + float mxp_opacity = 1.0 +) += let { + float trans = math::clamp(mxp_transmission, 0.0, 1.0); + bsdf bsdf_node = df::specular_bsdf(trans * mxp_transmission_color, df::scatter_transmit); + material_emission edf_node = material_emission(df::diffuse_edf(), (1.0 - trans) * mxp_emission * mxp_emission_color * math::PI); +} in material( + thin_walled: true, + surface: material_surface( + scattering: bsdf_node, + emission: edf_node + ), + geometry: material_geometry( + cutout_opacity: mxp_opacity + ) +); + +// Texture Nodes + +// Helper function mapping texture node addressmodes to MDL wrap modes +::tex::wrap_mode map_addressmode( core::mx_addressmode_type value) { + switch (value) { + case core::mx_addressmode_type_clamp: + return ::tex::wrap_clamp; + case core::mx_addressmode_type_mirror: + return ::tex::wrap_mirrored_repeat; + default: + return ::tex::wrap_repeat; + } +} + +// NOTE: need to map MaterialX return type overloads to different function names +// or we require the mx_default to be always set explicitly + +export float mx_image_float( + uniform texture_2d mxp_file = texture_2d() + [[ + anno::display_name("Filename") + ]], + uniform string mxp_layer = string("") + [[ + anno::display_name("Layer"), anno::unused() + ]], + float mxp_default = float(0.0) + [[ + anno::display_name("Default Color") + ]], + float2 mxp_texcoord = float2(swizzle::xy(::state::texture_coordinate(0))) + [[ + anno::display_name("Texture Coordinates") + ]], + uniform core::mx_addressmode_type mxp_uaddressmode = core::mx_addressmode_type(core::mx_addressmode_type_periodic) + [[ + anno::description("Enumeration {constant,clamp,periodic,mirror}."), + anno::display_name("Address Mode U") + ]], + uniform core::mx_addressmode_type mxp_vaddressmode = core::mx_addressmode_type(core::mx_addressmode_type_periodic) + [[ + anno::description("Enumeration {constant,clamp,periodic,mirror}."), + anno::display_name("Address Mode V") + ]], + uniform core::mx_filterlookup_type mxp_filtertype = core::mx_filterlookup_type(core::mx_filterlookup_type_linear) + [[ + anno::description("Enumeration {closest,linear,cubic}."), + anno::display_name("Filter Type"), + anno::unused() + ]], + uniform string mxp_framerange = string("") + [[ + anno::display_name("Frame Range"), + anno::unused() + ]], + uniform int mxp_frameoffset = int(0) + [[ + anno::display_name("Frame Offset"), + anno::unused() + ]], + uniform core::mx_addressmode_type mxp_frameendaction = core::mx_addressmode_type(core::mx_addressmode_type_constant) + [[ + anno::description("Enumeration {constant,clamp,periodic,mirror}."), + anno::display_name("Frame End Action"), + anno::unused() + ]], + uniform bool mxp_flip_v = false + [[ + anno::usage("for applying the 'fileTextureVerticalFlip' shader generator option."), + anno::hidden() + ]] +) + [[ + anno::description("Node Group: texture2d") + ]] +{ + if ( mxp_uaddressmode == core::mx_addressmode_type_constant + && ( mxp_texcoord.x < 0.0 || mxp_texcoord.x > 1.0)) + return mxp_default; + if ( mxp_vaddressmode == core::mx_addressmode_type_constant + && ( mxp_texcoord.y < 0.0 || mxp_texcoord.y > 1.0)) + return mxp_default; + + float returnValue = ::tex::lookup_float(tex: mxp_file, + coord: mxp_flip_v + ? float2(mxp_texcoord.x, 1.0f - mxp_texcoord.y) + : mxp_texcoord, + wrap_u: map_addressmode(mxp_uaddressmode), + wrap_v: map_addressmode(mxp_vaddressmode)); + return returnValue; +} + +export color mx_image_color3( + uniform texture_2d mxp_file = texture_2d() + [[ + anno::display_name("Filename") + ]], + uniform string mxp_layer = string("") + [[ + anno::display_name("Layer"), anno::unused() + ]], + color mxp_default = color(0.0, 0.0, 0.0) + [[ + anno::display_name("Default Color") + ]], + float2 mxp_texcoord = float2(swizzle::xy(::state::texture_coordinate(0))) + [[ + anno::display_name("Texture Coordinates") + ]], + uniform core::mx_addressmode_type mxp_uaddressmode = core::mx_addressmode_type(core::mx_addressmode_type_periodic) + [[ + anno::description("Enumeration {constant,clamp,periodic,mirror}."), + anno::display_name("Address Mode U") + ]], + uniform core::mx_addressmode_type mxp_vaddressmode = core::mx_addressmode_type(core::mx_addressmode_type_periodic) + [[ + anno::description("Enumeration {constant,clamp,periodic,mirror}."), + anno::display_name("Address Mode V") + ]], + uniform core::mx_filterlookup_type mxp_filtertype = core::mx_filterlookup_type(core::mx_filterlookup_type_linear) + [[ + anno::description("Enumeration {closest,linear,cubic}."), + anno::display_name("Filter Type"), + anno::unused() + ]], + uniform string mxp_framerange = string("") + [[ + anno::display_name("Frame Range"), + anno::unused() + ]], + uniform int mxp_frameoffset = int(0) + [[ + anno::display_name("Frame Offset"), + anno::unused() + ]], + uniform core::mx_addressmode_type mxp_frameendaction = core::mx_addressmode_type(core::mx_addressmode_type_constant) + [[ + anno::description("Enumeration {constant,clamp,periodic,mirror}."), + anno::display_name("Frame End Action"), + anno::unused() + ]], + uniform bool mxp_flip_v = false + [[ + anno::usage("for applying the 'fileTextureVerticalFlip' shader generator option."), + anno::hidden() + ]] +) + [[ + anno::description("Node Group: texture2d") + ]] +{ + if ( mxp_uaddressmode == core::mx_addressmode_type_constant + && ( mxp_texcoord.x < 0.0 || mxp_texcoord.x > 1.0)) + return mxp_default; + if ( mxp_vaddressmode == core::mx_addressmode_type_constant + && ( mxp_texcoord.y < 0.0 || mxp_texcoord.y > 1.0)) + return mxp_default; + + color returnValue = ::tex::lookup_color(tex: mxp_file, + coord: mxp_flip_v + ? float2(mxp_texcoord.x, 1.0f - mxp_texcoord.y) + : mxp_texcoord, + wrap_u: map_addressmode(mxp_uaddressmode), + wrap_v: map_addressmode(mxp_vaddressmode)); + return returnValue; +} + +export core::color4 mx_image_color4( + uniform texture_2d mxp_file = texture_2d() + [[ + anno::display_name("Filename") + ]], + uniform string mxp_layer = string("") + [[ + anno::display_name("Layer"), anno::unused() + ]], + core::color4 mxp_default = core::mk_color4(0.0, 0.0, 0.0, 0.0) + [[ + anno::display_name("Default Color") + ]], + float2 mxp_texcoord = float2(swizzle::xy(::state::texture_coordinate(0))) + [[ + anno::display_name("Texture Coordinates") + ]], + uniform core::mx_addressmode_type mxp_uaddressmode = core::mx_addressmode_type(core::mx_addressmode_type_periodic) + [[ + anno::description("Enumeration {constant,clamp,periodic,mirror}."), + anno::display_name("Address Mode U") + ]], + uniform core::mx_addressmode_type mxp_vaddressmode = core::mx_addressmode_type(core::mx_addressmode_type_periodic) + [[ + anno::description("Enumeration {constant,clamp,periodic,mirror}."), + anno::display_name("Address Mode V") + ]], + uniform core::mx_filterlookup_type mxp_filtertype = core::mx_filterlookup_type(core::mx_filterlookup_type_linear) + [[ + anno::description("Enumeration {closest,linear,cubic}."), + anno::display_name("Filter Type"), + anno::unused() + ]], + uniform string mxp_framerange = string("") + [[ + anno::display_name("Frame Range"), + anno::unused() + ]], + uniform int mxp_frameoffset = int(0) + [[ + anno::display_name("Frame Offset"), + anno::unused() + ]], + uniform core::mx_addressmode_type mxp_frameendaction = core::mx_addressmode_type(core::mx_addressmode_type_constant) + [[ + anno::description("Enumeration {constant,clamp,periodic,mirror}."), + anno::display_name("Frame End Action"), + anno::unused() + ]], + uniform bool mxp_flip_v = false + [[ + anno::usage("for applying the 'fileTextureVerticalFlip' shader generator option."), + anno::hidden() + ]] +) + [[ + anno::description("Node Group: texture2d") + ]] +{ + if ( mxp_uaddressmode == core::mx_addressmode_type_constant + && ( mxp_texcoord.x < 0.0 || mxp_texcoord.x > 1.0)) + return mxp_default; + if ( mxp_vaddressmode == core::mx_addressmode_type_constant + && ( mxp_texcoord.y < 0.0 || mxp_texcoord.y > 1.0)) + return mxp_default; + + core::color4 returnValue = core::mk_color4(::tex::lookup_float4(tex: mxp_file, + coord: mxp_flip_v + ? float2(mxp_texcoord.x, 1.0f - mxp_texcoord.y) + : mxp_texcoord, + wrap_u: map_addressmode(mxp_uaddressmode), + wrap_v: map_addressmode(mxp_vaddressmode))); + return returnValue; +} + +export float2 mx_image_vector2( + uniform texture_2d mxp_file = texture_2d() + [[ + anno::display_name("Filename") + ]], + uniform string mxp_layer = string("") + [[ + anno::display_name("Layer"), anno::unused() + ]], + float2 mxp_default = float2(0.0, 0.0) + [[ + anno::display_name("Default Color") + ]], + float2 mxp_texcoord = float2(swizzle::xy(::state::texture_coordinate(0))) + [[ + anno::display_name("Texture Coordinates") + ]], + uniform core::mx_addressmode_type mxp_uaddressmode = core::mx_addressmode_type(core::mx_addressmode_type_periodic) + [[ + anno::description("Enumeration {constant,clamp,periodic,mirror}."), + anno::display_name("Address Mode U") + ]], + uniform core::mx_addressmode_type mxp_vaddressmode = core::mx_addressmode_type(core::mx_addressmode_type_periodic) + [[ + anno::description("Enumeration {constant,clamp,periodic,mirror}."), + anno::display_name("Address Mode V") + ]], + uniform core::mx_filterlookup_type mxp_filtertype = core::mx_filterlookup_type(core::mx_filterlookup_type_linear) + [[ + anno::description("Enumeration {closest,linear,cubic}."), + anno::display_name("Filter Type"), + anno::unused() + ]], + uniform string mxp_framerange = string("") + [[ + anno::display_name("Frame Range"), + anno::unused() + ]], + uniform int mxp_frameoffset = int(0) + [[ + anno::display_name("Frame Offset"), + anno::unused() + ]], + uniform core::mx_addressmode_type mxp_frameendaction = core::mx_addressmode_type(core::mx_addressmode_type_constant) + [[ + anno::description("Enumeration {constant,clamp,periodic,mirror}."), + anno::display_name("Frame End Action"), + anno::unused() + ]], + uniform bool mxp_flip_v = false + [[ + anno::usage("for applying the 'fileTextureVerticalFlip' shader generator option."), + anno::hidden() + ]] +) + [[ + anno::description("Node Group: texture2d") + ]] +{ + if ( mxp_uaddressmode == core::mx_addressmode_type_constant + && ( mxp_texcoord.x < 0.0 || mxp_texcoord.x > 1.0)) + return mxp_default; + if ( mxp_vaddressmode == core::mx_addressmode_type_constant + && ( mxp_texcoord.y < 0.0 || mxp_texcoord.y > 1.0)) + return mxp_default; + + float2 returnValue = ::tex::lookup_float2(tex: mxp_file, + coord: mxp_flip_v + ? float2(mxp_texcoord.x, 1.0f - mxp_texcoord.y) + : mxp_texcoord, + wrap_u: map_addressmode(mxp_uaddressmode), + wrap_v: map_addressmode(mxp_vaddressmode)); + return returnValue; +} + +export float3 mx_image_vector3( + uniform texture_2d mxp_file = texture_2d() + [[ + anno::display_name("Filename") + ]], + uniform string mxp_layer = string("") + [[ + anno::display_name("Layer"), anno::unused() + ]], + float3 mxp_default = float3(0.0, 0.0, 0.0) + [[ + anno::display_name("Default Color") + ]], + float2 mxp_texcoord = float2(swizzle::xy(::state::texture_coordinate(0))) + [[ + anno::display_name("Texture Coordinates") + ]], + uniform core::mx_addressmode_type mxp_uaddressmode = core::mx_addressmode_type(core::mx_addressmode_type_periodic) + [[ + anno::description("Enumeration {constant,clamp,periodic,mirror}."), + anno::display_name("Address Mode U") + ]], + uniform core::mx_addressmode_type mxp_vaddressmode = core::mx_addressmode_type(core::mx_addressmode_type_periodic) + [[ + anno::description("Enumeration {constant,clamp,periodic,mirror}."), + anno::display_name("Address Mode V") + ]], + uniform core::mx_filterlookup_type mxp_filtertype = core::mx_filterlookup_type(core::mx_filterlookup_type_linear) + [[ + anno::description("Enumeration {closest,linear,cubic}."), + anno::display_name("Filter Type"), + anno::unused() + ]], + uniform string mxp_framerange = string("") + [[ + anno::display_name("Frame Range"), + anno::unused() + ]], + uniform int mxp_frameoffset = int(0) + [[ + anno::display_name("Frame Offset"), + anno::unused() + ]], + uniform core::mx_addressmode_type mxp_frameendaction = core::mx_addressmode_type(core::mx_addressmode_type_constant) + [[ + anno::description("Enumeration {constant,clamp,periodic,mirror}."), + anno::display_name("Frame End Action"), + anno::unused() + ]], + uniform bool mxp_flip_v = false + [[ + anno::usage("for applying the 'fileTextureVerticalFlip' shader generator option."), + anno::hidden() + ]] +) + [[ + anno::description("Node Group: texture2d") + ]] +{ + if ( mxp_uaddressmode == core::mx_addressmode_type_constant + && ( mxp_texcoord.x < 0.0 || mxp_texcoord.x > 1.0)) + return mxp_default; + if ( mxp_vaddressmode == core::mx_addressmode_type_constant + && ( mxp_texcoord.y < 0.0 || mxp_texcoord.y > 1.0)) + return mxp_default; + + float3 returnValue = ::tex::lookup_float3(tex: mxp_file, + coord: mxp_flip_v + ? float2(mxp_texcoord.x, 1.0f - mxp_texcoord.y) + : mxp_texcoord, + wrap_u: map_addressmode(mxp_uaddressmode), + wrap_v: map_addressmode(mxp_vaddressmode)); + return returnValue; +} + +export float4 mx_image_vector4( + uniform texture_2d mxp_file = texture_2d() + [[ + anno::display_name("Filename") + ]], + uniform string mxp_layer = string("") + [[ + anno::display_name("Layer"), anno::unused() + ]], + float4 mxp_default = float4(0.0, 0.0, 0.0, 0.0) + [[ + anno::display_name("Default Color") + ]], + float2 mxp_texcoord = float2(swizzle::xy(::state::texture_coordinate(0))) + [[ + anno::display_name("Texture Coordinates") + ]], + uniform core::mx_addressmode_type mxp_uaddressmode = core::mx_addressmode_type(core::mx_addressmode_type_periodic) + [[ + anno::description("Enumeration {constant,clamp,periodic,mirror}."), + anno::display_name("Address Mode U") + ]], + uniform core::mx_addressmode_type mxp_vaddressmode = core::mx_addressmode_type(core::mx_addressmode_type_periodic) + [[ + anno::description("Enumeration {constant,clamp,periodic,mirror}."), + anno::display_name("Address Mode V") + ]], + uniform core::mx_filterlookup_type mxp_filtertype = core::mx_filterlookup_type(core::mx_filterlookup_type_linear) + [[ + anno::description("Enumeration {closest,linear,cubic}."), + anno::display_name("Filter Type"), + anno::unused() + ]], + uniform string mxp_framerange = string("") + [[ + anno::display_name("Frame Range"), + anno::unused() + ]], + uniform int mxp_frameoffset = int(0) + [[ + anno::display_name("Frame Offset"), + anno::unused() + ]], + uniform core::mx_addressmode_type mxp_frameendaction = core::mx_addressmode_type(core::mx_addressmode_type_constant) + [[ + anno::description("Enumeration {constant,clamp,periodic,mirror}."), + anno::display_name("Frame End Action"), + anno::unused() + ]], + uniform bool mxp_flip_v = false + [[ + anno::usage("for applying the 'fileTextureVerticalFlip' shader generator option."), + anno::hidden() + ]] +) + [[ + anno::description("Node Group: texture2d") + ]] +{ + if ( mxp_uaddressmode == core::mx_addressmode_type_constant + && ( mxp_texcoord.x < 0.0 || mxp_texcoord.x > 1.0)) + return mxp_default; + if ( mxp_vaddressmode == core::mx_addressmode_type_constant + && ( mxp_texcoord.y < 0.0 || mxp_texcoord.y > 1.0)) + return mxp_default; + + float4 returnValue = ::tex::lookup_float4(tex: mxp_file, + coord: mxp_flip_v + ? float2(mxp_texcoord.x, 1.0f - mxp_texcoord.y) + : mxp_texcoord, + wrap_u: map_addressmode(mxp_uaddressmode), + wrap_v: map_addressmode(mxp_vaddressmode)); + return returnValue; +} + +// Nodedef: ND_tiledimage_float is represented by a nodegraph: NG_tiledimage_float +// Nodedef: ND_tiledimage_color3 is represented by a nodegraph: NG_tiledimage_color3 +// Nodedef: ND_tiledimage_color4 is represented by a nodegraph: NG_tiledimage_color4 +// Nodedef: ND_tiledimage_vector2 is represented by a nodegraph: NG_tiledimage_vector2 +// Nodedef: ND_tiledimage_vector3 is represented by a nodegraph: NG_tiledimage_vector3 +// Nodedef: ND_tiledimage_vector4 is represented by a nodegraph: NG_tiledimage_vector4 +// Nodedef: ND_triplanarprojection_float is represented by a nodegraph: NG_triplanarprojection_float +// Nodedef: ND_triplanarprojection_color3 is represented by a nodegraph: NG_triplanarprojection_color3 +// Nodedef: ND_triplanarprojection_color4 is represented by a nodegraph: NG_triplanarprojection_color4 +// Nodedef: ND_triplanarprojection_vector2 is represented by a nodegraph: NG_triplanarprojection_vector2 +// Nodedef: ND_triplanarprojection_vector3 is represented by a nodegraph: NG_triplanarprojection_vector3 +// Nodedef: ND_triplanarprojection_vector4 is represented by a nodegraph: NG_triplanarprojection_vector4 + +export float mx_constant_float( + float mxp_value = float(0.0) +) + [[ + anno::description("Node Group: procedural") + ]] +{ + return mxp_value; +} + +export color mx_constant_color3( + color mxp_value = color(0.0, 0.0, 0.0) +) + [[ + anno::description("Node Group: procedural") + ]] +{ + return mxp_value; +} + +export core::color4 mx_constant_color4( + core::color4 mxp_value = core::mk_color4(0.0, 0.0, 0.0, 0.0) +) + [[ + anno::description("Node Group: procedural") + ]] +{ + return mxp_value; +} + +export float2 mx_constant_vector2( + float2 mxp_value = float2(0.0, 0.0) +) + [[ + anno::description("Node Group: procedural") + ]] +{ + return mxp_value; +} + +export float3 mx_constant_vector3( + float3 mxp_value = float3(0.0, 0.0, 0.0) +) + [[ + anno::description("Node Group: procedural") + ]] +{ + return mxp_value; +} + +export float4 mx_constant_vector4( + float4 mxp_value = float4(0.0, 0.0, 0.0, 0.0) +) + [[ + anno::description("Node Group: procedural") + ]] +{ + return mxp_value; +} + +export bool mx_constant_boolean( + bool mxp_value = bool(false) +) + [[ + anno::description("Node Group: procedural") + ]] +{ + return mxp_value; +} + +export int mx_constant_integer( + int mxp_value = int(0) +) + [[ + anno::description("Node Group: procedural") + ]] +{ + return mxp_value; +} + +export float3x3 mx_constant_matrix33( + float3x3 mxp_value = float3x3(1.0,0.0,0.0, 0.0,1.0,0.0, 0.0,0.0,1.0) +) + [[ + anno::description("Node Group: procedural") + ]] +{ + return mxp_value; +} + +export float4x4 mx_constant_matrix44( + float4x4 mxp_value = float4x4(1.0,0.0,0.0,0.0, 0.0,1.0,0.0,0.0, 0.0,0.0,1.0,0.0, 0.0,0.0,0.0,1.0) +) + [[ + anno::description("Node Group: procedural") + ]] +{ + return mxp_value; +} + +export string mx_constant_string( + uniform string mxp_value = string("") +) + [[ + anno::description("Node Group: procedural") + ]] +{ + return mxp_value; +} + +export string mx_constant_filename( + uniform string mxp_value = string("") +) + [[ + anno::description("Node Group: procedural") + ]] +{ + return mxp_value; +} + +export float mx_ramplr_float( + float mxp_valuel = float(0.0), + float mxp_valuer = float(0.0), + float2 mxp_texcoord = float2(swizzle::xy(::state::texture_coordinate(0))) +) + [[ + anno::description("Node Group: procedural2d") + ]] +{ + return math::lerp(mxp_valuel, mxp_valuer, math::clamp(mxp_texcoord.x, 0.0, 1.0)); +} + +export color mx_ramplr_color3( + color mxp_valuel = color(0.0, 0.0, 0.0), + color mxp_valuer = color(0.0, 0.0, 0.0), + float2 mxp_texcoord = float2(swizzle::xy(::state::texture_coordinate(0))) +) + [[ + anno::description("Node Group: procedural2d") + ]] +{ + return math::lerp(mxp_valuel, mxp_valuer, math::clamp(mxp_texcoord.x, 0.0, 1.0)); +} + +export core::color4 mx_ramplr_color4( + core::color4 mxp_valuel = core::mk_color4(0.0, 0.0, 0.0, 0.0), + core::color4 mxp_valuer = core::mk_color4(0.0, 0.0, 0.0, 0.0), + float2 mxp_texcoord = float2(swizzle::xy(::state::texture_coordinate(0))) +) + [[ + anno::description("Node Group: procedural2d") + ]] +{ + color rgb = math::lerp(mxp_valuel.rgb, mxp_valuer.rgb, math::clamp(mxp_texcoord.x, 0.0, 1.0)); + float a = math::lerp(mxp_valuel.a, mxp_valuer.a, math::clamp(mxp_texcoord.x, 0.0, 1.0)); + return core::color4(rgb, a);} + +export float2 mx_ramplr_vector2( + float2 mxp_valuel = float2(0.0, 0.0), + float2 mxp_valuer = float2(0.0, 0.0), + float2 mxp_texcoord = float2(swizzle::xy(::state::texture_coordinate(0))) +) + [[ + anno::description("Node Group: procedural2d") + ]] +{ + return math::lerp(mxp_valuel, mxp_valuer, math::clamp(mxp_texcoord.x, 0.0, 1.0)); +} + +export float3 mx_ramplr_vector3( + float3 mxp_valuel = float3(0.0, 0.0, 0.0), + float3 mxp_valuer = float3(0.0, 0.0, 0.0), + float2 mxp_texcoord = float2(swizzle::xy(::state::texture_coordinate(0))) +) + [[ + anno::description("Node Group: procedural2d") + ]] +{ + return math::lerp(mxp_valuel, mxp_valuer, math::clamp(mxp_texcoord.x, 0.0, 1.0)); +} + +export float4 mx_ramplr_vector4( + float4 mxp_valuel = float4(0.0, 0.0, 0.0, 0.0), + float4 mxp_valuer = float4(0.0, 0.0, 0.0, 0.0), + float2 mxp_texcoord = float2(swizzle::xy(::state::texture_coordinate(0))) +) + [[ + anno::description("Node Group: procedural2d") + ]] +{ + return math::lerp(mxp_valuel, mxp_valuer, math::clamp(mxp_texcoord.x, 0.0, 1.0)); +} + +export float mx_ramptb_float( + float mxp_valuet = float(0.0), + float mxp_valueb = float(0.0), + float2 mxp_texcoord = float2(swizzle::xy(::state::texture_coordinate(0))) +) + [[ + anno::description("Node Group: procedural2d") + ]] +{ + return math::lerp(mxp_valuet, mxp_valueb, math::clamp(mxp_texcoord.y, 0.0, 1.0)); +} + +export color mx_ramptb_color3( + color mxp_valuet = color(0.0, 0.0, 0.0), + color mxp_valueb = color(0.0, 0.0, 0.0), + float2 mxp_texcoord = float2(swizzle::xy(::state::texture_coordinate(0))) +) + [[ + anno::description("Node Group: procedural2d") + ]] +{ + return math::lerp(mxp_valuet, mxp_valueb, math::clamp(mxp_texcoord.y, 0.0, 1.0)); +} + +export core::color4 mx_ramptb_color4( + core::color4 mxp_valuet = core::mk_color4(0.0, 0.0, 0.0, 0.0), + core::color4 mxp_valueb = core::mk_color4(0.0, 0.0, 0.0, 0.0), + float2 mxp_texcoord = float2(swizzle::xy(::state::texture_coordinate(0))) +) + [[ + anno::description("Node Group: procedural2d") + ]] +{ + color rgb = math::lerp(mxp_valuet.rgb, mxp_valueb.rgb, math::clamp(mxp_texcoord.y, 0.0, 1.0)); + float a = math::lerp(mxp_valuet.a, mxp_valueb.a, math::clamp(mxp_texcoord.y, 0.0, 1.0)); + return core::color4(rgb, a);} + +export float2 mx_ramptb_vector2( + float2 mxp_valuet = float2(0.0, 0.0), + float2 mxp_valueb = float2(0.0, 0.0), + float2 mxp_texcoord = float2(swizzle::xy(::state::texture_coordinate(0))) +) + [[ + anno::description("Node Group: procedural2d") + ]] +{ + return math::lerp(mxp_valuet, mxp_valueb, math::clamp(mxp_texcoord.y, 0.0, 1.0)); +} + +export float3 mx_ramptb_vector3( + float3 mxp_valuet = float3(0.0, 0.0, 0.0), + float3 mxp_valueb = float3(0.0, 0.0, 0.0), + float2 mxp_texcoord = float2(swizzle::xy(::state::texture_coordinate(0))) +) + [[ + anno::description("Node Group: procedural2d") + ]] +{ + return math::lerp(mxp_valuet, mxp_valueb, math::clamp(mxp_texcoord.y, 0.0, 1.0)); +} + +export float4 mx_ramptb_vector4( + float4 mxp_valuet = float4(0.0, 0.0, 0.0, 0.0), + float4 mxp_valueb = float4(0.0, 0.0, 0.0, 0.0), + float2 mxp_texcoord = float2(swizzle::xy(::state::texture_coordinate(0))) +) + [[ + anno::description("Node Group: procedural2d") + ]] +{ + return math::lerp(mxp_valuet, mxp_valueb, math::clamp(mxp_texcoord.y, 0.0, 1.0)); +} + +// Nodedef: ND_ramp4_float is represented by a nodegraph: NG_ramp4_float +// Nodedef: ND_ramp4_color3 is represented by a nodegraph: NG_ramp4_color3 +// Nodedef: ND_ramp4_color4 is represented by a nodegraph: NG_ramp4_color4 +// Nodedef: ND_ramp4_vector2 is represented by a nodegraph: NG_ramp4_vector2 +// Nodedef: ND_ramp4_vector3 is represented by a nodegraph: NG_ramp4_vector3 +// Nodedef: ND_ramp4_vector4 is represented by a nodegraph: NG_ramp4_vector4 + +export float mx_splitlr_float( + float mxp_valuel = float(0.0) + [[ + anno::display_name("Left") + ]], + float mxp_valuer = float(0.0) + [[ + anno::display_name("Right") + ]], + float mxp_center = float(0.5) + [[ + anno::display_name("Center") + ]], + float2 mxp_texcoord = float2(swizzle::xy(::state::texture_coordinate(0))) +) + [[ + anno::description("Node Group: procedural2d") + ]] +{ + return math::lerp(mxp_valuel, mxp_valuer, math::step(mxp_center, math::clamp(mxp_texcoord.x,0,1))); +} + +export color mx_splitlr_color3( + color mxp_valuel = color(0.0, 0.0, 0.0) + [[ + anno::display_name("Left") + ]], + color mxp_valuer = color(0.0, 0.0, 0.0) + [[ + anno::display_name("Right") + ]], + float mxp_center = float(0.5) + [[ + anno::display_name("Center") + ]], + float2 mxp_texcoord = float2(swizzle::xy(::state::texture_coordinate(0))) +) + [[ + anno::description("Node Group: procedural2d") + ]] +{ + return math::lerp(mxp_valuel, mxp_valuer, math::step(mxp_center, math::clamp(mxp_texcoord.x,0,1))); +} + +export core::color4 mx_splitlr_color4( + core::color4 mxp_valuel = core::mk_color4(0.0, 0.0, 0.0, 0.0) + [[ + anno::display_name("Left") + ]], + core::color4 mxp_valuer = core::mk_color4(0.0, 0.0, 0.0, 0.0) + [[ + anno::display_name("Right") + ]], + float mxp_center = float(0.5) + [[ + anno::display_name("Center") + ]], + float2 mxp_texcoord = float2(swizzle::xy(::state::texture_coordinate(0))) +) + [[ + anno::description("Node Group: procedural2d") + ]] +{ + color rgb = math::lerp(mxp_valuel.rgb, mxp_valuer.rgb, math::step(mxp_center, math::clamp(mxp_texcoord.x,0,1))); + float a = math::lerp(mxp_valuel.a, mxp_valuer.a, math::step(mxp_center, math::clamp(mxp_texcoord.x,0,1))); + return core::color4(rgb, a); +} + +export float2 mx_splitlr_vector2( + float2 mxp_valuel = float2(0.0, 0.0) + [[ + anno::display_name("Left") + ]], + float2 mxp_valuer = float2(0.0, 0.0) + [[ + anno::display_name("Right") + ]], + float mxp_center = float(0.5) + [[ + anno::display_name("Center") + ]], + float2 mxp_texcoord = float2(swizzle::xy(::state::texture_coordinate(0))) +) + [[ + anno::description("Node Group: procedural2d") + ]] +{ + return math::lerp(mxp_valuel, mxp_valuer, math::step(mxp_center, math::clamp(mxp_texcoord.x,0,1))); +} + +export float3 mx_splitlr_vector3( + float3 mxp_valuel = float3(0.0, 0.0, 0.0) + [[ + anno::display_name("Left") + ]], + float3 mxp_valuer = float3(0.0, 0.0, 0.0) + [[ + anno::display_name("Right") + ]], + float mxp_center = float(0.5) + [[ + anno::display_name("Center") + ]], + float2 mxp_texcoord = float2(swizzle::xy(::state::texture_coordinate(0))) +) + [[ + anno::description("Node Group: procedural2d") + ]] +{ + return math::lerp(mxp_valuel, mxp_valuer, math::step(mxp_center, math::clamp(mxp_texcoord.x,0,1))); +} + +export float4 mx_splitlr_vector4( + float4 mxp_valuel = float4(0.0, 0.0, 0.0, 0.0) + [[ + anno::display_name("Left") + ]], + float4 mxp_valuer = float4(0.0, 0.0, 0.0, 0.0) + [[ + anno::display_name("Right") + ]], + float mxp_center = float(0.5) + [[ + anno::display_name("Center") + ]], + float2 mxp_texcoord = float2(swizzle::xy(::state::texture_coordinate(0))) +) + [[ + anno::description("Node Group: procedural2d") + ]] +{ + return math::lerp(mxp_valuel, mxp_valuer, math::step(mxp_center, math::clamp(mxp_texcoord.x,0,1))); +} + +export float mx_splittb_float( + float mxp_valuet = float(0.0) + [[ + anno::display_name("Top") + ]], + float mxp_valueb = float(0.0) + [[ + anno::display_name("Bottom") + ]], + float mxp_center = float(0.5) + [[ + anno::display_name("Center") + ]], + float2 mxp_texcoord = float2(swizzle::xy(::state::texture_coordinate(0))) +) + [[ + anno::description("Node Group: procedural2d") + ]] +{ + return math::lerp(mxp_valuet, mxp_valueb, math::step(mxp_center, math::clamp(mxp_texcoord.x,0,1))); +} + +export color mx_splittb_color3( + color mxp_valuet = color(0.0, 0.0, 0.0) + [[ + anno::display_name("Top") + ]], + color mxp_valueb = color(0.0, 0.0, 0.0) + [[ + anno::display_name("Bottom") + ]], + float mxp_center = float(0.5) + [[ + anno::display_name("Center") + ]], + float2 mxp_texcoord = float2(swizzle::xy(::state::texture_coordinate(0))) +) + [[ + anno::description("Node Group: procedural2d") + ]] +{ + return math::lerp(mxp_valuet, mxp_valueb, math::step(mxp_center, math::clamp(mxp_texcoord.x,0,1))); +} + +export core::color4 mx_splittb_color4( + core::color4 mxp_valuet = core::mk_color4(0.0, 0.0, 0.0, 0.0) + [[ + anno::display_name("Top") + ]], + core::color4 mxp_valueb = core::mk_color4(0.0, 0.0, 0.0, 0.0) + [[ + anno::display_name("Bottom") + ]], + float mxp_center = float(0.5) + [[ + anno::display_name("Center") + ]], + float2 mxp_texcoord = float2(swizzle::xy(::state::texture_coordinate(0))) +) + [[ + anno::description("Node Group: procedural2d") + ]] +{ + color rgb = math::lerp(mxp_valuet.rgb, mxp_valueb.rgb, math::step(mxp_center, math::clamp(mxp_texcoord.x,0,1))); float a = math::lerp(mxp_valuet.a, mxp_valueb.a, math::step(mxp_center, math::clamp(mxp_texcoord.x,0,1))); return core::color4(rgb, a); +} + +export float2 mx_splittb_vector2( + float2 mxp_valuet = float2(0.0, 0.0) + [[ + anno::display_name("Top") + ]], + float2 mxp_valueb = float2(0.0, 0.0) + [[ + anno::display_name("Bottom") + ]], + float mxp_center = float(0.5) + [[ + anno::display_name("Center") + ]], + float2 mxp_texcoord = float2(swizzle::xy(::state::texture_coordinate(0))) +) + [[ + anno::description("Node Group: procedural2d") + ]] +{ + return math::lerp(mxp_valuet, mxp_valueb, math::step(mxp_center, math::clamp(mxp_texcoord.x,0,1))); +} + +export float3 mx_splittb_vector3( + float3 mxp_valuet = float3(0.0, 0.0, 0.0) + [[ + anno::display_name("Top") + ]], + float3 mxp_valueb = float3(0.0, 0.0, 0.0) + [[ + anno::display_name("Bottom") + ]], + float mxp_center = float(0.5) + [[ + anno::display_name("Center") + ]], + float2 mxp_texcoord = float2(swizzle::xy(::state::texture_coordinate(0))) +) + [[ + anno::description("Node Group: procedural2d") + ]] +{ + return math::lerp(mxp_valuet, mxp_valueb, math::step(mxp_center, math::clamp(mxp_texcoord.x,0,1))); +} + +export float4 mx_splittb_vector4( + float4 mxp_valuet = float4(0.0, 0.0, 0.0, 0.0) + [[ + anno::display_name("Top") + ]], + float4 mxp_valueb = float4(0.0, 0.0, 0.0, 0.0) + [[ + anno::display_name("Bottom") + ]], + float mxp_center = float(0.5) + [[ + anno::display_name("Center") + ]], + float2 mxp_texcoord = float2(swizzle::xy(::state::texture_coordinate(0))) +) + [[ + anno::description("Node Group: procedural2d") + ]] +{ + return math::lerp(mxp_valuet, mxp_valueb, math::step(mxp_center, math::clamp(mxp_texcoord.x,0,1))); +} + +export float3 mx_position_vector3( + uniform core::mx_coordinatespace_type mxp_space = core::mx_coordinatespace_type(core::mx_coordinatespace_type_object) + [[ + anno::description("Enumeration {model,object,world}.") + ]] +) + [[ + anno::description("Node Group: geometric") + ]] +{ + state::coordinate_space fromSpace = ::core::mx_map_space(core::mx_coordinatespace_type_model); + state::coordinate_space toSpace = ::core::mx_map_space(mxp_space); + return state::transform_point(fromSpace, toSpace, state::position()); +} + +export float3 mx_normal_vector3( + uniform core::mx_coordinatespace_type mxp_space = core::mx_coordinatespace_type(core::mx_coordinatespace_type_object) + [[ + anno::description("Enumeration {model,object,world}.") + ]] +) + [[ + anno::description("Node Group: geometric") + ]] +{ + state::coordinate_space fromSpace = ::core::mx_map_space(core::mx_coordinatespace_type_model); + state::coordinate_space toSpace = ::core::mx_map_space(mxp_space); + return state::transform_normal(fromSpace, toSpace, state::normal()); +} + +export float3 mx_tangent_vector3( + uniform core::mx_coordinatespace_type mxp_space = core::mx_coordinatespace_type(core::mx_coordinatespace_type_object) + [[ + anno::description("Enumeration {model,object,world}.") + ]], + uniform int mxp_index = int(0) +) + [[ + anno::description("Node Group: geometric") + ]] +{ + state::coordinate_space fromSpace = ::core::mx_map_space(core::mx_coordinatespace_type_model); + state::coordinate_space toSpace = ::core::mx_map_space(mxp_space); + return ::math::normalize(state::transform_vector(fromSpace, toSpace, state::texture_tangent_u(mxp_index))); +} + +export float3 mx_bitangent_vector3( + uniform core::mx_coordinatespace_type mxp_space = core::mx_coordinatespace_type(core::mx_coordinatespace_type_object) + [[ + anno::description("Enumeration {model,object,world}.") + ]], + uniform int mxp_index = int(0) +) + [[ + anno::description("Node Group: geometric") + ]] +{ + state::coordinate_space fromSpace = ::core::mx_map_space(core::mx_coordinatespace_type_model); + state::coordinate_space toSpace = ::core::mx_map_space(mxp_space); + return ::math::normalize(state::transform_vector(fromSpace, toSpace, state::texture_tangent_v(mxp_index))); +} + +export float2 mx_texcoord_vector2( + uniform int mxp_index = int(0) +) + [[ + anno::description("Node Group: geometric") + ]] +{ + return swizzle::xy((state::texture_coordinate(mxp_index))); +} + +export float3 mx_texcoord_vector3( + uniform int mxp_index = int(0) +) + [[ + anno::description("Node Group: geometric") + ]] +{ + return state::texture_coordinate(mxp_index); +} + +export float mx_geomcolor_float( + uniform int mxp_index = int(0) [[ anno::unused() ]] +) + [[ + anno::description("Node Group: geometric") + ]] +{ + // Not implemented: mx_geomcolor_float + float defaultValue = float(0.0); + return defaultValue; +} + +export color mx_geomcolor_color3( + uniform int mxp_index = int(0) [[ anno::unused() ]] +) + [[ + anno::description("Node Group: geometric") + ]] +{ + // Not implemented: mx_geomcolor_color3 + color defaultValue = color(0.0, 0.0, 0.0); + return defaultValue; +} + +export core::color4 mx_geomcolor_color4( + uniform int mxp_index = int(0) [[ anno::unused() ]] +) + [[ + anno::description("Node Group: geometric") + ]] +{ + // Not implemented: mx_geomcolor_color4 + core::color4 defaultValue = core::mk_color4(0.0, 0.0, 0.0, 0.0); + return defaultValue; +} + +export int mx_geompropvalue_integer( + uniform string mxp_geomprop = string("") [[ anno::unused() ]], + int mxp_default = int(0) [[ anno::unused() ]] +) + [[ + anno::description("Node Group: geometric") + ]] +{ + // Not implemented: mx_geompropvalue_integer + int defaultValue = int(0); + return defaultValue; +} + +export bool mx_geompropvalue_boolean( + uniform string mxp_geomprop = string("") [[ anno::unused() ]], + bool mxp_default = bool(false) [[ anno::unused() ]] +) + [[ + anno::description("Node Group: geometric") + ]] +{ + // Not implemented: mx_geompropvalue_boolean + bool defaultValue = bool(false); + return defaultValue; +} + +export string mx_geompropvalue_string( + uniform string mxp_geomprop = string("") [[ anno::unused() ]], + string mxp_default = string("") [[ anno::unused() ]] +) + [[ + anno::description("Node Group: geometric") + ]] +{ + // Not implemented: mx_geompropvalue_string + string defaultValue; + return defaultValue; +} + +export float mx_geompropvalue_float( + uniform string mxp_geomprop = string("") [[ anno::unused() ]], + float mxp_default = float(0.0) [[ anno::unused() ]] +) + [[ + anno::description("Node Group: geometric") + ]] +{ + // Not implemented: mx_geompropvalue_float + float defaultValue = float(0.0); + return defaultValue; +} + +export color mx_geompropvalue_color3( + uniform string mxp_geomprop = string("") [[ anno::unused() ]], + color mxp_default = color(0.0, 0.0, 0.0) [[ anno::unused() ]] +) + [[ + anno::description("Node Group: geometric") + ]] +{ + // Not implemented: mx_geompropvalue_color3 + color defaultValue = color(0.0, 0.0, 0.0); + return defaultValue; +} + +export core::color4 mx_geompropvalue_color4( + uniform string mxp_geomprop = string("") [[ anno::unused() ]], + core::color4 mxp_default = core::mk_color4(0.0, 0.0, 0.0, 0.0) [[ anno::unused() ]] +) + [[ + anno::description("Node Group: geometric") + ]] +{ + // Not implemented: mx_geompropvalue_color4 + core::color4 defaultValue = core::mk_color4(0.0, 0.0, 0.0, 0.0); + return defaultValue; +} + +export float2 mx_geompropvalue_vector2( + uniform string mxp_geomprop = string("") [[ anno::unused() ]], + float2 mxp_default = float2(0.0, 0.0) [[ anno::unused() ]] +) + [[ + anno::description("Node Group: geometric") + ]] +{ + // Not implemented: mx_geompropvalue_vector2 + float2 defaultValue = float2(0.0, 0.0); + return defaultValue; +} + +export float3 mx_geompropvalue_vector3( + uniform string mxp_geomprop = string("") [[ anno::unused() ]], + float3 mxp_default = float3(0.0, 0.0, 0.0) [[ anno::unused() ]] +) + [[ + anno::description("Node Group: geometric") + ]] +{ + // Not implemented: mx_geompropvalue_vector3 + float3 defaultValue = float3(0.0, 0.0, 0.0); + return defaultValue; +} + +export float4 mx_geompropvalue_vector4( + uniform string mxp_geomprop = string("") [[ anno::unused() ]], + float4 mxp_default = float4(0.0, 0.0, 0.0, 0.0) [[ anno::unused() ]] +) + [[ + anno::description("Node Group: geometric") + ]] +{ + // Not implemented: mx_geompropvalue_vector4 + float4 defaultValue = float4(0.0, 0.0, 0.0, 0.0); + return defaultValue; +} + +export float mx_ambientocclusion_float( + float mxp_coneangle = float(90.0) + [[ + anno::description("Unit Type:angle. Unit:degrees."), + anno::unused() + ]], + float mxp_maxdistance = float(1e38) [[ anno::unused() ]] +) + [[ + anno::description("Node Group: global") + ]] +{ + // Not implemented: mx_ambientocclusion_float + float defaultValue = float(1.0); + return defaultValue; +} + +export float mx_frame_float( +) + [[ + anno::description("Node Group: application") + ]] +{ + // Not implemented: mx_frame_float + float defaultValue = float(1.0); + return defaultValue; +} + +export float mx_time_float( + uniform float mxp_fps = float(24.0) [[ anno::unused() ]] +) + [[ + anno::description("Node Group: application") + ]] +{ + return ::state::animation_time(); +} + +export float3 mx_viewdirection_vector3( + uniform core::mx_coordinatespace_type mxp_space = core::mx_coordinatespace_type_world + [[ + anno::description("Enumeration {model,object,world}."), + anno::unused() + ]] +) + [[ + anno::description("Node Group: nprlib") + ]] +{ + // Not implemented: mx_viewdirection_vector3 + float3 defaultValue = float3(0.0, 0.0, 1.0); + return defaultValue; +} + +export color mx_modulo_color3( + color mxp_in1 = color(0.0, 0.0, 0.0), + color mxp_in2 = color(1.0, 1.0, 1.0) +) + [[ + anno::description("Node Group: math") + ]] +{ + return color(core::mx_mod(float3(mxp_in1), float3(mxp_in2))); +} + +export core::color4 mx_modulo_color4( + core::color4 mxp_in1 = core::mk_color4(0.0, 0.0, 0.0, 0.0), + core::color4 mxp_in2 = core::mk_color4(1.0, 1.0, 1.0, 1.0) +) + [[ + anno::description("Node Group: math") + ]] +{ + return core::mk_color4(core::mx_mod(core::mk_float4(mxp_in1), core::mk_float4(mxp_in2))); +} + +export color mx_modulo_color3FA( + color mxp_in1 = color(0.0, 0.0, 0.0), + float mxp_in2 = float(1.0) +) + [[ + anno::description("Node Group: math") + ]] +{ + return color(core::mx_mod(float3(mxp_in1), float3(mxp_in2))); +} + +export core::color4 mx_modulo_color4FA( + core::color4 mxp_in1 = core::mk_color4(0.0, 0.0, 0.0, 0.0), + float mxp_in2 = float(1.0) +) + [[ + anno::description("Node Group: math") + ]] +{ + return core::mk_color4(core::mx_mod(core::mk_float4(mxp_in1), float4(mxp_in2))); +} + +export core::color4 mx_invert_color4( + core::color4 mxp_in = core::mk_color4(0.0, 0.0, 0.0, 0.0), + core::color4 mxp_amount = core::mk_color4(1.0, 1.0, 1.0, 1.0) +) + [[ + anno::description("Node Group: math") + ]] +{ + return core::mk_color4(core::mk_float4(mxp_amount) - core::mk_float4(mxp_in)); +} + +export core::color4 mx_invert_color4FA( + core::color4 mxp_in = core::mk_color4(0.0, 0.0, 0.0, 0.0), + float mxp_amount = float(1.0) +) + [[ + anno::description("Node Group: math") + ]] +{ + return core::mk_color4(float4(mxp_amount) - core::mk_float4(mxp_in)); +} + +export core::color4 mx_absval_color4( + core::color4 mxp_in = core::mk_color4(0.0, 0.0, 0.0, 0.0) +) + [[ + anno::description("Node Group: math") + ]] +{ + return core::mk_color4(::math::abs(core::mk_float4(mxp_in))); +} + +export color mx_floor_color3( + color mxp_in = color(0.0, 0.0, 0.0) +) + [[ + anno::description("Node Group: math") + ]] +{ + return color(::math::floor(float3(mxp_in))); +} + +export core::color4 mx_floor_color4( + core::color4 mxp_in = core::mk_color4(0.0, 0.0, 0.0, 0.0) +) + [[ + anno::description("Node Group: math") + ]] +{ + return core::mk_color4(::math::floor(core::mk_float4(mxp_in))); +} + +export color mx_ceil_color3( + color mxp_in = color(0.0, 0.0, 0.0) +) + [[ + anno::description("Node Group: math") + ]] +{ + return color(::math::ceil(float3(mxp_in))); +} + +export core::color4 mx_ceil_color4( + core::color4 mxp_in = core::mk_color4(0.0, 0.0, 0.0, 0.0) +) + [[ + anno::description("Node Group: math") + ]] +{ + return core::mk_color4(::math::ceil(core::mk_float4(mxp_in))); +} + +export color mx_round_color3( + color mxp_in = color(0.0, 0.0, 0.0) +) + [[ + anno::description("Node Group: math") + ]] +{ + return color(::math::round(float3(mxp_in))); +} + +export core::color4 mx_round_color4( + core::color4 mxp_in = core::mk_color4(0.0, 0.0, 0.0, 0.0) +) + [[ + anno::description("Node Group: math") + ]] +{ + return core::mk_color4(::math::round(core::mk_float4(mxp_in))); +} + +export core::color4 mx_power_color4( + core::color4 mxp_in1 = core::mk_color4(0.0, 0.0, 0.0, 0.0), + core::color4 mxp_in2 = core::mk_color4(1.0, 1.0, 1.0, 1.0) +) + [[ + anno::description("Node Group: math") + ]] +{ + return core::mk_color4(::math::pow(core::mk_float4(mxp_in1), core::mk_float4(mxp_in2))); +} + +export core::color4 mx_power_color4FA( + core::color4 mxp_in1 = core::mk_color4(0.0, 0.0, 0.0, 0.0), + float mxp_in2 = float(1.0) +) + [[ + anno::description("Node Group: math") + ]] +{ + return core::mk_color4(::math::pow(core::mk_float4(mxp_in1), float4(mxp_in2))); +} + +export float mx_sin_float( + float mxp_in = float(0.0) +) + [[ + anno::description("Node Group: math") + ]] +{ + return ::math::sin(mxp_in); +} + +export float mx_cos_float( + float mxp_in = float(0.0) +) + [[ + anno::description("Node Group: math") + ]] +{ + return ::math::cos(mxp_in); +} + +export float mx_tan_float( + float mxp_in = float(0.0) +) + [[ + anno::description("Node Group: math") + ]] +{ + return ::math::tan(mxp_in); +} + +export float mx_asin_float( + float mxp_in = float(0.0) +) + [[ + anno::description("Node Group: math") + ]] +{ + return ::math::asin(mxp_in); +} + +export float mx_acos_float( + float mxp_in = float(0.0) +) + [[ + anno::description("Node Group: math") + ]] +{ + return ::math::acos(mxp_in); +} + +export float mx_atan2_float( + float mxp_in1 = float(1.0), + float mxp_in2 = float(0.0) +) + [[ + anno::description("Node Group: math") + ]] +{ + return ::math::atan2(mxp_in1, mxp_in2); +} + +export float2 mx_sin_vector2( + float2 mxp_in = float2(0.0, 0.0) +) + [[ + anno::description("Node Group: math") + ]] +{ + return ::math::sin(mxp_in); +} + +export float2 mx_cos_vector2( + float2 mxp_in = float2(0.0, 0.0) +) + [[ + anno::description("Node Group: math") + ]] +{ + return ::math::cos(mxp_in); +} + +export float2 mx_tan_vector2( + float2 mxp_in = float2(0.0, 0.0) +) + [[ + anno::description("Node Group: math") + ]] +{ + return ::math::tan(mxp_in); +} + +export float2 mx_asin_vector2( + float2 mxp_in = float2(0.0, 0.0) +) + [[ + anno::description("Node Group: math") + ]] +{ + return ::math::asin(mxp_in); +} + +export float2 mx_acos_vector2( + float2 mxp_in = float2(0.0, 0.0) +) + [[ + anno::description("Node Group: math") + ]] +{ + return ::math::acos(mxp_in); +} + +export float2 mx_atan2_vector2( + float2 mxp_in1 = float2(1.0, 1.0), + float2 mxp_in2 = float2(0.0, 0.0) +) + [[ + anno::description("Node Group: math") + ]] +{ + return ::math::atan2(mxp_in1, mxp_in2); +} + +export float3 mx_sin_vector3( + float3 mxp_in = float3(0.0, 0.0, 0.0) +) + [[ + anno::description("Node Group: math") + ]] +{ + return ::math::sin(mxp_in); +} + +export float3 mx_cos_vector3( + float3 mxp_in = float3(0.0, 0.0, 0.0) +) + [[ + anno::description("Node Group: math") + ]] +{ + return ::math::cos(mxp_in); +} + +export float3 mx_tan_vector3( + float3 mxp_in = float3(0.0, 0.0, 0.0) +) + [[ + anno::description("Node Group: math") + ]] +{ + return ::math::tan(mxp_in); +} + +export float3 mx_asin_vector3( + float3 mxp_in = float3(0.0, 0.0, 0.0) +) + [[ + anno::description("Node Group: math") + ]] +{ + return ::math::asin(mxp_in); +} + +export float3 mx_acos_vector3( + float3 mxp_in = float3(0.0, 0.0, 0.0) +) + [[ + anno::description("Node Group: math") + ]] +{ + return ::math::acos(mxp_in); +} + +export float3 mx_atan2_vector3( + float3 mxp_in1 = float3(1.0, 1.0, 1.0), + float3 mxp_in2 = float3(0.0, 0.0, 0.0) +) + [[ + anno::description("Node Group: math") + ]] +{ + return ::math::atan2(mxp_in1, mxp_in2); +} + +export float4 mx_sin_vector4( + float4 mxp_in = float4(0.0, 0.0, 0.0, 0.0) +) + [[ + anno::description("Node Group: math") + ]] +{ + return ::math::sin(mxp_in); +} + +export float4 mx_cos_vector4( + float4 mxp_in = float4(0.0, 0.0, 0.0, 0.0) +) + [[ + anno::description("Node Group: math") + ]] +{ + return ::math::cos(mxp_in); +} + +export float4 mx_tan_vector4( + float4 mxp_in = float4(0.0, 0.0, 0.0, 0.0) +) + [[ + anno::description("Node Group: math") + ]] +{ + return ::math::tan(mxp_in); +} + +export float4 mx_asin_vector4( + float4 mxp_in = float4(0.0, 0.0, 0.0, 0.0) +) + [[ + anno::description("Node Group: math") + ]] +{ + return ::math::asin(mxp_in); +} + +export float4 mx_acos_vector4( + float4 mxp_in = float4(0.0, 0.0, 0.0, 0.0) +) + [[ + anno::description("Node Group: math") + ]] +{ + return ::math::acos(mxp_in); +} + +export float4 mx_atan2_vector4( + float4 mxp_in1 = float4(1.0, 1.0, 1.0, 1.0), + float4 mxp_in2 = float4(0.0, 0.0, 0.0, 0.0) +) + [[ + anno::description("Node Group: math") + ]] +{ + return ::math::atan2(mxp_in1, mxp_in2); +} + +export float mx_sqrt_float( + float mxp_in = float(0.0) +) + [[ + anno::description("Node Group: math") + ]] +{ + return ::math::sqrt(mxp_in); +} + +export float mx_ln_float( + float mxp_in = float(1.0) +) + [[ + anno::description("Node Group: math") + ]] +{ + return ::math::log(mxp_in); +} + +export float mx_exp_float( + float mxp_in = float(0.0) +) + [[ + anno::description("Node Group: math") + ]] +{ + return ::math::exp(mxp_in); +} + +export float2 mx_sqrt_vector2( + float2 mxp_in = float2(0.0, 0.0) +) + [[ + anno::description("Node Group: math") + ]] +{ + return ::math::sqrt(mxp_in); +} + +export float2 mx_ln_vector2( + float2 mxp_in = float2(1.0, 1.0) +) + [[ + anno::description("Node Group: math") + ]] +{ + return ::math::log(mxp_in); +} + +export float2 mx_exp_vector2( + float2 mxp_in = float2(0.0, 0.0) +) + [[ + anno::description("Node Group: math") + ]] +{ + return ::math::exp(mxp_in); +} + +export float3 mx_sqrt_vector3( + float3 mxp_in = float3(0.0, 0.0, 0.0) +) + [[ + anno::description("Node Group: math") + ]] +{ + return ::math::sqrt(mxp_in); +} + +export float3 mx_ln_vector3( + float3 mxp_in = float3(1.0, 1.0, 1.0) +) + [[ + anno::description("Node Group: math") + ]] +{ + return ::math::log(mxp_in); +} + +export float3 mx_exp_vector3( + float3 mxp_in = float3(0.0, 0.0, 0.0) +) + [[ + anno::description("Node Group: math") + ]] +{ + return ::math::exp(mxp_in); +} + +export float4 mx_sqrt_vector4( + float4 mxp_in = float4(0.0, 0.0, 0.0, 0.0) +) + [[ + anno::description("Node Group: math") + ]] +{ + return ::math::sqrt(mxp_in); +} + +export float4 mx_ln_vector4( + float4 mxp_in = float4(1.0, 1.0, 1.0, 1.0) +) + [[ + anno::description("Node Group: math") + ]] +{ + return ::math::log(mxp_in); +} + +export float4 mx_exp_vector4( + float4 mxp_in = float4(0.0, 0.0, 0.0, 0.0) +) + [[ + anno::description("Node Group: math") + ]] +{ + return ::math::exp(mxp_in); +} + +export color mx_sign_color3( + color mxp_in = color(0.0, 0.0, 0.0) +) + [[ + anno::description("Node Group: math") + ]] +{ + return color(::math::sign(float3(mxp_in))); +} + +export core::color4 mx_sign_color4( + core::color4 mxp_in = core::mk_color4(0.0, 0.0, 0.0, 0.0) +) + [[ + anno::description("Node Group: math") + ]] +{ + return core::mk_color4(::math::sign(core::mk_float4(mxp_in))); +} + +export core::color4 mx_clamp_color4( + core::color4 mxp_in = core::mk_color4(0.0, 0.0, 0.0, 0.0), + core::color4 mxp_low = core::mk_color4(0.0, 0.0, 0.0, 0.0), + core::color4 mxp_high = core::mk_color4(1.0, 1.0, 1.0, 1.0) +) + [[ + anno::description("Node Group: math") + ]] +{ + return core::mk_color4(::math::clamp(core::mk_float4(mxp_in), core::mk_float4(mxp_low), core::mk_float4(mxp_high))); +} + +export core::color4 mx_clamp_color4FA( + core::color4 mxp_in = core::mk_color4(0.0, 0.0, 0.0, 0.0), + float mxp_low = float(0.0), + float mxp_high = float(1.0) +) + [[ + anno::description("Node Group: math") + ]] +{ + return core::mk_color4(::math::clamp(core::mk_float4(mxp_in), float4(mxp_low), float4(mxp_high))); +} + +export core::color4 mx_min_color4( + core::color4 mxp_in1 = core::mk_color4(0.0, 0.0, 0.0, 0.0), + core::color4 mxp_in2 = core::mk_color4(0.0, 0.0, 0.0, 0.0) +) + [[ + anno::description("Node Group: math") + ]] +{ + return core::mk_color4(::math::min(core::mk_float4(mxp_in1), core::mk_float4(mxp_in2))); +} + +export core::color4 mx_min_color4( + core::color4 mxp_in1 = core::mk_color4(0.0, 0.0, 0.0, 0.0), + float mxp_in2 = float(0.0) +) + [[ + anno::description("Node Group: math") + ]] +{ + return core::mk_color4(::math::min(core::mk_float4(mxp_in1), float4(mxp_in2))); +} + +export core::color4 mx_max_color4( + core::color4 mxp_in1 = core::mk_color4(0.0, 0.0, 0.0, 0.0), + core::color4 mxp_in2 = core::mk_color4(0.0, 0.0, 0.0, 0.0) +) + [[ + anno::description("Node Group: math") + ]] +{ + return core::mk_color4(::math::max(core::mk_float4(mxp_in1), core::mk_float4(mxp_in2))); +} + +export core::color4 mx_max_color4( + core::color4 mxp_in1 = core::mk_color4(0.0, 0.0, 0.0, 0.0), + float mxp_in2 = float(0.0) +) + [[ + anno::description("Node Group: math") + ]] +{ + return core::mk_color4(::math::max(core::mk_float4(mxp_in1), float4(mxp_in2))); +} + +export float3 mx_transformpoint_vector3( + float3 mxp_in = float3(0.0, 0.0, 0.0), + uniform string mxp_fromspace = "object", + uniform string mxp_tospace = "world" +) + [[ + anno::description("Node Group: math") + ]] +{ + state::coordinate_space fromSpace = ::core::mx_map_space(mxp_fromspace); + state::coordinate_space toSpace = ::core::mx_map_space(mxp_tospace); + return state::transform_point(fromSpace, toSpace, mxp_in); +} + +export float3 mx_transformvector_vector3( + float3 mxp_in = float3(0.0, 0.0, 0.0), + uniform string mxp_fromspace = "object", + uniform string mxp_tospace = "world" +) + [[ + anno::description("Node Group: math") + ]] +{ + state::coordinate_space fromSpace = ::core::mx_map_space(mxp_fromspace); + state::coordinate_space toSpace = ::core::mx_map_space(mxp_tospace); + return state::transform_vector(fromSpace, toSpace, mxp_in); +} + +export float3 mx_transformnormal_vector3( + float3 mxp_in = float3(0.0, 0.0, 1.0), + uniform string mxp_fromspace = "object", + uniform string mxp_tospace = "world" +) + [[ + anno::description("Node Group: math") + ]] +{ + state::coordinate_space fromSpace = ::core::mx_map_space(mxp_fromspace); + state::coordinate_space toSpace = ::core::mx_map_space(mxp_tospace); + return state::transform_normal(fromSpace, toSpace, mxp_in); +} + +export float2 mx_transformmatrix_vector2M3( + float2 mxp_in = float2(0.0, 0.0), + float3x3 mxp_mat = float3x3(1.0,0.0,0.0, 0.0,1.0,0.0, 0.0,0.0,1.0) +) + [[ + anno::description("Node Group: math") + ]] +{ + float3 returnValue = mxp_mat * float3(mxp_in.x, mxp_in.y, 1.0); + return float2(returnValue.x, returnValue.y); +} + +export float3 mx_transformmatrix_vector3( + float3 mxp_in = float3(0.0, 0.0, 0.0), + float3x3 mxp_mat = float3x3(1.0,0.0,0.0, 0.0,1.0,0.0, 0.0,0.0,1.0) +) + [[ + anno::description("Node Group: math") + ]] +{ + return mxp_mat * mxp_in; +} + +export float3 mx_transformmatrix_vector3M4( + float3 mxp_in = float3(0.0, 0.0, 0.0), + float4x4 mxp_mat = float4x4(1.0,0.0,0.0,0.0, 0.0,1.0,0.0,0.0, 0.0,0.0,1.0,0.0, 0.0,0.0,0.0,1.0) +) + [[ + anno::description("Node Group: math") + ]] +{ + float4 returnValue = mxp_mat * float4(mxp_in.x, mxp_in.y, mxp_in.z, 1.0); + return float3(returnValue.x, returnValue.y, returnValue.z); +} + +export float4 mx_transformmatrix_vector4( + float4 mxp_in = float4(0.0, 0.0, 0.0, 0.0), + float4x4 mxp_mat = float4x4(1.0,0.0,0.0,0.0, 0.0,1.0,0.0,0.0, 0.0,0.0,1.0,0.0, 0.0,0.0,0.0,1.0) +) + [[ + anno::description("Node Group: math") + ]] +{ + return mxp_mat * mxp_in; +} + +export float3 mx_normalmap_vector2( + float3 mxp_in = float3(0.5, 0.5, 1.0), + uniform string mxp_space = string("tangent") + [[ + anno::description("Enumeration {tangent, object}.") + ]], + float2 mxp_scale = float2(1.0, 1.0), + float3 mxp_normal = float3(::state::transform_normal(::state::coordinate_internal,::state::coordinate_world,::state::normal())), + float3 mxp_tangent = float3(state::transform_vector(::state::coordinate_internal,::state::coordinate_world,::state::texture_tangent_u(0))) +) + [[ + anno::description("Node Group: math") + ]] +{ + if (mxp_space == "tangent") + { + float3 v = mxp_in * 2.0 - 1.0; + float3 binormal = ::math::normalize(::math::cross(mxp_normal, mxp_tangent)); + return ::math::normalize(mxp_tangent * v.x * mxp_scale.x + binormal * v.y * mxp_scale.y + mxp_normal * v.z); + } + else + { + float3 n = mxp_in * 2.0 - 1.0; + return ::math::normalize(n); + } +} + +export float3 mx_normalmap_float( + float3 mxp_in = float3(0.5, 0.5, 1.0), + uniform string mxp_space = string("tangent") + [[ + anno::description("Enumeration {tangent, object}.") + ]], + float mxp_scale = float(1.0), + float3 mxp_normal = float3(::state::transform_normal(::state::coordinate_internal,::state::coordinate_world,::state::normal())), + float3 mxp_tangent = float3(state::transform_vector(::state::coordinate_internal,::state::coordinate_world,::state::texture_tangent_u(0))) +) + [[ + anno::description("Node Group: math") + ]] +{ + return mx_normalmap_vector2(mxp_in, mxp_space, float2(mxp_scale, mxp_scale), mxp_normal, mxp_tangent); +} + +export float3x3 mx_transpose_matrix33( + float3x3 mxp_in = float3x3(1.0,0.0,0.0, 0.0,1.0,0.0, 0.0,0.0,1.0) +) + [[ + anno::description("Node Group: math") + ]] +{ + return ::math::transpose(mxp_in); +} + +export float4x4 mx_transpose_matrix44( + float4x4 mxp_in = float4x4(1.0,0.0,0.0,0.0, 0.0,1.0,0.0,0.0, 0.0,0.0,1.0,0.0, 0.0,0.0,0.0,1.0) +) + [[ + anno::description("Node Group: math") + ]] +{ + return ::math::transpose(mxp_in); +} + +export float mx_determinant_matrix33(float3x3 mxp_in) +[[ + anno::description("Node Group: math") +]] +{ + return mxp_in[0][0] * (mxp_in[2][2]*mxp_in[1][1] - mxp_in[1][2]*mxp_in[2][1]) + + mxp_in[0][1] * (mxp_in[1][2]*mxp_in[2][0] - mxp_in[2][2]*mxp_in[1][0]) + + mxp_in[0][2] * (mxp_in[2][1]*mxp_in[1][0] - mxp_in[1][1]*mxp_in[2][0]); +} + +export float mx_determinant_matrix44(float4x4 mxp_in) +[[ + anno::description("Node Group: math") +]] +{ + float + b00 = mxp_in[0][0] * mxp_in[1][1] - mxp_in[0][1] * mxp_in[1][0], + b01 = mxp_in[0][0] * mxp_in[1][2] - mxp_in[0][2] * mxp_in[1][0], + b02 = mxp_in[0][0] * mxp_in[1][3] - mxp_in[0][3] * mxp_in[1][0], + b03 = mxp_in[0][1] * mxp_in[1][2] - mxp_in[0][2] * mxp_in[1][1], + b04 = mxp_in[0][1] * mxp_in[1][3] - mxp_in[0][3] * mxp_in[1][1], + b05 = mxp_in[0][2] * mxp_in[1][3] - mxp_in[0][3] * mxp_in[1][2], + b06 = mxp_in[2][0] * mxp_in[3][1] - mxp_in[2][1] * mxp_in[3][0], + b07 = mxp_in[2][0] * mxp_in[3][2] - mxp_in[2][2] * mxp_in[3][0], + b08 = mxp_in[2][0] * mxp_in[3][3] - mxp_in[2][3] * mxp_in[3][0], + b09 = mxp_in[2][1] * mxp_in[3][2] - mxp_in[2][2] * mxp_in[3][1], + b10 = mxp_in[2][1] * mxp_in[3][3] - mxp_in[2][3] * mxp_in[3][1], + b11 = mxp_in[2][2] * mxp_in[3][3] - mxp_in[2][3] * mxp_in[3][2]; + return b00 * b11 - b01 * b10 + b02 * b09 + b03 * b08 - b04 * b07 + b05 * b06; +} + +export float3x3 mx_invertmatrix_matrix33( + float3x3 mxp_in = float3x3(1.0,0.0,0.0, 0.0,1.0,0.0, 0.0,0.0,1.0) +) + [[ + anno::description("Node Group: math") + ]] +{ + // Not implemented: mx_invertmatrix_matrix33 + float3x3 defaultValue = mxp_in; + return defaultValue; +} + +export float4x4 mx_invertmatrix_matrix44( + float4x4 mxp_in = float4x4(1.0,0.0,0.0,0.0, 0.0,1.0,0.0,0.0, 0.0,0.0,1.0,0.0, 0.0,0.0,0.0,1.0) +) + [[ + anno::description("Node Group: math") + ]] +{ + // Not implemented: mx_invertmatrix_matrix44 + float4x4 defaultValue = mxp_in; + return defaultValue; +} + +export float2 mx_rotate2d_vector2( + float2 mxp_in = float2(0.0, 0.0), + float mxp_amount = float(0.0) + [[ + anno::description("Unit Type:angle. Unit:degrees.") + ]] +) +[[ + anno::description("Node Group: math") +]] +{ + float angleRadians = math::radians(mxp_amount); + float sinAngle = math::sin(angleRadians); + float cosAngle = math::cos(angleRadians); + return float2(cosAngle*mxp_in.x + sinAngle*mxp_in.y, -sinAngle*mxp_in.x + cosAngle*mxp_in.y); +} + +float4x4 mx_rotationMatrix(float3 mxp_axis, float mxp_amount) +{ + float sinAngle = math::sin(mxp_amount); + float cosAngle = math::cos(mxp_amount); + float oc = 1.0 - cosAngle; + + return float4x4( + oc * mxp_axis.x * mxp_axis.x + cosAngle, oc * mxp_axis.x * mxp_axis.y - mxp_axis.z * sinAngle, oc * mxp_axis.z * mxp_axis.x + mxp_axis.y * sinAngle, 0.0, + oc * mxp_axis.x * mxp_axis.y + mxp_axis.z * sinAngle, oc * mxp_axis.y * mxp_axis.y + cosAngle, oc * mxp_axis.y * mxp_axis.z - mxp_axis.x * sinAngle, 0.0, + oc * mxp_axis.z * mxp_axis.x - mxp_axis.y * sinAngle, oc * mxp_axis.y * mxp_axis.z + mxp_axis.x * sinAngle, oc * mxp_axis.z * mxp_axis.z + cosAngle, 0.0, + 0.0, 0.0, 0.0, 1.0); +} + +export float3 mx_rotate3d_vector3( + float3 mxp_in = float3(0.0, 0.0, 0.0), + float mxp_amount = float(0.0) + [[ + anno::description("Unit Type:angle. Unit:degrees.") + ]], + float3 mxp_axis = float3(0.0, 1.0, 0.0) +) + [[ + anno::description("Node Group: math") + ]] +{ + float angleRadians = math::radians(mxp_amount); + float4x4 m = mx_rotationMatrix(mxp_axis, angleRadians); + float4 v = m * float4(mxp_in.x, mxp_in.y, mxp_in.z, 1.0); + return float3(v.x, v.y, v.z); +} + +// Nodedef: ND_place2d_vector2 is represented by a nodegraph: NG_place2d_vector2 + +export float mx_remap_float( + float mxp_in = float(0.0), + float mxp_inlow = float(0.0), + float mxp_inhigh = float(1.0), + float mxp_outlow = float(0.0), + float mxp_outhigh = float(1.0) +) + [[ + anno::description("Node Group: adjustment") + ]] +{ + return mxp_outlow + (mxp_in - mxp_inlow) * (mxp_outhigh - mxp_outlow) / (mxp_inhigh - mxp_inlow); +} + +export color mx_remap_color3( + color mxp_in = color(0.0, 0.0, 0.0), + color mxp_inlow = color(0.0, 0.0, 0.0), + color mxp_inhigh = color(1.0, 1.0, 1.0), + color mxp_outlow = color(0.0, 0.0, 0.0), + color mxp_outhigh = color(1.0, 1.0, 1.0) +) + [[ + anno::description("Node Group: adjustment") + ]] +{ + return mxp_outlow + (mxp_in - mxp_inlow) * (mxp_outhigh - mxp_outlow) / (mxp_inhigh - mxp_inlow); +} + +export core::color4 mx_remap_color4( + core::color4 mxp_in = core::mk_color4(0.0, 0.0, 0.0, 0.0), + core::color4 mxp_inlow = core::mk_color4(0.0, 0.0, 0.0, 0.0), + core::color4 mxp_inhigh = core::mk_color4(1.0, 1.0, 1.0, 1.0), + core::color4 mxp_outlow = core::mk_color4(0.0, 0.0, 0.0, 0.0), + core::color4 mxp_outhigh = core::mk_color4(1.0, 1.0, 1.0, 1.0) +) + [[ + anno::description("Node Group: adjustment") + ]] +{ + core::color4 val = mxp_outlow; + core::color4 val2 = core::mx_add(val, core::mx_subtract(mxp_in, mxp_inlow)); + core::color4 val3 = core::mx_multiply(val2, core::mx_subtract(mxp_outhigh, mxp_outlow)); + return core::mx_divide(val3, core::mx_subtract(mxp_inhigh, mxp_inlow)); +} + +export float2 mx_remap_vector2( + float2 mxp_in = float2(0.0, 0.0), + float2 mxp_inlow = float2(0.0, 0.0), + float2 mxp_inhigh = float2(1.0, 1.0), + float2 mxp_outlow = float2(0.0, 0.0), + float2 mxp_outhigh = float2(1.0, 1.0) +) + [[ + anno::description("Node Group: adjustment") + ]] +{ + return mxp_outlow + (mxp_in - mxp_inlow) * (mxp_outhigh - mxp_outlow) / (mxp_inhigh - mxp_inlow); +} + +export float3 mx_remap_vector3( + float3 mxp_in = float3(0.0, 0.0, 0.0), + float3 mxp_inlow = float3(0.0, 0.0, 0.0), + float3 mxp_inhigh = float3(1.0, 1.0, 1.0), + float3 mxp_outlow = float3(0.0, 0.0, 0.0), + float3 mxp_outhigh = float3(1.0, 1.0, 1.0) +) + [[ + anno::description("Node Group: adjustment") + ]] +{ + return mxp_outlow + (mxp_in - mxp_inlow) * (mxp_outhigh - mxp_outlow) / (mxp_inhigh - mxp_inlow); +} + +export float4 mx_remap_vector4( + float4 mxp_in = float4(0.0, 0.0, 0.0, 0.0), + float4 mxp_inlow = float4(0.0, 0.0, 0.0, 0.0), + float4 mxp_inhigh = float4(1.0, 1.0, 1.0, 1.0), + float4 mxp_outlow = float4(0.0, 0.0, 0.0, 0.0), + float4 mxp_outhigh = float4(1.0, 1.0, 1.0, 1.0) +) + [[ + anno::description("Node Group: adjustment") + ]] +{ + return mxp_outlow + (mxp_in - mxp_inlow) * (mxp_outhigh - mxp_outlow) / (mxp_inhigh - mxp_inlow); +} + +export color mx_remap_color3FA( + color mxp_in = color(0.0, 0.0, 0.0), + float mxp_inlow = float(0.0), + float mxp_inhigh = float(1.0), + float mxp_outlow = float(0.0), + float mxp_outhigh = float(1.0) +) + [[ + anno::description("Node Group: adjustment") + ]] +{ + return mxp_outlow + (mxp_in - mxp_inlow) * (mxp_outhigh - mxp_outlow) / (mxp_inhigh - mxp_inlow); +} + +export core::color4 mx_remap_color4FA( + core::color4 mxp_in = core::mk_color4(0.0, 0.0, 0.0, 0.0), + float mxp_inlow = float(0.0), + float mxp_inhigh = float(1.0), + float mxp_outlow = float(0.0), + float mxp_outhigh = float(1.0) +) + [[ + anno::description("Node Group: adjustment") + ]] +{ + core::color4 val = core::mk_color4(mxp_outlow); + core::color4 val2 = core::mx_add(val, core::mx_subtract(mxp_in, core::mk_color4(mxp_inlow))); + core::color4 val3 = core::mx_multiply(val2, core::mx_subtract(core::mk_color4(mxp_outhigh), core::mk_color4(mxp_outlow))); + return core::mx_divide(val3, core::mx_subtract(core::mk_color4(mxp_inhigh), core::mk_color4(mxp_inlow))); +} + +export float2 mx_remap_vector2FA( + float2 mxp_in = float2(0.0, 0.0), + float mxp_inlow = float(0.0), + float mxp_inhigh = float(1.0), + float mxp_outlow = float(0.0), + float mxp_outhigh = float(1.0) +) + [[ + anno::description("Node Group: adjustment") + ]] +{ + return mxp_outlow + (mxp_in - mxp_inlow) * (mxp_outhigh - mxp_outlow) / (mxp_inhigh - mxp_inlow); +} + +export float3 mx_remap_vector3FA( + float3 mxp_in = float3(0.0, 0.0, 0.0), + float mxp_inlow = float(0.0), + float mxp_inhigh = float(1.0), + float mxp_outlow = float(0.0), + float mxp_outhigh = float(1.0) +) + [[ + anno::description("Node Group: adjustment") + ]] +{ + return mxp_outlow + (mxp_in - mxp_inlow) * (mxp_outhigh - mxp_outlow) / (mxp_inhigh - mxp_inlow); +} + +export float4 mx_remap_vector4FA( + float4 mxp_in = float4(0.0, 0.0, 0.0, 0.0), + float mxp_inlow = float(0.0), + float mxp_inhigh = float(1.0), + float mxp_outlow = float(0.0), + float mxp_outhigh = float(1.0) +) + [[ + anno::description("Node Group: adjustment") + ]] +{ + return mxp_outlow + (mxp_in - mxp_inlow) * (mxp_outhigh - mxp_outlow) / (mxp_inhigh - mxp_inlow); +} + +export float mx_smoothstep_float( + float mxp_in = float(0.0), + float mxp_low = float(0.0), + float mxp_high = float(1.0) +) + [[ + anno::description("Node Group: adjustment") + ]] +{ + return ::math::smoothstep(float(mxp_low), float(mxp_high), float(mxp_in)); +} + +export color mx_smoothstep_color3( + color mxp_in = color(0.0, 0.0, 0.0), + color mxp_low = color(0.0, 0.0, 0.0), + color mxp_high = color(1.0, 1.0, 1.0) +) + [[ + anno::description("Node Group: adjustment") + ]] +{ + return color(::math::smoothstep(float3(mxp_low), float3(mxp_high), float3(mxp_in))); +} + +export core::color4 mx_smoothstep_color4( + core::color4 mxp_in = core::mk_color4(0.0, 0.0, 0.0, 0.0), + core::color4 mxp_low = core::mk_color4(0.0, 0.0, 0.0, 0.0), + core::color4 mxp_high = core::mk_color4(1.0, 1.0, 1.0, 1.0) +) + [[ + anno::description("Node Group: adjustment") + ]] +{ + return core::mk_color4(::math::smoothstep(core::mk_float4(mxp_low), core::mk_float4(mxp_high), core::mk_float4(mxp_in))); +} + +export float2 mx_smoothstep_vector2( + float2 mxp_in = float2(0.0, 0.0), + float2 mxp_low = float2(0.0, 0.0), + float2 mxp_high = float2(1.0, 1.0) +) + [[ + anno::description("Node Group: adjustment") + ]] +{ + return ::math::smoothstep(float2(mxp_low), float2(mxp_high), float2(mxp_in)); +} + +export float3 mx_smoothstep_vector3( + float3 mxp_in = float3(0.0, 0.0, 0.0), + float3 mxp_low = float3(0.0, 0.0, 0.0), + float3 mxp_high = float3(1.0, 1.0, 1.0) +) + [[ + anno::description("Node Group: adjustment") + ]] +{ + return ::math::smoothstep(float3(mxp_low), float3(mxp_high), float3(mxp_in)); +} + +export float4 mx_smoothstep_vector4( + float4 mxp_in = float4(0.0, 0.0, 0.0, 0.0), + float4 mxp_low = float4(0.0, 0.0, 0.0, 0.0), + float4 mxp_high = float4(1.0, 1.0, 1.0, 1.0) +) + [[ + anno::description("Node Group: adjustment") + ]] +{ + return ::math::smoothstep(float4(mxp_low), float4(mxp_high), float4(mxp_in)); +} + +export color mx_smoothstep_color3FA( + color mxp_in = color(0.0, 0.0, 0.0), + float mxp_low = float(0.0), + float mxp_high = float(1.0) +) + [[ + anno::description("Node Group: adjustment") + ]] +{ + return color(::math::smoothstep(float3(mxp_in), float3(mxp_low), float3(mxp_high))); +} + +export core::color4 mx_smoothstep_color4FA( + core::color4 mxp_in = core::mk_color4(0.0, 0.0, 0.0, 0.0), + float mxp_low = float(0.0), + float mxp_high = float(1.0) +) + [[ + anno::description("Node Group: adjustment") + ]] +{ + return core::mk_color4(::math::smoothstep(core::mk_float4(mxp_in), float4(mxp_low), float4(mxp_high))); +} + +export float2 mx_smoothstep_vector2FA( + float2 mxp_in = float2(0.0, 0.0), + float mxp_low = float(0.0), + float mxp_high = float(1.0) +) + [[ + anno::description("Node Group: adjustment") + ]] +{ + return ::math::smoothstep(float2(mxp_low), float2(mxp_high), float2(mxp_in)); +} + +export float3 mx_smoothstep_vector3FA( + float3 mxp_in = float3(0.0, 0.0, 0.0), + float mxp_low = float(0.0), + float mxp_high = float(1.0) +) + [[ + anno::description("Node Group: adjustment") + ]] +{ + return ::math::smoothstep(float3(mxp_low), float3(mxp_high), float3(mxp_in)); +} + +export float4 mx_smoothstep_vector4FA( + float4 mxp_in = float4(0.0, 0.0, 0.0, 0.0), + float mxp_low = float(0.0), + float mxp_high = float(1.0) +) + [[ + anno::description("Node Group: adjustment") + ]] +{ + return ::math::smoothstep(float4(mxp_low), float4(mxp_high), float4(mxp_in)); +} + +export float mx_curveadjust_float( + float mxp_in = float(0.0), + float2[] mxp_knots = float2[]() [[ anno::unused() ]] +) + [[ + anno::description("Node Group: adjustment") + ]] +{ + // Not implemented: mx_curveadjust_float + float defaultValue = mxp_in; + return defaultValue; +} + +export color mx_curveadjust_color3( + color mxp_in = color(0.0, 0.0, 0.0), + float2[] mxp_knots = float2[]() [[ anno::unused() ]] +) + [[ + anno::description("Node Group: adjustment") + ]] +{ + // Not implemented: mx_curveadjust_color3 + color defaultValue = mxp_in; + return defaultValue; +} + +export core::color4 mx_curveadjust_color4( + core::color4 mxp_in = core::mk_color4(0.0, 0.0, 0.0, 0.0), + float2[] mxp_knots = float2[]() [[ anno::unused() ]] +) + [[ + anno::description("Node Group: adjustment") + ]] +{ + // Not implemented: mx_curveadjust_color4 + core::color4 defaultValue = mxp_in; + return defaultValue; +} + +export float2 mx_curveadjust_vector2( + float2 mxp_in = float2(0.0, 0.0), + float2[] mxp_knots = float2[]() [[ anno::unused() ]] +) + [[ + anno::description("Node Group: adjustment") + ]] +{ + // Not implemented: mx_curveadjust_vector2 + float2 defaultValue = mxp_in; + return defaultValue; +} + +export float3 mx_curveadjust_vector3( + float3 mxp_in = float3(0.0, 0.0, 0.0), + float2[] mxp_knots = float2[]() [[ anno::unused() ]] +) + [[ + anno::description("Node Group: adjustment") + ]] +{ + // Not implemented: mx_curveadjust_vector3 + float3 defaultValue = mxp_in; + return defaultValue; +} + +export float4 mx_curveadjust_vector4( + float4 mxp_in = float4(0.0, 0.0, 0.0, 0.0), + float2[] mxp_knots = float2[]() [[ anno::unused() ]] +) + [[ + anno::description("Node Group: adjustment") + ]] +{ + // Not implemented: mx_curveadjust_vector4 + float4 defaultValue = mxp_in; + return defaultValue; +} + +export color mx_luminance_color3( + color mxp_in = color(0.0, 0.0, 0.0), + uniform color mxp_lumacoeffs = color(0.2722287, 0.6740818, 0.0536895) + [[ + anno::description("Enumeration {acescg, rec709, rec2020, rec2100}."), + anno::unused() + ]] +) + [[ + anno::description("Node Group: adjustment") + ]] +{ + return color(::math::luminance(mxp_in)); +} + +export core::color4 mx_luminance_color4( + core::color4 mxp_in = core::mk_color4(0.0, 0.0, 0.0, 0.0), + uniform color mxp_lumacoeffs = color(0.2722287, 0.6740818, 0.0536895) + [[ + anno::description("Enumeration {acescg, rec709, rec2020, rec2100}."), + anno::unused() + ]] +) + [[ + anno::description("Node Group: adjustment") + ]] +{ + color rgb = color(mxp_in.rgb); + core::color4 returnValue = core::mk_color4(::math::luminance(rgb)); + returnValue.a = mxp_in.a; + return returnValue; +} + +export color mx_rgbtohsv_color3( + color mxp_in = color(0.0, 0.0, 0.0) +) + [[ + anno::description("Node Group: adjustment") + ]] +{ + return color(::hsv::mx_rgbtohsv(float3(mxp_in))); +} + +export core::color4 mx_rgbtohsv_color4( + core::color4 mxp_in = core::mk_color4(0.0, 0.0, 0.0, 0.0) +) + [[ + anno::description("Node Group: adjustment") + ]] +{ + float3 rgb = hsv::mx_rgbtohsv(float3(mxp_in.rgb)); + return core::color4(color(rgb), mxp_in.a); +} + +export color mx_hsvtorgb_color3( + color mxp_in = color(0.0, 0.0, 0.0) +) + [[ + anno::description("Node Group: adjustment") + ]] +{ + return color(hsv::mx_hsvtorgb(float3(mxp_in))); +} + +export core::color4 mx_hsvtorgb_color4( + core::color4 mxp_in = core::mk_color4(0.0, 0.0, 0.0, 0.0) +) + [[ + anno::description("Node Group: adjustment") + ]] +{ + float3 rgb = hsv::mx_hsvtorgb(float3(mxp_in.rgb)); + return core::color4(color(rgb), mxp_in.a); +} + +export core::color4 mx_premult_color4( + core::color4 mxp_in = core::mk_color4(0.0, 0.0, 0.0, 1.0) +) + [[ + anno::description("Node Group: compositing") + ]] +{ + // Not implemented: mx_premult_color4 + core::color4 defaultValue = mxp_in; + return defaultValue; +} + +export core::color4 mx_unpremult_color4( + core::color4 mxp_in = core::mk_color4(0.0, 0.0, 0.0, 1.0) +) + [[ + anno::description("Node Group: compositing") + ]] +{ + // Not implemented: mx_unpremult_color4 + core::color4 defaultValue = mxp_in; + return defaultValue; +} + +export core::color4 mx_plus_color4( + core::color4 mxp_fg = core::mk_color4(0.0, 0.0, 0.0, 0.0), + core::color4 mxp_bg = core::mk_color4(0.0, 0.0, 0.0, 0.0), + float mxp_mix = float(1.0) +) + [[ + anno::description("Node Group: compositing") + ]] +{ + color rgb = (mxp_mix*(mxp_bg.rgb + mxp_fg.rgb)) + ((1.0-mxp_mix)*mxp_bg.rgb); + float a = (mxp_mix*(mxp_bg.a + mxp_fg.a )) + ((1.0-mxp_mix)*mxp_bg.a ); + return core::color4(rgb,a); +} + +export core::color4 mx_minus_color4( + core::color4 mxp_fg = core::mk_color4(0.0, 0.0, 0.0, 0.0), + core::color4 mxp_bg = core::mk_color4(0.0, 0.0, 0.0, 0.0), + float mxp_mix = float(1.0) +) + [[ + anno::description("Node Group: compositing") + ]] +{ + color rgb = (mxp_mix*(mxp_bg.rgb - mxp_fg.rgb)) + ((1.0-mxp_mix)*mxp_bg.rgb); + float a = (mxp_mix*(mxp_bg.a - mxp_fg.a )) + ((1.0-mxp_mix)*mxp_bg.a ); + return core::color4(rgb,a); +} + +export core::color4 mx_difference_color4( + core::color4 mxp_fg = core::mk_color4(0.0, 0.0, 0.0, 0.0), + core::color4 mxp_bg = core::mk_color4(0.0, 0.0, 0.0, 0.0), + float mxp_mix = float(1.0) +) + [[ + anno::description("Node Group: compositing") + ]] +{ + color rgb = (mxp_mix*math::abs(mxp_bg.rgb - mxp_fg.rgb)) + ((1.0-mxp_mix)*mxp_bg.rgb); + float a = (mxp_mix*math::abs(mxp_bg.a - mxp_fg.a )) + ((1.0-mxp_mix)*mxp_bg.a ); + return core::color4(rgb,a); +} + +export float mx_burn_float( + float mxp_fg = 0.0, + float mxp_bg = 0.0, + float mxp_mix = 1.0 +) + [[ + anno::description("Node Group: compositing") + ]] +{ + if (math::abs(mxp_fg) < core::FLOAT_EPS) + { + return 0.0; + } + return mxp_mix*(1.0 - ((1.0 - mxp_bg) / mxp_fg)) + ((1.0 - mxp_mix)*mxp_bg); +} + +export color mx_burn_color3( + color mxp_fg = color(0.0), + color mxp_bg = color(0.0), + float mxp_mix = 1.0 +) + [[ + anno::description("Node Group: compositing") + ]] +{ + float3 fg(mxp_fg); + float3 bg(mxp_bg); + return color( + mx_burn_float(fg.x, bg.x, mxp_mix), + mx_burn_float(fg.y, bg.y, mxp_mix), + mx_burn_float(fg.z, bg.z, mxp_mix) + ); +} + +export core::color4 mx_burn_color4( + core::color4 mxp_fg = core::mk_color4(0.0, 0.0, 0.0, 0.0), + core::color4 mxp_bg = core::mk_color4(0.0, 0.0, 0.0, 0.0), + float mxp_mix = 1.0 +) + [[ + anno::description("Node Group: compositing") + ]] +{ + return core::color4( + mx_burn_color3(mxp_fg.rgb, mxp_bg.rgb, mxp_mix), + mx_burn_float(mxp_fg.a, mxp_bg.a, mxp_mix) + ); +} + +export float mx_dodge_float( + float mxp_fg = float(0.0), + float mxp_bg = float(0.0), + float mxp_mix = 1.0 +) + [[ + anno::description("Node Group: compositing") + ]] +{ + if (math::abs(1.0 - mxp_fg) < core::FLOAT_EPS) + { + return 0.0; + } + return mxp_mix*(mxp_bg / (1.0 - mxp_fg)) + ((1.0-mxp_mix)*mxp_bg); +} + +export color mx_dodge_color3( + color mxp_fg = color(0.0), + color mxp_bg = color(0.0), + float mxp_mix = 1.0 +) + [[ + anno::description("Node Group: compositing") + ]] +{ + float3 fg(mxp_fg); + float3 bg(mxp_bg); + return color( + mx_dodge_float(fg.x, bg.x, mxp_mix), + mx_dodge_float(fg.y, bg.y, mxp_mix), + mx_dodge_float(fg.z, bg.z, mxp_mix) + ); +} + +export core::color4 mx_dodge_color4( + core::color4 mxp_fg = core::mk_color4(0.0, 0.0, 0.0, 0.0), + core::color4 mxp_bg = core::mk_color4(0.0, 0.0, 0.0, 0.0), + float mxp_mix = float(1.0) +) + [[ + anno::description("Node Group: compositing") + ]] +{ + return core::color4( + mx_dodge_color3(mxp_fg.rgb, mxp_bg.rgb, mxp_mix), + mx_dodge_float(mxp_fg.a, mxp_bg.a, mxp_mix) + ); +} + +export core::color4 mx_screen_color4( + core::color4 mxp_fg = core::mk_color4(0.0, 0.0, 0.0, 0.0), + core::color4 mxp_bg = core::mk_color4(0.0, 0.0, 0.0, 0.0), + float mxp_mix = float(1.0) +) + [[ + anno::description("Node Group: compositing") + ]] +{ + color rgb = (mxp_mix*((1.0 - (1.0 - mxp_fg.rgb) * (1 - mxp_bg.rgb)))) + ((1.0-mxp_mix)*mxp_bg.rgb); + float a = (mxp_mix*((1.0 - (1.0 - mxp_fg.a ) * (1 - mxp_bg.a )))) + ((1.0-mxp_mix)*mxp_bg.a ); + return core::color4(rgb,a); +} + +export core::color4 mx_disjointover_color4( + core::color4 mxp_fg = core::mk_color4(0.0, 0.0, 0.0, 0.0), + core::color4 mxp_bg = core::mk_color4(0.0, 0.0, 0.0, 0.0), + float mxp_mix = float(1.0) +) + [[ + anno::description("Node Group: compositing") + ]] +{ + core::color4 result; + float summedAlpha = mxp_fg.a + mxp_bg.a; + if (summedAlpha <= 1) + { + result.rgb = mxp_fg.rgb + mxp_bg.rgb; + } + else + { + if (math::abs(mxp_bg.a) < core::FLOAT_EPS) + { + result.rgb = color(0.0); + } + else + { + float x = (1 - mxp_fg.a) / mxp_bg.a; + result.rgb = mxp_fg.rgb + mxp_bg.rgb * x; + } + } + result.a = math::min(summedAlpha, 1.0); + result.rgb = result.rgb * mxp_mix + (1.0 - mxp_mix) * mxp_bg.rgb; + result.a = result.a * mxp_mix + (1.0 - mxp_mix) * mxp_bg.a; + return result; +} + +export core::color4 mx_in_color4( + core::color4 mxp_fg = core::mk_color4(0.0, 0.0, 0.0, 0.0), + core::color4 mxp_bg = core::mk_color4(0.0, 0.0, 0.0, 0.0), + float mxp_mix = float(1.0) +) + [[ + anno::description("Node Group: compositing") + ]] +{ + color rgb = mxp_fg.rgb*mxp_bg.a * mxp_mix + mxp_bg.rgb * (1.0-mxp_mix); + float a = mxp_fg.a *mxp_bg.a * mxp_mix + mxp_bg.a * (1.0-mxp_mix); + return core::color4(rgb,a); +} + +export core::color4 mx_mask_color4( + core::color4 mxp_fg = core::mk_color4(0.0, 0.0, 0.0, 0.0), + core::color4 mxp_bg = core::mk_color4(0.0, 0.0, 0.0, 0.0), + float mxp_mix = float(1.0) +) + [[ + anno::description("Node Group: compositing") + ]] +{ + color rgb = mxp_bg.rgb*mxp_fg.a * mxp_mix + mxp_bg.rgb * (1.0-mxp_mix); + float a = mxp_bg.a *mxp_fg.a * mxp_mix + mxp_bg.a * (1.0-mxp_mix); + return core::color4(rgb,a); +} + +export core::color4 mx_matte_color4( + core::color4 mxp_fg = core::mk_color4(0.0, 0.0, 0.0, 0.0), + core::color4 mxp_bg = core::mk_color4(0.0, 0.0, 0.0, 0.0), + float mxp_mix = 1.0 +) + [[ + anno::description("Node Group: compositing") + ]] +{ + color rgb = (mxp_fg.rgb*mxp_fg.a + mxp_bg.rgb*(1.0-mxp_fg.a)) * mxp_mix + mxp_bg.rgb * (1.0-mxp_mix); + float a = (mxp_fg.a + mxp_bg.a*(1.0-mxp_fg.a)) * mxp_mix + mxp_bg.a * (1.0-mxp_mix); + return core::color4(rgb, a); +} + +export core::color4 mx_out_color4( + core::color4 mxp_fg = core::mk_color4(0.0, 0.0, 0.0, 0.0), + core::color4 mxp_bg = core::mk_color4(0.0, 0.0, 0.0, 0.0), + float mxp_mix = float(1.0) +) + [[ + anno::description("Node Group: compositing") + ]] +{ + color rgb = (mxp_fg.rgb*(1.0 - mxp_bg.a) * mxp_mix) + (mxp_bg.rgb * (1.0-mxp_mix)); + float a = (mxp_fg.a *(1.0 - mxp_bg.a) * mxp_mix) + (mxp_bg.a * (1.0-mxp_mix)); + return core::color4(rgb,a); +} + +export core::color4 mx_over_color4( + core::color4 mxp_fg = core::mk_color4(0.0, 0.0, 0.0, 0.0), + core::color4 mxp_bg = core::mk_color4(0.0, 0.0, 0.0, 0.0), + float mxp_mix = float(1.0) +) + [[ + anno::description("Node Group: compositing") + ]] +{ + color rgb = (mxp_fg.rgb + (mxp_bg.rgb*(1.0-mxp_fg.a))) * mxp_mix + mxp_bg.rgb * (1.0-mxp_mix); + float a = (mxp_fg.a + (mxp_bg.a *(1.0-mxp_fg.a))) * mxp_mix + mxp_bg.a * (1.0-mxp_mix); + return core::color4(rgb,a); +} + +export core::color4 mx_mix_color4( + core::color4 mxp_fg = core::mk_color4(0.0, 0.0, 0.0, 0.0), + core::color4 mxp_bg = core::mk_color4(0.0, 0.0, 0.0, 0.0), + float mxp_mix = float(0.0) +) + [[ + anno::description("Node Group: compositing") + ]] +{ + return core::mk_color4(::math::lerp(core::mk_float4(mxp_bg), core::mk_float4(mxp_fg), float4(mxp_mix))); +} + +export core::color4 mx_mix_color4_color4( + core::color4 mxp_fg = core::mk_color4(0.0, 0.0, 0.0, 0.0), + core::color4 mxp_bg = core::mk_color4(0.0, 0.0, 0.0, 0.0), + core::color4 mxp_mix = core::mk_color4(0.0, 0.0, 0.0, 0.0) +) + [[ + anno::description("Node Group: compositing") + ]] +{ + return core::mk_color4(::math::lerp(core::mk_float4(mxp_bg), core::mk_float4(mxp_fg), core::mk_float4(mxp_mix))); +} + +// mix all parts of the material, bsdf, edf, and vdf, geometry +export material mx_mix_surfaceshader( + material mxp_fg = material() [[ anno::usage( "materialx:surfaceshader") ]], + material mxp_bg = material() [[ anno::usage( "materialx:surfaceshader") ]], + float mxp_mix = 0.0 +) [[ + anno::description("Node Group: compositing"), + anno::usage( "materialx:surfaceshader") +]] += material( + surface: material_surface( + scattering: df::weighted_layer( + weight: mxp_mix, + layer: mxp_fg.surface.scattering, + base: mxp_bg.surface.scattering + ), + emission: material_emission( + emission: df::clamped_mix( + df::edf_component[]( + df::edf_component( mxp_mix, mxp_fg.surface.emission.emission), + df::edf_component( 1.0 - mxp_mix, mxp_bg.surface.emission.emission)) + ), + intensity: mxp_mix * mxp_fg.surface.emission.intensity + + (1.0 - mxp_mix) * mxp_bg.surface.emission.intensity + ) + ), + + // we need to carry volume properties along for SSS + ior: mxp_fg.ior, // NOTE: IOR is uniform, cannot mix here + volume: material_volume( + scattering: df::clamped_mix( + df::vdf_component[]( + df::vdf_component( mxp_mix, mxp_fg.volume.scattering), + df::vdf_component( 1.0 - mxp_mix, mxp_bg.volume.scattering)) + ), + absorption_coefficient: mxp_mix * mxp_fg.volume.absorption_coefficient + + (1.0 - mxp_mix) * mxp_bg.volume.absorption_coefficient, + scattering_coefficient: mxp_mix * mxp_fg.volume.scattering_coefficient + + (1.0 - mxp_mix) * mxp_bg.volume.scattering_coefficient + ), + geometry: material_geometry( + displacement: mxp_mix * mxp_fg.geometry.displacement + + (1.0 - mxp_mix) * mxp_bg.geometry.displacement, + cutout_opacity: mxp_mix * mxp_fg.geometry.cutout_opacity + + (1.0 - mxp_mix) * mxp_bg.geometry.cutout_opacity, + normal: mxp_mix * mxp_fg.geometry.normal + + (1.0 - mxp_mix) * mxp_bg.geometry.normal + ) +); + +export material mx_mix_volumeshader( + material mxp_fg = material() [[ anno::usage( "materialx:volumeshader") ]], + material mxp_bg = material() [[ anno::usage( "materialx:volumeshader") ]], + float mxp_mix = 0.0 +) [[ + anno::description("Node Group: compositing"), + anno::usage( "materialx:volumeshader") +]] += mx_mix_surfaceshader( + mxp_fg: mxp_fg, + mxp_bg: mxp_bg, + mxp_mix: mxp_mix); + +export material mx_mix_displacementshader( + material mxp_fg = material() [[ anno::usage( "materialx:displacementshader") ]], + material mxp_bg = material() [[ anno::usage( "materialx:displacementshader") ]], + float mxp_mix = 0.0 +) [[ + anno::description("Node Group: compositing"), + anno::usage( "materialx:displacementshader") +]] += mx_mix_surfaceshader( + mxp_fg: mxp_fg, + mxp_bg: mxp_bg, + mxp_mix: mxp_mix); + +export float mx_ifgreater_float( + float mxp_value1 = float(1.0), + float mxp_value2 = float(0.0), + float mxp_in1 = float(0.0), + float mxp_in2 = float(0.0) +) + [[ + anno::description("Node Group: conditional") + ]] +{ + if (mxp_value1 > mxp_value2) { return mxp_in1; } return mxp_in2; +} + +export color mx_ifgreater_color3( + float mxp_value1 = float(1.0), + float mxp_value2 = float(0.0), + color mxp_in1 = color(0.0, 0.0, 0.0), + color mxp_in2 = color(0.0, 0.0, 0.0) +) + [[ + anno::description("Node Group: conditional") + ]] +{ + if (mxp_value1 > mxp_value2) { return mxp_in1; } return mxp_in2; +} + +export core::color4 mx_ifgreater_color4( + float mxp_value1 = float(1.0), + float mxp_value2 = float(0.0), + core::color4 mxp_in1 = core::mk_color4(0.0, 0.0, 0.0, 0.0), + core::color4 mxp_in2 = core::mk_color4(0.0, 0.0, 0.0, 0.0) +) + [[ + anno::description("Node Group: conditional") + ]] +{ + if (mxp_value1 > mxp_value2) { return mxp_in1; } return mxp_in2; +} + +export float2 mx_ifgreater_vector2( + float mxp_value1 = float(1.0), + float mxp_value2 = float(0.0), + float2 mxp_in1 = float2(0.0, 0.0), + float2 mxp_in2 = float2(0.0, 0.0) +) + [[ + anno::description("Node Group: conditional") + ]] +{ + if (mxp_value1 > mxp_value2) { return mxp_in1; } return mxp_in2; +} + +export float3 mx_ifgreater_vector3( + float mxp_value1 = float(1.0), + float mxp_value2 = float(0.0), + float3 mxp_in1 = float3(0.0, 0.0, 0.0), + float3 mxp_in2 = float3(0.0, 0.0, 0.0) +) + [[ + anno::description("Node Group: conditional") + ]] +{ + if (mxp_value1 > mxp_value2) { return mxp_in1; } return mxp_in2; +} + +export float4 mx_ifgreater_vector4( + float mxp_value1 = float(1.0), + float mxp_value2 = float(0.0), + float4 mxp_in1 = float4(0.0, 0.0, 0.0, 0.0), + float4 mxp_in2 = float4(0.0, 0.0, 0.0, 0.0) +) + [[ + anno::description("Node Group: conditional") + ]] +{ + if (mxp_value1 > mxp_value2) { return mxp_in1; } return mxp_in2; +} + +export float mx_ifgreater_floatI( + int mxp_value1 = int(1), + int mxp_value2 = int(0), + float mxp_in1 = float(0.0), + float mxp_in2 = float(0.0) +) + [[ + anno::description("Node Group: conditional") + ]] +{ + if (mxp_value1 > mxp_value2) { return mxp_in1; } return mxp_in2; +} + +export color mx_ifgreater_color3I( + int mxp_value1 = int(1), + int mxp_value2 = int(0), + color mxp_in1 = color(0.0, 0.0, 0.0), + color mxp_in2 = color(0.0, 0.0, 0.0) +) + [[ + anno::description("Node Group: conditional") + ]] +{ + if (mxp_value1 > mxp_value2) { return mxp_in1; } return mxp_in2; +} + +export core::color4 mx_ifgreater_color4I( + int mxp_value1 = int(1), + int mxp_value2 = int(0), + core::color4 mxp_in1 = core::mk_color4(0.0, 0.0, 0.0, 0.0), + core::color4 mxp_in2 = core::mk_color4(0.0, 0.0, 0.0, 0.0) +) + [[ + anno::description("Node Group: conditional") + ]] +{ + if (mxp_value1 > mxp_value2) { return mxp_in1; } return mxp_in2; +} + +export float2 mx_ifgreater_vector2I( + int mxp_value1 = int(1), + int mxp_value2 = int(0), + float2 mxp_in1 = float2(0.0, 0.0), + float2 mxp_in2 = float2(0.0, 0.0) +) + [[ + anno::description("Node Group: conditional") + ]] +{ + if (mxp_value1 > mxp_value2) { return mxp_in1; } return mxp_in2; +} + +export float3 mx_ifgreater_vector3I( + int mxp_value1 = int(1), + int mxp_value2 = int(0), + float3 mxp_in1 = float3(0.0, 0.0, 0.0), + float3 mxp_in2 = float3(0.0, 0.0, 0.0) +) + [[ + anno::description("Node Group: conditional") + ]] +{ + if (mxp_value1 > mxp_value2) { return mxp_in1; } return mxp_in2; +} + +export float4 mx_ifgreater_vector4I( + int mxp_value1 = int(1), + int mxp_value2 = int(0), + float4 mxp_in1 = float4(0.0, 0.0, 0.0, 0.0), + float4 mxp_in2 = float4(0.0, 0.0, 0.0, 0.0) +) + [[ + anno::description("Node Group: conditional") + ]] +{ + if (mxp_value1 > mxp_value2) { return mxp_in1; } return mxp_in2; +} + +export float mx_ifgreatereq_float( + float mxp_value1 = float(1.0), + float mxp_value2 = float(0.0), + float mxp_in1 = float(0.0), + float mxp_in2 = float(0.0) +) + [[ + anno::description("Node Group: conditional") + ]] +{ + if (mxp_value1 >= mxp_value2) { return mxp_in1; } return mxp_in2; +} + +export color mx_ifgreatereq_color3( + float mxp_value1 = float(1.0), + float mxp_value2 = float(0.0), + color mxp_in1 = color(0.0, 0.0, 0.0), + color mxp_in2 = color(0.0, 0.0, 0.0) +) + [[ + anno::description("Node Group: conditional") + ]] +{ + if (mxp_value1 >= mxp_value2) { return mxp_in1; } return mxp_in2; +} + +export core::color4 mx_ifgreatereq_color4( + float mxp_value1 = float(1.0), + float mxp_value2 = float(0.0), + core::color4 mxp_in1 = core::mk_color4(0.0, 0.0, 0.0, 0.0), + core::color4 mxp_in2 = core::mk_color4(0.0, 0.0, 0.0, 0.0) +) + [[ + anno::description("Node Group: conditional") + ]] +{ + if (mxp_value1 >= mxp_value2) { return mxp_in1; } return mxp_in2; +} + +export float2 mx_ifgreatereq_vector2( + float mxp_value1 = float(1.0), + float mxp_value2 = float(0.0), + float2 mxp_in1 = float2(0.0, 0.0), + float2 mxp_in2 = float2(0.0, 0.0) +) + [[ + anno::description("Node Group: conditional") + ]] +{ + if (mxp_value1 >= mxp_value2) { return mxp_in1; } return mxp_in2; +} + +export float3 mx_ifgreatereq_vector3( + float mxp_value1 = float(1.0), + float mxp_value2 = float(0.0), + float3 mxp_in1 = float3(0.0, 0.0, 0.0), + float3 mxp_in2 = float3(0.0, 0.0, 0.0) +) + [[ + anno::description("Node Group: conditional") + ]] +{ + if (mxp_value1 >= mxp_value2) { return mxp_in1; } return mxp_in2; +} + +export float4 mx_ifgreatereq_vector4( + float mxp_value1 = float(1.0), + float mxp_value2 = float(0.0), + float4 mxp_in1 = float4(0.0, 0.0, 0.0, 0.0), + float4 mxp_in2 = float4(0.0, 0.0, 0.0, 0.0) +) + [[ + anno::description("Node Group: conditional") + ]] +{ + if (mxp_value1 >= mxp_value2) { return mxp_in1; } return mxp_in2; +} + +export float mx_ifgreatereq_floatI( + int mxp_value1 = int(1), + int mxp_value2 = int(0), + float mxp_in1 = float(0.0), + float mxp_in2 = float(0.0) +) + [[ + anno::description("Node Group: conditional") + ]] +{ + if (mxp_value1 >= mxp_value2) { return mxp_in1; } return mxp_in2; +} + +export color mx_ifgreatereq_color3I( + int mxp_value1 = int(1), + int mxp_value2 = int(0), + color mxp_in1 = color(0.0, 0.0, 0.0), + color mxp_in2 = color(0.0, 0.0, 0.0) +) + [[ + anno::description("Node Group: conditional") + ]] +{ + if (mxp_value1 >= mxp_value2) { return mxp_in1; } return mxp_in2; +} + +export core::color4 mx_ifgreatereq_color4I( + int mxp_value1 = int(1), + int mxp_value2 = int(0), + core::color4 mxp_in1 = core::mk_color4(0.0, 0.0, 0.0, 0.0), + core::color4 mxp_in2 = core::mk_color4(0.0, 0.0, 0.0, 0.0) +) + [[ + anno::description("Node Group: conditional") + ]] +{ + if (mxp_value1 >= mxp_value2) { return mxp_in1; } return mxp_in2; +} + +export float2 mx_ifgreatereq_vector2I( + int mxp_value1 = int(1), + int mxp_value2 = int(0), + float2 mxp_in1 = float2(0.0, 0.0), + float2 mxp_in2 = float2(0.0, 0.0) +) + [[ + anno::description("Node Group: conditional") + ]] +{ + if (mxp_value1 >= mxp_value2) { return mxp_in1; } return mxp_in2; +} + +export float3 mx_ifgreatereq_vector3I( + int mxp_value1 = int(1), + int mxp_value2 = int(0), + float3 mxp_in1 = float3(0.0, 0.0, 0.0), + float3 mxp_in2 = float3(0.0, 0.0, 0.0) +) + [[ + anno::description("Node Group: conditional") + ]] +{ + if (mxp_value1 >= mxp_value2) { return mxp_in1; } return mxp_in2; +} + +export float4 mx_ifgreatereq_vector4I( + int mxp_value1 = int(1), + int mxp_value2 = int(0), + float4 mxp_in1 = float4(0.0, 0.0, 0.0, 0.0), + float4 mxp_in2 = float4(0.0, 0.0, 0.0, 0.0) +) + [[ + anno::description("Node Group: conditional") + ]] +{ + if (mxp_value1 >= mxp_value2) { return mxp_in1; } return mxp_in2; +} + +export float mx_ifequal_float( + float mxp_value1 = float(0.0), + float mxp_value2 = float(0.0), + float mxp_in1 = float(0.0), + float mxp_in2 = float(0.0) +) + [[ + anno::description("Node Group: conditional") + ]] +{ + if (mxp_value1 == mxp_value2) { return mxp_in1; } return mxp_in2; +} + +export color mx_ifequal_color3( + float mxp_value1 = float(0.0), + float mxp_value2 = float(0.0), + color mxp_in1 = color(0.0, 0.0, 0.0), + color mxp_in2 = color(0.0, 0.0, 0.0) +) + [[ + anno::description("Node Group: conditional") + ]] +{ + if (mxp_value1 == mxp_value2) { return mxp_in1; } return mxp_in2; +} + +export core::color4 mx_ifequal_color4( + float mxp_value1 = float(0.0), + float mxp_value2 = float(0.0), + core::color4 mxp_in1 = core::mk_color4(0.0, 0.0, 0.0, 0.0), + core::color4 mxp_in2 = core::mk_color4(0.0, 0.0, 0.0, 0.0) +) + [[ + anno::description("Node Group: conditional") + ]] +{ + if (mxp_value1 == mxp_value2) { return mxp_in1; } return mxp_in2; +} + +export float2 mx_ifequal_vector2( + float mxp_value1 = float(0.0), + float mxp_value2 = float(0.0), + float2 mxp_in1 = float2(0.0, 0.0), + float2 mxp_in2 = float2(0.0, 0.0) +) + [[ + anno::description("Node Group: conditional") + ]] +{ + if (mxp_value1 == mxp_value2) { return mxp_in1; } return mxp_in2; +} + +export float3 mx_ifequal_vector3( + float mxp_value1 = float(0.0), + float mxp_value2 = float(0.0), + float3 mxp_in1 = float3(0.0, 0.0, 0.0), + float3 mxp_in2 = float3(0.0, 0.0, 0.0) +) + [[ + anno::description("Node Group: conditional") + ]] +{ + if (mxp_value1 == mxp_value2) { return mxp_in1; } return mxp_in2; +} + +export float4 mx_ifequal_vector4( + float mxp_value1 = float(0.0), + float mxp_value2 = float(0.0), + float4 mxp_in1 = float4(0.0, 0.0, 0.0, 0.0), + float4 mxp_in2 = float4(0.0, 0.0, 0.0, 0.0) +) + [[ + anno::description("Node Group: conditional") + ]] +{ + if (mxp_value1 == mxp_value2) { return mxp_in1; } return mxp_in2; +} + +export float mx_ifequal_floatI( + int mxp_value1 = int(0), + int mxp_value2 = int(0), + float mxp_in1 = float(0.0), + float mxp_in2 = float(0.0) +) + [[ + anno::description("Node Group: conditional") + ]] +{ + if (mxp_value1 == mxp_value2) { return mxp_in1; } return mxp_in2; +} + +export color mx_ifequal_color3I( + int mxp_value1 = int(0), + int mxp_value2 = int(0), + color mxp_in1 = color(0.0, 0.0, 0.0), + color mxp_in2 = color(0.0, 0.0, 0.0) +) + [[ + anno::description("Node Group: conditional") + ]] +{ + if (mxp_value1 == mxp_value2) { return mxp_in1; } return mxp_in2; +} + +export core::color4 mx_ifequal_color4I( + int mxp_value1 = int(0), + int mxp_value2 = int(0), + core::color4 mxp_in1 = core::mk_color4(0.0, 0.0, 0.0, 0.0), + core::color4 mxp_in2 = core::mk_color4(0.0, 0.0, 0.0, 0.0) +) + [[ + anno::description("Node Group: conditional") + ]] +{ + if (mxp_value1 == mxp_value2) { return mxp_in1; } return mxp_in2; +} + +export float2 mx_ifequal_vector2I( + int mxp_value1 = int(0), + int mxp_value2 = int(0), + float2 mxp_in1 = float2(0.0, 0.0), + float2 mxp_in2 = float2(0.0, 0.0) +) + [[ + anno::description("Node Group: conditional") + ]] +{ + if (mxp_value1 == mxp_value2) { return mxp_in1; } return mxp_in2; +} + +export float3 mx_ifequal_vector3I( + int mxp_value1 = int(0), + int mxp_value2 = int(0), + float3 mxp_in1 = float3(0.0, 0.0, 0.0), + float3 mxp_in2 = float3(0.0, 0.0, 0.0) +) + [[ + anno::description("Node Group: conditional") + ]] +{ + if (mxp_value1 == mxp_value2) { return mxp_in1; } return mxp_in2; +} + +export float4 mx_ifequal_vector4I( + int mxp_value1 = int(0), + int mxp_value2 = int(0), + float4 mxp_in1 = float4(0.0, 0.0, 0.0, 0.0), + float4 mxp_in2 = float4(0.0, 0.0, 0.0, 0.0) +) + [[ + anno::description("Node Group: conditional") + ]] +{ + if (mxp_value1 == mxp_value2) { return mxp_in1; } return mxp_in2; +} + +export float mx_ifequal_floatB( + bool mxp_value1 = bool(false), + bool mxp_value2 = bool(false), + float mxp_in1 = float(0.0), + float mxp_in2 = float(0.0) +) + [[ + anno::description("Node Group: conditional") + ]] +{ + if (mxp_value1 == mxp_value2) { return mxp_in1; } return mxp_in2; +} + +export color mx_ifequal_color3B( + bool mxp_value1 = bool(false), + bool mxp_value2 = bool(false), + color mxp_in1 = color(0.0, 0.0, 0.0), + color mxp_in2 = color(0.0, 0.0, 0.0) +) + [[ + anno::description("Node Group: conditional") + ]] +{ + if (mxp_value1 == mxp_value2) { return mxp_in1; } return mxp_in2; +} + +export core::color4 mx_ifequal_color4B( + bool mxp_value1 = bool(false), + bool mxp_value2 = bool(false), + core::color4 mxp_in1 = core::mk_color4(0.0, 0.0, 0.0, 0.0), + core::color4 mxp_in2 = core::mk_color4(0.0, 0.0, 0.0, 0.0) +) + [[ + anno::description("Node Group: conditional") + ]] +{ + if (mxp_value1 == mxp_value2) { return mxp_in1; } return mxp_in2; +} + +export float2 mx_ifequal_vector2B( + bool mxp_value1 = bool(false), + bool mxp_value2 = bool(false), + float2 mxp_in1 = float2(0.0, 0.0), + float2 mxp_in2 = float2(0.0, 0.0) +) + [[ + anno::description("Node Group: conditional") + ]] +{ + if (mxp_value1 == mxp_value2) { return mxp_in1; } return mxp_in2; +} + +export float3 mx_ifequal_vector3B( + bool mxp_value1 = bool(false), + bool mxp_value2 = bool(false), + float3 mxp_in1 = float3(0.0, 0.0, 0.0), + float3 mxp_in2 = float3(0.0, 0.0, 0.0) +) + [[ + anno::description("Node Group: conditional") + ]] +{ + if (mxp_value1 == mxp_value2) { return mxp_in1; } return mxp_in2; +} + +export float4 mx_ifequal_vector4B( + bool mxp_value1 = bool(false), + bool mxp_value2 = bool(false), + float4 mxp_in1 = float4(0.0, 0.0, 0.0, 0.0), + float4 mxp_in2 = float4(0.0, 0.0, 0.0, 0.0) +) + [[ + anno::description("Node Group: conditional") + ]] +{ + if (mxp_value1 == mxp_value2) { return mxp_in1; } return mxp_in2; +} + +export float mx_switch_float( + float mxp_in1 = float(0.0), + float mxp_in2 = float(0.0), + float mxp_in3 = float(0.0), + float mxp_in4 = float(0.0), + float mxp_in5 = float(0.0), + float mxp_which = float(0.0) +) + [[ + anno::description("Node Group: conditional") + ]] +{ + float returnValue; + switch (int(mxp_which)) { + case 0: returnValue=mxp_in1; break; + case 1: returnValue=mxp_in2; break; + case 2: returnValue=mxp_in3; break; + case 3: returnValue=mxp_in4; break; + case 4: returnValue=mxp_in5; break; + default: returnValue=mxp_in1; break; + } + return returnValue; +} + +export color mx_switch_color3( + color mxp_in1 = color(0.0, 0.0, 0.0), + color mxp_in2 = color(0.0, 0.0, 0.0), + color mxp_in3 = color(0.0, 0.0, 0.0), + color mxp_in4 = color(0.0, 0.0, 0.0), + color mxp_in5 = color(0.0, 0.0, 0.0), + float mxp_which = float(0.0) +) + [[ + anno::description("Node Group: conditional") + ]] +{ + color returnValue; + switch (int(mxp_which)) { + case 0: returnValue=mxp_in1; break; + case 1: returnValue=mxp_in2; break; + case 2: returnValue=mxp_in3; break; + case 3: returnValue=mxp_in4; break; + case 4: returnValue=mxp_in5; break; + default: returnValue=mxp_in1; break; + } + return returnValue; +} + +export core::color4 mx_switch_color4( + core::color4 mxp_in1 = core::mk_color4(0.0, 0.0, 0.0, 0.0), + core::color4 mxp_in2 = core::mk_color4(0.0, 0.0, 0.0, 0.0), + core::color4 mxp_in3 = core::mk_color4(0.0, 0.0, 0.0, 0.0), + core::color4 mxp_in4 = core::mk_color4(0.0, 0.0, 0.0, 0.0), + core::color4 mxp_in5 = core::mk_color4(0.0, 0.0, 0.0, 0.0), + float mxp_which = float(0.0) +) + [[ + anno::description("Node Group: conditional") + ]] +{ + core::color4 returnValue; + switch (int(mxp_which)) { + case 0: returnValue=mxp_in1; break; + case 1: returnValue=mxp_in2; break; + case 2: returnValue=mxp_in3; break; + case 3: returnValue=mxp_in4; break; + case 4: returnValue=mxp_in5; break; + default: returnValue=mxp_in1; break; + } + return returnValue; +} + +export float2 mx_switch_vector2( + float2 mxp_in1 = float2(0.0, 0.0), + float2 mxp_in2 = float2(0.0, 0.0), + float2 mxp_in3 = float2(0.0, 0.0), + float2 mxp_in4 = float2(0.0, 0.0), + float2 mxp_in5 = float2(0.0, 0.0), + float mxp_which = float(0.0) +) + [[ + anno::description("Node Group: conditional") + ]] +{ + float2 returnValue; + switch (int(mxp_which)) { + case 0: returnValue=mxp_in1; break; + case 1: returnValue=mxp_in2; break; + case 2: returnValue=mxp_in3; break; + case 3: returnValue=mxp_in4; break; + case 4: returnValue=mxp_in5; break; + default: returnValue=mxp_in1; break; + } + return returnValue; +} + +export float3 mx_switch_vector3( + float3 mxp_in1 = float3(0.0, 0.0, 0.0), + float3 mxp_in2 = float3(0.0, 0.0, 0.0), + float3 mxp_in3 = float3(0.0, 0.0, 0.0), + float3 mxp_in4 = float3(0.0, 0.0, 0.0), + float3 mxp_in5 = float3(0.0, 0.0, 0.0), + float mxp_which = float(0.0) +) + [[ + anno::description("Node Group: conditional") + ]] +{ + float3 returnValue; + switch (int(mxp_which)) { + case 0: returnValue=mxp_in1; break; + case 1: returnValue=mxp_in2; break; + case 2: returnValue=mxp_in3; break; + case 3: returnValue=mxp_in4; break; + case 4: returnValue=mxp_in5; break; + default: returnValue=mxp_in1; break; + } + return returnValue; +} + +export float4 mx_switch_vector4( + float4 mxp_in1 = float4(0.0, 0.0, 0.0, 0.0), + float4 mxp_in2 = float4(0.0, 0.0, 0.0, 0.0), + float4 mxp_in3 = float4(0.0, 0.0, 0.0, 0.0), + float4 mxp_in4 = float4(0.0, 0.0, 0.0, 0.0), + float4 mxp_in5 = float4(0.0, 0.0, 0.0, 0.0), + float mxp_which = float(0.0) +) + [[ + anno::description("Node Group: conditional") + ]] +{ + float4 returnValue; + switch (int(mxp_which)) { + case 0: returnValue=mxp_in1; break; + case 1: returnValue=mxp_in2; break; + case 2: returnValue=mxp_in3; break; + case 3: returnValue=mxp_in4; break; + case 4: returnValue=mxp_in5; break; + default: returnValue=mxp_in1; break; + } + return returnValue; +} + +export float mx_switch_floatI( + float mxp_in1 = float(0.0), + float mxp_in2 = float(0.0), + float mxp_in3 = float(0.0), + float mxp_in4 = float(0.0), + float mxp_in5 = float(0.0), + int mxp_which = int(0) +) + [[ + anno::description("Node Group: conditional") + ]] +{ + float returnValue; + switch (int(mxp_which)) { + case 0: returnValue=mxp_in1; break; + case 1: returnValue=mxp_in2; break; + case 2: returnValue=mxp_in3; break; + case 3: returnValue=mxp_in4; break; + case 4: returnValue=mxp_in5; break; + default: returnValue=mxp_in1; break; + } + return returnValue; +} + +export color mx_switch_color3I( + color mxp_in1 = color(0.0, 0.0, 0.0), + color mxp_in2 = color(0.0, 0.0, 0.0), + color mxp_in3 = color(0.0, 0.0, 0.0), + color mxp_in4 = color(0.0, 0.0, 0.0), + color mxp_in5 = color(0.0, 0.0, 0.0), + int mxp_which = int(0) +) + [[ + anno::description("Node Group: conditional") + ]] +{ + color returnValue; + switch (int(mxp_which)) { + case 0: returnValue=mxp_in1; break; + case 1: returnValue=mxp_in2; break; + case 2: returnValue=mxp_in3; break; + case 3: returnValue=mxp_in4; break; + case 4: returnValue=mxp_in5; break; + default: returnValue=mxp_in1; break; + } + return returnValue; +} + +export core::color4 mx_switch_color4I( + core::color4 mxp_in1 = core::mk_color4(0.0, 0.0, 0.0, 0.0), + core::color4 mxp_in2 = core::mk_color4(0.0, 0.0, 0.0, 0.0), + core::color4 mxp_in3 = core::mk_color4(0.0, 0.0, 0.0, 0.0), + core::color4 mxp_in4 = core::mk_color4(0.0, 0.0, 0.0, 0.0), + core::color4 mxp_in5 = core::mk_color4(0.0, 0.0, 0.0, 0.0), + int mxp_which = int(0) +) + [[ + anno::description("Node Group: conditional") + ]] +{ + core::color4 returnValue; + switch (int(mxp_which)) { + case 0: returnValue=mxp_in1; break; + case 1: returnValue=mxp_in2; break; + case 2: returnValue=mxp_in3; break; + case 3: returnValue=mxp_in4; break; + case 4: returnValue=mxp_in5; break; + default: returnValue=mxp_in1; break; + } + return returnValue; +} + +export float2 mx_switch_vector2I( + float2 mxp_in1 = float2(0.0, 0.0), + float2 mxp_in2 = float2(0.0, 0.0), + float2 mxp_in3 = float2(0.0, 0.0), + float2 mxp_in4 = float2(0.0, 0.0), + float2 mxp_in5 = float2(0.0, 0.0), + int mxp_which = int(0) +) + [[ + anno::description("Node Group: conditional") + ]] +{ + float2 returnValue; + switch (int(mxp_which)) { + case 0: returnValue=mxp_in1; break; + case 1: returnValue=mxp_in2; break; + case 2: returnValue=mxp_in3; break; + case 3: returnValue=mxp_in4; break; + case 4: returnValue=mxp_in5; break; + default: returnValue=mxp_in1; break; + } + return returnValue; +} + +export float3 mx_switch_vector3I( + float3 mxp_in1 = float3(0.0, 0.0, 0.0), + float3 mxp_in2 = float3(0.0, 0.0, 0.0), + float3 mxp_in3 = float3(0.0, 0.0, 0.0), + float3 mxp_in4 = float3(0.0, 0.0, 0.0), + float3 mxp_in5 = float3(0.0, 0.0, 0.0), + int mxp_which = int(0) +) + [[ + anno::description("Node Group: conditional") + ]] +{ + float3 returnValue; + switch (int(mxp_which)) { + case 0: returnValue=mxp_in1; break; + case 1: returnValue=mxp_in2; break; + case 2: returnValue=mxp_in3; break; + case 3: returnValue=mxp_in4; break; + case 4: returnValue=mxp_in5; break; + default: returnValue=mxp_in1; break; + } + return returnValue; +} + +export float4 mx_switch_vector4I( + float4 mxp_in1 = float4(0.0, 0.0, 0.0, 0.0), + float4 mxp_in2 = float4(0.0, 0.0, 0.0, 0.0), + float4 mxp_in3 = float4(0.0, 0.0, 0.0, 0.0), + float4 mxp_in4 = float4(0.0, 0.0, 0.0, 0.0), + float4 mxp_in5 = float4(0.0, 0.0, 0.0, 0.0), + int mxp_which = int(0) +) + [[ + anno::description("Node Group: conditional") + ]] +{ + float4 returnValue; + switch (int(mxp_which)) { + case 0: returnValue=mxp_in1; break; + case 1: returnValue=mxp_in2; break; + case 2: returnValue=mxp_in3; break; + case 3: returnValue=mxp_in4; break; + case 4: returnValue=mxp_in5; break; + default: returnValue=mxp_in1; break; + } + return returnValue; +} + +export color mx_convert_float_color3( + float mxp_in = float(0.0) +) + [[ + anno::description("Node Group: channel") + ]] +{ + return color(mxp_in); +} + +export core::color4 mx_convert_float_color4( + float mxp_in = float(0.0) +) + [[ + anno::description("Node Group: channel") + ]] +{ + return core::mk_color4(mxp_in); +} + +export float2 mx_convert_float_vector2( + float mxp_in = float(0.0) +) + [[ + anno::description("Node Group: channel") + ]] +{ + return float2(mxp_in); +} + +export float3 mx_convert_float_vector3( + float mxp_in = float(0.0) +) + [[ + anno::description("Node Group: channel") + ]] +{ + return float3(mxp_in); +} + +export float4 mx_convert_float_vector4( + float mxp_in = float(0.0) +) + [[ + anno::description("Node Group: channel") + ]] +{ + return float4(mxp_in); +} + +export float3 mx_convert_vector2_vector3( + float2 mxp_in = float2(0.0, 0.0) +) + [[ + anno::description("Node Group: channel") + ]] +{ + return float3(mxp_in.x, mxp_in.y, 0.0); +} + +export color mx_convert_vector3_color3( + float3 mxp_in = float3(0.0, 0.0, 0.0) +) + [[ + anno::description("Node Group: channel") + ]] +{ + return color(mxp_in); +} + +export float2 mx_convert_vector3_vector2( + float3 mxp_in = float3(0.0, 0.0, 0.0) +) + [[ + anno::description("Node Group: channel") + ]] +{ + return float2(mxp_in.x, mxp_in.y); +} + +export float4 mx_convert_vector3_vector4( + float3 mxp_in = float3(0.0, 0.0, 0.0) +) + [[ + anno::description("Node Group: channel") + ]] +{ + return float4(mxp_in.x, mxp_in.y, mxp_in.z, 0.0); +} + +export core::color4 mx_convert_vector4_color4( + float4 mxp_in = float4(0.0, 0.0, 0.0, 0.0) +) + [[ + anno::description("Node Group: channel") + ]] +{ + return core::mk_color4(mxp_in); +} + +export float3 mx_convert_vector4_vector3( + float4 mxp_in = float4(0.0, 0.0, 0.0, 0.0) +) + [[ + anno::description("Node Group: channel") + ]] +{ + return float3(mxp_in.x, mxp_in.y, mxp_in.z); +} + +export float3 mx_convert_color3_vector3( + color mxp_in = color(0.0, 0.0, 0.0) +) + [[ + anno::description("Node Group: channel") + ]] +{ + return float3(mxp_in); +} + +export float4 mx_convert_color4_vector4( + core::color4 mxp_in = core::mk_color4(0.0, 0.0, 0.0, 0.0) +) + [[ + anno::description("Node Group: channel") + ]] +{ + return core::mk_float4(mxp_in); +} + +export core::color4 mx_convert_color3_color4( + color mxp_in = color(0.0, 0.0, 0.0) +) + [[ + anno::description("Node Group: channel") + ]] +{ + return core::mk_color4(mxp_in); +} + +export color mx_convert_color4_color3( + core::color4 mxp_in = core::mk_color4(0.0, 0.0, 0.0, 0.0) +) + [[ + anno::description("Node Group: channel") + ]] +{ + return mxp_in.rgb; +} + +export float mx_convert_boolean_float( + bool mxp_in = bool(false) +) + [[ + anno::description("Node Group: channel") + ]] +{ + return float(mxp_in); +} + +export float mx_convert_integer_float( + int mxp_in = int(0) +) + [[ + anno::description("Node Group: channel") + ]] +{ + return float(mxp_in); +} + +export float2 mx_combine2_vector2( + float mxp_in1 = float(0.0), + float mxp_in2 = float(0.0) +) + [[ + anno::description("Node Group: channel") + ]] +{ + return float2(mxp_in1, mxp_in2); +} + +export core::color4 mx_combine2_color4CF( + color mxp_in1 = color(0.0, 0.0, 0.0), + float mxp_in2 = float(0.0) +) + [[ + anno::description("Node Group: channel") + ]] +{ + return core::color4(mxp_in1, mxp_in2); +} + +export float4 mx_combine2_vector4VF( + float3 mxp_in1 = float3(0.0, 0.0, 0.0), + float mxp_in2 = float(0.0) +) + [[ + anno::description("Node Group: channel") + ]] +{ + return float4(mxp_in1.x, mxp_in1.y, mxp_in1.z, mxp_in2); +} + +export core::color4 mx_combine2_color4CC( + float2 mxp_in1 = float2(0.0, 0.0), + float2 mxp_in2 = float2(0.0, 0.0) +) + [[ + anno::description("Node Group: channel") + ]] +{ + return core::color4(color(mxp_in1.x, mxp_in1.y, mxp_in2.x), mxp_in2.y); +} + +export float4 mx_combine2_vector4VV( + float2 mxp_in1 = float2(0.0, 0.0), + float2 mxp_in2 = float2(0.0, 0.0) +) + [[ + anno::description("Node Group: channel") + ]] +{ + return float4(mxp_in1.x, mxp_in1.y, mxp_in2.x, mxp_in2.y); +} + +export color mx_combine3_color3( + float mxp_in1 = float(0.0), + float mxp_in2 = float(0.0), + float mxp_in3 = float(0.0) +) + [[ + anno::description("Node Group: channel") + ]] +{ + return color(mxp_in1, mxp_in2, mxp_in3); +} + +export float3 mx_combine3_vector3( + float mxp_in1 = float(0.0), + float mxp_in2 = float(0.0), + float mxp_in3 = float(0.0) +) + [[ + anno::description("Node Group: channel") + ]] +{ + return float3(mxp_in1, mxp_in2, mxp_in3); +} + +export core::color4 mx_combine4_color4( + float mxp_in1 = float(0.0), + float mxp_in2 = float(0.0), + float mxp_in3 = float(0.0), + float mxp_in4 = float(0.0) +) + [[ + anno::description("Node Group: channel") + ]] +{ + return core::mk_color4(mxp_in1, mxp_in2, mxp_in3, mxp_in4); +} + +export float4 mx_combine4_vector4( + float mxp_in1 = float(0.0), + float mxp_in2 = float(0.0), + float mxp_in3 = float(0.0), + float mxp_in4 = float(0.0) +) + [[ + anno::description("Node Group: channel") + ]] +{ + return float4(mxp_in1, mxp_in2, mxp_in3, mxp_in4); +} + +export float3x3 mx_creatematrix_vector3_matrix33( + float3 mxp_in1 = float3(1.0, 0.0, 0.0), + float3 mxp_in2 = float3(0.0, 1.0, 0.0), + float3 mxp_in3 = float3(0.0, 0.0, 1.0) +) + [[ + anno::description("Node Group: math") + ]] +{ + return float3x3( + mxp_in1[0], mxp_in1[1], mxp_in1[2], + mxp_in2[0], mxp_in2[1], mxp_in2[2], + mxp_in3[0], mxp_in3[1], mxp_in3[2]); +} + + +export float4x4 mx_creatematrix_vector3_matrix44( + float3 mxp_in1 = float3(1.0, 0.0, 0.0), + float3 mxp_in2 = float3(0.0, 1.0, 0.0), + float3 mxp_in3 = float3(0.0, 0.0, 1.0), + float3 mxp_in4 = float3(0.0, 0.0, 0.0) +) + [[ + anno::description("Node Group: math") + ]] +{ + return float4x4( + mxp_in1[0], mxp_in1[1], mxp_in1[2], 0.0, + mxp_in2[0], mxp_in2[1], mxp_in2[2], 0.0, + mxp_in3[0], mxp_in3[1], mxp_in3[2], 0.0, + mxp_in4[0], mxp_in4[1], mxp_in4[2], 1.0); +} + + +export float4x4 mx_creatematrix_vector4_matrix44( + float4 mxp_in1 = float4(1.0, 0.0, 0.0, 0.0), + float4 mxp_in2 = float4(0.0, 1.0, 0.0, 0.0), + float4 mxp_in3 = float4(0.0, 0.0, 1.0, 0.0), + float4 mxp_in4 = float4(0.0, 0.0, 0.0, 1.0) +) + [[ + anno::description("Node Group: math") + ]] +{ + return float4x4( + mxp_in1[0], mxp_in1[1], mxp_in1[2], mxp_in1[3], + mxp_in2[0], mxp_in2[1], mxp_in2[2], mxp_in2[3], + mxp_in3[0], mxp_in3[1], mxp_in3[2], mxp_in3[3], + mxp_in4[0], mxp_in4[1], mxp_in4[2], mxp_in4[3]); +} + +// Nodedef: ND_extract_color3 is represented by a nodegraph: NG_extract_color3 +// Nodedef: ND_extract_color4 is represented by a nodegraph: NG_extract_color4 +// Nodedef: ND_extract_vector2 is represented by a nodegraph: NG_extract_vector2 +// Nodedef: ND_extract_vector3 is represented by a nodegraph: NG_extract_vector3 +// Nodedef: ND_extract_vector4 is represented by a nodegraph: NG_extract_vector4 +// Nodedef: ND_separate2_vector2 is represented by a nodegraph: NG_separate2_vector2 +// Nodedef: ND_separate3_color3 is represented by a nodegraph: NG_separate3_color3 +// Nodedef: ND_separate3_vector3 is represented by a nodegraph: NG_separate3_vector3 +// Nodedef: ND_separate4_color4 is represented by a nodegraph: NG_separate4_color4 +// Nodedef: ND_separate4_vector4 is represented by a nodegraph: NG_separate4_vector4 + +export float mx_blur_float( + float mxp_in = float(0.0), + float mxp_size = float(0.0) + [[ + anno::unused() + ]], + uniform core::mx_filter_type mxp_filtertype = core::mx_filter_type(core::mx_filter_type_box) + [[ + anno::description("Enumeration {box,gaussian}."), + anno::unused() + ]] +) + [[ + anno::description("Node Group: convolution2d") + ]] +{ + // Not implemented: mx_blur_float + float defaultValue = mxp_in; + return defaultValue; +} + +export color mx_blur_color3( + color mxp_in = color(0.0, 0.0, 0.0), + float mxp_size = float(0.0) + [[ + anno::unused() + ]], + uniform core::mx_filter_type mxp_filtertype = core::mx_filter_type(core::mx_filter_type_box) + [[ + anno::description("Enumeration {box,gaussian}."), + anno::unused() + ]] +) + [[ + anno::description("Node Group: convolution2d") + ]] +{ + // Not implemented: mx_blur_color3 + color defaultValue = mxp_in; + return defaultValue; +} + +export core::color4 mx_blur_color4( + core::color4 mxp_in = core::mk_color4(0.0, 0.0, 0.0, 0.0), + float mxp_size = float(0.0) + [[ + anno::unused() + ]], + uniform core::mx_filter_type mxp_filtertype = core::mx_filter_type(core::mx_filter_type_box) + [[ + anno::description("Enumeration {box,gaussian}."), + anno::unused() + ]] +) + [[ + anno::description("Node Group: convolution2d") + ]] +{ + // Not implemented: mx_blur_color4 + core::color4 defaultValue = mxp_in; + return defaultValue; +} + +export float2 mx_blur_vector2( + float2 mxp_in = float2(0.0, 0.0), + float mxp_size = float(0.0) + [[ + anno::unused() + ]], + uniform core::mx_filter_type mxp_filtertype = core::mx_filter_type(core::mx_filter_type_box) + [[ + anno::description("Enumeration {box,gaussian}."), + anno::unused() + ]] +) + [[ + anno::description("Node Group: convolution2d") + ]] +{ + // Not implemented: mx_blur_vector2 + float2 defaultValue = mxp_in; + return defaultValue; +} + +export float3 mx_blur_vector3( + float3 mxp_in = float3(0.0, 0.0, 0.0), + float mxp_size = float(0.0) + [[ + anno::unused() + ]], + uniform core::mx_filter_type mxp_filtertype = core::mx_filter_type(core::mx_filter_type_box) + [[ + anno::description("Enumeration {box,gaussian}."), + anno::unused() + ]] +) + [[ + anno::description("Node Group: convolution2d") + ]] +{ + // Not implemented: mx_blur_vector3 + float3 defaultValue = mxp_in; + return defaultValue; +} + +export float4 mx_blur_vector4( + float4 mxp_in = float4(0.0, 0.0, 0.0, 0.0), + float mxp_size = float(0.0) + [[ + anno::unused() + ]], + uniform core::mx_filter_type mxp_filtertype = core::mx_filter_type(core::mx_filter_type_box) + [[ + anno::description("Enumeration {box,gaussian}."), + anno::unused() + ]] +) + [[ + anno::description("Node Group: convolution2d") + ]] +{ + // Not implemented: mx_blur_vector4 + float4 defaultValue = mxp_in; + return defaultValue; +} + +export float3 mx_heighttonormal_vector3( + float mxp_in = float(0.0) [[ anno::unused() ]], + float mxp_scale = float(1.0) [[ anno::unused() ]] +) + [[ + anno::description("Node Group: convolution2d") + ]] +{ + // Not implemented: mx_heighttonormal_vector3 + float3 defaultValue = float3(0.0, 1.0, 0.0); + return defaultValue; +} + +export float mx_noise2d_float( + float mxp_amplitude = 1.0, + float mxp_pivot = 0.0, + float2 mxp_texcoord = swizzle::xy( ::state::texture_coordinate(0)) +) +{ + float value = noise::mx_perlin_noise_float(mxp_texcoord); + return value * mxp_amplitude + mxp_pivot; +} + +export float2 mx_noise2d_float2( + float2 mxp_amplitude = float2(1.0), + float mxp_pivot = 0.0, + float2 mxp_texcoord = swizzle::xy( ::state::texture_coordinate(0)) +) +{ + float3 value = noise::mx_perlin_noise_float3(mxp_texcoord); + return swizzle::xy(value) * mxp_amplitude + mxp_pivot; +} + +export float3 mx_noise2d_float3( + float3 mxp_amplitude = float3(1.0), + float mxp_pivot = 0.0, + float2 mxp_texcoord = swizzle::xy( ::state::texture_coordinate(0)) +) +{ + float3 value = noise::mx_perlin_noise_float3(mxp_texcoord); + return value * mxp_amplitude + mxp_pivot; +} + +export float4 mx_noise2d_float4( + float4 mxp_amplitude = float4(1.0), + float mxp_pivot = 0.0, + float2 mxp_texcoord = swizzle::xy( ::state::texture_coordinate(0)) +) +{ + float3 v = noise::mx_perlin_noise_float3(mxp_texcoord); + float w = noise::mx_perlin_noise_float(mxp_texcoord + float2(19, 73)); + return float4(v.x, v.y, v.z, w) * mxp_amplitude + mxp_pivot; +} + +export float mx_noise3d_float( + float mxp_amplitude = 1.0, + float mxp_pivot = 0.0, + float3 mxp_position = state::transform_point(state::coordinate_internal, state::coordinate_object, state::position()) +) +{ + float value = noise::mx_perlin_noise_float(mxp_position); + return value * mxp_amplitude + mxp_pivot; +} + +export float2 mx_noise3d_float2( + float2 mxp_amplitude = float2(1.0), + float mxp_pivot = 0.0, + float3 mxp_position = state::transform_point(state::coordinate_internal, state::coordinate_object, state::position()) +) +{ + float3 value = noise::mx_perlin_noise_float3(mxp_position); + return swizzle::xy(value) * mxp_amplitude + mxp_pivot; +} + +export float3 mx_noise3d_float3( + float3 mxp_amplitude = float3(1.0), + float mxp_pivot = 0.0, + float3 mxp_position = state::transform_point(state::coordinate_internal, state::coordinate_object, state::position()) +) +{ + float3 value = noise::mx_perlin_noise_float3(mxp_position); + return value * mxp_amplitude + mxp_pivot; +} + +export float4 mx_noise3d_float4( + float4 mxp_amplitude = float4(1.0), + float mxp_pivot = 0.0, + float3 mxp_position = state::transform_point(state::coordinate_internal, state::coordinate_object, state::position()) +) +{ + float3 v = noise::mx_perlin_noise_float3(mxp_position); + float w = noise::mx_perlin_noise_float(mxp_position + float3(19, 73, 29)); + return float4(v.x, v.y, v.z, w) * mxp_amplitude + mxp_pivot; +} + +export float mx_fractal3d_float( + float mxp_amplitude = 1.0, + int mxp_octaves = 3, + float mxp_lacunarity = 2.0, + float mxp_diminish= 0.5, + float3 mxp_position = state::transform_point(state::coordinate_internal, state::coordinate_object, state::position()) +) +{ + float v = noise::mx_fractal_noise_float(mxp_position, mxp_octaves, mxp_lacunarity, mxp_diminish); + return v * mxp_amplitude; +} + +export float2 mx_fractal3d_float2( + float2 mxp_amplitude = float2(1.0), + int mxp_octaves = 3, + float mxp_lacunarity = 2.0, + float mxp_diminish= 0.5, + float3 mxp_position = state::transform_point(state::coordinate_internal, state::coordinate_object, state::position()) +) +{ + float2 v = noise::mx_fractal_noise_float2(mxp_position, mxp_octaves, mxp_lacunarity, mxp_diminish); + return v * mxp_amplitude; +} + +export float3 mx_fractal3d_float3( + float3 mxp_amplitude = float3(1.0), + int mxp_octaves = 3, + float mxp_lacunarity = 2.0, + float mxp_diminish= 0.5, + float3 mxp_position = state::transform_point(state::coordinate_internal, state::coordinate_object, state::position()) +) +{ + float3 v = noise::mx_fractal_noise_float3(mxp_position, mxp_octaves, mxp_lacunarity, mxp_diminish); + return v * mxp_amplitude; +} + +export float4 mx_fractal3d_float4( + float4 mxp_amplitude = float4(1.0), + int mxp_octaves = 3, + float mxp_lacunarity = 2.0, + float mxp_diminish= 0.5, + float3 mxp_position = state::transform_point(state::coordinate_internal, state::coordinate_object, state::position()) +) +{ + float4 v = noise::mx_fractal_noise_float4(mxp_position, mxp_octaves, mxp_lacunarity, mxp_diminish); + return v * mxp_amplitude; +} + +export float mx_cellnoise2d_float( + float2 mxp_texcoord = swizzle::xy( ::state::texture_coordinate(0)) +) +{ + return noise::mx_cell_noise_float(mxp_texcoord); +} + +export float mx_cellnoise3d_float( + float3 mxp_position = state::transform_point(state::coordinate_internal, state::coordinate_object, state::position()) +) +{ + return noise::mx_cell_noise_float(mxp_position); +} + +export float mx_worleynoise2d_float( + float2 mxp_texcoord = swizzle::xy( ::state::texture_coordinate(0)), + float mxp_jitter = 1.0 +) +{ + return noise::mx_worley_noise_float(mxp_texcoord, mxp_jitter, 0); +} + +export float2 mx_worleynoise2d_float2( + float2 mxp_texcoord = swizzle::xy( ::state::texture_coordinate(0)), + float mxp_jitter = 1.0 +) +{ + return noise::mx_worley_noise_float2(mxp_texcoord, mxp_jitter, 0); +} + +export float3 mx_worleynoise2d_float3( + float2 mxp_texcoord = swizzle::xy( ::state::texture_coordinate(0)), + float mxp_jitter = 1.0 +) +{ + return noise::mx_worley_noise_float3(mxp_texcoord, mxp_jitter, 0); +} + +export float mx_worleynoise3d_float( + float3 mxp_position = state::transform_point(state::coordinate_internal, state::coordinate_object, state::position()), + float mxp_jitter = 1.0 +) +{ + return noise::mx_worley_noise_float(mxp_position, mxp_jitter, 0); +} + +export float2 mx_worleynoise3d_float2( + float3 mxp_position = state::transform_point(state::coordinate_internal, state::coordinate_object, state::position()), + float mxp_jitter = 1.0 +) +{ + return noise::mx_worley_noise_float2(mxp_position, mxp_jitter, 0); +} + +export float3 mx_worleynoise3d_float3( + float3 mxp_position = state::transform_point(state::coordinate_internal, state::coordinate_object, state::position()), + float mxp_jitter = 1.0 +) +{ + return noise::mx_worley_noise_float3(mxp_position, mxp_jitter, 0); +} diff --git a/source/MaterialXGenMdl/mdl/materialx/stdlib_1_7.mdl b/source/MaterialXGenMdl/mdl/materialx/stdlib_1_7.mdl new file mode 100644 index 0000000000..019bbb1548 --- /dev/null +++ b/source/MaterialXGenMdl/mdl/materialx/stdlib_1_7.mdl @@ -0,0 +1,18 @@ +// +// Copyright Contributors to the MaterialX Project +// SPDX-License-Identifier: Apache-2.0 +// +// MDL implementation of all Standard Source Nodes of +// MaterialX: An Open Standard for Network-Based CG Object Looks +// Document v1.37 REV2, January 19, 2020 +// www.materialx.org +// in +// NVIDIA Material Definition Language 1.7 +// Language Specification +// Document version 1.7.2, January 17, 2022 +// www.nvidia.com/mdl + +mdl 1.7; + +// forward all unchanged definitions from the previous version +export using .::stdlib_1_6 import *; diff --git a/source/MaterialXGenMdl/mdl/materialx/stdlib_1_8.mdl b/source/MaterialXGenMdl/mdl/materialx/stdlib_1_8.mdl new file mode 100644 index 0000000000..0173cfcf7d --- /dev/null +++ b/source/MaterialXGenMdl/mdl/materialx/stdlib_1_8.mdl @@ -0,0 +1,449 @@ +// +// Copyright Contributors to the MaterialX Project +// SPDX-License-Identifier: Apache-2.0 +// +// MDL implementation of all Standard Source Nodes of +// MaterialX: An Open Standard for Network-Based CG Object Looks +// Document v1.37 REV2, January 19, 2020 +// www.materialx.org +// in +// NVIDIA Material Definition Language 1.8 +// Language Specification +// Document version 1.8.2, May 24, 2023 +// www.nvidia.com/mdl + +mdl 1.8; + +import ::anno::*; +import ::math::*; +import ::scene::*; +import ::state::*; + +import .::core::*; +import .::noise::*; +import .::swizzle::*; +import .::hsv::*; + +// Changes since MDL 1.7 +// - Scene data lookups used for PrimVar readers allow non-literal string names + +// forward all unchanged definitions from the previous version +export using .::stdlib_1_7 import mx_surfacematerial; +export using .::stdlib_1_7 import mx_surface_unlit; +export using .::stdlib_1_7 import mx_image_float; +export using .::stdlib_1_7 import mx_image_color3; +export using .::stdlib_1_7 import mx_image_color4; +export using .::stdlib_1_7 import mx_image_vector2; +export using .::stdlib_1_7 import mx_image_vector3; +export using .::stdlib_1_7 import mx_image_vector4; +export using .::stdlib_1_7 import mx_constant_float; +export using .::stdlib_1_7 import mx_constant_color3; +export using .::stdlib_1_7 import mx_constant_color4; +export using .::stdlib_1_7 import mx_constant_vector2; +export using .::stdlib_1_7 import mx_constant_vector3; +export using .::stdlib_1_7 import mx_constant_vector4; +export using .::stdlib_1_7 import mx_constant_boolean; +export using .::stdlib_1_7 import mx_constant_integer; +export using .::stdlib_1_7 import mx_constant_matrix33; +export using .::stdlib_1_7 import mx_constant_matrix44; +export using .::stdlib_1_7 import mx_constant_string; +export using .::stdlib_1_7 import mx_constant_filename; +export using .::stdlib_1_7 import mx_ramplr_float; +export using .::stdlib_1_7 import mx_ramplr_color3; +export using .::stdlib_1_7 import mx_ramplr_color4; +export using .::stdlib_1_7 import mx_ramplr_vector2; +export using .::stdlib_1_7 import mx_ramplr_vector3; +export using .::stdlib_1_7 import mx_ramplr_vector4; +export using .::stdlib_1_7 import mx_ramptb_float; +export using .::stdlib_1_7 import mx_ramptb_color3; +export using .::stdlib_1_7 import mx_ramptb_color4; +export using .::stdlib_1_7 import mx_ramptb_vector2; +export using .::stdlib_1_7 import mx_ramptb_vector3; +export using .::stdlib_1_7 import mx_ramptb_vector4; +export using .::stdlib_1_7 import mx_splitlr_float; +export using .::stdlib_1_7 import mx_splitlr_color3; +export using .::stdlib_1_7 import mx_splitlr_color4; +export using .::stdlib_1_7 import mx_splitlr_vector2; +export using .::stdlib_1_7 import mx_splitlr_vector3; +export using .::stdlib_1_7 import mx_splitlr_vector4; +export using .::stdlib_1_7 import mx_splittb_float; +export using .::stdlib_1_7 import mx_splittb_color3; +export using .::stdlib_1_7 import mx_splittb_color4; +export using .::stdlib_1_7 import mx_splittb_vector2; +export using .::stdlib_1_7 import mx_splittb_vector3; +export using .::stdlib_1_7 import mx_splittb_vector4; +export using .::stdlib_1_7 import mx_position_vector3; +export using .::stdlib_1_7 import mx_normal_vector3; +export using .::stdlib_1_7 import mx_tangent_vector3; +export using .::stdlib_1_7 import mx_bitangent_vector3; +export using .::stdlib_1_7 import mx_texcoord_vector2; +export using .::stdlib_1_7 import mx_texcoord_vector3; +export using .::stdlib_1_7 import mx_geomcolor_float; +export using .::stdlib_1_7 import mx_geomcolor_color3; +export using .::stdlib_1_7 import mx_geomcolor_color4; +export using .::stdlib_1_7 import mx_ambientocclusion_float; +export using .::stdlib_1_7 import mx_frame_float; +export using .::stdlib_1_7 import mx_time_float; +export using .::stdlib_1_7 import mx_modulo_color3; +export using .::stdlib_1_7 import mx_modulo_color4; +export using .::stdlib_1_7 import mx_modulo_color3FA; +export using .::stdlib_1_7 import mx_modulo_color4FA; +export using .::stdlib_1_7 import mx_invert_color4; +export using .::stdlib_1_7 import mx_invert_color4FA; +export using .::stdlib_1_7 import mx_absval_color4; +export using .::stdlib_1_7 import mx_floor_color3; +export using .::stdlib_1_7 import mx_floor_color4; +export using .::stdlib_1_7 import mx_ceil_color3; +export using .::stdlib_1_7 import mx_ceil_color4; +export using .::stdlib_1_7 import mx_round_color3; +export using .::stdlib_1_7 import mx_round_color4; +export using .::stdlib_1_7 import mx_power_color4; +export using .::stdlib_1_7 import mx_power_color4FA; +export using .::stdlib_1_7 import mx_sin_float; +export using .::stdlib_1_7 import mx_cos_float; +export using .::stdlib_1_7 import mx_tan_float; +export using .::stdlib_1_7 import mx_asin_float; +export using .::stdlib_1_7 import mx_acos_float; +export using .::stdlib_1_7 import mx_atan2_float; +export using .::stdlib_1_7 import mx_sin_vector2; +export using .::stdlib_1_7 import mx_cos_vector2; +export using .::stdlib_1_7 import mx_tan_vector2; +export using .::stdlib_1_7 import mx_asin_vector2; +export using .::stdlib_1_7 import mx_acos_vector2; +export using .::stdlib_1_7 import mx_atan2_vector2; +export using .::stdlib_1_7 import mx_sin_vector3; +export using .::stdlib_1_7 import mx_cos_vector3; +export using .::stdlib_1_7 import mx_tan_vector3; +export using .::stdlib_1_7 import mx_asin_vector3; +export using .::stdlib_1_7 import mx_acos_vector3; +export using .::stdlib_1_7 import mx_atan2_vector3; +export using .::stdlib_1_7 import mx_sin_vector4; +export using .::stdlib_1_7 import mx_cos_vector4; +export using .::stdlib_1_7 import mx_tan_vector4; +export using .::stdlib_1_7 import mx_asin_vector4; +export using .::stdlib_1_7 import mx_acos_vector4; +export using .::stdlib_1_7 import mx_atan2_vector4; +export using .::stdlib_1_7 import mx_sqrt_float; +export using .::stdlib_1_7 import mx_ln_float; +export using .::stdlib_1_7 import mx_exp_float; +export using .::stdlib_1_7 import mx_sqrt_vector2; +export using .::stdlib_1_7 import mx_ln_vector2; +export using .::stdlib_1_7 import mx_exp_vector2; +export using .::stdlib_1_7 import mx_sqrt_vector3; +export using .::stdlib_1_7 import mx_ln_vector3; +export using .::stdlib_1_7 import mx_exp_vector3; +export using .::stdlib_1_7 import mx_sqrt_vector4; +export using .::stdlib_1_7 import mx_ln_vector4; +export using .::stdlib_1_7 import mx_exp_vector4; +export using .::stdlib_1_7 import mx_sign_color3; +export using .::stdlib_1_7 import mx_sign_color4; +export using .::stdlib_1_7 import mx_clamp_color4; +export using .::stdlib_1_7 import mx_clamp_color4FA; +export using .::stdlib_1_7 import mx_min_color4; +export using .::stdlib_1_7 import mx_min_color4; +export using .::stdlib_1_7 import mx_max_color4; +export using .::stdlib_1_7 import mx_max_color4; +export using .::stdlib_1_7 import mx_transformpoint_vector3; +export using .::stdlib_1_7 import mx_transformvector_vector3; +export using .::stdlib_1_7 import mx_transformnormal_vector3; +export using .::stdlib_1_7 import mx_transformmatrix_vector2M3; +export using .::stdlib_1_7 import mx_transformmatrix_vector3; +export using .::stdlib_1_7 import mx_transformmatrix_vector3M4; +export using .::stdlib_1_7 import mx_transformmatrix_vector4; +export using .::stdlib_1_7 import mx_normalmap_float; +export using .::stdlib_1_7 import mx_normalmap_vector2; +export using .::stdlib_1_7 import mx_transpose_matrix33; +export using .::stdlib_1_7 import mx_transpose_matrix44; +export using .::stdlib_1_7 import mx_determinant_matrix33; +export using .::stdlib_1_7 import mx_determinant_matrix44; +export using .::stdlib_1_7 import mx_invertmatrix_matrix33; +export using .::stdlib_1_7 import mx_invertmatrix_matrix44; +export using .::stdlib_1_7 import mx_rotate2d_vector2; +export using .::stdlib_1_7 import mx_rotate3d_vector3; +export using .::stdlib_1_7 import mx_remap_float; +export using .::stdlib_1_7 import mx_remap_color3; +export using .::stdlib_1_7 import mx_remap_color4; +export using .::stdlib_1_7 import mx_remap_vector2; +export using .::stdlib_1_7 import mx_remap_vector3; +export using .::stdlib_1_7 import mx_remap_vector4; +export using .::stdlib_1_7 import mx_remap_color3FA; +export using .::stdlib_1_7 import mx_remap_color4FA; +export using .::stdlib_1_7 import mx_remap_vector2FA; +export using .::stdlib_1_7 import mx_remap_vector3FA; +export using .::stdlib_1_7 import mx_remap_vector4FA; +export using .::stdlib_1_7 import mx_smoothstep_float; +export using .::stdlib_1_7 import mx_smoothstep_color3; +export using .::stdlib_1_7 import mx_smoothstep_color4; +export using .::stdlib_1_7 import mx_smoothstep_vector2; +export using .::stdlib_1_7 import mx_smoothstep_vector3; +export using .::stdlib_1_7 import mx_smoothstep_vector4; +export using .::stdlib_1_7 import mx_smoothstep_color3FA; +export using .::stdlib_1_7 import mx_smoothstep_color4FA; +export using .::stdlib_1_7 import mx_smoothstep_vector2FA; +export using .::stdlib_1_7 import mx_smoothstep_vector3FA; +export using .::stdlib_1_7 import mx_smoothstep_vector4FA; +export using .::stdlib_1_7 import mx_curveadjust_float; +export using .::stdlib_1_7 import mx_curveadjust_color3; +export using .::stdlib_1_7 import mx_curveadjust_color4; +export using .::stdlib_1_7 import mx_curveadjust_vector2; +export using .::stdlib_1_7 import mx_curveadjust_vector3; +export using .::stdlib_1_7 import mx_curveadjust_vector4; +export using .::stdlib_1_7 import mx_luminance_color3; +export using .::stdlib_1_7 import mx_luminance_color4; +export using .::stdlib_1_7 import mx_rgbtohsv_color3; +export using .::stdlib_1_7 import mx_rgbtohsv_color4; +export using .::stdlib_1_7 import mx_hsvtorgb_color3; +export using .::stdlib_1_7 import mx_hsvtorgb_color4; +export using .::stdlib_1_7 import mx_premult_color4; +export using .::stdlib_1_7 import mx_unpremult_color4; +export using .::stdlib_1_7 import mx_plus_color4; +export using .::stdlib_1_7 import mx_minus_color4; +export using .::stdlib_1_7 import mx_difference_color4; +export using .::stdlib_1_7 import mx_burn_float; +export using .::stdlib_1_7 import mx_burn_color3; +export using .::stdlib_1_7 import mx_burn_color4; +export using .::stdlib_1_7 import mx_dodge_float; +export using .::stdlib_1_7 import mx_dodge_color3; +export using .::stdlib_1_7 import mx_dodge_color4; +export using .::stdlib_1_7 import mx_screen_color4; +export using .::stdlib_1_7 import mx_disjointover_color4; +export using .::stdlib_1_7 import mx_in_color4; +export using .::stdlib_1_7 import mx_mask_color4; +export using .::stdlib_1_7 import mx_matte_color4; +export using .::stdlib_1_7 import mx_out_color4; +export using .::stdlib_1_7 import mx_over_color4; +export using .::stdlib_1_7 import mx_mix_color4; +export using .::stdlib_1_7 import mx_mix_color4_color4; +export using .::stdlib_1_7 import mx_mix_surfaceshader; +export using .::stdlib_1_7 import mx_mix_volumeshader; +export using .::stdlib_1_7 import mx_mix_displacementshader; +export using .::stdlib_1_7 import mx_ifgreater_float; +export using .::stdlib_1_7 import mx_ifgreater_color3; +export using .::stdlib_1_7 import mx_ifgreater_color4; +export using .::stdlib_1_7 import mx_ifgreater_vector2; +export using .::stdlib_1_7 import mx_ifgreater_vector3; +export using .::stdlib_1_7 import mx_ifgreater_vector4; +export using .::stdlib_1_7 import mx_ifgreater_floatI; +export using .::stdlib_1_7 import mx_ifgreater_color3I; +export using .::stdlib_1_7 import mx_ifgreater_color4I; +export using .::stdlib_1_7 import mx_ifgreater_vector2I; +export using .::stdlib_1_7 import mx_ifgreater_vector3I; +export using .::stdlib_1_7 import mx_ifgreater_vector4I; +export using .::stdlib_1_7 import mx_ifgreatereq_float; +export using .::stdlib_1_7 import mx_ifgreatereq_color3; +export using .::stdlib_1_7 import mx_ifgreatereq_color4; +export using .::stdlib_1_7 import mx_ifgreatereq_vector2; +export using .::stdlib_1_7 import mx_ifgreatereq_vector3; +export using .::stdlib_1_7 import mx_ifgreatereq_vector4; +export using .::stdlib_1_7 import mx_ifgreatereq_floatI; +export using .::stdlib_1_7 import mx_ifgreatereq_color3I; +export using .::stdlib_1_7 import mx_ifgreatereq_color4I; +export using .::stdlib_1_7 import mx_ifgreatereq_vector2I; +export using .::stdlib_1_7 import mx_ifgreatereq_vector3I; +export using .::stdlib_1_7 import mx_ifgreatereq_vector4I; +export using .::stdlib_1_7 import mx_ifequal_float; +export using .::stdlib_1_7 import mx_ifequal_color3; +export using .::stdlib_1_7 import mx_ifequal_color4; +export using .::stdlib_1_7 import mx_ifequal_vector2; +export using .::stdlib_1_7 import mx_ifequal_vector3; +export using .::stdlib_1_7 import mx_ifequal_vector4; +export using .::stdlib_1_7 import mx_ifequal_floatI; +export using .::stdlib_1_7 import mx_ifequal_color3I; +export using .::stdlib_1_7 import mx_ifequal_color4I; +export using .::stdlib_1_7 import mx_ifequal_vector2I; +export using .::stdlib_1_7 import mx_ifequal_vector3I; +export using .::stdlib_1_7 import mx_ifequal_vector4I; +export using .::stdlib_1_7 import mx_ifequal_floatB; +export using .::stdlib_1_7 import mx_ifequal_color3B; +export using .::stdlib_1_7 import mx_ifequal_color4B; +export using .::stdlib_1_7 import mx_ifequal_vector2B; +export using .::stdlib_1_7 import mx_ifequal_vector3B; +export using .::stdlib_1_7 import mx_ifequal_vector4B; +export using .::stdlib_1_7 import mx_switch_float; +export using .::stdlib_1_7 import mx_switch_color3; +export using .::stdlib_1_7 import mx_switch_color4; +export using .::stdlib_1_7 import mx_switch_vector2; +export using .::stdlib_1_7 import mx_switch_vector3; +export using .::stdlib_1_7 import mx_switch_vector4; +export using .::stdlib_1_7 import mx_switch_floatI; +export using .::stdlib_1_7 import mx_switch_color3I; +export using .::stdlib_1_7 import mx_switch_color4I; +export using .::stdlib_1_7 import mx_switch_vector2I; +export using .::stdlib_1_7 import mx_switch_vector3I; +export using .::stdlib_1_7 import mx_switch_vector4I; +export using .::stdlib_1_7 import mx_convert_float_color3; +export using .::stdlib_1_7 import mx_convert_float_color4; +export using .::stdlib_1_7 import mx_convert_float_vector2; +export using .::stdlib_1_7 import mx_convert_float_vector3; +export using .::stdlib_1_7 import mx_convert_float_vector4; +export using .::stdlib_1_7 import mx_convert_vector2_vector3; +export using .::stdlib_1_7 import mx_convert_vector3_color3; +export using .::stdlib_1_7 import mx_convert_vector3_vector2; +export using .::stdlib_1_7 import mx_convert_vector3_vector4; +export using .::stdlib_1_7 import mx_convert_vector4_color4; +export using .::stdlib_1_7 import mx_convert_vector4_vector3; +export using .::stdlib_1_7 import mx_convert_color3_vector3; +export using .::stdlib_1_7 import mx_convert_color4_vector4; +export using .::stdlib_1_7 import mx_convert_color3_color4; +export using .::stdlib_1_7 import mx_convert_color4_color3; +export using .::stdlib_1_7 import mx_convert_boolean_float; +export using .::stdlib_1_7 import mx_convert_integer_float; +export using .::stdlib_1_7 import mx_combine2_vector2; +export using .::stdlib_1_7 import mx_combine2_color4CF; +export using .::stdlib_1_7 import mx_combine2_vector4VF; +export using .::stdlib_1_7 import mx_combine2_color4CC; +export using .::stdlib_1_7 import mx_combine2_vector4VV; +export using .::stdlib_1_7 import mx_combine3_color3; +export using .::stdlib_1_7 import mx_combine3_vector3; +export using .::stdlib_1_7 import mx_combine4_color4; +export using .::stdlib_1_7 import mx_combine4_vector4; +export using .::stdlib_1_7 import mx_creatematrix_vector3_matrix33; +export using .::stdlib_1_7 import mx_creatematrix_vector3_matrix44; +export using .::stdlib_1_7 import mx_creatematrix_vector4_matrix44; +export using .::stdlib_1_7 import mx_blur_float; +export using .::stdlib_1_7 import mx_blur_color3; +export using .::stdlib_1_7 import mx_blur_color4; +export using .::stdlib_1_7 import mx_blur_vector2; +export using .::stdlib_1_7 import mx_blur_vector3; +export using .::stdlib_1_7 import mx_blur_vector4; +export using .::stdlib_1_7 import mx_heighttonormal_vector3; +export using .::stdlib_1_7 import mx_noise2d_float; +export using .::stdlib_1_7 import mx_noise2d_float2; +export using .::stdlib_1_7 import mx_noise2d_float3; +export using .::stdlib_1_7 import mx_noise2d_float4; +export using .::stdlib_1_7 import mx_noise3d_float; +export using .::stdlib_1_7 import mx_noise3d_float2; +export using .::stdlib_1_7 import mx_noise3d_float3; +export using .::stdlib_1_7 import mx_noise3d_float4; +export using .::stdlib_1_7 import mx_fractal3d_float; +export using .::stdlib_1_7 import mx_fractal3d_float2; +export using .::stdlib_1_7 import mx_fractal3d_float3; +export using .::stdlib_1_7 import mx_fractal3d_float4; +export using .::stdlib_1_7 import mx_cellnoise2d_float; +export using .::stdlib_1_7 import mx_cellnoise3d_float; +export using .::stdlib_1_7 import mx_worleynoise2d_float; +export using .::stdlib_1_7 import mx_worleynoise2d_float2; +export using .::stdlib_1_7 import mx_worleynoise2d_float3; +export using .::stdlib_1_7 import mx_worleynoise3d_float; +export using .::stdlib_1_7 import mx_worleynoise3d_float2; +export using .::stdlib_1_7 import mx_worleynoise3d_float3; + +// NOTE: Not planned to be implemented. +export using .::stdlib_1_7 import mx_geompropvalue_string; + +// NOTE: No boolean scene data in MDL so it's mapped to integer. +// Returns false if the scene data is zero, true otherwise. +export bool mx_geompropvalue_boolean( + uniform string mxp_geomprop = string(""), + bool mxp_default = bool(false) +) + [[ + anno::description("Node Group: geometric") + ]] +{ + int defaultValue = mxp_default ? 1 : 0; + return scene::data_lookup_int(mxp_geomprop, defaultValue) == 0 ? false : true; +} + +export int mx_geompropvalue_integer( + uniform string mxp_geomprop = string(""), + int mxp_default = int(0) +) + [[ + anno::description("Node Group: geometric") + ]] +{ + return scene::data_lookup_int(mxp_geomprop, mxp_default); +} + +export float mx_geompropvalue_float( + uniform string mxp_geomprop = string(""), + float mxp_default = float(0.0) +) + [[ + anno::description("Node Group: geometric") + ]] +{ + return scene::data_lookup_float(mxp_geomprop, mxp_default); +} + +export color mx_geompropvalue_color3( + uniform string mxp_geomprop = string(""), + color mxp_default = color(0.0, 0.0, 0.0) +) + [[ + anno::description("Node Group: geometric") + ]] +{ + return scene::data_lookup_color(mxp_geomprop, mxp_default); +} + +export core::color4 mx_geompropvalue_color4( + uniform string mxp_geomprop = string(""), + core::color4 mxp_default = core::mk_color4(0.0, 0.0, 0.0, 0.0) +) + [[ + anno::description("Node Group: geometric") + ]] +{ + float3 rgbValue = float3(mxp_default.rgb); + float4 defaultValue = float4(rgbValue.x, rgbValue.y, rgbValue.z, mxp_default.a); + float4 value = scene::data_lookup_float4(mxp_geomprop, defaultValue); + return core::mk_color4(value.x, value.y, value.z, value.w); +} + +export float2 mx_geompropvalue_vector2( + uniform string mxp_geomprop = string(""), + float2 mxp_default = float2(0.0, 0.0) +) + [[ + anno::description("Node Group: geometric") + ]] +{ + return scene::data_lookup_float2(mxp_geomprop, mxp_default); +} + +export float3 mx_geompropvalue_vector3( + uniform string mxp_geomprop = string(""), + float3 mxp_default = float3(0.0, 0.0, 0.0) +) + [[ + anno::description("Node Group: geometric") + ]] +{ + return scene::data_lookup_float3(mxp_geomprop, mxp_default); +} + +export float4 mx_geompropvalue_vector4( + uniform string mxp_geomprop = string(""), + float4 mxp_default = float4(0.0, 0.0, 0.0, 0.0) +) +{ + return scene::data_lookup_float4(mxp_geomprop, mxp_default); +} + +export float3 mx_viewdirection_vector3( + uniform core::mx_coordinatespace_type mxp_space = core::mx_coordinatespace_type_world + [[ + anno::description("Enumeration {model,object,world}."), + anno::unused() + ]] +) + [[ + anno::description("Node Group: nprlib") + ]] +{ + float3 internal_space_direction = + state::position() - scene::data_lookup_float3("CAMERA_POSITION", float3(0.0, 0.0, 0.0)); + + if (mxp_space == core::mx_coordinatespace_type_world) + return math::normalize(state::transform_vector( + ::state::coordinate_internal, + ::state::coordinate_world, + internal_space_direction)); + else + return math::normalize(state::transform_vector( + ::state::coordinate_internal, + ::state::coordinate_object, + internal_space_direction)); +} diff --git a/source/MaterialXGenMdl/mdl/materialx/swizzle.mdl b/source/MaterialXGenMdl/mdl/materialx/swizzle.mdl index 414f8dac77..fb87022adb 100644 --- a/source/MaterialXGenMdl/mdl/materialx/swizzle.mdl +++ b/source/MaterialXGenMdl/mdl/materialx/swizzle.mdl @@ -16,12 +16,12 @@ // Support functions to simplify conversions between vector types with swizzles // Supported argument types: float (with implied field name x), float2, float3, -// float4, color, color4 (as RGB and RGBA) +// float4, color, core::color4 (as RGB and RGBA) // Supported return types: float, float2, float3, float4 mdl 1.6; -using .::core import color4; +import .::core::*; // Swizzles with float return type export float x( float a) { return a; } @@ -42,10 +42,10 @@ export float x( color a) { return x( float3(a)); } export float y( color a) { return y( float3(a)); } export float z( color a) { return z( float3(a)); } -export float x( color4 a) { return float3( a.rgb).x; } -export float y( color4 a) { return float3( a.rgb).y; } -export float z( color4 a) { return float3( a.rgb).z; } -export float w( color4 a) { return a.a; } +export float x( core::color4 a) { return float3( a.rgb).x; } +export float y( core::color4 a) { return float3( a.rgb).y; } +export float z( core::color4 a) { return float3( a.rgb).z; } +export float w( core::color4 a) { return a.a; } // Swizzles with float2 return type export float2 xx( float a) { return float2( a, a); } @@ -92,22 +92,22 @@ export float2 zx( color a) { return zx( float3(a)); } export float2 zy( color a) { return zy( float3(a)); } export float2 zz( color a) { return zz( float3(a)); } -export float2 xx( color4 a) { return xx( float3( a.rgb)); } -export float2 xy( color4 a) { return xy( float3( a.rgb)); } -export float2 xz( color4 a) { return xz( float3( a.rgb)); } -export float2 xw( color4 a) { return float2( float3( a.rgb).x, a.a); } -export float2 yx( color4 a) { return yx( float3( a.rgb)); } -export float2 yy( color4 a) { return yy( float3( a.rgb)); } -export float2 yz( color4 a) { return yz( float3( a.rgb)); } -export float2 yw( color4 a) { return float2( float3( a.rgb).y, a.a); } -export float2 zx( color4 a) { return zx( float3( a.rgb)); } -export float2 zy( color4 a) { return zy( float3( a.rgb)); } -export float2 zz( color4 a) { return zz( float3( a.rgb)); } -export float2 zw( color4 a) { return float2( float3( a.rgb).z, a.a); } -export float2 wx( color4 a) { return float2( a.a, float3( a.rgb).x); } -export float2 wy( color4 a) { return float2( a.a, float3( a.rgb).y); } -export float2 wz( color4 a) { return float2( a.a, float3( a.rgb).z); } -export float2 ww( color4 a) { return float2( a.a, a.a); } +export float2 xx( core::color4 a) { return xx( float3( a.rgb)); } +export float2 xy( core::color4 a) { return xy( float3( a.rgb)); } +export float2 xz( core::color4 a) { return xz( float3( a.rgb)); } +export float2 xw( core::color4 a) { return float2( float3( a.rgb).x, a.a); } +export float2 yx( core::color4 a) { return yx( float3( a.rgb)); } +export float2 yy( core::color4 a) { return yy( float3( a.rgb)); } +export float2 yz( core::color4 a) { return yz( float3( a.rgb)); } +export float2 yw( core::color4 a) { return float2( float3( a.rgb).y, a.a); } +export float2 zx( core::color4 a) { return zx( float3( a.rgb)); } +export float2 zy( core::color4 a) { return zy( float3( a.rgb)); } +export float2 zz( core::color4 a) { return zz( float3( a.rgb)); } +export float2 zw( core::color4 a) { return float2( float3( a.rgb).z, a.a); } +export float2 wx( core::color4 a) { return float2( a.a, float3( a.rgb).x); } +export float2 wy( core::color4 a) { return float2( a.a, float3( a.rgb).y); } +export float2 wz( core::color4 a) { return float2( a.a, float3( a.rgb).z); } +export float2 ww( core::color4 a) { return float2( a.a, a.a); } // Swizzles with float3 return type export float3 xxx( float a) { return float3( a, a, a); } @@ -242,70 +242,70 @@ export float3 zzx( color a) { return zzx( float3(a)); } export float3 zzy( color a) { return zzy( float3(a)); } export float3 zzz( color a) { return zzz( float3(a)); } -export float3 xxx( color4 a) { return xxx( float3( a.rgb)); } -export float3 xxy( color4 a) { return xxy( float3( a.rgb)); } -export float3 xxz( color4 a) { return xxz( float3( a.rgb)); } -export float3 xxw( color4 a) { return float3( float3( a.rgb).x, float3( a.rgb).x, a.a); } -export float3 xyx( color4 a) { return xyx( float3( a.rgb)); } -export float3 xyy( color4 a) { return xyy( float3( a.rgb)); } -export float3 xyz( color4 a) { return xyz( float3( a.rgb)); } -export float3 xyw( color4 a) { return float3( float3( a.rgb).x, float3( a.rgb).y, a.a); } -export float3 xzx( color4 a) { return xzx( float3( a.rgb)); } -export float3 xzy( color4 a) { return xzy( float3( a.rgb)); } -export float3 xzz( color4 a) { return xzz( float3( a.rgb)); } -export float3 xzw( color4 a) { return float3( float3( a.rgb).x, float3( a.rgb).z, a.a); } -export float3 xwx( color4 a) { return float3( float3( a.rgb).x, a.a, float3( a.rgb).x); } -export float3 xwy( color4 a) { return float3( float3( a.rgb).x, a.a, float3( a.rgb).y); } -export float3 xwz( color4 a) { return float3( float3( a.rgb).x, a.a, float3( a.rgb).z); } -export float3 xww( color4 a) { return float3( float3( a.rgb).x, a.a, a.a); } -export float3 yxx( color4 a) { return yxx( float3( a.rgb)); } -export float3 yxy( color4 a) { return yxy( float3( a.rgb)); } -export float3 yxz( color4 a) { return yxz( float3( a.rgb)); } -export float3 yxw( color4 a) { return float3( float3( a.rgb).y, float3( a.rgb).x, a.a); } -export float3 yyx( color4 a) { return yyx( float3( a.rgb)); } -export float3 yyy( color4 a) { return yyy( float3( a.rgb)); } -export float3 yyz( color4 a) { return yyz( float3( a.rgb)); } -export float3 yyw( color4 a) { return float3( float3( a.rgb).y, float3( a.rgb).y, a.a); } -export float3 yzx( color4 a) { return yzx( float3( a.rgb)); } -export float3 yzy( color4 a) { return yzy( float3( a.rgb)); } -export float3 yzz( color4 a) { return yzz( float3( a.rgb)); } -export float3 yzw( color4 a) { return float3( float3( a.rgb).y, float3( a.rgb).z, a.a); } -export float3 ywx( color4 a) { return float3( float3( a.rgb).y, a.a, float3( a.rgb).x); } -export float3 ywy( color4 a) { return float3( float3( a.rgb).y, a.a, float3( a.rgb).y); } -export float3 ywz( color4 a) { return float3( float3( a.rgb).y, a.a, float3( a.rgb).z); } -export float3 yww( color4 a) { return float3( float3( a.rgb).y, a.a, a.a); } -export float3 zxx( color4 a) { return zxx( float3( a.rgb)); } -export float3 zxy( color4 a) { return zxy( float3( a.rgb)); } -export float3 zxz( color4 a) { return zxz( float3( a.rgb)); } -export float3 zxw( color4 a) { return float3( float3( a.rgb).z, float3( a.rgb).x, a.a); } -export float3 zyx( color4 a) { return zyx( float3( a.rgb)); } -export float3 zyy( color4 a) { return zyy( float3( a.rgb)); } -export float3 zyz( color4 a) { return zyz( float3( a.rgb)); } -export float3 zyw( color4 a) { return float3( float3( a.rgb).z, float3( a.rgb).y, a.a); } -export float3 zzx( color4 a) { return zzx( float3( a.rgb)); } -export float3 zzy( color4 a) { return zzy( float3( a.rgb)); } -export float3 zzz( color4 a) { return zzz( float3( a.rgb)); } -export float3 zzw( color4 a) { return float3( float3( a.rgb).z, float3( a.rgb).z, a.a); } -export float3 zwx( color4 a) { return float3( float3( a.rgb).z, a.a, float3( a.rgb).x); } -export float3 zwy( color4 a) { return float3( float3( a.rgb).z, a.a, float3( a.rgb).y); } -export float3 zwz( color4 a) { return float3( float3( a.rgb).z, a.a, float3( a.rgb).z); } -export float3 zww( color4 a) { return float3( float3( a.rgb).z, a.a, a.a); } -export float3 wxx( color4 a) { return float3( a.a, float3( a.rgb).x, float3( a.rgb).x); } -export float3 wxy( color4 a) { return float3( a.a, float3( a.rgb).x, float3( a.rgb).y); } -export float3 wxz( color4 a) { return float3( a.a, float3( a.rgb).x, float3( a.rgb).z); } -export float3 wxw( color4 a) { return float3( a.a, float3( a.rgb).x, a.a); } -export float3 wyx( color4 a) { return float3( a.a, float3( a.rgb).y, float3( a.rgb).x); } -export float3 wyy( color4 a) { return float3( a.a, float3( a.rgb).y, float3( a.rgb).y); } -export float3 wyz( color4 a) { return float3( a.a, float3( a.rgb).y, float3( a.rgb).z); } -export float3 wyw( color4 a) { return float3( a.a, float3( a.rgb).y, a.a); } -export float3 wzx( color4 a) { return float3( a.a, float3( a.rgb).z, float3( a.rgb).x); } -export float3 wzy( color4 a) { return float3( a.a, float3( a.rgb).z, float3( a.rgb).y); } -export float3 wzz( color4 a) { return float3( a.a, float3( a.rgb).z, float3( a.rgb).z); } -export float3 wzw( color4 a) { return float3( a.a, float3( a.rgb).z, a.a); } -export float3 wwx( color4 a) { return float3( a.a, a.a, float3( a.rgb).x); } -export float3 wwy( color4 a) { return float3( a.a, a.a, float3( a.rgb).y); } -export float3 wwz( color4 a) { return float3( a.a, a.a, float3( a.rgb).z); } -export float3 www( color4 a) { return float3( a.a, a.a, a.a); } +export float3 xxx( core::color4 a) { return xxx( float3( a.rgb)); } +export float3 xxy( core::color4 a) { return xxy( float3( a.rgb)); } +export float3 xxz( core::color4 a) { return xxz( float3( a.rgb)); } +export float3 xxw( core::color4 a) { return float3( float3( a.rgb).x, float3( a.rgb).x, a.a); } +export float3 xyx( core::color4 a) { return xyx( float3( a.rgb)); } +export float3 xyy( core::color4 a) { return xyy( float3( a.rgb)); } +export float3 xyz( core::color4 a) { return xyz( float3( a.rgb)); } +export float3 xyw( core::color4 a) { return float3( float3( a.rgb).x, float3( a.rgb).y, a.a); } +export float3 xzx( core::color4 a) { return xzx( float3( a.rgb)); } +export float3 xzy( core::color4 a) { return xzy( float3( a.rgb)); } +export float3 xzz( core::color4 a) { return xzz( float3( a.rgb)); } +export float3 xzw( core::color4 a) { return float3( float3( a.rgb).x, float3( a.rgb).z, a.a); } +export float3 xwx( core::color4 a) { return float3( float3( a.rgb).x, a.a, float3( a.rgb).x); } +export float3 xwy( core::color4 a) { return float3( float3( a.rgb).x, a.a, float3( a.rgb).y); } +export float3 xwz( core::color4 a) { return float3( float3( a.rgb).x, a.a, float3( a.rgb).z); } +export float3 xww( core::color4 a) { return float3( float3( a.rgb).x, a.a, a.a); } +export float3 yxx( core::color4 a) { return yxx( float3( a.rgb)); } +export float3 yxy( core::color4 a) { return yxy( float3( a.rgb)); } +export float3 yxz( core::color4 a) { return yxz( float3( a.rgb)); } +export float3 yxw( core::color4 a) { return float3( float3( a.rgb).y, float3( a.rgb).x, a.a); } +export float3 yyx( core::color4 a) { return yyx( float3( a.rgb)); } +export float3 yyy( core::color4 a) { return yyy( float3( a.rgb)); } +export float3 yyz( core::color4 a) { return yyz( float3( a.rgb)); } +export float3 yyw( core::color4 a) { return float3( float3( a.rgb).y, float3( a.rgb).y, a.a); } +export float3 yzx( core::color4 a) { return yzx( float3( a.rgb)); } +export float3 yzy( core::color4 a) { return yzy( float3( a.rgb)); } +export float3 yzz( core::color4 a) { return yzz( float3( a.rgb)); } +export float3 yzw( core::color4 a) { return float3( float3( a.rgb).y, float3( a.rgb).z, a.a); } +export float3 ywx( core::color4 a) { return float3( float3( a.rgb).y, a.a, float3( a.rgb).x); } +export float3 ywy( core::color4 a) { return float3( float3( a.rgb).y, a.a, float3( a.rgb).y); } +export float3 ywz( core::color4 a) { return float3( float3( a.rgb).y, a.a, float3( a.rgb).z); } +export float3 yww( core::color4 a) { return float3( float3( a.rgb).y, a.a, a.a); } +export float3 zxx( core::color4 a) { return zxx( float3( a.rgb)); } +export float3 zxy( core::color4 a) { return zxy( float3( a.rgb)); } +export float3 zxz( core::color4 a) { return zxz( float3( a.rgb)); } +export float3 zxw( core::color4 a) { return float3( float3( a.rgb).z, float3( a.rgb).x, a.a); } +export float3 zyx( core::color4 a) { return zyx( float3( a.rgb)); } +export float3 zyy( core::color4 a) { return zyy( float3( a.rgb)); } +export float3 zyz( core::color4 a) { return zyz( float3( a.rgb)); } +export float3 zyw( core::color4 a) { return float3( float3( a.rgb).z, float3( a.rgb).y, a.a); } +export float3 zzx( core::color4 a) { return zzx( float3( a.rgb)); } +export float3 zzy( core::color4 a) { return zzy( float3( a.rgb)); } +export float3 zzz( core::color4 a) { return zzz( float3( a.rgb)); } +export float3 zzw( core::color4 a) { return float3( float3( a.rgb).z, float3( a.rgb).z, a.a); } +export float3 zwx( core::color4 a) { return float3( float3( a.rgb).z, a.a, float3( a.rgb).x); } +export float3 zwy( core::color4 a) { return float3( float3( a.rgb).z, a.a, float3( a.rgb).y); } +export float3 zwz( core::color4 a) { return float3( float3( a.rgb).z, a.a, float3( a.rgb).z); } +export float3 zww( core::color4 a) { return float3( float3( a.rgb).z, a.a, a.a); } +export float3 wxx( core::color4 a) { return float3( a.a, float3( a.rgb).x, float3( a.rgb).x); } +export float3 wxy( core::color4 a) { return float3( a.a, float3( a.rgb).x, float3( a.rgb).y); } +export float3 wxz( core::color4 a) { return float3( a.a, float3( a.rgb).x, float3( a.rgb).z); } +export float3 wxw( core::color4 a) { return float3( a.a, float3( a.rgb).x, a.a); } +export float3 wyx( core::color4 a) { return float3( a.a, float3( a.rgb).y, float3( a.rgb).x); } +export float3 wyy( core::color4 a) { return float3( a.a, float3( a.rgb).y, float3( a.rgb).y); } +export float3 wyz( core::color4 a) { return float3( a.a, float3( a.rgb).y, float3( a.rgb).z); } +export float3 wyw( core::color4 a) { return float3( a.a, float3( a.rgb).y, a.a); } +export float3 wzx( core::color4 a) { return float3( a.a, float3( a.rgb).z, float3( a.rgb).x); } +export float3 wzy( core::color4 a) { return float3( a.a, float3( a.rgb).z, float3( a.rgb).y); } +export float3 wzz( core::color4 a) { return float3( a.a, float3( a.rgb).z, float3( a.rgb).z); } +export float3 wzw( core::color4 a) { return float3( a.a, float3( a.rgb).z, a.a); } +export float3 wwx( core::color4 a) { return float3( a.a, a.a, float3( a.rgb).x); } +export float3 wwy( core::color4 a) { return float3( a.a, a.a, float3( a.rgb).y); } +export float3 wwz( core::color4 a) { return float3( a.a, a.a, float3( a.rgb).z); } +export float3 www( core::color4 a) { return float3( a.a, a.a, a.a); } // Swizzles with float4 return type export float4 xxxx( float a) { return float4( a, a, a, a); } @@ -748,260 +748,260 @@ export float4 zzzx( color a) { return zzzx( float3(a)); } export float4 zzzy( color a) { return zzzy( float3(a)); } export float4 zzzz( color a) { return zzzz( float3(a)); } -export float4 xxxx( color4 a) { return xxxx( float3( a.rgb)); } -export float4 xxxy( color4 a) { return xxxy( float3( a.rgb)); } -export float4 xxxz( color4 a) { return xxxz( float3( a.rgb)); } -export float4 xxxw( color4 a) { return float4( float3( a.rgb).x, float3( a.rgb).x, float3( a.rgb).x, a.a); } -export float4 xxyx( color4 a) { return xxyx( float3( a.rgb)); } -export float4 xxyy( color4 a) { return xxyy( float3( a.rgb)); } -export float4 xxyz( color4 a) { return xxyz( float3( a.rgb)); } -export float4 xxyw( color4 a) { return float4( float3( a.rgb).x, float3( a.rgb).x, float3( a.rgb).y, a.a); } -export float4 xxzx( color4 a) { return xxzx( float3( a.rgb)); } -export float4 xxzy( color4 a) { return xxzy( float3( a.rgb)); } -export float4 xxzz( color4 a) { return xxzz( float3( a.rgb)); } -export float4 xxzw( color4 a) { return float4( float3( a.rgb).x, float3( a.rgb).x, float3( a.rgb).z, a.a); } -export float4 xxwx( color4 a) { return float4( float3( a.rgb).x, float3( a.rgb).x, a.a, float3( a.rgb).x); } -export float4 xxwy( color4 a) { return float4( float3( a.rgb).x, float3( a.rgb).x, a.a, float3( a.rgb).y); } -export float4 xxwz( color4 a) { return float4( float3( a.rgb).x, float3( a.rgb).x, a.a, float3( a.rgb).z); } -export float4 xxww( color4 a) { return float4( float3( a.rgb).x, float3( a.rgb).x, a.a, a.a); } -export float4 xyxx( color4 a) { return xyxx( float3( a.rgb)); } -export float4 xyxy( color4 a) { return xyxy( float3( a.rgb)); } -export float4 xyxz( color4 a) { return xyxz( float3( a.rgb)); } -export float4 xyxw( color4 a) { return float4( float3( a.rgb).x, float3( a.rgb).y, float3( a.rgb).x, a.a); } -export float4 xyyx( color4 a) { return xyyx( float3( a.rgb)); } -export float4 xyyy( color4 a) { return xyyy( float3( a.rgb)); } -export float4 xyyz( color4 a) { return xyyz( float3( a.rgb)); } -export float4 xyyw( color4 a) { return float4( float3( a.rgb).x, float3( a.rgb).y, float3( a.rgb).y, a.a); } -export float4 xyzx( color4 a) { return xyzx( float3( a.rgb)); } -export float4 xyzy( color4 a) { return xyzy( float3( a.rgb)); } -export float4 xyzz( color4 a) { return xyzz( float3( a.rgb)); } -export float4 xyzw( color4 a) { return float4( float3( a.rgb).x, float3( a.rgb).y, float3( a.rgb).z, a.a); } -export float4 xywx( color4 a) { return float4( float3( a.rgb).x, float3( a.rgb).y, a.a, float3( a.rgb).x); } -export float4 xywy( color4 a) { return float4( float3( a.rgb).x, float3( a.rgb).y, a.a, float3( a.rgb).y); } -export float4 xywz( color4 a) { return float4( float3( a.rgb).x, float3( a.rgb).y, a.a, float3( a.rgb).z); } -export float4 xyww( color4 a) { return float4( float3( a.rgb).x, float3( a.rgb).y, a.a, a.a); } -export float4 xzxx( color4 a) { return xzxx( float3( a.rgb)); } -export float4 xzxy( color4 a) { return xzxy( float3( a.rgb)); } -export float4 xzxz( color4 a) { return xzxz( float3( a.rgb)); } -export float4 xzxw( color4 a) { return float4( float3( a.rgb).x, float3( a.rgb).z, float3( a.rgb).x, a.a); } -export float4 xzyx( color4 a) { return xzyx( float3( a.rgb)); } -export float4 xzyy( color4 a) { return xzyy( float3( a.rgb)); } -export float4 xzyz( color4 a) { return xzyz( float3( a.rgb)); } -export float4 xzyw( color4 a) { return float4( float3( a.rgb).x, float3( a.rgb).z, float3( a.rgb).y, a.a); } -export float4 xzzx( color4 a) { return xzzx( float3( a.rgb)); } -export float4 xzzy( color4 a) { return xzzy( float3( a.rgb)); } -export float4 xzzz( color4 a) { return xzzz( float3( a.rgb)); } -export float4 xzzw( color4 a) { return float4( float3( a.rgb).x, float3( a.rgb).z, float3( a.rgb).z, a.a); } -export float4 xzwx( color4 a) { return float4( float3( a.rgb).x, float3( a.rgb).z, a.a, float3( a.rgb).x); } -export float4 xzwy( color4 a) { return float4( float3( a.rgb).x, float3( a.rgb).z, a.a, float3( a.rgb).y); } -export float4 xzwz( color4 a) { return float4( float3( a.rgb).x, float3( a.rgb).z, a.a, float3( a.rgb).z); } -export float4 xzww( color4 a) { return float4( float3( a.rgb).x, float3( a.rgb).z, a.a, a.a); } -export float4 xwxx( color4 a) { return float4( float3( a.rgb).x, a.a, float3( a.rgb).x, float3( a.rgb).x); } -export float4 xwxy( color4 a) { return float4( float3( a.rgb).x, a.a, float3( a.rgb).x, float3( a.rgb).y); } -export float4 xwxz( color4 a) { return float4( float3( a.rgb).x, a.a, float3( a.rgb).x, float3( a.rgb).z); } -export float4 xwxw( color4 a) { return float4( float3( a.rgb).x, a.a, float3( a.rgb).x, a.a); } -export float4 xwyx( color4 a) { return float4( float3( a.rgb).x, a.a, float3( a.rgb).y, float3( a.rgb).x); } -export float4 xwyy( color4 a) { return float4( float3( a.rgb).x, a.a, float3( a.rgb).y, float3( a.rgb).y); } -export float4 xwyz( color4 a) { return float4( float3( a.rgb).x, a.a, float3( a.rgb).y, float3( a.rgb).z); } -export float4 xwyw( color4 a) { return float4( float3( a.rgb).x, a.a, float3( a.rgb).y, a.a); } -export float4 xwzx( color4 a) { return float4( float3( a.rgb).x, a.a, float3( a.rgb).z, float3( a.rgb).x); } -export float4 xwzy( color4 a) { return float4( float3( a.rgb).x, a.a, float3( a.rgb).z, float3( a.rgb).y); } -export float4 xwzz( color4 a) { return float4( float3( a.rgb).x, a.a, float3( a.rgb).z, float3( a.rgb).z); } -export float4 xwzw( color4 a) { return float4( float3( a.rgb).x, a.a, float3( a.rgb).z, a.a); } -export float4 xwwx( color4 a) { return float4( float3( a.rgb).x, a.a, a.a, float3( a.rgb).x); } -export float4 xwwy( color4 a) { return float4( float3( a.rgb).x, a.a, a.a, float3( a.rgb).y); } -export float4 xwwz( color4 a) { return float4( float3( a.rgb).x, a.a, a.a, float3( a.rgb).z); } -export float4 xwww( color4 a) { return float4( float3( a.rgb).x, a.a, a.a, a.a); } -export float4 yxxx( color4 a) { return yxxx( float3( a.rgb)); } -export float4 yxxy( color4 a) { return yxxy( float3( a.rgb)); } -export float4 yxxz( color4 a) { return yxxz( float3( a.rgb)); } -export float4 yxxw( color4 a) { return float4( float3( a.rgb).y, float3( a.rgb).x, float3( a.rgb).x, a.a); } -export float4 yxyx( color4 a) { return yxyx( float3( a.rgb)); } -export float4 yxyy( color4 a) { return yxyy( float3( a.rgb)); } -export float4 yxyz( color4 a) { return yxyz( float3( a.rgb)); } -export float4 yxyw( color4 a) { return float4( float3( a.rgb).y, float3( a.rgb).x, float3( a.rgb).y, a.a); } -export float4 yxzx( color4 a) { return yxzx( float3( a.rgb)); } -export float4 yxzy( color4 a) { return yxzy( float3( a.rgb)); } -export float4 yxzz( color4 a) { return yxzz( float3( a.rgb)); } -export float4 yxzw( color4 a) { return float4( float3( a.rgb).y, float3( a.rgb).x, float3( a.rgb).z, a.a); } -export float4 yxwx( color4 a) { return float4( float3( a.rgb).y, float3( a.rgb).x, a.a, float3( a.rgb).x); } -export float4 yxwy( color4 a) { return float4( float3( a.rgb).y, float3( a.rgb).x, a.a, float3( a.rgb).y); } -export float4 yxwz( color4 a) { return float4( float3( a.rgb).y, float3( a.rgb).x, a.a, float3( a.rgb).z); } -export float4 yxww( color4 a) { return float4( float3( a.rgb).y, float3( a.rgb).x, a.a, a.a); } -export float4 yyxx( color4 a) { return yyxx( float3( a.rgb)); } -export float4 yyxy( color4 a) { return yyxy( float3( a.rgb)); } -export float4 yyxz( color4 a) { return yyxz( float3( a.rgb)); } -export float4 yyxw( color4 a) { return float4( float3( a.rgb).y, float3( a.rgb).y, float3( a.rgb).x, a.a); } -export float4 yyyx( color4 a) { return yyyx( float3( a.rgb)); } -export float4 yyyy( color4 a) { return yyyy( float3( a.rgb)); } -export float4 yyyz( color4 a) { return yyyz( float3( a.rgb)); } -export float4 yyyw( color4 a) { return float4( float3( a.rgb).y, float3( a.rgb).y, float3( a.rgb).y, a.a); } -export float4 yyzx( color4 a) { return yyzx( float3( a.rgb)); } -export float4 yyzy( color4 a) { return yyzy( float3( a.rgb)); } -export float4 yyzz( color4 a) { return yyzz( float3( a.rgb)); } -export float4 yyzw( color4 a) { return float4( float3( a.rgb).y, float3( a.rgb).y, float3( a.rgb).z, a.a); } -export float4 yywx( color4 a) { return float4( float3( a.rgb).y, float3( a.rgb).y, a.a, float3( a.rgb).x); } -export float4 yywy( color4 a) { return float4( float3( a.rgb).y, float3( a.rgb).y, a.a, float3( a.rgb).y); } -export float4 yywz( color4 a) { return float4( float3( a.rgb).y, float3( a.rgb).y, a.a, float3( a.rgb).z); } -export float4 yyww( color4 a) { return float4( float3( a.rgb).y, float3( a.rgb).y, a.a, a.a); } -export float4 yzxx( color4 a) { return yzxx( float3( a.rgb)); } -export float4 yzxy( color4 a) { return yzxy( float3( a.rgb)); } -export float4 yzxz( color4 a) { return yzxz( float3( a.rgb)); } -export float4 yzxw( color4 a) { return float4( float3( a.rgb).y, float3( a.rgb).z, float3( a.rgb).x, a.a); } -export float4 yzyx( color4 a) { return yzyx( float3( a.rgb)); } -export float4 yzyy( color4 a) { return yzyy( float3( a.rgb)); } -export float4 yzyz( color4 a) { return yzyz( float3( a.rgb)); } -export float4 yzyw( color4 a) { return float4( float3( a.rgb).y, float3( a.rgb).z, float3( a.rgb).y, a.a); } -export float4 yzzx( color4 a) { return yzzx( float3( a.rgb)); } -export float4 yzzy( color4 a) { return yzzy( float3( a.rgb)); } -export float4 yzzz( color4 a) { return yzzz( float3( a.rgb)); } -export float4 yzzw( color4 a) { return float4( float3( a.rgb).y, float3( a.rgb).z, float3( a.rgb).z, a.a); } -export float4 yzwx( color4 a) { return float4( float3( a.rgb).y, float3( a.rgb).z, a.a, float3( a.rgb).x); } -export float4 yzwy( color4 a) { return float4( float3( a.rgb).y, float3( a.rgb).z, a.a, float3( a.rgb).y); } -export float4 yzwz( color4 a) { return float4( float3( a.rgb).y, float3( a.rgb).z, a.a, float3( a.rgb).z); } -export float4 yzww( color4 a) { return float4( float3( a.rgb).y, float3( a.rgb).z, a.a, a.a); } -export float4 ywxx( color4 a) { return float4( float3( a.rgb).y, a.a, float3( a.rgb).x, float3( a.rgb).x); } -export float4 ywxy( color4 a) { return float4( float3( a.rgb).y, a.a, float3( a.rgb).x, float3( a.rgb).y); } -export float4 ywxz( color4 a) { return float4( float3( a.rgb).y, a.a, float3( a.rgb).x, float3( a.rgb).z); } -export float4 ywxw( color4 a) { return float4( float3( a.rgb).y, a.a, float3( a.rgb).x, a.a); } -export float4 ywyx( color4 a) { return float4( float3( a.rgb).y, a.a, float3( a.rgb).y, float3( a.rgb).x); } -export float4 ywyy( color4 a) { return float4( float3( a.rgb).y, a.a, float3( a.rgb).y, float3( a.rgb).y); } -export float4 ywyz( color4 a) { return float4( float3( a.rgb).y, a.a, float3( a.rgb).y, float3( a.rgb).z); } -export float4 ywyw( color4 a) { return float4( float3( a.rgb).y, a.a, float3( a.rgb).y, a.a); } -export float4 ywzx( color4 a) { return float4( float3( a.rgb).y, a.a, float3( a.rgb).z, float3( a.rgb).x); } -export float4 ywzy( color4 a) { return float4( float3( a.rgb).y, a.a, float3( a.rgb).z, float3( a.rgb).y); } -export float4 ywzz( color4 a) { return float4( float3( a.rgb).y, a.a, float3( a.rgb).z, float3( a.rgb).z); } -export float4 ywzw( color4 a) { return float4( float3( a.rgb).y, a.a, float3( a.rgb).z, a.a); } -export float4 ywwx( color4 a) { return float4( float3( a.rgb).y, a.a, a.a, float3( a.rgb).x); } -export float4 ywwy( color4 a) { return float4( float3( a.rgb).y, a.a, a.a, float3( a.rgb).y); } -export float4 ywwz( color4 a) { return float4( float3( a.rgb).y, a.a, a.a, float3( a.rgb).z); } -export float4 ywww( color4 a) { return float4( float3( a.rgb).y, a.a, a.a, a.a); } -export float4 zxxx( color4 a) { return zxxx( float3( a.rgb)); } -export float4 zxxy( color4 a) { return zxxy( float3( a.rgb)); } -export float4 zxxz( color4 a) { return zxxz( float3( a.rgb)); } -export float4 zxxw( color4 a) { return float4( float3( a.rgb).z, float3( a.rgb).x, float3( a.rgb).x, a.a); } -export float4 zxyx( color4 a) { return zxyx( float3( a.rgb)); } -export float4 zxyy( color4 a) { return zxyy( float3( a.rgb)); } -export float4 zxyz( color4 a) { return zxyz( float3( a.rgb)); } -export float4 zxyw( color4 a) { return float4( float3( a.rgb).z, float3( a.rgb).x, float3( a.rgb).y, a.a); } -export float4 zxzx( color4 a) { return zxzx( float3( a.rgb)); } -export float4 zxzy( color4 a) { return zxzy( float3( a.rgb)); } -export float4 zxzz( color4 a) { return zxzz( float3( a.rgb)); } -export float4 zxzw( color4 a) { return float4( float3( a.rgb).z, float3( a.rgb).x, float3( a.rgb).z, a.a); } -export float4 zxwx( color4 a) { return float4( float3( a.rgb).z, float3( a.rgb).x, a.a, float3( a.rgb).x); } -export float4 zxwy( color4 a) { return float4( float3( a.rgb).z, float3( a.rgb).x, a.a, float3( a.rgb).y); } -export float4 zxwz( color4 a) { return float4( float3( a.rgb).z, float3( a.rgb).x, a.a, float3( a.rgb).z); } -export float4 zxww( color4 a) { return float4( float3( a.rgb).z, float3( a.rgb).x, a.a, a.a); } -export float4 zyxx( color4 a) { return zyxx( float3( a.rgb)); } -export float4 zyxy( color4 a) { return zyxy( float3( a.rgb)); } -export float4 zyxz( color4 a) { return zyxz( float3( a.rgb)); } -export float4 zyxw( color4 a) { return float4( float3( a.rgb).z, float3( a.rgb).y, float3( a.rgb).x, a.a); } -export float4 zyyx( color4 a) { return zyyx( float3( a.rgb)); } -export float4 zyyy( color4 a) { return zyyy( float3( a.rgb)); } -export float4 zyyz( color4 a) { return zyyz( float3( a.rgb)); } -export float4 zyyw( color4 a) { return float4( float3( a.rgb).z, float3( a.rgb).y, float3( a.rgb).y, a.a); } -export float4 zyzx( color4 a) { return zyzx( float3( a.rgb)); } -export float4 zyzy( color4 a) { return zyzy( float3( a.rgb)); } -export float4 zyzz( color4 a) { return zyzz( float3( a.rgb)); } -export float4 zyzw( color4 a) { return float4( float3( a.rgb).z, float3( a.rgb).y, float3( a.rgb).z, a.a); } -export float4 zywx( color4 a) { return float4( float3( a.rgb).z, float3( a.rgb).y, a.a, float3( a.rgb).x); } -export float4 zywy( color4 a) { return float4( float3( a.rgb).z, float3( a.rgb).y, a.a, float3( a.rgb).y); } -export float4 zywz( color4 a) { return float4( float3( a.rgb).z, float3( a.rgb).y, a.a, float3( a.rgb).z); } -export float4 zyww( color4 a) { return float4( float3( a.rgb).z, float3( a.rgb).y, a.a, a.a); } -export float4 zzxx( color4 a) { return zzxx( float3( a.rgb)); } -export float4 zzxy( color4 a) { return zzxy( float3( a.rgb)); } -export float4 zzxz( color4 a) { return zzxz( float3( a.rgb)); } -export float4 zzxw( color4 a) { return float4( float3( a.rgb).z, float3( a.rgb).z, float3( a.rgb).x, a.a); } -export float4 zzyx( color4 a) { return zzyx( float3( a.rgb)); } -export float4 zzyy( color4 a) { return zzyy( float3( a.rgb)); } -export float4 zzyz( color4 a) { return zzyz( float3( a.rgb)); } -export float4 zzyw( color4 a) { return float4( float3( a.rgb).z, float3( a.rgb).z, float3( a.rgb).y, a.a); } -export float4 zzzx( color4 a) { return zzzx( float3( a.rgb)); } -export float4 zzzy( color4 a) { return zzzy( float3( a.rgb)); } -export float4 zzzz( color4 a) { return zzzz( float3( a.rgb)); } -export float4 zzzw( color4 a) { return float4( float3( a.rgb).z, float3( a.rgb).z, float3( a.rgb).z, a.a); } -export float4 zzwx( color4 a) { return float4( float3( a.rgb).z, float3( a.rgb).z, a.a, float3( a.rgb).x); } -export float4 zzwy( color4 a) { return float4( float3( a.rgb).z, float3( a.rgb).z, a.a, float3( a.rgb).y); } -export float4 zzwz( color4 a) { return float4( float3( a.rgb).z, float3( a.rgb).z, a.a, float3( a.rgb).z); } -export float4 zzww( color4 a) { return float4( float3( a.rgb).z, float3( a.rgb).z, a.a, a.a); } -export float4 zwxx( color4 a) { return float4( float3( a.rgb).z, a.a, float3( a.rgb).x, float3( a.rgb).x); } -export float4 zwxy( color4 a) { return float4( float3( a.rgb).z, a.a, float3( a.rgb).x, float3( a.rgb).y); } -export float4 zwxz( color4 a) { return float4( float3( a.rgb).z, a.a, float3( a.rgb).x, float3( a.rgb).z); } -export float4 zwxw( color4 a) { return float4( float3( a.rgb).z, a.a, float3( a.rgb).x, a.a); } -export float4 zwyx( color4 a) { return float4( float3( a.rgb).z, a.a, float3( a.rgb).y, float3( a.rgb).x); } -export float4 zwyy( color4 a) { return float4( float3( a.rgb).z, a.a, float3( a.rgb).y, float3( a.rgb).y); } -export float4 zwyz( color4 a) { return float4( float3( a.rgb).z, a.a, float3( a.rgb).y, float3( a.rgb).z); } -export float4 zwyw( color4 a) { return float4( float3( a.rgb).z, a.a, float3( a.rgb).y, a.a); } -export float4 zwzx( color4 a) { return float4( float3( a.rgb).z, a.a, float3( a.rgb).z, float3( a.rgb).x); } -export float4 zwzy( color4 a) { return float4( float3( a.rgb).z, a.a, float3( a.rgb).z, float3( a.rgb).y); } -export float4 zwzz( color4 a) { return float4( float3( a.rgb).z, a.a, float3( a.rgb).z, float3( a.rgb).z); } -export float4 zwzw( color4 a) { return float4( float3( a.rgb).z, a.a, float3( a.rgb).z, a.a); } -export float4 zwwx( color4 a) { return float4( float3( a.rgb).z, a.a, a.a, float3( a.rgb).x); } -export float4 zwwy( color4 a) { return float4( float3( a.rgb).z, a.a, a.a, float3( a.rgb).y); } -export float4 zwwz( color4 a) { return float4( float3( a.rgb).z, a.a, a.a, float3( a.rgb).z); } -export float4 zwww( color4 a) { return float4( float3( a.rgb).z, a.a, a.a, a.a); } -export float4 wxxx( color4 a) { return float4( a.a, float3( a.rgb).x, float3( a.rgb).x, float3( a.rgb).x); } -export float4 wxxy( color4 a) { return float4( a.a, float3( a.rgb).x, float3( a.rgb).x, float3( a.rgb).y); } -export float4 wxxz( color4 a) { return float4( a.a, float3( a.rgb).x, float3( a.rgb).x, float3( a.rgb).z); } -export float4 wxxw( color4 a) { return float4( a.a, float3( a.rgb).x, float3( a.rgb).x, a.a); } -export float4 wxyx( color4 a) { return float4( a.a, float3( a.rgb).x, float3( a.rgb).y, float3( a.rgb).x); } -export float4 wxyy( color4 a) { return float4( a.a, float3( a.rgb).x, float3( a.rgb).y, float3( a.rgb).y); } -export float4 wxyz( color4 a) { return float4( a.a, float3( a.rgb).x, float3( a.rgb).y, float3( a.rgb).z); } -export float4 wxyw( color4 a) { return float4( a.a, float3( a.rgb).x, float3( a.rgb).y, a.a); } -export float4 wxzx( color4 a) { return float4( a.a, float3( a.rgb).x, float3( a.rgb).z, float3( a.rgb).x); } -export float4 wxzy( color4 a) { return float4( a.a, float3( a.rgb).x, float3( a.rgb).z, float3( a.rgb).y); } -export float4 wxzz( color4 a) { return float4( a.a, float3( a.rgb).x, float3( a.rgb).z, float3( a.rgb).z); } -export float4 wxzw( color4 a) { return float4( a.a, float3( a.rgb).x, float3( a.rgb).z, a.a); } -export float4 wxwx( color4 a) { return float4( a.a, float3( a.rgb).x, a.a, float3( a.rgb).x); } -export float4 wxwy( color4 a) { return float4( a.a, float3( a.rgb).x, a.a, float3( a.rgb).y); } -export float4 wxwz( color4 a) { return float4( a.a, float3( a.rgb).x, a.a, float3( a.rgb).z); } -export float4 wxww( color4 a) { return float4( a.a, float3( a.rgb).x, a.a, a.a); } -export float4 wyxx( color4 a) { return float4( a.a, float3( a.rgb).y, float3( a.rgb).x, float3( a.rgb).x); } -export float4 wyxy( color4 a) { return float4( a.a, float3( a.rgb).y, float3( a.rgb).x, float3( a.rgb).y); } -export float4 wyxz( color4 a) { return float4( a.a, float3( a.rgb).y, float3( a.rgb).x, float3( a.rgb).z); } -export float4 wyxw( color4 a) { return float4( a.a, float3( a.rgb).y, float3( a.rgb).x, a.a); } -export float4 wyyx( color4 a) { return float4( a.a, float3( a.rgb).y, float3( a.rgb).y, float3( a.rgb).x); } -export float4 wyyy( color4 a) { return float4( a.a, float3( a.rgb).y, float3( a.rgb).y, float3( a.rgb).y); } -export float4 wyyz( color4 a) { return float4( a.a, float3( a.rgb).y, float3( a.rgb).y, float3( a.rgb).z); } -export float4 wyyw( color4 a) { return float4( a.a, float3( a.rgb).y, float3( a.rgb).y, a.a); } -export float4 wyzx( color4 a) { return float4( a.a, float3( a.rgb).y, float3( a.rgb).z, float3( a.rgb).x); } -export float4 wyzy( color4 a) { return float4( a.a, float3( a.rgb).y, float3( a.rgb).z, float3( a.rgb).y); } -export float4 wyzz( color4 a) { return float4( a.a, float3( a.rgb).y, float3( a.rgb).z, float3( a.rgb).z); } -export float4 wyzw( color4 a) { return float4( a.a, float3( a.rgb).y, float3( a.rgb).z, a.a); } -export float4 wywx( color4 a) { return float4( a.a, float3( a.rgb).y, a.a, float3( a.rgb).x); } -export float4 wywy( color4 a) { return float4( a.a, float3( a.rgb).y, a.a, float3( a.rgb).y); } -export float4 wywz( color4 a) { return float4( a.a, float3( a.rgb).y, a.a, float3( a.rgb).z); } -export float4 wyww( color4 a) { return float4( a.a, float3( a.rgb).y, a.a, a.a); } -export float4 wzxx( color4 a) { return float4( a.a, float3( a.rgb).z, float3( a.rgb).x, float3( a.rgb).x); } -export float4 wzxy( color4 a) { return float4( a.a, float3( a.rgb).z, float3( a.rgb).x, float3( a.rgb).y); } -export float4 wzxz( color4 a) { return float4( a.a, float3( a.rgb).z, float3( a.rgb).x, float3( a.rgb).z); } -export float4 wzxw( color4 a) { return float4( a.a, float3( a.rgb).z, float3( a.rgb).x, a.a); } -export float4 wzyx( color4 a) { return float4( a.a, float3( a.rgb).z, float3( a.rgb).y, float3( a.rgb).x); } -export float4 wzyy( color4 a) { return float4( a.a, float3( a.rgb).z, float3( a.rgb).y, float3( a.rgb).y); } -export float4 wzyz( color4 a) { return float4( a.a, float3( a.rgb).z, float3( a.rgb).y, float3( a.rgb).z); } -export float4 wzyw( color4 a) { return float4( a.a, float3( a.rgb).z, float3( a.rgb).y, a.a); } -export float4 wzzx( color4 a) { return float4( a.a, float3( a.rgb).z, float3( a.rgb).z, float3( a.rgb).x); } -export float4 wzzy( color4 a) { return float4( a.a, float3( a.rgb).z, float3( a.rgb).z, float3( a.rgb).y); } -export float4 wzzz( color4 a) { return float4( a.a, float3( a.rgb).z, float3( a.rgb).z, float3( a.rgb).z); } -export float4 wzzw( color4 a) { return float4( a.a, float3( a.rgb).z, float3( a.rgb).z, a.a); } -export float4 wzwx( color4 a) { return float4( a.a, float3( a.rgb).z, a.a, float3( a.rgb).x); } -export float4 wzwy( color4 a) { return float4( a.a, float3( a.rgb).z, a.a, float3( a.rgb).y); } -export float4 wzwz( color4 a) { return float4( a.a, float3( a.rgb).z, a.a, float3( a.rgb).z); } -export float4 wzww( color4 a) { return float4( a.a, float3( a.rgb).z, a.a, a.a); } -export float4 wwxx( color4 a) { return float4( a.a, a.a, float3( a.rgb).x, float3( a.rgb).x); } -export float4 wwxy( color4 a) { return float4( a.a, a.a, float3( a.rgb).x, float3( a.rgb).y); } -export float4 wwxz( color4 a) { return float4( a.a, a.a, float3( a.rgb).x, float3( a.rgb).z); } -export float4 wwxw( color4 a) { return float4( a.a, a.a, float3( a.rgb).x, a.a); } -export float4 wwyx( color4 a) { return float4( a.a, a.a, float3( a.rgb).y, float3( a.rgb).x); } -export float4 wwyy( color4 a) { return float4( a.a, a.a, float3( a.rgb).y, float3( a.rgb).y); } -export float4 wwyz( color4 a) { return float4( a.a, a.a, float3( a.rgb).y, float3( a.rgb).z); } -export float4 wwyw( color4 a) { return float4( a.a, a.a, float3( a.rgb).y, a.a); } -export float4 wwzx( color4 a) { return float4( a.a, a.a, float3( a.rgb).z, float3( a.rgb).x); } -export float4 wwzy( color4 a) { return float4( a.a, a.a, float3( a.rgb).z, float3( a.rgb).y); } -export float4 wwzz( color4 a) { return float4( a.a, a.a, float3( a.rgb).z, float3( a.rgb).z); } -export float4 wwzw( color4 a) { return float4( a.a, a.a, float3( a.rgb).z, a.a); } -export float4 wwwx( color4 a) { return float4( a.a, a.a, a.a, float3( a.rgb).x); } -export float4 wwwy( color4 a) { return float4( a.a, a.a, a.a, float3( a.rgb).y); } -export float4 wwwz( color4 a) { return float4( a.a, a.a, a.a, float3( a.rgb).z); } -export float4 wwww( color4 a) { return float4( a.a, a.a, a.a, a.a); } +export float4 xxxx( core::color4 a) { return xxxx( float3( a.rgb)); } +export float4 xxxy( core::color4 a) { return xxxy( float3( a.rgb)); } +export float4 xxxz( core::color4 a) { return xxxz( float3( a.rgb)); } +export float4 xxxw( core::color4 a) { return float4( float3( a.rgb).x, float3( a.rgb).x, float3( a.rgb).x, a.a); } +export float4 xxyx( core::color4 a) { return xxyx( float3( a.rgb)); } +export float4 xxyy( core::color4 a) { return xxyy( float3( a.rgb)); } +export float4 xxyz( core::color4 a) { return xxyz( float3( a.rgb)); } +export float4 xxyw( core::color4 a) { return float4( float3( a.rgb).x, float3( a.rgb).x, float3( a.rgb).y, a.a); } +export float4 xxzx( core::color4 a) { return xxzx( float3( a.rgb)); } +export float4 xxzy( core::color4 a) { return xxzy( float3( a.rgb)); } +export float4 xxzz( core::color4 a) { return xxzz( float3( a.rgb)); } +export float4 xxzw( core::color4 a) { return float4( float3( a.rgb).x, float3( a.rgb).x, float3( a.rgb).z, a.a); } +export float4 xxwx( core::color4 a) { return float4( float3( a.rgb).x, float3( a.rgb).x, a.a, float3( a.rgb).x); } +export float4 xxwy( core::color4 a) { return float4( float3( a.rgb).x, float3( a.rgb).x, a.a, float3( a.rgb).y); } +export float4 xxwz( core::color4 a) { return float4( float3( a.rgb).x, float3( a.rgb).x, a.a, float3( a.rgb).z); } +export float4 xxww( core::color4 a) { return float4( float3( a.rgb).x, float3( a.rgb).x, a.a, a.a); } +export float4 xyxx( core::color4 a) { return xyxx( float3( a.rgb)); } +export float4 xyxy( core::color4 a) { return xyxy( float3( a.rgb)); } +export float4 xyxz( core::color4 a) { return xyxz( float3( a.rgb)); } +export float4 xyxw( core::color4 a) { return float4( float3( a.rgb).x, float3( a.rgb).y, float3( a.rgb).x, a.a); } +export float4 xyyx( core::color4 a) { return xyyx( float3( a.rgb)); } +export float4 xyyy( core::color4 a) { return xyyy( float3( a.rgb)); } +export float4 xyyz( core::color4 a) { return xyyz( float3( a.rgb)); } +export float4 xyyw( core::color4 a) { return float4( float3( a.rgb).x, float3( a.rgb).y, float3( a.rgb).y, a.a); } +export float4 xyzx( core::color4 a) { return xyzx( float3( a.rgb)); } +export float4 xyzy( core::color4 a) { return xyzy( float3( a.rgb)); } +export float4 xyzz( core::color4 a) { return xyzz( float3( a.rgb)); } +export float4 xyzw( core::color4 a) { return float4( float3( a.rgb).x, float3( a.rgb).y, float3( a.rgb).z, a.a); } +export float4 xywx( core::color4 a) { return float4( float3( a.rgb).x, float3( a.rgb).y, a.a, float3( a.rgb).x); } +export float4 xywy( core::color4 a) { return float4( float3( a.rgb).x, float3( a.rgb).y, a.a, float3( a.rgb).y); } +export float4 xywz( core::color4 a) { return float4( float3( a.rgb).x, float3( a.rgb).y, a.a, float3( a.rgb).z); } +export float4 xyww( core::color4 a) { return float4( float3( a.rgb).x, float3( a.rgb).y, a.a, a.a); } +export float4 xzxx( core::color4 a) { return xzxx( float3( a.rgb)); } +export float4 xzxy( core::color4 a) { return xzxy( float3( a.rgb)); } +export float4 xzxz( core::color4 a) { return xzxz( float3( a.rgb)); } +export float4 xzxw( core::color4 a) { return float4( float3( a.rgb).x, float3( a.rgb).z, float3( a.rgb).x, a.a); } +export float4 xzyx( core::color4 a) { return xzyx( float3( a.rgb)); } +export float4 xzyy( core::color4 a) { return xzyy( float3( a.rgb)); } +export float4 xzyz( core::color4 a) { return xzyz( float3( a.rgb)); } +export float4 xzyw( core::color4 a) { return float4( float3( a.rgb).x, float3( a.rgb).z, float3( a.rgb).y, a.a); } +export float4 xzzx( core::color4 a) { return xzzx( float3( a.rgb)); } +export float4 xzzy( core::color4 a) { return xzzy( float3( a.rgb)); } +export float4 xzzz( core::color4 a) { return xzzz( float3( a.rgb)); } +export float4 xzzw( core::color4 a) { return float4( float3( a.rgb).x, float3( a.rgb).z, float3( a.rgb).z, a.a); } +export float4 xzwx( core::color4 a) { return float4( float3( a.rgb).x, float3( a.rgb).z, a.a, float3( a.rgb).x); } +export float4 xzwy( core::color4 a) { return float4( float3( a.rgb).x, float3( a.rgb).z, a.a, float3( a.rgb).y); } +export float4 xzwz( core::color4 a) { return float4( float3( a.rgb).x, float3( a.rgb).z, a.a, float3( a.rgb).z); } +export float4 xzww( core::color4 a) { return float4( float3( a.rgb).x, float3( a.rgb).z, a.a, a.a); } +export float4 xwxx( core::color4 a) { return float4( float3( a.rgb).x, a.a, float3( a.rgb).x, float3( a.rgb).x); } +export float4 xwxy( core::color4 a) { return float4( float3( a.rgb).x, a.a, float3( a.rgb).x, float3( a.rgb).y); } +export float4 xwxz( core::color4 a) { return float4( float3( a.rgb).x, a.a, float3( a.rgb).x, float3( a.rgb).z); } +export float4 xwxw( core::color4 a) { return float4( float3( a.rgb).x, a.a, float3( a.rgb).x, a.a); } +export float4 xwyx( core::color4 a) { return float4( float3( a.rgb).x, a.a, float3( a.rgb).y, float3( a.rgb).x); } +export float4 xwyy( core::color4 a) { return float4( float3( a.rgb).x, a.a, float3( a.rgb).y, float3( a.rgb).y); } +export float4 xwyz( core::color4 a) { return float4( float3( a.rgb).x, a.a, float3( a.rgb).y, float3( a.rgb).z); } +export float4 xwyw( core::color4 a) { return float4( float3( a.rgb).x, a.a, float3( a.rgb).y, a.a); } +export float4 xwzx( core::color4 a) { return float4( float3( a.rgb).x, a.a, float3( a.rgb).z, float3( a.rgb).x); } +export float4 xwzy( core::color4 a) { return float4( float3( a.rgb).x, a.a, float3( a.rgb).z, float3( a.rgb).y); } +export float4 xwzz( core::color4 a) { return float4( float3( a.rgb).x, a.a, float3( a.rgb).z, float3( a.rgb).z); } +export float4 xwzw( core::color4 a) { return float4( float3( a.rgb).x, a.a, float3( a.rgb).z, a.a); } +export float4 xwwx( core::color4 a) { return float4( float3( a.rgb).x, a.a, a.a, float3( a.rgb).x); } +export float4 xwwy( core::color4 a) { return float4( float3( a.rgb).x, a.a, a.a, float3( a.rgb).y); } +export float4 xwwz( core::color4 a) { return float4( float3( a.rgb).x, a.a, a.a, float3( a.rgb).z); } +export float4 xwww( core::color4 a) { return float4( float3( a.rgb).x, a.a, a.a, a.a); } +export float4 yxxx( core::color4 a) { return yxxx( float3( a.rgb)); } +export float4 yxxy( core::color4 a) { return yxxy( float3( a.rgb)); } +export float4 yxxz( core::color4 a) { return yxxz( float3( a.rgb)); } +export float4 yxxw( core::color4 a) { return float4( float3( a.rgb).y, float3( a.rgb).x, float3( a.rgb).x, a.a); } +export float4 yxyx( core::color4 a) { return yxyx( float3( a.rgb)); } +export float4 yxyy( core::color4 a) { return yxyy( float3( a.rgb)); } +export float4 yxyz( core::color4 a) { return yxyz( float3( a.rgb)); } +export float4 yxyw( core::color4 a) { return float4( float3( a.rgb).y, float3( a.rgb).x, float3( a.rgb).y, a.a); } +export float4 yxzx( core::color4 a) { return yxzx( float3( a.rgb)); } +export float4 yxzy( core::color4 a) { return yxzy( float3( a.rgb)); } +export float4 yxzz( core::color4 a) { return yxzz( float3( a.rgb)); } +export float4 yxzw( core::color4 a) { return float4( float3( a.rgb).y, float3( a.rgb).x, float3( a.rgb).z, a.a); } +export float4 yxwx( core::color4 a) { return float4( float3( a.rgb).y, float3( a.rgb).x, a.a, float3( a.rgb).x); } +export float4 yxwy( core::color4 a) { return float4( float3( a.rgb).y, float3( a.rgb).x, a.a, float3( a.rgb).y); } +export float4 yxwz( core::color4 a) { return float4( float3( a.rgb).y, float3( a.rgb).x, a.a, float3( a.rgb).z); } +export float4 yxww( core::color4 a) { return float4( float3( a.rgb).y, float3( a.rgb).x, a.a, a.a); } +export float4 yyxx( core::color4 a) { return yyxx( float3( a.rgb)); } +export float4 yyxy( core::color4 a) { return yyxy( float3( a.rgb)); } +export float4 yyxz( core::color4 a) { return yyxz( float3( a.rgb)); } +export float4 yyxw( core::color4 a) { return float4( float3( a.rgb).y, float3( a.rgb).y, float3( a.rgb).x, a.a); } +export float4 yyyx( core::color4 a) { return yyyx( float3( a.rgb)); } +export float4 yyyy( core::color4 a) { return yyyy( float3( a.rgb)); } +export float4 yyyz( core::color4 a) { return yyyz( float3( a.rgb)); } +export float4 yyyw( core::color4 a) { return float4( float3( a.rgb).y, float3( a.rgb).y, float3( a.rgb).y, a.a); } +export float4 yyzx( core::color4 a) { return yyzx( float3( a.rgb)); } +export float4 yyzy( core::color4 a) { return yyzy( float3( a.rgb)); } +export float4 yyzz( core::color4 a) { return yyzz( float3( a.rgb)); } +export float4 yyzw( core::color4 a) { return float4( float3( a.rgb).y, float3( a.rgb).y, float3( a.rgb).z, a.a); } +export float4 yywx( core::color4 a) { return float4( float3( a.rgb).y, float3( a.rgb).y, a.a, float3( a.rgb).x); } +export float4 yywy( core::color4 a) { return float4( float3( a.rgb).y, float3( a.rgb).y, a.a, float3( a.rgb).y); } +export float4 yywz( core::color4 a) { return float4( float3( a.rgb).y, float3( a.rgb).y, a.a, float3( a.rgb).z); } +export float4 yyww( core::color4 a) { return float4( float3( a.rgb).y, float3( a.rgb).y, a.a, a.a); } +export float4 yzxx( core::color4 a) { return yzxx( float3( a.rgb)); } +export float4 yzxy( core::color4 a) { return yzxy( float3( a.rgb)); } +export float4 yzxz( core::color4 a) { return yzxz( float3( a.rgb)); } +export float4 yzxw( core::color4 a) { return float4( float3( a.rgb).y, float3( a.rgb).z, float3( a.rgb).x, a.a); } +export float4 yzyx( core::color4 a) { return yzyx( float3( a.rgb)); } +export float4 yzyy( core::color4 a) { return yzyy( float3( a.rgb)); } +export float4 yzyz( core::color4 a) { return yzyz( float3( a.rgb)); } +export float4 yzyw( core::color4 a) { return float4( float3( a.rgb).y, float3( a.rgb).z, float3( a.rgb).y, a.a); } +export float4 yzzx( core::color4 a) { return yzzx( float3( a.rgb)); } +export float4 yzzy( core::color4 a) { return yzzy( float3( a.rgb)); } +export float4 yzzz( core::color4 a) { return yzzz( float3( a.rgb)); } +export float4 yzzw( core::color4 a) { return float4( float3( a.rgb).y, float3( a.rgb).z, float3( a.rgb).z, a.a); } +export float4 yzwx( core::color4 a) { return float4( float3( a.rgb).y, float3( a.rgb).z, a.a, float3( a.rgb).x); } +export float4 yzwy( core::color4 a) { return float4( float3( a.rgb).y, float3( a.rgb).z, a.a, float3( a.rgb).y); } +export float4 yzwz( core::color4 a) { return float4( float3( a.rgb).y, float3( a.rgb).z, a.a, float3( a.rgb).z); } +export float4 yzww( core::color4 a) { return float4( float3( a.rgb).y, float3( a.rgb).z, a.a, a.a); } +export float4 ywxx( core::color4 a) { return float4( float3( a.rgb).y, a.a, float3( a.rgb).x, float3( a.rgb).x); } +export float4 ywxy( core::color4 a) { return float4( float3( a.rgb).y, a.a, float3( a.rgb).x, float3( a.rgb).y); } +export float4 ywxz( core::color4 a) { return float4( float3( a.rgb).y, a.a, float3( a.rgb).x, float3( a.rgb).z); } +export float4 ywxw( core::color4 a) { return float4( float3( a.rgb).y, a.a, float3( a.rgb).x, a.a); } +export float4 ywyx( core::color4 a) { return float4( float3( a.rgb).y, a.a, float3( a.rgb).y, float3( a.rgb).x); } +export float4 ywyy( core::color4 a) { return float4( float3( a.rgb).y, a.a, float3( a.rgb).y, float3( a.rgb).y); } +export float4 ywyz( core::color4 a) { return float4( float3( a.rgb).y, a.a, float3( a.rgb).y, float3( a.rgb).z); } +export float4 ywyw( core::color4 a) { return float4( float3( a.rgb).y, a.a, float3( a.rgb).y, a.a); } +export float4 ywzx( core::color4 a) { return float4( float3( a.rgb).y, a.a, float3( a.rgb).z, float3( a.rgb).x); } +export float4 ywzy( core::color4 a) { return float4( float3( a.rgb).y, a.a, float3( a.rgb).z, float3( a.rgb).y); } +export float4 ywzz( core::color4 a) { return float4( float3( a.rgb).y, a.a, float3( a.rgb).z, float3( a.rgb).z); } +export float4 ywzw( core::color4 a) { return float4( float3( a.rgb).y, a.a, float3( a.rgb).z, a.a); } +export float4 ywwx( core::color4 a) { return float4( float3( a.rgb).y, a.a, a.a, float3( a.rgb).x); } +export float4 ywwy( core::color4 a) { return float4( float3( a.rgb).y, a.a, a.a, float3( a.rgb).y); } +export float4 ywwz( core::color4 a) { return float4( float3( a.rgb).y, a.a, a.a, float3( a.rgb).z); } +export float4 ywww( core::color4 a) { return float4( float3( a.rgb).y, a.a, a.a, a.a); } +export float4 zxxx( core::color4 a) { return zxxx( float3( a.rgb)); } +export float4 zxxy( core::color4 a) { return zxxy( float3( a.rgb)); } +export float4 zxxz( core::color4 a) { return zxxz( float3( a.rgb)); } +export float4 zxxw( core::color4 a) { return float4( float3( a.rgb).z, float3( a.rgb).x, float3( a.rgb).x, a.a); } +export float4 zxyx( core::color4 a) { return zxyx( float3( a.rgb)); } +export float4 zxyy( core::color4 a) { return zxyy( float3( a.rgb)); } +export float4 zxyz( core::color4 a) { return zxyz( float3( a.rgb)); } +export float4 zxyw( core::color4 a) { return float4( float3( a.rgb).z, float3( a.rgb).x, float3( a.rgb).y, a.a); } +export float4 zxzx( core::color4 a) { return zxzx( float3( a.rgb)); } +export float4 zxzy( core::color4 a) { return zxzy( float3( a.rgb)); } +export float4 zxzz( core::color4 a) { return zxzz( float3( a.rgb)); } +export float4 zxzw( core::color4 a) { return float4( float3( a.rgb).z, float3( a.rgb).x, float3( a.rgb).z, a.a); } +export float4 zxwx( core::color4 a) { return float4( float3( a.rgb).z, float3( a.rgb).x, a.a, float3( a.rgb).x); } +export float4 zxwy( core::color4 a) { return float4( float3( a.rgb).z, float3( a.rgb).x, a.a, float3( a.rgb).y); } +export float4 zxwz( core::color4 a) { return float4( float3( a.rgb).z, float3( a.rgb).x, a.a, float3( a.rgb).z); } +export float4 zxww( core::color4 a) { return float4( float3( a.rgb).z, float3( a.rgb).x, a.a, a.a); } +export float4 zyxx( core::color4 a) { return zyxx( float3( a.rgb)); } +export float4 zyxy( core::color4 a) { return zyxy( float3( a.rgb)); } +export float4 zyxz( core::color4 a) { return zyxz( float3( a.rgb)); } +export float4 zyxw( core::color4 a) { return float4( float3( a.rgb).z, float3( a.rgb).y, float3( a.rgb).x, a.a); } +export float4 zyyx( core::color4 a) { return zyyx( float3( a.rgb)); } +export float4 zyyy( core::color4 a) { return zyyy( float3( a.rgb)); } +export float4 zyyz( core::color4 a) { return zyyz( float3( a.rgb)); } +export float4 zyyw( core::color4 a) { return float4( float3( a.rgb).z, float3( a.rgb).y, float3( a.rgb).y, a.a); } +export float4 zyzx( core::color4 a) { return zyzx( float3( a.rgb)); } +export float4 zyzy( core::color4 a) { return zyzy( float3( a.rgb)); } +export float4 zyzz( core::color4 a) { return zyzz( float3( a.rgb)); } +export float4 zyzw( core::color4 a) { return float4( float3( a.rgb).z, float3( a.rgb).y, float3( a.rgb).z, a.a); } +export float4 zywx( core::color4 a) { return float4( float3( a.rgb).z, float3( a.rgb).y, a.a, float3( a.rgb).x); } +export float4 zywy( core::color4 a) { return float4( float3( a.rgb).z, float3( a.rgb).y, a.a, float3( a.rgb).y); } +export float4 zywz( core::color4 a) { return float4( float3( a.rgb).z, float3( a.rgb).y, a.a, float3( a.rgb).z); } +export float4 zyww( core::color4 a) { return float4( float3( a.rgb).z, float3( a.rgb).y, a.a, a.a); } +export float4 zzxx( core::color4 a) { return zzxx( float3( a.rgb)); } +export float4 zzxy( core::color4 a) { return zzxy( float3( a.rgb)); } +export float4 zzxz( core::color4 a) { return zzxz( float3( a.rgb)); } +export float4 zzxw( core::color4 a) { return float4( float3( a.rgb).z, float3( a.rgb).z, float3( a.rgb).x, a.a); } +export float4 zzyx( core::color4 a) { return zzyx( float3( a.rgb)); } +export float4 zzyy( core::color4 a) { return zzyy( float3( a.rgb)); } +export float4 zzyz( core::color4 a) { return zzyz( float3( a.rgb)); } +export float4 zzyw( core::color4 a) { return float4( float3( a.rgb).z, float3( a.rgb).z, float3( a.rgb).y, a.a); } +export float4 zzzx( core::color4 a) { return zzzx( float3( a.rgb)); } +export float4 zzzy( core::color4 a) { return zzzy( float3( a.rgb)); } +export float4 zzzz( core::color4 a) { return zzzz( float3( a.rgb)); } +export float4 zzzw( core::color4 a) { return float4( float3( a.rgb).z, float3( a.rgb).z, float3( a.rgb).z, a.a); } +export float4 zzwx( core::color4 a) { return float4( float3( a.rgb).z, float3( a.rgb).z, a.a, float3( a.rgb).x); } +export float4 zzwy( core::color4 a) { return float4( float3( a.rgb).z, float3( a.rgb).z, a.a, float3( a.rgb).y); } +export float4 zzwz( core::color4 a) { return float4( float3( a.rgb).z, float3( a.rgb).z, a.a, float3( a.rgb).z); } +export float4 zzww( core::color4 a) { return float4( float3( a.rgb).z, float3( a.rgb).z, a.a, a.a); } +export float4 zwxx( core::color4 a) { return float4( float3( a.rgb).z, a.a, float3( a.rgb).x, float3( a.rgb).x); } +export float4 zwxy( core::color4 a) { return float4( float3( a.rgb).z, a.a, float3( a.rgb).x, float3( a.rgb).y); } +export float4 zwxz( core::color4 a) { return float4( float3( a.rgb).z, a.a, float3( a.rgb).x, float3( a.rgb).z); } +export float4 zwxw( core::color4 a) { return float4( float3( a.rgb).z, a.a, float3( a.rgb).x, a.a); } +export float4 zwyx( core::color4 a) { return float4( float3( a.rgb).z, a.a, float3( a.rgb).y, float3( a.rgb).x); } +export float4 zwyy( core::color4 a) { return float4( float3( a.rgb).z, a.a, float3( a.rgb).y, float3( a.rgb).y); } +export float4 zwyz( core::color4 a) { return float4( float3( a.rgb).z, a.a, float3( a.rgb).y, float3( a.rgb).z); } +export float4 zwyw( core::color4 a) { return float4( float3( a.rgb).z, a.a, float3( a.rgb).y, a.a); } +export float4 zwzx( core::color4 a) { return float4( float3( a.rgb).z, a.a, float3( a.rgb).z, float3( a.rgb).x); } +export float4 zwzy( core::color4 a) { return float4( float3( a.rgb).z, a.a, float3( a.rgb).z, float3( a.rgb).y); } +export float4 zwzz( core::color4 a) { return float4( float3( a.rgb).z, a.a, float3( a.rgb).z, float3( a.rgb).z); } +export float4 zwzw( core::color4 a) { return float4( float3( a.rgb).z, a.a, float3( a.rgb).z, a.a); } +export float4 zwwx( core::color4 a) { return float4( float3( a.rgb).z, a.a, a.a, float3( a.rgb).x); } +export float4 zwwy( core::color4 a) { return float4( float3( a.rgb).z, a.a, a.a, float3( a.rgb).y); } +export float4 zwwz( core::color4 a) { return float4( float3( a.rgb).z, a.a, a.a, float3( a.rgb).z); } +export float4 zwww( core::color4 a) { return float4( float3( a.rgb).z, a.a, a.a, a.a); } +export float4 wxxx( core::color4 a) { return float4( a.a, float3( a.rgb).x, float3( a.rgb).x, float3( a.rgb).x); } +export float4 wxxy( core::color4 a) { return float4( a.a, float3( a.rgb).x, float3( a.rgb).x, float3( a.rgb).y); } +export float4 wxxz( core::color4 a) { return float4( a.a, float3( a.rgb).x, float3( a.rgb).x, float3( a.rgb).z); } +export float4 wxxw( core::color4 a) { return float4( a.a, float3( a.rgb).x, float3( a.rgb).x, a.a); } +export float4 wxyx( core::color4 a) { return float4( a.a, float3( a.rgb).x, float3( a.rgb).y, float3( a.rgb).x); } +export float4 wxyy( core::color4 a) { return float4( a.a, float3( a.rgb).x, float3( a.rgb).y, float3( a.rgb).y); } +export float4 wxyz( core::color4 a) { return float4( a.a, float3( a.rgb).x, float3( a.rgb).y, float3( a.rgb).z); } +export float4 wxyw( core::color4 a) { return float4( a.a, float3( a.rgb).x, float3( a.rgb).y, a.a); } +export float4 wxzx( core::color4 a) { return float4( a.a, float3( a.rgb).x, float3( a.rgb).z, float3( a.rgb).x); } +export float4 wxzy( core::color4 a) { return float4( a.a, float3( a.rgb).x, float3( a.rgb).z, float3( a.rgb).y); } +export float4 wxzz( core::color4 a) { return float4( a.a, float3( a.rgb).x, float3( a.rgb).z, float3( a.rgb).z); } +export float4 wxzw( core::color4 a) { return float4( a.a, float3( a.rgb).x, float3( a.rgb).z, a.a); } +export float4 wxwx( core::color4 a) { return float4( a.a, float3( a.rgb).x, a.a, float3( a.rgb).x); } +export float4 wxwy( core::color4 a) { return float4( a.a, float3( a.rgb).x, a.a, float3( a.rgb).y); } +export float4 wxwz( core::color4 a) { return float4( a.a, float3( a.rgb).x, a.a, float3( a.rgb).z); } +export float4 wxww( core::color4 a) { return float4( a.a, float3( a.rgb).x, a.a, a.a); } +export float4 wyxx( core::color4 a) { return float4( a.a, float3( a.rgb).y, float3( a.rgb).x, float3( a.rgb).x); } +export float4 wyxy( core::color4 a) { return float4( a.a, float3( a.rgb).y, float3( a.rgb).x, float3( a.rgb).y); } +export float4 wyxz( core::color4 a) { return float4( a.a, float3( a.rgb).y, float3( a.rgb).x, float3( a.rgb).z); } +export float4 wyxw( core::color4 a) { return float4( a.a, float3( a.rgb).y, float3( a.rgb).x, a.a); } +export float4 wyyx( core::color4 a) { return float4( a.a, float3( a.rgb).y, float3( a.rgb).y, float3( a.rgb).x); } +export float4 wyyy( core::color4 a) { return float4( a.a, float3( a.rgb).y, float3( a.rgb).y, float3( a.rgb).y); } +export float4 wyyz( core::color4 a) { return float4( a.a, float3( a.rgb).y, float3( a.rgb).y, float3( a.rgb).z); } +export float4 wyyw( core::color4 a) { return float4( a.a, float3( a.rgb).y, float3( a.rgb).y, a.a); } +export float4 wyzx( core::color4 a) { return float4( a.a, float3( a.rgb).y, float3( a.rgb).z, float3( a.rgb).x); } +export float4 wyzy( core::color4 a) { return float4( a.a, float3( a.rgb).y, float3( a.rgb).z, float3( a.rgb).y); } +export float4 wyzz( core::color4 a) { return float4( a.a, float3( a.rgb).y, float3( a.rgb).z, float3( a.rgb).z); } +export float4 wyzw( core::color4 a) { return float4( a.a, float3( a.rgb).y, float3( a.rgb).z, a.a); } +export float4 wywx( core::color4 a) { return float4( a.a, float3( a.rgb).y, a.a, float3( a.rgb).x); } +export float4 wywy( core::color4 a) { return float4( a.a, float3( a.rgb).y, a.a, float3( a.rgb).y); } +export float4 wywz( core::color4 a) { return float4( a.a, float3( a.rgb).y, a.a, float3( a.rgb).z); } +export float4 wyww( core::color4 a) { return float4( a.a, float3( a.rgb).y, a.a, a.a); } +export float4 wzxx( core::color4 a) { return float4( a.a, float3( a.rgb).z, float3( a.rgb).x, float3( a.rgb).x); } +export float4 wzxy( core::color4 a) { return float4( a.a, float3( a.rgb).z, float3( a.rgb).x, float3( a.rgb).y); } +export float4 wzxz( core::color4 a) { return float4( a.a, float3( a.rgb).z, float3( a.rgb).x, float3( a.rgb).z); } +export float4 wzxw( core::color4 a) { return float4( a.a, float3( a.rgb).z, float3( a.rgb).x, a.a); } +export float4 wzyx( core::color4 a) { return float4( a.a, float3( a.rgb).z, float3( a.rgb).y, float3( a.rgb).x); } +export float4 wzyy( core::color4 a) { return float4( a.a, float3( a.rgb).z, float3( a.rgb).y, float3( a.rgb).y); } +export float4 wzyz( core::color4 a) { return float4( a.a, float3( a.rgb).z, float3( a.rgb).y, float3( a.rgb).z); } +export float4 wzyw( core::color4 a) { return float4( a.a, float3( a.rgb).z, float3( a.rgb).y, a.a); } +export float4 wzzx( core::color4 a) { return float4( a.a, float3( a.rgb).z, float3( a.rgb).z, float3( a.rgb).x); } +export float4 wzzy( core::color4 a) { return float4( a.a, float3( a.rgb).z, float3( a.rgb).z, float3( a.rgb).y); } +export float4 wzzz( core::color4 a) { return float4( a.a, float3( a.rgb).z, float3( a.rgb).z, float3( a.rgb).z); } +export float4 wzzw( core::color4 a) { return float4( a.a, float3( a.rgb).z, float3( a.rgb).z, a.a); } +export float4 wzwx( core::color4 a) { return float4( a.a, float3( a.rgb).z, a.a, float3( a.rgb).x); } +export float4 wzwy( core::color4 a) { return float4( a.a, float3( a.rgb).z, a.a, float3( a.rgb).y); } +export float4 wzwz( core::color4 a) { return float4( a.a, float3( a.rgb).z, a.a, float3( a.rgb).z); } +export float4 wzww( core::color4 a) { return float4( a.a, float3( a.rgb).z, a.a, a.a); } +export float4 wwxx( core::color4 a) { return float4( a.a, a.a, float3( a.rgb).x, float3( a.rgb).x); } +export float4 wwxy( core::color4 a) { return float4( a.a, a.a, float3( a.rgb).x, float3( a.rgb).y); } +export float4 wwxz( core::color4 a) { return float4( a.a, a.a, float3( a.rgb).x, float3( a.rgb).z); } +export float4 wwxw( core::color4 a) { return float4( a.a, a.a, float3( a.rgb).x, a.a); } +export float4 wwyx( core::color4 a) { return float4( a.a, a.a, float3( a.rgb).y, float3( a.rgb).x); } +export float4 wwyy( core::color4 a) { return float4( a.a, a.a, float3( a.rgb).y, float3( a.rgb).y); } +export float4 wwyz( core::color4 a) { return float4( a.a, a.a, float3( a.rgb).y, float3( a.rgb).z); } +export float4 wwyw( core::color4 a) { return float4( a.a, a.a, float3( a.rgb).y, a.a); } +export float4 wwzx( core::color4 a) { return float4( a.a, a.a, float3( a.rgb).z, float3( a.rgb).x); } +export float4 wwzy( core::color4 a) { return float4( a.a, a.a, float3( a.rgb).z, float3( a.rgb).y); } +export float4 wwzz( core::color4 a) { return float4( a.a, a.a, float3( a.rgb).z, float3( a.rgb).z); } +export float4 wwzw( core::color4 a) { return float4( a.a, a.a, float3( a.rgb).z, a.a); } +export float4 wwwx( core::color4 a) { return float4( a.a, a.a, a.a, float3( a.rgb).x); } +export float4 wwwy( core::color4 a) { return float4( a.a, a.a, a.a, float3( a.rgb).y); } +export float4 wwwz( core::color4 a) { return float4( a.a, a.a, a.a, float3( a.rgb).z); } +export float4 wwww( core::color4 a) { return float4( a.a, a.a, a.a, a.a); } diff --git a/source/MaterialXGenMsl/MslResourceBindingContext.cpp b/source/MaterialXGenMsl/MslResourceBindingContext.cpp index 7b61f41854..5d6cbab6f9 100644 --- a/source/MaterialXGenMsl/MslResourceBindingContext.cpp +++ b/source/MaterialXGenMsl/MslResourceBindingContext.cpp @@ -32,7 +32,7 @@ void MslResourceBindingContext::emitDirectives(GenContext&, ShaderStage&) void MslResourceBindingContext::emitResourceBindings(GenContext& context, const VariableBlock& uniforms, ShaderStage& stage) { - ShaderGenerator& generator = context.getShaderGenerator(); + const ShaderGenerator& generator = context.getShaderGenerator(); // First, emit all value uniforms in a block with single layout binding bool hasValueUniforms = false; @@ -69,7 +69,7 @@ void MslResourceBindingContext::emitStructuredResourceBindings(GenContext& conte ShaderStage& stage, const std::string& structInstanceName, const std::string& arraySuffix) { - ShaderGenerator& generator = context.getShaderGenerator(); + const ShaderGenerator& generator = context.getShaderGenerator(); const size_t baseAlignment = 16; // Values are adjusted based on diff --git a/source/MaterialXGenMsl/MslShaderGenerator.cpp b/source/MaterialXGenMsl/MslShaderGenerator.cpp index dcb0a3ed69..c6f8ed979f 100644 --- a/source/MaterialXGenMsl/MslShaderGenerator.cpp +++ b/source/MaterialXGenMsl/MslShaderGenerator.cpp @@ -6,15 +6,8 @@ #include #include -#include -#include -#include -#include -#include #include #include -#include -#include #include #include #include @@ -23,9 +16,6 @@ #include #include #include -#include -#include -#include #include #include @@ -34,6 +24,15 @@ #include #include #include +#include +#include +#include +#include +#include +#include +#include +#include +#include #include #include #include @@ -170,16 +169,16 @@ MslShaderGenerator::MslShaderGenerator() : registerImplementation(elementNames, CombineNode::create); // - registerImplementation("IM_position_vector3_" + MslShaderGenerator::TARGET, PositionNodeMsl::create); + registerImplementation("IM_position_vector3_" + MslShaderGenerator::TARGET, HwPositionNode::create); // - registerImplementation("IM_normal_vector3_" + MslShaderGenerator::TARGET, NormalNodeMsl::create); + registerImplementation("IM_normal_vector3_" + MslShaderGenerator::TARGET, HwNormalNode::create); // - registerImplementation("IM_tangent_vector3_" + MslShaderGenerator::TARGET, TangentNodeMsl::create); + registerImplementation("IM_tangent_vector3_" + MslShaderGenerator::TARGET, HwTangentNode::create); // - registerImplementation("IM_bitangent_vector3_" + MslShaderGenerator::TARGET, BitangentNodeMsl::create); + registerImplementation("IM_bitangent_vector3_" + MslShaderGenerator::TARGET, HwBitangentNode::create); // - registerImplementation("IM_texcoord_vector2_" + MslShaderGenerator::TARGET, TexCoordNodeMsl::create); - registerImplementation("IM_texcoord_vector3_" + MslShaderGenerator::TARGET, TexCoordNodeMsl::create); + registerImplementation("IM_texcoord_vector2_" + MslShaderGenerator::TARGET, HwTexCoordNode::create); + registerImplementation("IM_texcoord_vector3_" + MslShaderGenerator::TARGET, HwTexCoordNode::create); // registerImplementation("IM_geomcolor_float_" + MslShaderGenerator::TARGET, GeomColorNodeMsl::create); registerImplementation("IM_geomcolor_color3_" + MslShaderGenerator::TARGET, GeomColorNodeMsl::create); @@ -199,9 +198,11 @@ MslShaderGenerator::MslShaderGenerator() : registerImplementation("IM_geompropvalue_string_" + MslShaderGenerator::TARGET, GeomPropValueNodeMslAsUniform::create); // - registerImplementation("IM_frame_float_" + MslShaderGenerator::TARGET, FrameNodeMsl::create); + registerImplementation("IM_frame_float_" + MslShaderGenerator::TARGET, HwFrameNode::create); // - registerImplementation("IM_time_float_" + MslShaderGenerator::TARGET, TimeNodeMsl::create); + registerImplementation("IM_time_float_" + MslShaderGenerator::TARGET, HwTimeNode::create); + // + registerImplementation("IM_viewdirection_vector3_" + MslShaderGenerator::TARGET, HwViewDirectionNode::create); // registerImplementation("IM_surface_" + MslShaderGenerator::TARGET, SurfaceNodeMsl::create); @@ -232,13 +233,13 @@ MslShaderGenerator::MslShaderGenerator() : registerImplementation(elementNames, BlurNodeMsl::create); // elementNames = { @@ -283,9 +284,7 @@ ShaderPtr MslShaderGenerator::generate(const string& name, ElementPtr element, G { ShaderPtr shader = createShader(name, element, context); - // Turn on fixed float formatting to make sure float values are - // emitted with a decimal point and not as integers, and to avoid - // any scientific notation which isn't supported by all OpenGL targets. + // Request fixed floating-point notation for consistency across targets. ScopedFloatFormatting fmt(Value::FloatFormatFixed); // Make sure we initialize/reset the binding context before generation. @@ -605,7 +604,7 @@ void MslShaderGenerator::emitGlobalVariables(GenContext& context, bool hasUniforms = false; for (const ShaderPort* uniform : uniforms.getVariableOrder()) { - if (uniform->getType() == Type::FILENAME) + if (*uniform->getType() == *Type::FILENAME) { emitString(separator, stage); emitString("texture2d " + TEXTURE_NAME(uniform->getVariable()), stage); @@ -1022,7 +1021,7 @@ void MslShaderGenerator::emitPixelStage(const ShaderGraph& graph, GenContext& co emitLightData(context, stage); } } - + bool needsLightBuffer = lighting && context.getOptions().hwMaxActiveLightSources > 0; emitMathMatrixScalarMathOperators(context, stage); @@ -1059,7 +1058,14 @@ void MslShaderGenerator::emitPixelStage(const ShaderGraph& graph, GenContext& co // Emit directional albedo table code. if (context.getOptions().hwWriteAlbedoTable) { - emitLibraryInclude("pbrlib/genglsl/lib/mx_table.glsl", context, stage); + emitLibraryInclude("pbrlib/genglsl/lib/mx_generate_albedo_table.glsl", context, stage); + emitLineBreak(stage); + } + + // Emit environment prefiltering code + if (context.getOptions().hwWriteEnvPrefilter) + { + emitLibraryInclude("pbrlib/genglsl/lib/mx_generate_prefilter_env.glsl", context, stage); emitLineBreak(stage); } @@ -1108,6 +1114,10 @@ void MslShaderGenerator::emitPixelStage(const ShaderGraph& graph, GenContext& co { emitLine(outputSocket->getVariable() + " = float4(mx_generate_dir_albedo_table(), 1.0)", stage); } + else if (context.getOptions().hwWriteEnvPrefilter) + { + emitLine(outputSocket->getVariable() + " = float4(mx_generate_prefilter_env(), 1.0)", stage); + } else { // Add all function calls. @@ -1272,11 +1282,11 @@ void MslShaderGenerator::toVec4(const TypeDesc* type, string& variable) { variable = "float4(" + variable + ", 0.0, 1.0)"; } - else if (type == Type::FLOAT || type == Type::INTEGER) + else if (*type == *Type::FLOAT || *type == *Type::INTEGER) { variable = "float4(" + variable + ", " + variable + ", " + variable + ", 1.0)"; } - else if (type == Type::BSDF || type == Type::EDF) + else if (*type == *Type::BSDF || *type == *Type::EDF) { variable = "float4(" + variable + ", 1.0)"; } @@ -1292,7 +1302,7 @@ void MslShaderGenerator::emitVariableDeclaration(const ShaderPort* variable, con bool assignValue) const { // A file texture input needs special handling on MSL - if (variable->getType() == Type::FILENAME) + if (*variable->getType() == *Type::FILENAME) { // Samplers must always be uniforms string str = qualifier.empty() ? EMPTY_STRING : qualifier + " "; @@ -1317,7 +1327,7 @@ void MslShaderGenerator::emitVariableDeclaration(const ShaderPort* variable, con // Varying parameters of type int must be flat qualified on output from vertex stage and // input to pixel stage. The only way to get these is with geompropvalue_integer nodes. - if (qualifier.empty() && variable->getType() == Type::INTEGER && !assignValue && variable->getName().rfind(HW::T_IN_GEOMPROP, 0) == 0) + if (qualifier.empty() && *variable->getType() == *Type::INTEGER && !assignValue && variable->getName().rfind(HW::T_IN_GEOMPROP, 0) == 0) { str += "[[ " + MslSyntax::FLAT_QUALIFIER + " ]]"; } @@ -1362,7 +1372,7 @@ ShaderNodeImplPtr MslShaderGenerator::getImplementation(const NodeDef& nodedef, if (implElement->isA()) { // Use a compound implementation. - if (outputType == Type::LIGHTSHADER) + if (*outputType == *Type::LIGHTSHADER) { impl = LightCompoundNodeMsl::create(); } @@ -1405,36 +1415,9 @@ ShaderNodeImplPtr MslShaderGenerator::getImplementation(const NodeDef& nodedef, return impl; } -const string MslImplementation::SPACE = "space"; -const string MslImplementation::TO_SPACE = "tospace"; -const string MslImplementation::FROM_SPACE = "fromspace"; -const string MslImplementation::WORLD = "world"; -const string MslImplementation::OBJECT = "object"; -const string MslImplementation::MODEL = "model"; -const string MslImplementation::INDEX = "index"; -const string MslImplementation::GEOMPROP = "geomprop"; - -namespace -{ - -// List name of inputs that are not to be editable and -// published as shader uniforms in MSL. -const std::set IMMUTABLE_INPUTS = -{ - // Geometric node inputs are immutable since a shader needs regeneration if they change. - "index", "space", "attrname" -}; - -} // namespace - const string& MslImplementation::getTarget() const { return MslShaderGenerator::TARGET; } -bool MslImplementation::isEditable(const ShaderInput& input) const -{ - return IMMUTABLE_INPUTS.count(input.getName()) == 0; -} - MATERIALX_NAMESPACE_END diff --git a/source/MaterialXGenMsl/MslShaderGenerator.h b/source/MaterialXGenMsl/MslShaderGenerator.h index ecbf37d7a6..e9f2981045 100644 --- a/source/MaterialXGenMsl/MslShaderGenerator.h +++ b/source/MaterialXGenMsl/MslShaderGenerator.h @@ -48,7 +48,7 @@ class MX_GENMSL_API MslShaderGenerator : public HwShaderGenerator ShaderNodeImplPtr getImplementation(const NodeDef& nodedef, GenContext& context) const override; /// Determine the prefix of vertex data variables. - virtual string getVertexDataPrefix(const VariableBlock& vertexData) const; + string getVertexDataPrefix(const VariableBlock& vertexData) const override; public: /// Unique identifier for this generator target @@ -115,35 +115,13 @@ class MX_GENMSL_API MslShaderGenerator : public HwShaderGenerator }; /// Base class for common MSL node implementations -class MX_GENMSL_API MslImplementation : public ShaderNodeImpl +class MX_GENMSL_API MslImplementation : public HwImplementation { public: const string& getTarget() const override; - bool isEditable(const ShaderInput& input) const override; - protected: MslImplementation() { } - - // Integer identifiers for coordinate spaces. - // The order must match the order given for - // the space enum string in stdlib. - enum Space - { - MODEL_SPACE = 0, - OBJECT_SPACE = 1, - WORLD_SPACE = 2 - }; - - /// Internal string constants - static const string SPACE; - static const string TO_SPACE; - static const string FROM_SPACE; - static const string WORLD; - static const string OBJECT; - static const string MODEL; - static const string INDEX; - static const string GEOMPROP; }; MATERIALX_NAMESPACE_END diff --git a/source/MaterialXGenMsl/MslSyntax.cpp b/source/MaterialXGenMsl/MslSyntax.cpp index a1e2d6bb83..a4ec46e0c0 100644 --- a/source/MaterialXGenMsl/MslSyntax.cpp +++ b/source/MaterialXGenMsl/MslSyntax.cpp @@ -352,7 +352,7 @@ bool MslSyntax::remapEnumeration(const string& value, const TypeDesc* type, cons // Don't convert already supported types // or filenames and arrays. if (typeSupported(type) || - type == Type::FILENAME || (type && type->isArray())) + *type == *Type::FILENAME || (type && type->isArray())) { return false; } diff --git a/source/MaterialXGenMsl/Nodes/BitangentNodeMsl.h b/source/MaterialXGenMsl/Nodes/BitangentNodeMsl.h deleted file mode 100644 index 7239bb36d4..0000000000 --- a/source/MaterialXGenMsl/Nodes/BitangentNodeMsl.h +++ /dev/null @@ -1,26 +0,0 @@ -// -// Copyright Contributors to the MaterialX Project -// SPDX-License-Identifier: Apache-2.0 -// - -#ifndef MATERIALX_BITANGENTNODEMSL_H -#define MATERIALX_BITANGENTNODEMSL_H - -#include - -MATERIALX_NAMESPACE_BEGIN - -/// Bitangent node implementation for MSL -class MX_GENMSL_API BitangentNodeMsl : public MslImplementation -{ - public: - static ShaderNodeImplPtr create(); - - void createVariables(const ShaderNode& node, GenContext& context, Shader& shader) const override; - - void emitFunctionCall(const ShaderNode& node, GenContext& context, ShaderStage& stage) const override; -}; - -MATERIALX_NAMESPACE_END - -#endif diff --git a/source/MaterialXGenMsl/Nodes/FrameNodeMsl.h b/source/MaterialXGenMsl/Nodes/FrameNodeMsl.h deleted file mode 100644 index 4ad554102b..0000000000 --- a/source/MaterialXGenMsl/Nodes/FrameNodeMsl.h +++ /dev/null @@ -1,26 +0,0 @@ -// -// Copyright Contributors to the MaterialX Project -// SPDX-License-Identifier: Apache-2.0 -// - -#ifndef MATERIALX_FRAMENODEMSL_H -#define MATERIALX_FRAMENODEMSL_H - -#include - -MATERIALX_NAMESPACE_BEGIN - -/// Frame node implementation for MSL -class MX_GENMSL_API FrameNodeMsl : public MslImplementation -{ - public: - static ShaderNodeImplPtr create(); - - void createVariables(const ShaderNode& node, GenContext& context, Shader& shader) const override; - - void emitFunctionCall(const ShaderNode& node, GenContext& context, ShaderStage& stage) const override; -}; - -MATERIALX_NAMESPACE_END - -#endif diff --git a/source/MaterialXGenMsl/Nodes/GeomColorNodeMsl.cpp b/source/MaterialXGenMsl/Nodes/GeomColorNodeMsl.cpp index 3845e2ae76..c540960906 100644 --- a/source/MaterialXGenMsl/Nodes/GeomColorNodeMsl.cpp +++ b/source/MaterialXGenMsl/Nodes/GeomColorNodeMsl.cpp @@ -49,11 +49,11 @@ void GeomColorNodeMsl::emitFunctionCall(const ShaderNode& node, GenContext& cont DEFINE_SHADER_STAGE(stage, Stage::PIXEL) { string suffix = ""; - if (output->getType() == Type::FLOAT) + if (*output->getType() == *Type::FLOAT) { suffix = ".r"; } - else if (output->getType() == Type::COLOR3) + else if (*output->getType() == *Type::COLOR3) { suffix = ".rgb"; } diff --git a/source/MaterialXGenMsl/Nodes/HeightToNormalNodeMsl.cpp b/source/MaterialXGenMsl/Nodes/HeightToNormalNodeMsl.cpp index 12b1a9675c..2f07e55dfd 100644 --- a/source/MaterialXGenMsl/Nodes/HeightToNormalNodeMsl.cpp +++ b/source/MaterialXGenMsl/Nodes/HeightToNormalNodeMsl.cpp @@ -33,6 +33,11 @@ ShaderNodeImplPtr HeightToNormalNodeMsl::create() return std::make_shared(); } +void HeightToNormalNodeMsl::createVariables(const ShaderNode&, GenContext&, Shader&) const +{ + // Default filter kernels from ConvolutionNode are not used by this derived class. +} + void HeightToNormalNodeMsl::computeSampleOffsetStrings(const string& sampleSizeName, const string& offsetTypeString, unsigned int, StringVec& offsetStrings) const { @@ -49,7 +54,7 @@ void HeightToNormalNodeMsl::computeSampleOffsetStrings(const string& sampleSizeN bool HeightToNormalNodeMsl::acceptsInputType(const TypeDesc* type) const { // Only support inputs which are float scalar - return (type == Type::FLOAT && type->isScalar()); + return (*type == *Type::FLOAT && type->isScalar()); } void HeightToNormalNodeMsl::emitFunctionDefinition(const ShaderNode&, GenContext& context, ShaderStage& stage) const diff --git a/source/MaterialXGenMsl/Nodes/HeightToNormalNodeMsl.h b/source/MaterialXGenMsl/Nodes/HeightToNormalNodeMsl.h index 752c411ed5..035ad300b4 100644 --- a/source/MaterialXGenMsl/Nodes/HeightToNormalNodeMsl.h +++ b/source/MaterialXGenMsl/Nodes/HeightToNormalNodeMsl.h @@ -18,6 +18,8 @@ class MX_GENMSL_API HeightToNormalNodeMsl : public ConvolutionNode public: static ShaderNodeImplPtr create(); + void createVariables(const ShaderNode&, GenContext&, Shader& shader) const override; + void emitFunctionDefinition(const ShaderNode& node, GenContext& context, ShaderStage& stage) const override; void emitFunctionCall(const ShaderNode& node, GenContext& context, ShaderStage& stage) const override; diff --git a/source/MaterialXGenMsl/Nodes/NormalNodeMsl.cpp b/source/MaterialXGenMsl/Nodes/NormalNodeMsl.cpp deleted file mode 100644 index 6250290960..0000000000 --- a/source/MaterialXGenMsl/Nodes/NormalNodeMsl.cpp +++ /dev/null @@ -1,88 +0,0 @@ -// -// Copyright Contributors to the MaterialX Project -// SPDX-License-Identifier: Apache-2.0 -// - -#include - -#include - -MATERIALX_NAMESPACE_BEGIN - -ShaderNodeImplPtr NormalNodeMsl::create() -{ - return std::make_shared(); -} - -void NormalNodeMsl::createVariables(const ShaderNode& node, GenContext&, Shader& shader) const -{ - ShaderStage& vs = shader.getStage(Stage::VERTEX); - ShaderStage& ps = shader.getStage(Stage::PIXEL); - - addStageInput(HW::VERTEX_INPUTS, Type::VECTOR3, HW::T_IN_NORMAL, vs); - - const ShaderInput* spaceInput = node.getInput(SPACE); - const int space = spaceInput ? spaceInput->getValue()->asA() : OBJECT_SPACE; - if (space == WORLD_SPACE) - { - addStageUniform(HW::PRIVATE_UNIFORMS, Type::MATRIX44, HW::T_WORLD_INVERSE_TRANSPOSE_MATRIX, vs); - addStageConnector(HW::VERTEX_DATA, Type::VECTOR3, HW::T_NORMAL_WORLD, vs, ps); - } - else - { - addStageConnector(HW::VERTEX_DATA, Type::VECTOR3, HW::T_NORMAL_OBJECT, vs, ps); - } -} - -void NormalNodeMsl::emitFunctionCall(const ShaderNode& node, GenContext& context, ShaderStage& stage) const -{ - const MslShaderGenerator& shadergen = static_cast(context.getShaderGenerator()); - - const ShaderInput* spaceInput = node.getInput(SPACE); - const int space = spaceInput ? spaceInput->getValue()->asA() : OBJECT_SPACE; - - DEFINE_SHADER_STAGE(stage, Stage::VERTEX) - { - VariableBlock& vertexData = stage.getOutputBlock(HW::VERTEX_DATA); - const string prefix = shadergen.getVertexDataPrefix(vertexData); - if (space == WORLD_SPACE) - { - ShaderPort* normal = vertexData[HW::T_NORMAL_WORLD]; - if (!normal->isEmitted()) - { - normal->setEmitted(); - shadergen.emitLine(prefix + normal->getVariable() + " = normalize((" + HW::T_WORLD_INVERSE_TRANSPOSE_MATRIX + " * float4(" + HW::T_IN_NORMAL + ", 0.0)).xyz)", stage); - } - } - else - { - ShaderPort* normal = vertexData[HW::T_NORMAL_OBJECT]; - if (!normal->isEmitted()) - { - normal->setEmitted(); - shadergen.emitLine(prefix + normal->getVariable() + " = " + HW::T_IN_NORMAL, stage); - } - } - } - - DEFINE_SHADER_STAGE(stage, Stage::PIXEL) - { - VariableBlock& vertexData = stage.getInputBlock(HW::VERTEX_DATA); - const string prefix = shadergen.getVertexDataPrefix(vertexData); - shadergen.emitLineBegin(stage); - shadergen.emitOutput(node.getOutput(), true, false, context, stage); - if (space == WORLD_SPACE) - { - const ShaderPort* normal = vertexData[HW::T_NORMAL_WORLD]; - shadergen.emitString(" = normalize(" + prefix + normal->getVariable() + ")", stage); - } - else - { - const ShaderPort* normal = vertexData[HW::T_NORMAL_OBJECT]; - shadergen.emitString(" = normalize(" + prefix + normal->getVariable() + ")", stage); - } - shadergen.emitLineEnd(stage); - } -} - -MATERIALX_NAMESPACE_END diff --git a/source/MaterialXGenMsl/Nodes/NormalNodeMsl.h b/source/MaterialXGenMsl/Nodes/NormalNodeMsl.h deleted file mode 100644 index 7248613a74..0000000000 --- a/source/MaterialXGenMsl/Nodes/NormalNodeMsl.h +++ /dev/null @@ -1,26 +0,0 @@ -// -// Copyright Contributors to the MaterialX Project -// SPDX-License-Identifier: Apache-2.0 -// - -#ifndef MATERIALX_NORMALNODEMSL_H -#define MATERIALX_NORMALNODEMSL_H - -#include - -MATERIALX_NAMESPACE_BEGIN - -/// Normal node implementation for MSL -class MX_GENMSL_API NormalNodeMsl : public MslImplementation -{ - public: - static ShaderNodeImplPtr create(); - - void createVariables(const ShaderNode& node, GenContext& context, Shader& shader) const override; - - void emitFunctionCall(const ShaderNode& node, GenContext& context, ShaderStage& stage) const override; -}; - -MATERIALX_NAMESPACE_END - -#endif diff --git a/source/MaterialXGenMsl/Nodes/PositionNodeMsl.h b/source/MaterialXGenMsl/Nodes/PositionNodeMsl.h deleted file mode 100644 index 1dada988be..0000000000 --- a/source/MaterialXGenMsl/Nodes/PositionNodeMsl.h +++ /dev/null @@ -1,26 +0,0 @@ -// -// Copyright Contributors to the MaterialX Project -// SPDX-License-Identifier: Apache-2.0 -// - -#ifndef MATERIALX_POSITIONNODEMSL_H -#define MATERIALX_POSITIONNODEMSL_H - -#include - -MATERIALX_NAMESPACE_BEGIN - -/// Position node implementation for MSL -class MX_GENMSL_API PositionNodeMsl : public MslImplementation -{ - public: - static ShaderNodeImplPtr create(); - - void createVariables(const ShaderNode& node, GenContext& context, Shader& shader) const override; - - void emitFunctionCall(const ShaderNode& node, GenContext& context, ShaderStage& stage) const override; -}; - -MATERIALX_NAMESPACE_END - -#endif diff --git a/source/MaterialXGenMsl/Nodes/SurfaceNodeMsl.cpp b/source/MaterialXGenMsl/Nodes/SurfaceNodeMsl.cpp index c7fb7745b7..bd0cd91fb1 100644 --- a/source/MaterialXGenMsl/Nodes/SurfaceNodeMsl.cpp +++ b/source/MaterialXGenMsl/Nodes/SurfaceNodeMsl.cpp @@ -45,8 +45,8 @@ void SurfaceNodeMsl::createVariables(const ShaderNode&, GenContext& context, Sha { // TODO: // The surface shader needs position, normal, view position and light sources. We should solve this by adding some - // dependency mechanism so this implementation can be set to depend on the PositionNodeMsl, NormalNodeMsl - // ViewDirectionNodeMsl and LightNodeMsl nodes instead? This is where the MaterialX attribute "internalgeomprops" + // dependency mechanism so this implementation can be set to depend on the HwPositionNode, HwNormalNode + // HwViewDirectionNode and LightNodeMsl nodes instead? This is where the MaterialX attribute "internalgeomprops" // is needed. // ShaderStage& vs = shader.getStage(Stage::VERTEX); diff --git a/source/MaterialXGenMsl/Nodes/SurfaceShaderNodeMsl.cpp b/source/MaterialXGenMsl/Nodes/SurfaceShaderNodeMsl.cpp index a579c46f1b..a09796a557 100644 --- a/source/MaterialXGenMsl/Nodes/SurfaceShaderNodeMsl.cpp +++ b/source/MaterialXGenMsl/Nodes/SurfaceShaderNodeMsl.cpp @@ -24,8 +24,8 @@ void SurfaceShaderNodeMsl::createVariables(const ShaderNode&, GenContext& contex { // TODO: // The surface shader needs position, view position and light sources. We should solve this by adding some - // dependency mechanism so this implementation can be set to depend on the PositionNodeMsl, - // ViewDirectionNodeMsl and LightNodeMsl nodes instead? This is where the MaterialX attribute "internalgeomprops" + // dependency mechanism so this implementation can be set to depend on the HwPositionNode, + // HwViewDirectionNode and LightNodeMsl nodes instead? This is where the MaterialX attribute "internalgeomprops" // is needed. // ShaderStage& vs = shader.getStage(Stage::VERTEX); diff --git a/source/MaterialXGenMsl/Nodes/TangentNodeMsl.cpp b/source/MaterialXGenMsl/Nodes/TangentNodeMsl.cpp deleted file mode 100644 index 5e557e4e30..0000000000 --- a/source/MaterialXGenMsl/Nodes/TangentNodeMsl.cpp +++ /dev/null @@ -1,88 +0,0 @@ -// -// Copyright Contributors to the MaterialX Project -// SPDX-License-Identifier: Apache-2.0 -// - -#include - -#include - -MATERIALX_NAMESPACE_BEGIN - -ShaderNodeImplPtr TangentNodeMsl::create() -{ - return std::make_shared(); -} - -void TangentNodeMsl::createVariables(const ShaderNode& node, GenContext&, Shader& shader) const -{ - ShaderStage& vs = shader.getStage(Stage::VERTEX); - ShaderStage& ps = shader.getStage(Stage::PIXEL); - - addStageInput(HW::VERTEX_INPUTS, Type::VECTOR3, HW::T_IN_TANGENT, vs); - - const ShaderInput* spaceInput = node.getInput(SPACE); - const int space = spaceInput ? spaceInput->getValue()->asA() : OBJECT_SPACE; - if (space == WORLD_SPACE) - { - addStageUniform(HW::PRIVATE_UNIFORMS, Type::MATRIX44, HW::T_WORLD_MATRIX, vs); - addStageConnector(HW::VERTEX_DATA, Type::VECTOR3, HW::T_TANGENT_WORLD, vs, ps); - } - else - { - addStageConnector(HW::VERTEX_DATA, Type::VECTOR3, HW::T_TANGENT_OBJECT, vs, ps); - } -} - -void TangentNodeMsl::emitFunctionCall(const ShaderNode& node, GenContext& context, ShaderStage& stage) const -{ - const MslShaderGenerator& shadergen = static_cast(context.getShaderGenerator()); - - const ShaderInput* spaceInput = node.getInput(SPACE); - const int space = spaceInput ? spaceInput->getValue()->asA() : OBJECT_SPACE; - - DEFINE_SHADER_STAGE(stage, Stage::VERTEX) - { - VariableBlock& vertexData = stage.getOutputBlock(HW::VERTEX_DATA); - const string prefix = shadergen.getVertexDataPrefix(vertexData); - if (space == WORLD_SPACE) - { - ShaderPort* tangent = vertexData[HW::T_TANGENT_WORLD]; - if (!tangent->isEmitted()) - { - tangent->setEmitted(); - shadergen.emitLine(prefix + tangent->getVariable() + " = normalize((" + HW::T_WORLD_MATRIX + " * float4(" + HW::T_IN_TANGENT + ", 0.0)).xyz)", stage); - } - } - else - { - ShaderPort* tangent = vertexData[HW::T_TANGENT_OBJECT]; - if (!tangent->isEmitted()) - { - tangent->setEmitted(); - shadergen.emitLine(prefix + tangent->getVariable() + " = " + HW::T_IN_TANGENT, stage); - } - } - } - - DEFINE_SHADER_STAGE(stage, Stage::PIXEL) - { - VariableBlock& vertexData = stage.getInputBlock(HW::VERTEX_DATA); - const string prefix = shadergen.getVertexDataPrefix(vertexData); - shadergen.emitLineBegin(stage); - shadergen.emitOutput(node.getOutput(), true, false, context, stage); - if (space == WORLD_SPACE) - { - const ShaderPort* tangent = vertexData[HW::T_TANGENT_WORLD]; - shadergen.emitString(" = normalize(" + prefix + tangent->getVariable() + ")", stage); - } - else - { - const ShaderPort* tangent = vertexData[HW::T_TANGENT_OBJECT]; - shadergen.emitString(" = normalize(" + prefix + tangent->getVariable() + ")", stage); - } - shadergen.emitLineEnd(stage); - } -} - -MATERIALX_NAMESPACE_END diff --git a/source/MaterialXGenMsl/Nodes/TangentNodeMsl.h b/source/MaterialXGenMsl/Nodes/TangentNodeMsl.h deleted file mode 100644 index 42e2c7ef7c..0000000000 --- a/source/MaterialXGenMsl/Nodes/TangentNodeMsl.h +++ /dev/null @@ -1,26 +0,0 @@ -// -// Copyright Contributors to the MaterialX Project -// SPDX-License-Identifier: Apache-2.0 -// - -#ifndef MATERIALX_TANGENTNODEMSL_H -#define MATERIALX_TANGENTNODEMSL_H - -#include - -MATERIALX_NAMESPACE_BEGIN - -/// Tangent node implementation for MSL -class MX_GENMSL_API TangentNodeMsl : public MslImplementation -{ - public: - static ShaderNodeImplPtr create(); - - void createVariables(const ShaderNode& node, GenContext& context, Shader& shader) const override; - - void emitFunctionCall(const ShaderNode& node, GenContext& context, ShaderStage& stage) const override; -}; - -MATERIALX_NAMESPACE_END - -#endif diff --git a/source/MaterialXGenMsl/Nodes/TexCoordNodeMsl.cpp b/source/MaterialXGenMsl/Nodes/TexCoordNodeMsl.cpp deleted file mode 100644 index a88152eb82..0000000000 --- a/source/MaterialXGenMsl/Nodes/TexCoordNodeMsl.cpp +++ /dev/null @@ -1,62 +0,0 @@ -// -// Copyright Contributors to the MaterialX Project -// SPDX-License-Identifier: Apache-2.0 -// - -#include - -#include - -MATERIALX_NAMESPACE_BEGIN - -ShaderNodeImplPtr TexCoordNodeMsl::create() -{ - return std::make_shared(); -} - -void TexCoordNodeMsl::createVariables(const ShaderNode& node, GenContext&, Shader& shader) const -{ - const ShaderOutput* output = node.getOutput(); - const ShaderInput* indexInput = node.getInput(INDEX); - const string index = indexInput ? indexInput->getValue()->getValueString() : "0"; - - ShaderStage& vs = shader.getStage(Stage::VERTEX); - ShaderStage& ps = shader.getStage(Stage::PIXEL); - - addStageInput(HW::VERTEX_INPUTS, output->getType(), HW::T_IN_TEXCOORD + "_" + index, vs); - addStageConnector(HW::VERTEX_DATA, output->getType(), HW::T_TEXCOORD + "_" + index, vs, ps); -} - -void TexCoordNodeMsl::emitFunctionCall(const ShaderNode& node, GenContext& context, ShaderStage& stage) const -{ - const MslShaderGenerator& shadergen = static_cast(context.getShaderGenerator()); - - const ShaderInput* indexInput = node.getInput(INDEX); - const string index = indexInput ? indexInput->getValue()->getValueString() : "0"; - const string variable = HW::T_TEXCOORD + "_" + index; - - DEFINE_SHADER_STAGE(stage, Stage::VERTEX) - { - VariableBlock& vertexData = stage.getOutputBlock(HW::VERTEX_DATA); - const string prefix = shadergen.getVertexDataPrefix(vertexData); - ShaderPort* texcoord = vertexData[variable]; - if (!texcoord->isEmitted()) - { - shadergen.emitLine(prefix + texcoord->getVariable() + " = " + HW::T_IN_TEXCOORD + "_" + index, stage); - texcoord->setEmitted(); - } - } - - DEFINE_SHADER_STAGE(stage, Stage::PIXEL) - { - VariableBlock& vertexData = stage.getInputBlock(HW::VERTEX_DATA); - const string prefix = shadergen.getVertexDataPrefix(vertexData); - ShaderPort* texcoord = vertexData[variable]; - shadergen.emitLineBegin(stage); - shadergen.emitOutput(node.getOutput(), true, false, context, stage); - shadergen.emitString(" = " + prefix + texcoord->getVariable(), stage); - shadergen.emitLineEnd(stage); - } -} - -MATERIALX_NAMESPACE_END diff --git a/source/MaterialXGenMsl/Nodes/TexCoordNodeMsl.h b/source/MaterialXGenMsl/Nodes/TexCoordNodeMsl.h deleted file mode 100644 index 6c227cc63b..0000000000 --- a/source/MaterialXGenMsl/Nodes/TexCoordNodeMsl.h +++ /dev/null @@ -1,26 +0,0 @@ -// -// Copyright Contributors to the MaterialX Project -// SPDX-License-Identifier: Apache-2.0 -// - -#ifndef MATERIALX_TEXCOORDNODEMSL_H -#define MATERIALX_TEXCOORDNODEMSL_H - -#include - -MATERIALX_NAMESPACE_BEGIN - -/// TexCoord node implementation for MSL -class MX_GENMSL_API TexCoordNodeMsl : public MslImplementation -{ - public: - static ShaderNodeImplPtr create(); - - void createVariables(const ShaderNode& node, GenContext& context, Shader& shader) const override; - - void emitFunctionCall(const ShaderNode& node, GenContext& context, ShaderStage& stage) const override; -}; - -MATERIALX_NAMESPACE_END - -#endif diff --git a/source/MaterialXGenMsl/Nodes/TimeNodeMsl.h b/source/MaterialXGenMsl/Nodes/TimeNodeMsl.h deleted file mode 100644 index 07c505a082..0000000000 --- a/source/MaterialXGenMsl/Nodes/TimeNodeMsl.h +++ /dev/null @@ -1,26 +0,0 @@ -// -// Copyright Contributors to the MaterialX Project -// SPDX-License-Identifier: Apache-2.0 -// - -#ifndef MATERIALX_TIMENODEMSL_H -#define MATERIALX_TIMENODEMSL_H - -#include - -MATERIALX_NAMESPACE_BEGIN - -/// Time node implementation for MSL -class MX_GENMSL_API TimeNodeMsl : public MslImplementation -{ - public: - static ShaderNodeImplPtr create(); - - void createVariables(const ShaderNode& node, GenContext& context, Shader& shader) const override; - - void emitFunctionCall(const ShaderNode& node, GenContext& context, ShaderStage& stage) const override; -}; - -MATERIALX_NAMESPACE_END - -#endif diff --git a/source/MaterialXGenMsl/Nodes/TransformNormalNodeMsl.cpp b/source/MaterialXGenMsl/Nodes/TransformNormalNodeMsl.cpp deleted file mode 100644 index 98810c025b..0000000000 --- a/source/MaterialXGenMsl/Nodes/TransformNormalNodeMsl.cpp +++ /dev/null @@ -1,43 +0,0 @@ -// -// Copyright Contributors to the MaterialX Project -// SPDX-License-Identifier: Apache-2.0 -// - -#include - -MATERIALX_NAMESPACE_BEGIN - -ShaderNodeImplPtr TransformNormalNodeMsl::create() -{ - return std::make_shared(); -} - -void TransformNormalNodeMsl::emitFunctionCall(const ShaderNode& node, GenContext& context, ShaderStage& stage) const -{ - TransformVectorNodeMsl::emitFunctionCall(node, context, stage); - - DEFINE_SHADER_STAGE(stage, Stage::PIXEL) - { - const ShaderGenerator& shadergen = context.getShaderGenerator(); - const ShaderOutput* output = node.getOutput(); - shadergen.emitLineBegin(stage); - shadergen.emitOutput(output, false, false, context, stage); - shadergen.emitString(" = normalize(" + output->getVariable() + ")", stage); - shadergen.emitLineEnd(stage); - } -} - -const string& TransformNormalNodeMsl::getMatrix(const string& fromSpace, const string& toSpace) const -{ - if ((fromSpace == MODEL || fromSpace == OBJECT) && toSpace == WORLD) - { - return HW::T_WORLD_INVERSE_TRANSPOSE_MATRIX; - } - else if (fromSpace == WORLD && (toSpace == MODEL || toSpace == OBJECT)) - { - return HW::T_WORLD_TRANSPOSE_MATRIX; - } - return EMPTY_STRING; -} - -MATERIALX_NAMESPACE_END diff --git a/source/MaterialXGenMsl/Nodes/TransformNormalNodeMsl.h b/source/MaterialXGenMsl/Nodes/TransformNormalNodeMsl.h deleted file mode 100644 index 603ba3771c..0000000000 --- a/source/MaterialXGenMsl/Nodes/TransformNormalNodeMsl.h +++ /dev/null @@ -1,27 +0,0 @@ -// -// Copyright Contributors to the MaterialX Project -// SPDX-License-Identifier: Apache-2.0 -// - -#ifndef MATERIALX_TRANSFORMNORMALNODEMSL_H -#define MATERIALX_TRANSFORMNORMALNODEMSL_H - -#include - -MATERIALX_NAMESPACE_BEGIN - -/// TransformNormal node implementation for MSL -class MX_GENMSL_API TransformNormalNodeMsl : public TransformVectorNodeMsl -{ - public: - static ShaderNodeImplPtr create(); - - protected: - void emitFunctionCall(const ShaderNode& node, GenContext& context, ShaderStage& stage) const override; - - const string& getMatrix(const string& fromSpace, const string& toSpace) const override; -}; - -MATERIALX_NAMESPACE_END - -#endif diff --git a/source/MaterialXGenMsl/Nodes/TransformPointNodeMsl.cpp b/source/MaterialXGenMsl/Nodes/TransformPointNodeMsl.cpp deleted file mode 100644 index 38db776855..0000000000 --- a/source/MaterialXGenMsl/Nodes/TransformPointNodeMsl.cpp +++ /dev/null @@ -1,23 +0,0 @@ -// -// Copyright Contributors to the MaterialX Project -// SPDX-License-Identifier: Apache-2.0 -// - -#include - -#include - -MATERIALX_NAMESPACE_BEGIN - -ShaderNodeImplPtr TransformPointNodeMsl::create() -{ - return std::make_shared(); -} - -string TransformPointNodeMsl::getHomogeneousCoordinate(const ShaderInput* in, GenContext& context) const -{ - const ShaderGenerator& shadergen = context.getShaderGenerator(); - return "float4(" + shadergen.getUpstreamResult(in, context) + ", 1.0)"; -} - -MATERIALX_NAMESPACE_END diff --git a/source/MaterialXGenMsl/Nodes/TransformPointNodeMsl.h b/source/MaterialXGenMsl/Nodes/TransformPointNodeMsl.h deleted file mode 100644 index 9fc2361d7d..0000000000 --- a/source/MaterialXGenMsl/Nodes/TransformPointNodeMsl.h +++ /dev/null @@ -1,25 +0,0 @@ -// -// Copyright Contributors to the MaterialX Project -// SPDX-License-Identifier: Apache-2.0 -// - -#ifndef MATERIALX_TRANSFORMPOINTNODEMSL_H -#define MATERIALX_TRANSFORMPOINTNODEMSL_H - -#include - -MATERIALX_NAMESPACE_BEGIN - -/// TransformPoint node implementation for MSL -class MX_GENMSL_API TransformPointNodeMsl : public TransformVectorNodeMsl -{ - public: - static ShaderNodeImplPtr create(); - - protected: - virtual string getHomogeneousCoordinate(const ShaderInput* in, GenContext& context) const override; -}; - -MATERIALX_NAMESPACE_END - -#endif diff --git a/source/MaterialXGenMsl/Nodes/TransformVectorNodeMsl.cpp b/source/MaterialXGenMsl/Nodes/TransformVectorNodeMsl.cpp deleted file mode 100644 index c5d6ce242a..0000000000 --- a/source/MaterialXGenMsl/Nodes/TransformVectorNodeMsl.cpp +++ /dev/null @@ -1,84 +0,0 @@ -// -// Copyright Contributors to the MaterialX Project -// SPDX-License-Identifier: Apache-2.0 -// - -#include - -#include - -MATERIALX_NAMESPACE_BEGIN - -ShaderNodeImplPtr TransformVectorNodeMsl::create() -{ - return std::make_shared(); -} - -void TransformVectorNodeMsl::createVariables(const ShaderNode& node, GenContext&, Shader& shader) const -{ - const ShaderInput* toSpaceInput = node.getInput(TO_SPACE); - string toSpace = toSpaceInput ? toSpaceInput->getValue()->getValueString() : EMPTY_STRING; - - const ShaderInput* fromSpaceInput = node.getInput(FROM_SPACE); - string fromSpace = fromSpaceInput ? fromSpaceInput->getValue()->getValueString() : EMPTY_STRING; - - const string& matrix = getMatrix(fromSpace, toSpace); - if (!matrix.empty()) - { - ShaderStage& ps = shader.getStage(Stage::PIXEL); - addStageUniform(HW::PRIVATE_UNIFORMS, Type::MATRIX44, matrix, ps); - } -} - -void TransformVectorNodeMsl::emitFunctionCall(const ShaderNode& node, GenContext& context, ShaderStage& stage) const -{ - DEFINE_SHADER_STAGE(stage, Stage::PIXEL) - { - const ShaderGenerator& shadergen = context.getShaderGenerator(); - - const ShaderInput* inInput = node.getInput("in"); - if (inInput->getType() != Type::VECTOR3 && inInput->getType() != Type::VECTOR4) - { - throw ExceptionShaderGenError("Transform node must have 'in' type of vector3 or vector4."); - } - - const ShaderInput* toSpaceInput = node.getInput(TO_SPACE); - string toSpace = toSpaceInput ? toSpaceInput->getValue()->getValueString() : EMPTY_STRING; - - const ShaderInput* fromSpaceInput = node.getInput(FROM_SPACE); - string fromSpace = fromSpaceInput ? fromSpaceInput->getValue()->getValueString() : EMPTY_STRING; - - shadergen.emitLineBegin(stage); - shadergen.emitOutput(node.getOutput(), true, false, context, stage); - shadergen.emitString(" = (", stage); - const string& matrix = getMatrix(fromSpace, toSpace); - if (!matrix.empty()) - { - shadergen.emitString(matrix + " * ", stage); - } - shadergen.emitString(getHomogeneousCoordinate(inInput, context), stage); - shadergen.emitString(").xyz", stage); - shadergen.emitLineEnd(stage); - } -} - -const string& TransformVectorNodeMsl::getMatrix(const string& fromSpace, const string& toSpace) const -{ - if ((fromSpace == MODEL || fromSpace == OBJECT) && toSpace == WORLD) - { - return HW::T_WORLD_MATRIX; - } - else if (fromSpace == WORLD && (toSpace == MODEL || toSpace == OBJECT)) - { - return HW::T_WORLD_INVERSE_MATRIX; - } - return EMPTY_STRING; -} - -string TransformVectorNodeMsl::getHomogeneousCoordinate(const ShaderInput* in, GenContext& context) const -{ - const ShaderGenerator& shadergen = context.getShaderGenerator(); - return "float4(" + shadergen.getUpstreamResult(in, context) + ", 0.0)"; -} - -MATERIALX_NAMESPACE_END diff --git a/source/MaterialXGenMsl/Nodes/TransformVectorNodeMsl.h b/source/MaterialXGenMsl/Nodes/TransformVectorNodeMsl.h deleted file mode 100644 index 013a3db29a..0000000000 --- a/source/MaterialXGenMsl/Nodes/TransformVectorNodeMsl.h +++ /dev/null @@ -1,30 +0,0 @@ -// -// Copyright Contributors to the MaterialX Project -// SPDX-License-Identifier: Apache-2.0 -// - -#ifndef MATERIALX_TRANSFORMVECTORNODEMSL_H -#define MATERIALX_TRANSFORMVECTORNODEMSL_H - -#include - -MATERIALX_NAMESPACE_BEGIN - -/// TransformVector node implementation for MSL -class MX_GENMSL_API TransformVectorNodeMsl : public MslImplementation -{ - public: - static ShaderNodeImplPtr create(); - - void createVariables(const ShaderNode& node, GenContext& context, Shader& shader) const override; - - void emitFunctionCall(const ShaderNode& node, GenContext& context, ShaderStage& stage) const override; - - protected: - virtual const string& getMatrix(const string& fromSpace, const string& toSpace) const; - virtual string getHomogeneousCoordinate(const ShaderInput* in, GenContext& context) const; -}; - -MATERIALX_NAMESPACE_END - -#endif diff --git a/source/MaterialXGenOsl/Nodes/ClosureLayerNodeOsl.cpp b/source/MaterialXGenOsl/Nodes/ClosureLayerNodeOsl.cpp index 7c3f9d460c..31f245e9e6 100644 --- a/source/MaterialXGenOsl/Nodes/ClosureLayerNodeOsl.cpp +++ b/source/MaterialXGenOsl/Nodes/ClosureLayerNodeOsl.cpp @@ -92,7 +92,7 @@ void ClosureLayerNodeOsl::emitFunctionCall(const ShaderNode& _node, GenContext& // Calculate the layering result. emitOutputVariables(node, context, stage); - if (base->getOutput()->getType() == Type::VDF) + if (*base->getOutput()->getType() == *Type::VDF) { // Combining a surface closure with a volumetric closure is simply done with the add operator in OSL. shadergen.emitLine(output->getVariable() + ".response = " + topResult + ".response + " + baseResult, stage); diff --git a/source/MaterialXGenOsl/OslShaderGenerator.cpp b/source/MaterialXGenOsl/OslShaderGenerator.cpp index a67c379454..95bee59a2e 100644 --- a/source/MaterialXGenOsl/OslShaderGenerator.cpp +++ b/source/MaterialXGenOsl/OslShaderGenerator.cpp @@ -26,7 +26,6 @@ MATERIALX_NAMESPACE_BEGIN const string OslShaderGenerator::TARGET = "genosl"; -const string OslShaderGenerator::T_FILE_EXTRA_ARGUMENTS = "$extraTextureLookupArguments"; // // OslShaderGenerator methods @@ -161,15 +160,15 @@ OslShaderGenerator::OslShaderGenerator() : // registerImplementation("IM_surfacematerial_" + OslShaderGenerator::TARGET, MaterialNodeOsl::create); - - // Extra arguments for texture lookups. - _tokenSubstitutions[T_FILE_EXTRA_ARGUMENTS] = EMPTY_STRING; } ShaderPtr OslShaderGenerator::generate(const string& name, ElementPtr element, GenContext& context) const { ShaderPtr shader = createShader(name, element, context); + // Request fixed floating-point notation for consistency across targets. + ScopedFloatFormatting fmt(Value::FloatFormatFixed); + ShaderGraph& graph = shader->getGraph(); ShaderStage& stage = shader->getStage(Stage::PIXEL); @@ -197,11 +196,11 @@ ShaderPtr OslShaderGenerator::generate(const string& name, ElementPtr element, G // Emit shader type, determined from the first // output if there are multiple outputs. const ShaderGraphOutputSocket* outputSocket0 = graph.getOutputSocket(0); - if (outputSocket0->getType() == Type::SURFACESHADER) + if (*outputSocket0->getType() == *Type::SURFACESHADER) { emitString("surface ", stage); } - else if (outputSocket0->getType() == Type::VOLUMESHADER) + else if (*outputSocket0->getType() == *Type::VOLUMESHADER) { emitString("volume ", stage); } @@ -251,10 +250,10 @@ ShaderPtr OslShaderGenerator::generate(const string& name, ElementPtr element, G const VariableBlock& outputs = stage.getOutputBlock(OSL::OUTPUTS); const ShaderPort* singleOutput = outputs.size() == 1 ? outputs[0] : NULL; - const bool isSurfaceShaderOutput = singleOutput && singleOutput->getType() == Type::SURFACESHADER; + const bool isSurfaceShaderOutput = singleOutput && *singleOutput->getType() == *Type::SURFACESHADER; #ifdef MATERIALX_OSL_LEGACY_CLOSURES - const bool isBsdfOutput = singleOutput && singleOutput->getType() == Type::BSDF; + const bool isBsdfOutput = singleOutput && *singleOutput->getType() == *Type::BSDF; #endif if (isSurfaceShaderOutput) @@ -295,6 +294,25 @@ ShaderPtr OslShaderGenerator::generate(const string& name, ElementPtr element, G emitLineBreak(stage); } + // Inputs of type 'filename' has been generated into two shader inputs. + // So here we construct a single 'textureresource' from these inputs, + // to be used further downstream. See emitShaderInputs() for details. + VariableBlock& inputs = stage.getUniformBlock(OSL::UNIFORMS); + for (size_t i = 0; i < inputs.size(); ++i) + { + ShaderPort* input = inputs[i]; + if (*input->getType() == *Type::FILENAME) + { + // Construct the textureresource variable. + const string newVariableName = input->getVariable() + "_"; + const string& type = _syntax->getTypeName(input->getType()); + emitLine(type + newVariableName + " = {" + input->getVariable() + ", " + input->getVariable() + "_colorspace}", stage); + + // Update the variable name to be used downstream. + input->setVariable(newVariableName); + } + } + // Emit all texturing nodes. These are inputs to any // closure/shader nodes and need to be emitted first. emitFunctionCalls(graph, context, stage, ShaderNode::Classification::TEXTURE); @@ -490,111 +508,75 @@ void OslShaderGenerator::emitLibraryIncludes(ShaderStage& stage, GenContext& con emitLineBreak(stage); } -namespace -{ - -std::unordered_map GEOMPROP_DEFINITIONS = -{ - { "Pobject", "transform(\"object\", P)" }, - { "Pworld", "P" }, - { "Nobject", "transform(\"object\", N)" }, - { "Nworld", "N" }, - { "Tobject", "transform(\"object\", dPdu)" }, - { "Tworld", "dPdu" }, - { "Bobject", "transform(\"object\", dPdv)" }, - { "Bworld", "dPdv" }, - { "UV0", "{u,v}" }, - { "Vworld", "I" } -}; - -} // anonymous namespace - void OslShaderGenerator::emitShaderInputs(const VariableBlock& inputs, ShaderStage& stage) const { - const std::unordered_map UI_WIDGET_METADATA = + static const std::unordered_map GEOMPROP_DEFINITIONS = { - { Type::FLOAT, ShaderMetadata("widget", Type::STRING, Value::createValueFromStrings("number", Type::STRING->getName())) }, - { Type::INTEGER, ShaderMetadata("widget", Type::STRING, Value::createValueFromStrings("number", Type::STRING->getName())) }, - { Type::FILENAME, ShaderMetadata("widget", Type::STRING, Value::createValueFromStrings("filename", Type::STRING->getName())) }, - { Type::BOOLEAN, ShaderMetadata("widget", Type::STRING, Value::createValueFromStrings("checkBox", Type::STRING->getName())) } - }; - - const std::set METADATA_TYPE_BLACKLIST = - { - Type::VECTOR2, // Custom struct types doesn't support metadata declarations. - Type::VECTOR4, // - Type::COLOR4, // - Type::FILENAME, // - Type::BSDF // + { "Pobject", "transform(\"object\", P)" }, + { "Pworld", "P" }, + { "Nobject", "transform(\"object\", N)" }, + { "Nworld", "N" }, + { "Tobject", "transform(\"object\", dPdu)" }, + { "Tworld", "dPdu" }, + { "Bobject", "transform(\"object\", dPdv)" }, + { "Bworld", "dPdv" }, + { "UV0", "{u,v}" }, + { "Vworld", "I" } }; for (size_t i = 0; i < inputs.size(); ++i) { const ShaderPort* input = inputs[i]; - const string& type = _syntax->getTypeName(input->getType()); - string value = _syntax->getValue(input, true); - emitLineBegin(stage); - emitString(type + " " + input->getVariable(), stage); - - const string& geomprop = input->getGeomProp(); - if (!geomprop.empty()) + if (*input->getType() == *Type::FILENAME) { - auto it = GEOMPROP_DEFINITIONS.find(geomprop); - if (it != GEOMPROP_DEFINITIONS.end()) - { - value = it->second; - } + // Shader inputs of type 'filename' (textures) need special handling. + // In OSL codegen a 'filename' is translated to the custom type 'textureresource', + // which is a struct containing a file string and a colorspace string. + // For the published shader interface we here split this into two separate inputs, + // which gives a nicer shader interface with widget metadata on each input. + + ValuePtr value = input->getValue(); + const string valueStr = value ? value->getValueString() : EMPTY_STRING; + + // Add the file string input + emitLineBegin(stage); + emitString("string " + input->getVariable() + " = \"" + valueStr + "\"", stage); + emitMetadata(input, stage); + emitString(",", stage); + emitLineEnd(stage, false); + + // Add the colorspace string input + emitLineBegin(stage); + emitString("string " + input->getVariable() + "_colorspace = \"" + input->getColorSpace() + "\"", stage); + emitLineEnd(stage, false); + emitScopeBegin(stage, Syntax::DOUBLE_SQUARE_BRACKETS); + emitLine("string widget = \"colorspace\"", stage, false); + emitScopeEnd(stage, false, false); } - - if (value.empty()) + else { - value = _syntax->getDefaultValue(input->getType()); - } - emitString(" = " + value, stage); - - // - // Add shader input metadata. - // + emitLineBegin(stage); + emitString(type + " " + input->getVariable(), stage); - auto widgetMetadataIt = UI_WIDGET_METADATA.find(input->getType()); - const ShaderMetadata* widgetMetadata = widgetMetadataIt != UI_WIDGET_METADATA.end() ? &widgetMetadataIt->second : nullptr; - const ShaderMetadataVecPtr& metadata = input->getMetadata(); - - if (widgetMetadata || (metadata && metadata->size())) - { - StringVec metadataLines; - if (metadata) + string value = _syntax->getValue(input, true); + const string& geomprop = input->getGeomProp(); + if (!geomprop.empty()) { - for (size_t j = 0; j < metadata->size(); ++j) + auto it = GEOMPROP_DEFINITIONS.find(geomprop); + if (it != GEOMPROP_DEFINITIONS.end()) { - const ShaderMetadata& data = metadata->at(j); - if (METADATA_TYPE_BLACKLIST.count(data.type) == 0) - { - const string& delim = (widgetMetadata || j < metadata->size() - 1) ? Syntax::COMMA : EMPTY_STRING; - const string& dataType = _syntax->getTypeName(data.type); - const string dataValue = _syntax->getValue(data.type, *data.value, true); - metadataLines.push_back(dataType + " " + data.name + " = " + dataValue + delim); - } + value = it->second; } } - if (widgetMetadata) + if (value.empty()) { - const string& dataType = _syntax->getTypeName(widgetMetadata->type); - const string dataValue = _syntax->getValue(widgetMetadata->type, *widgetMetadata->value, true); - metadataLines.push_back(dataType + " " + widgetMetadata->name + " = " + dataValue); - } - if (metadataLines.size()) - { - emitLineEnd(stage, false); - emitScopeBegin(stage, Syntax::DOUBLE_SQUARE_BRACKETS); - for (auto line : metadataLines) - { - emitLine(line, stage, false); - } - emitScopeEnd(stage, false, false); + value = _syntax->getDefaultValue(input->getType()); } + + emitString(" = " + value, stage); + emitMetadata(input, stage); } if (i < inputs.size()) @@ -619,6 +601,65 @@ void OslShaderGenerator::emitShaderOutputs(const VariableBlock& outputs, ShaderS } } +void OslShaderGenerator::emitMetadata(const ShaderPort* port, ShaderStage& stage) const +{ + static const std::unordered_map UI_WIDGET_METADATA = + { + { Type::FLOAT, ShaderMetadata("widget", Type::STRING, Value::createValueFromStrings("number", Type::STRING->getName())) }, + { Type::INTEGER, ShaderMetadata("widget", Type::STRING, Value::createValueFromStrings("number", Type::STRING->getName())) }, + { Type::FILENAME, ShaderMetadata("widget", Type::STRING, Value::createValueFromStrings("filename", Type::STRING->getName())) }, + { Type::BOOLEAN, ShaderMetadata("widget", Type::STRING, Value::createValueFromStrings("checkBox", Type::STRING->getName())) } + }; + + static const std::set METADATA_TYPE_BLACKLIST = + { + Type::VECTOR2, // Custom struct types doesn't support metadata declarations. + Type::VECTOR4, // + Type::COLOR4, // + Type::FILENAME, // + Type::BSDF // + }; + + auto widgetMetadataIt = UI_WIDGET_METADATA.find(port->getType()); + const ShaderMetadata* widgetMetadata = widgetMetadataIt != UI_WIDGET_METADATA.end() ? &widgetMetadataIt->second : nullptr; + const ShaderMetadataVecPtr& metadata = port->getMetadata(); + + if (widgetMetadata || (metadata && metadata->size())) + { + StringVec metadataLines; + if (metadata) + { + for (size_t j = 0; j < metadata->size(); ++j) + { + const ShaderMetadata& data = metadata->at(j); + if (METADATA_TYPE_BLACKLIST.count(data.type) == 0) + { + const string& delim = (widgetMetadata || j < metadata->size() - 1) ? Syntax::COMMA : EMPTY_STRING; + const string& dataType = _syntax->getTypeName(data.type); + const string dataValue = _syntax->getValue(data.type, *data.value, true); + metadataLines.push_back(dataType + " " + data.name + " = " + dataValue + delim); + } + } + } + if (widgetMetadata) + { + const string& dataType = _syntax->getTypeName(widgetMetadata->type); + const string dataValue = _syntax->getValue(widgetMetadata->type, *widgetMetadata->value, true); + metadataLines.push_back(dataType + " " + widgetMetadata->name + " = " + dataValue); + } + if (metadataLines.size()) + { + emitLineEnd(stage, false); + emitScopeBegin(stage, Syntax::DOUBLE_SQUARE_BRACKETS); + for (const auto& line : metadataLines) + { + emitLine(line, stage, false); + } + emitScopeEnd(stage, false, false); + } + } +} + namespace OSL { diff --git a/source/MaterialXGenOsl/OslShaderGenerator.h b/source/MaterialXGenOsl/OslShaderGenerator.h index 91690adc1d..e5cf13977e 100644 --- a/source/MaterialXGenOsl/OslShaderGenerator.h +++ b/source/MaterialXGenOsl/OslShaderGenerator.h @@ -48,9 +48,6 @@ class MX_GENOSL_API OslShaderGenerator : public ShaderGenerator void registerShaderMetadata(const DocumentPtr& doc, GenContext& context) const override; protected: - // Extra file arguments for texture lookup call - static const string T_FILE_EXTRA_ARGUMENTS; - /// Create and initialize a new OSL shader for shader generation. virtual ShaderPtr createShader(const string& name, ElementPtr element, GenContext& context) const; @@ -62,6 +59,9 @@ class MX_GENOSL_API OslShaderGenerator : public ShaderGenerator /// Emit a block of shader outputs. virtual void emitShaderOutputs(const VariableBlock& inputs, ShaderStage& stage) const; + + /// Emit metadata for a shader parameter. + virtual void emitMetadata(const ShaderPort* port, ShaderStage& stage) const; }; namespace OSL diff --git a/source/MaterialXGenOsl/OslSyntax.cpp b/source/MaterialXGenOsl/OslSyntax.cpp index d421c5e3d9..5a6b45dd61 100644 --- a/source/MaterialXGenOsl/OslSyntax.cpp +++ b/source/MaterialXGenOsl/OslSyntax.cpp @@ -220,7 +220,6 @@ class OSLMatrix3TypeSyntax : public AggregateTypeSyntax string getValue(const Value& value, bool uniform) const override { - ScopedFloatFormatting fmt(Value::FloatFormatFixed, 3); StringVec values = splitString(value.getValueString(), ","); return getValue(values, uniform); } diff --git a/source/MaterialXGenShader/GenContext.h b/source/MaterialXGenShader/GenContext.h index f1de04ace6..1a936ac0dd 100644 --- a/source/MaterialXGenShader/GenContext.h +++ b/source/MaterialXGenShader/GenContext.h @@ -125,6 +125,24 @@ class MX_GENSHADER_API GenContext return _closureContexts.size() ? _closureContexts.back() : nullptr; } + /// Push a parent node onto the stack + void pushParentNode(ConstNodePtr node) + { + _parentNodes.push_back(node); + } + + /// Pop the current parent node from the stack. + void popParentNode() + { + _parentNodes.pop_back(); + } + + /// Return the current stack of parent nodes. + const vector& getParentNodes() + { + return _parentNodes; + } + /// Add user data to the context to make it /// available during shader generator. void pushUserData(const string& name, GenUserDataPtr data) @@ -216,6 +234,7 @@ class MX_GENSHADER_API GenContext std::unordered_map _outputSuffix; vector _closureContexts; + vector _parentNodes; ApplicationVariableHandler _applicationVariableHandler; }; diff --git a/source/MaterialXGenShader/GenOptions.h b/source/MaterialXGenShader/GenOptions.h index 2876d297f2..ee312a97d6 100644 --- a/source/MaterialXGenShader/GenOptions.h +++ b/source/MaterialXGenShader/GenOptions.h @@ -90,6 +90,7 @@ class MX_GENSHADER_API GenOptions hwMaxActiveLightSources(3), hwNormalizeUdimTexCoords(false), hwWriteAlbedoTable(false), + hwWriteEnvPrefilter(false), hwImplicitBitangents(true), emitColorTransforms(true), elideConnectedConstants(true), @@ -176,6 +177,10 @@ class MX_GENSHADER_API GenOptions /// Defaults to false. bool hwWriteAlbedoTable; + /// Enables the generation of a prefiltered environment map. + /// Defaults to false. + bool hwWriteEnvPrefilter; + /// Calculate fallback bitangents from existing normals and tangents /// inside the bitangent node. bool hwImplicitBitangents; diff --git a/source/MaterialXGenShader/HwShaderGenerator.cpp b/source/MaterialXGenShader/HwShaderGenerator.cpp index 568c666478..0f13e95736 100644 --- a/source/MaterialXGenShader/HwShaderGenerator.cpp +++ b/source/MaterialXGenShader/HwShaderGenerator.cpp @@ -12,6 +12,24 @@ MATERIALX_NAMESPACE_BEGIN +const string HwImplementation::SPACE = "space"; +const string HwImplementation::INDEX = "index"; +const string HwImplementation::GEOMPROP = "geomprop"; + +namespace +{ + +// When node inputs with these names are modified, we assume the +// associated HW shader must be recompiled. +const StringSet IMMUTABLE_INPUTS = +{ + "index", + "space", + "attrname" +}; + +} // anonymous namespace + namespace HW { @@ -59,6 +77,8 @@ const string T_ENV_RADIANCE = "$envRadiance"; const string T_ENV_RADIANCE_MIPS = "$envRadianceMips"; const string T_ENV_RADIANCE_SAMPLES = "$envRadianceSamples"; const string T_ENV_IRRADIANCE = "$envIrradiance"; +const string T_ENV_LIGHT_INTENSITY = "$envLightIntensity"; +const string T_ENV_PREFILTER_MIP = "$envPrefilterMip"; const string T_REFRACTION_TWO_SIDED = "$refractionTwoSided"; const string T_ALBEDO_TABLE = "$albedoTable"; const string T_ALBEDO_TABLE_SIZE = "$albedoTableSize"; @@ -113,6 +133,8 @@ const string ENV_RADIANCE = "u_envRadiance"; const string ENV_RADIANCE_MIPS = "u_envRadianceMips"; const string ENV_RADIANCE_SAMPLES = "u_envRadianceSamples"; const string ENV_IRRADIANCE = "u_envIrradiance"; +const string ENV_LIGHT_INTENSITY = "u_envLightIntensity"; +const string ENV_PREFILTER_MIP = "u_envPrefilterMip"; const string REFRACTION_TWO_SIDED = "u_refractionTwoSided"; const string ALBEDO_TABLE = "u_albedoTable"; const string ALBEDO_TABLE_SIZE = "u_albedoTableSize"; @@ -213,6 +235,7 @@ HwShaderGenerator::HwShaderGenerator(SyntaxPtr syntax) : _tokenSubstitutions[HW::T_ENV_RADIANCE_MIPS] = HW::ENV_RADIANCE_MIPS; _tokenSubstitutions[HW::T_ENV_RADIANCE_SAMPLES] = HW::ENV_RADIANCE_SAMPLES; _tokenSubstitutions[HW::T_ENV_IRRADIANCE] = HW::ENV_IRRADIANCE; + _tokenSubstitutions[HW::T_ENV_LIGHT_INTENSITY] = HW::ENV_LIGHT_INTENSITY; _tokenSubstitutions[HW::T_REFRACTION_TWO_SIDED] = HW::REFRACTION_TWO_SIDED; _tokenSubstitutions[HW::T_ALBEDO_TABLE] = HW::ALBEDO_TABLE; _tokenSubstitutions[HW::T_ALBEDO_TABLE_SIZE] = HW::ALBEDO_TABLE_SIZE; @@ -222,6 +245,7 @@ HwShaderGenerator::HwShaderGenerator(SyntaxPtr syntax) : _tokenSubstitutions[HW::T_AMB_OCC_GAIN] = HW::AMB_OCC_GAIN; _tokenSubstitutions[HW::T_VERTEX_DATA_INSTANCE] = HW::VERTEX_DATA_INSTANCE; _tokenSubstitutions[HW::T_LIGHT_DATA_INSTANCE] = HW::LIGHT_DATA_INSTANCE; + _tokenSubstitutions[HW::T_ENV_PREFILTER_MIP] = HW::ENV_PREFILTER_MIP; // Setup closure contexts for defining closure functions // @@ -260,9 +284,9 @@ ShaderPtr HwShaderGenerator::createShader(const string& name, ElementPtr element if (geomprop) { // A default geomprop was assigned to this graph input. - // For all internal connections to this input, break the connection + // For all internal connections to this input, break the connection // and assign a geomprop node that generates this data. - // Note: If a geomprop node exists already it is reused, + // Note: If a geomprop node exists already it is reused, // so only a single node per geometry type is created. ShaderInputVec connections = socket->getConnections(); for (auto connection : connections) @@ -345,6 +369,7 @@ ShaderPtr HwShaderGenerator::createShader(const string& name, ElementPtr element const Matrix44 yRotationPI = Matrix44::createScale(Vector3(-1, 1, -1)); psPrivateUniforms->add(Type::MATRIX44, HW::T_ENV_MATRIX, Value::createValue(yRotationPI)); psPrivateUniforms->add(Type::FILENAME, HW::T_ENV_RADIANCE); + psPrivateUniforms->add(Type::FLOAT, HW::T_ENV_LIGHT_INTENSITY, Value::createValue(1.0f)); psPrivateUniforms->add(Type::INTEGER, HW::T_ENV_RADIANCE_MIPS, Value::createValue(1)); psPrivateUniforms->add(Type::INTEGER, HW::T_ENV_RADIANCE_SAMPLES, Value::createValue(16)); psPrivateUniforms->add(Type::FILENAME, HW::T_ENV_IRRADIANCE); @@ -359,6 +384,17 @@ ShaderPtr HwShaderGenerator::createShader(const string& name, ElementPtr element psPrivateUniforms->add(Type::INTEGER, HW::T_ALBEDO_TABLE_SIZE, Value::createValue(64)); } + // Add uniforms for environment prefiltering. + if (context.getOptions().hwWriteEnvPrefilter) + { + psPrivateUniforms->add(Type::FILENAME, HW::T_ENV_RADIANCE); + psPrivateUniforms->add(Type::FLOAT, HW::T_ENV_LIGHT_INTENSITY, Value::createValue(1.0f)); + psPrivateUniforms->add(Type::INTEGER, HW::T_ENV_PREFILTER_MIP, Value::createValue(1)); + const Matrix44 yRotationPI = Matrix44::createScale(Vector3(-1, 1, -1)); + psPrivateUniforms->add(Type::MATRIX44, HW::T_ENV_MATRIX, Value::createValue(yRotationPI)); + psPrivateUniforms->add(Type::INTEGER, HW::T_ENV_RADIANCE_MIPS, Value::createValue(1)); + } + // Create uniforms for the published graph interface for (ShaderGraphInputSocket* inputSocket : graph->getInputSockets()) { @@ -426,7 +462,7 @@ ShaderPtr HwShaderGenerator::createShader(const string& name, ElementPtr element { for (ShaderInput* input : node->getInputs()) { - if (!input->getConnection() && input->getType() == Type::FILENAME) + if (!input->getConnection() && *input->getType() == *Type::FILENAME) { // Create the uniform using the filename type to make this uniform into a texture sampler. ShaderPort* filename = psPublicUniforms->add(Type::FILENAME, input->getVariable(), input->getValue()); @@ -606,4 +642,9 @@ void HwShaderGenerator::addStageLightingUniforms(GenContext& context, ShaderStag } } +bool HwImplementation::isEditable(const ShaderInput& input) const +{ + return IMMUTABLE_INPUTS.count(input.getName()) == 0; +} + MATERIALX_NAMESPACE_END diff --git a/source/MaterialXGenShader/HwShaderGenerator.h b/source/MaterialXGenShader/HwShaderGenerator.h index 66d60dc68a..bdd1e33a5c 100644 --- a/source/MaterialXGenShader/HwShaderGenerator.h +++ b/source/MaterialXGenShader/HwShaderGenerator.h @@ -71,6 +71,7 @@ Uniform variables : $envMatrix u_envMatrix mat4 Rotation matrix for the environment. $envIrradiance u_envIrradiance sampler2D Sampler for the texture used for diffuse environment lighting. $envRadiance u_envRadiance sampler2D Sampler for the texture used for specular environment lighting. + $envLightIntensity u_envLightIntensity float Linear multiplier for environment lighting $envRadianceMips u_envRadianceMips int Number of mipmaps used on the specular environment texture. $envRadianceSamples u_envRadianceSamples int Samples to use if Filtered Importance Sampling is used for specular environment lighting. @@ -126,6 +127,8 @@ extern MX_GENSHADER_API const string T_ENV_RADIANCE; extern MX_GENSHADER_API const string T_ENV_RADIANCE_MIPS; extern MX_GENSHADER_API const string T_ENV_RADIANCE_SAMPLES; extern MX_GENSHADER_API const string T_ENV_IRRADIANCE; +extern MX_GENSHADER_API const string T_ENV_LIGHT_INTENSITY; +extern MX_GENSHADER_API const string T_ENV_PREFILTER_MIP; extern MX_GENSHADER_API const string T_REFRACTION_TWO_SIDED; extern MX_GENSHADER_API const string T_ALBEDO_TABLE; extern MX_GENSHADER_API const string T_ALBEDO_TABLE_SIZE; @@ -182,6 +185,8 @@ extern MX_GENSHADER_API const string ENV_RADIANCE; extern MX_GENSHADER_API const string ENV_RADIANCE_MIPS; extern MX_GENSHADER_API const string ENV_RADIANCE_SAMPLES; extern MX_GENSHADER_API const string ENV_IRRADIANCE; +extern MX_GENSHADER_API const string ENV_LIGHT_INTENSITY; +extern MX_GENSHADER_API const string ENV_PREFILTER_MIP; extern MX_GENSHADER_API const string REFRACTION_TWO_SIDED; extern MX_GENSHADER_API const string ALBEDO_TABLE; extern MX_GENSHADER_API const string ALBEDO_TABLE_SIZE; @@ -306,6 +311,9 @@ class MX_GENSHADER_API HwShaderGenerator : public ShaderGenerator /// Unbind all light shaders previously bound. static void unbindLightShaders(GenContext& context); + /// Determine the prefix of vertex data variables. + virtual string getVertexDataPrefix(const VariableBlock& vertexData) const = 0; + /// Types of closure contexts for HW. enum ClosureContextType { @@ -335,6 +343,31 @@ class MX_GENSHADER_API HwShaderGenerator : public ShaderGenerator mutable ClosureContext _defEmission; }; +/// @class HwShaderGenerator +/// Base class for HW node implementations. +class MX_GENSHADER_API HwImplementation : public ShaderNodeImpl +{ + public: + bool isEditable(const ShaderInput& input) const override; + + protected: + HwImplementation() { } + + // Integer identifiers for coordinate spaces. + // The order must match the order given for the space enum string in stdlib. + enum Space + { + MODEL_SPACE = 0, + OBJECT_SPACE = 1, + WORLD_SPACE = 2 + }; + + /// Internal string constants + static const string SPACE; + static const string INDEX; + static const string GEOMPROP; +}; + /// @class HwResourceBindingContext /// Class representing a context for resource binding for hardware resources. class MX_GENSHADER_API HwResourceBindingContext : public GenUserData diff --git a/source/MaterialXGenShader/Nodes/BlurNode.cpp b/source/MaterialXGenShader/Nodes/BlurNode.cpp index bd30b40715..56f4de85a9 100644 --- a/source/MaterialXGenShader/Nodes/BlurNode.cpp +++ b/source/MaterialXGenShader/Nodes/BlurNode.cpp @@ -49,7 +49,7 @@ void BlurNode::computeSampleOffsetStrings(const string& sampleSizeName, const st bool BlurNode::acceptsInputType(const TypeDesc* type) const { // Float 1-4 is acceptable as input - return ((type == Type::FLOAT && type->isScalar()) || + return ((*type == *Type::FLOAT && type->isScalar()) || type->isFloat2() || type->isFloat3() || type->isFloat4()); } diff --git a/source/MaterialXGenShader/Nodes/ClosureAddNode.cpp b/source/MaterialXGenShader/Nodes/ClosureAddNode.cpp index 34883c6c36..f401b577d8 100644 --- a/source/MaterialXGenShader/Nodes/ClosureAddNode.cpp +++ b/source/MaterialXGenShader/Nodes/ClosureAddNode.cpp @@ -59,13 +59,13 @@ void ClosureAddNode::emitFunctionCall(const ShaderNode& _node, GenContext& conte const string in2Result = shadergen.getUpstreamResult(in2, context); ShaderOutput* output = node.getOutput(); - if (output->getType() == Type::BSDF) + if (*output->getType() == *Type::BSDF) { emitOutputVariables(node, context, stage); shadergen.emitLine(output->getVariable() + ".response = " + in1Result + ".response + " + in2Result + ".response", stage); shadergen.emitLine(output->getVariable() + ".throughput = " + in1Result + ".throughput * " + in2Result + ".throughput", stage); } - else if (output->getType() == Type::EDF) + else if (*output->getType() == *Type::EDF) { shadergen.emitLine(shadergen.getSyntax().getTypeName(Type::EDF) + " " + output->getVariable() + " = " + in1Result + " + " + in2Result, stage); } diff --git a/source/MaterialXGenShader/Nodes/ClosureCompoundNode.cpp b/source/MaterialXGenShader/Nodes/ClosureCompoundNode.cpp index a5f247926f..1cde95a1a6 100644 --- a/source/MaterialXGenShader/Nodes/ClosureCompoundNode.cpp +++ b/source/MaterialXGenShader/Nodes/ClosureCompoundNode.cpp @@ -171,7 +171,7 @@ void ClosureCompoundNode::emitFunctionCall(const ShaderNode& node, GenContext& c // Check if extra parameters has been added for this node. const ClosureContext::ClosureParams* params = cct->getClosureParams(&node); - if (closureType == Type::BSDF && params) + if (*closureType == *Type::BSDF && params) { // Assign the parameters to the BSDF. for (auto it : *params) diff --git a/source/MaterialXGenShader/Nodes/ClosureLayerNode.cpp b/source/MaterialXGenShader/Nodes/ClosureLayerNode.cpp index a2554365c1..2bcc1377d2 100644 --- a/source/MaterialXGenShader/Nodes/ClosureLayerNode.cpp +++ b/source/MaterialXGenShader/Nodes/ClosureLayerNode.cpp @@ -95,7 +95,7 @@ void ClosureLayerNode::emitFunctionCall(const ShaderNode& _node, GenContext& con // Calculate the layering result. emitOutputVariables(node, context, stage); - if (base->getOutput()->getType() == Type::VDF) + if (*(base->getOutput()->getType()) == *Type::VDF) { shadergen.emitLine(output->getVariable() + ".response = " + topResult + ".response * " + baseResult + ".throughput", stage); shadergen.emitLine(output->getVariable() + ".throughput = " + topResult + ".throughput * " + baseResult + ".throughput", stage); diff --git a/source/MaterialXGenShader/Nodes/ClosureMixNode.cpp b/source/MaterialXGenShader/Nodes/ClosureMixNode.cpp index bd314ac7ed..8e5b737698 100644 --- a/source/MaterialXGenShader/Nodes/ClosureMixNode.cpp +++ b/source/MaterialXGenShader/Nodes/ClosureMixNode.cpp @@ -61,13 +61,13 @@ void ClosureMixNode::emitFunctionCall(const ShaderNode& _node, GenContext& conte const string mixResult = shadergen.getUpstreamResult(mix, context); ShaderOutput* output = node.getOutput(); - if (output->getType() == Type::BSDF) + if (*output->getType() == *Type::BSDF) { emitOutputVariables(node, context, stage); shadergen.emitLine(output->getVariable() + ".response = mix(" + bgResult + ".response, " + fgResult + ".response, " + mixResult + ")", stage); shadergen.emitLine(output->getVariable() + ".throughput = mix(" + bgResult + ".throughput, " + fgResult + ".throughput, " + mixResult + ")", stage); } - else if (output->getType() == Type::EDF) + else if (*output->getType() == *Type::EDF) { shadergen.emitLine(shadergen.getSyntax().getTypeName(Type::EDF) + " " + output->getVariable() + " = mix(" + bgResult + ", " + fgResult + ", " + mixResult + ")", stage); } diff --git a/source/MaterialXGenShader/Nodes/ClosureMultiplyNode.cpp b/source/MaterialXGenShader/Nodes/ClosureMultiplyNode.cpp index ac7906e6bb..d582e19ebf 100644 --- a/source/MaterialXGenShader/Nodes/ClosureMultiplyNode.cpp +++ b/source/MaterialXGenShader/Nodes/ClosureMultiplyNode.cpp @@ -50,7 +50,7 @@ void ClosureMultiplyNode::emitFunctionCall(const ShaderNode& _node, GenContext& const string in2Result = shadergen.getUpstreamResult(in2, context); ShaderOutput* output = node.getOutput(); - if (output->getType() == Type::BSDF) + if (*output->getType() == *Type::BSDF) { const string in2clamped = output->getVariable() + "_in2_clamped"; shadergen.emitLine(syntax.getTypeName(in2->getType()) + " " + in2clamped + " = clamp(" + in2Result + ", 0.0, 1.0)", stage); @@ -59,7 +59,7 @@ void ClosureMultiplyNode::emitFunctionCall(const ShaderNode& _node, GenContext& shadergen.emitLine(output->getVariable() + ".response = " + in1Result + ".response * " + in2clamped, stage); shadergen.emitLine(output->getVariable() + ".throughput = " + in1Result + ".throughput * " + in2clamped, stage); } - else if (output->getType() == Type::EDF) + else if (*output->getType() == *Type::EDF) { shadergen.emitLine(shadergen.getSyntax().getTypeName(Type::EDF) + " " + output->getVariable() + " = " + in1Result + " * " + in2Result, stage); } diff --git a/source/MaterialXGenShader/Nodes/ClosureSourceCodeNode.cpp b/source/MaterialXGenShader/Nodes/ClosureSourceCodeNode.cpp index ec5a9aeabf..a1a53b3bcd 100644 --- a/source/MaterialXGenShader/Nodes/ClosureSourceCodeNode.cpp +++ b/source/MaterialXGenShader/Nodes/ClosureSourceCodeNode.cpp @@ -42,7 +42,7 @@ void ClosureSourceCodeNode::emitFunctionCall(const ShaderNode& node, GenContext& // Check if extra parameters has been added for this node. const TypeDesc* closureType = output->getType(); const ClosureContext::ClosureParams* params = cct->getClosureParams(&node); - if (closureType == Type::BSDF && params) + if (*closureType == *Type::BSDF && params) { // Assign the parameters to the BSDF. for (auto it : *params) diff --git a/source/MaterialXGenShader/Nodes/CombineNode.cpp b/source/MaterialXGenShader/Nodes/CombineNode.cpp index 0237830c52..d7b2eb6e22 100644 --- a/source/MaterialXGenShader/Nodes/CombineNode.cpp +++ b/source/MaterialXGenShader/Nodes/CombineNode.cpp @@ -34,7 +34,7 @@ void CombineNode::emitFunctionCall(const ShaderNode& node, GenContext& context, // components to use for constructing the new value. // StringVec valueComponents; - if (in1->getType() == Type::FLOAT) + if (*in1->getType() == *Type::FLOAT) { // Get the components of the input values. const size_t numInputs = node.numInputs(); @@ -45,7 +45,7 @@ void CombineNode::emitFunctionCall(const ShaderNode& node, GenContext& context, valueComponents[i] = shadergen.getUpstreamResult(input, context); } } - else if (in1->getType() == Type::COLOR3 || in1->getType() == Type::VECTOR3) + else if (*in1->getType() == *Type::COLOR3 || *in1->getType() == *Type::VECTOR3) { const ShaderInput* in2 = node.getInput(1); if (!in2 || in2->getType() != Type::FLOAT) @@ -84,7 +84,7 @@ void CombineNode::emitFunctionCall(const ShaderNode& node, GenContext& context, // Get component from in2 valueComponents[memberSize] = shadergen.getUpstreamResult(in2, context); } - else if (in1->getType() == Type::VECTOR2) + else if (*in1->getType() == *Type::VECTOR2) { const ShaderInput* in2 = node.getInput(1); if (!in2 || (in2->getType() != Type::VECTOR2)) diff --git a/source/MaterialXGenShader/Nodes/ConvolutionNode.cpp b/source/MaterialXGenShader/Nodes/ConvolutionNode.cpp index 45992e013f..892920569e 100644 --- a/source/MaterialXGenShader/Nodes/ConvolutionNode.cpp +++ b/source/MaterialXGenShader/Nodes/ConvolutionNode.cpp @@ -94,12 +94,12 @@ const ShaderInput* ConvolutionNode::getSamplingInput(const ShaderNode& node) con if (node.hasClassification(ShaderNode::Classification::SAMPLE2D)) { const ShaderInput* input = node.getInput(SAMPLE2D_INPUT); - return input->getType() == Type::VECTOR2 ? input : nullptr; + return *input->getType() == *Type::VECTOR2 ? input : nullptr; } else if (node.hasClassification(ShaderNode::Classification::SAMPLE3D)) { const ShaderInput* input = node.getInput(SAMPLE3D_INPUT); - return input->getType() == Type::VECTOR3 ? input : nullptr; + return *input->getType() == *Type::VECTOR3 ? input : nullptr; } return nullptr; } diff --git a/source/MaterialXGenMsl/Nodes/BitangentNodeMsl.cpp b/source/MaterialXGenShader/Nodes/HwBitangentNode.cpp similarity index 91% rename from source/MaterialXGenMsl/Nodes/BitangentNodeMsl.cpp rename to source/MaterialXGenShader/Nodes/HwBitangentNode.cpp index 97ca079d35..83c43a3398 100644 --- a/source/MaterialXGenMsl/Nodes/BitangentNodeMsl.cpp +++ b/source/MaterialXGenShader/Nodes/HwBitangentNode.cpp @@ -3,18 +3,18 @@ // SPDX-License-Identifier: Apache-2.0 // -#include +#include #include MATERIALX_NAMESPACE_BEGIN -ShaderNodeImplPtr BitangentNodeMsl::create() +ShaderNodeImplPtr HwBitangentNode::create() { - return std::make_shared(); + return std::make_shared(); } -void BitangentNodeMsl::createVariables(const ShaderNode& node, GenContext& context, Shader& shader) const +void HwBitangentNode::createVariables(const ShaderNode& node, GenContext& context, Shader& shader) const { const GenOptions& options = context.getOptions(); @@ -51,9 +51,9 @@ void BitangentNodeMsl::createVariables(const ShaderNode& node, GenContext& conte } } -void BitangentNodeMsl::emitFunctionCall(const ShaderNode& node, GenContext& context, ShaderStage& stage) const +void HwBitangentNode::emitFunctionCall(const ShaderNode& node, GenContext& context, ShaderStage& stage) const { - const MslShaderGenerator& shadergen = static_cast(context.getShaderGenerator()); + const HwShaderGenerator& shadergen = static_cast(context.getShaderGenerator()); const GenOptions& options = context.getOptions(); const ShaderInput* spaceInput = node.getInput(SPACE); diff --git a/source/MaterialXGenGlsl/Nodes/TangentNodeGlsl.h b/source/MaterialXGenShader/Nodes/HwBitangentNode.h similarity index 63% rename from source/MaterialXGenGlsl/Nodes/TangentNodeGlsl.h rename to source/MaterialXGenShader/Nodes/HwBitangentNode.h index 90a5b3aaad..a8bfa0bf11 100644 --- a/source/MaterialXGenGlsl/Nodes/TangentNodeGlsl.h +++ b/source/MaterialXGenShader/Nodes/HwBitangentNode.h @@ -3,15 +3,15 @@ // SPDX-License-Identifier: Apache-2.0 // -#ifndef MATERIALX_TANGENTNODEGLSL_H -#define MATERIALX_TANGENTNODEGLSL_H +#ifndef MATERIALX_HWBITANGENTNODE_H +#define MATERIALX_HWBITANGENTNODE_H -#include +#include MATERIALX_NAMESPACE_BEGIN -/// Tangent node implementation for GLSL -class MX_GENGLSL_API TangentNodeGlsl : public GlslImplementation +/// Bitangent node implementation for hardware languages +class MX_GENSHADER_API HwBitangentNode : public HwImplementation { public: static ShaderNodeImplPtr create(); diff --git a/source/MaterialXGenMsl/Nodes/FrameNodeMsl.cpp b/source/MaterialXGenShader/Nodes/HwFrameNode.cpp similarity index 67% rename from source/MaterialXGenMsl/Nodes/FrameNodeMsl.cpp rename to source/MaterialXGenShader/Nodes/HwFrameNode.cpp index faac05027a..cd6a3319a8 100644 --- a/source/MaterialXGenMsl/Nodes/FrameNodeMsl.cpp +++ b/source/MaterialXGenShader/Nodes/HwFrameNode.cpp @@ -3,24 +3,24 @@ // SPDX-License-Identifier: Apache-2.0 // -#include +#include #include MATERIALX_NAMESPACE_BEGIN -ShaderNodeImplPtr FrameNodeMsl::create() +ShaderNodeImplPtr HwFrameNode::create() { - return std::make_shared(); + return std::make_shared(); } -void FrameNodeMsl::createVariables(const ShaderNode&, GenContext&, Shader& shader) const +void HwFrameNode::createVariables(const ShaderNode&, GenContext&, Shader& shader) const { ShaderStage& ps = shader.getStage(Stage::PIXEL); addStageUniform(HW::PRIVATE_UNIFORMS, Type::FLOAT, HW::T_FRAME, ps); } -void FrameNodeMsl::emitFunctionCall(const ShaderNode& node, GenContext& context, ShaderStage& stage) const +void HwFrameNode::emitFunctionCall(const ShaderNode& node, GenContext& context, ShaderStage& stage) const { DEFINE_SHADER_STAGE(stage, Stage::PIXEL) { diff --git a/source/MaterialXGenGlsl/Nodes/TimeNodeGlsl.h b/source/MaterialXGenShader/Nodes/HwFrameNode.h similarity index 65% rename from source/MaterialXGenGlsl/Nodes/TimeNodeGlsl.h rename to source/MaterialXGenShader/Nodes/HwFrameNode.h index c97f6b4741..4487a6a0b9 100644 --- a/source/MaterialXGenGlsl/Nodes/TimeNodeGlsl.h +++ b/source/MaterialXGenShader/Nodes/HwFrameNode.h @@ -3,15 +3,15 @@ // SPDX-License-Identifier: Apache-2.0 // -#ifndef MATERIALX_TIMENODEGLSL_H -#define MATERIALX_TIMENODEGLSL_H +#ifndef MATERIALX_HWFRAMENODE_H +#define MATERIALX_HWFRAMENODE_H -#include +#include MATERIALX_NAMESPACE_BEGIN -/// Time node implementation for GLSL -class MX_GENGLSL_API TimeNodeGlsl : public GlslImplementation +/// Frame node implementation for hardware languages +class MX_GENSHADER_API HwFrameNode : public HwImplementation { public: static ShaderNodeImplPtr create(); diff --git a/source/MaterialXGenGlsl/Nodes/NormalNodeGlsl.cpp b/source/MaterialXGenShader/Nodes/HwNormalNode.cpp similarity index 85% rename from source/MaterialXGenGlsl/Nodes/NormalNodeGlsl.cpp rename to source/MaterialXGenShader/Nodes/HwNormalNode.cpp index d9e27b87df..01234dcb46 100644 --- a/source/MaterialXGenGlsl/Nodes/NormalNodeGlsl.cpp +++ b/source/MaterialXGenShader/Nodes/HwNormalNode.cpp @@ -3,18 +3,18 @@ // SPDX-License-Identifier: Apache-2.0 // -#include +#include #include MATERIALX_NAMESPACE_BEGIN -ShaderNodeImplPtr NormalNodeGlsl::create() +ShaderNodeImplPtr HwNormalNode::create() { - return std::make_shared(); + return std::make_shared(); } -void NormalNodeGlsl::createVariables(const ShaderNode& node, GenContext&, Shader& shader) const +void HwNormalNode::createVariables(const ShaderNode& node, GenContext&, Shader& shader) const { ShaderStage& vs = shader.getStage(Stage::VERTEX); ShaderStage& ps = shader.getStage(Stage::PIXEL); @@ -34,9 +34,9 @@ void NormalNodeGlsl::createVariables(const ShaderNode& node, GenContext&, Shader } } -void NormalNodeGlsl::emitFunctionCall(const ShaderNode& node, GenContext& context, ShaderStage& stage) const +void HwNormalNode::emitFunctionCall(const ShaderNode& node, GenContext& context, ShaderStage& stage) const { - const GlslShaderGenerator& shadergen = static_cast(context.getShaderGenerator()); + const HwShaderGenerator& shadergen = static_cast(context.getShaderGenerator()); const ShaderInput* spaceInput = node.getInput(SPACE); const int space = spaceInput ? spaceInput->getValue()->asA() : OBJECT_SPACE; diff --git a/source/MaterialXGenGlsl/Nodes/PositionNodeGlsl.h b/source/MaterialXGenShader/Nodes/HwNormalNode.h similarity index 64% rename from source/MaterialXGenGlsl/Nodes/PositionNodeGlsl.h rename to source/MaterialXGenShader/Nodes/HwNormalNode.h index 95dddbce8e..fb19050600 100644 --- a/source/MaterialXGenGlsl/Nodes/PositionNodeGlsl.h +++ b/source/MaterialXGenShader/Nodes/HwNormalNode.h @@ -3,15 +3,15 @@ // SPDX-License-Identifier: Apache-2.0 // -#ifndef MATERIALX_POSITIONNODEGLSL_H -#define MATERIALX_POSITIONNODEGLSL_H +#ifndef MATERIALX_HWNORMALNODE_H +#define MATERIALX_HWNORMALNODE_H -#include +#include MATERIALX_NAMESPACE_BEGIN -/// Position node implementation for GLSL -class MX_GENGLSL_API PositionNodeGlsl : public GlslImplementation +/// Normal node implementation for hardware languages +class MX_GENSHADER_API HwNormalNode : public HwImplementation { public: static ShaderNodeImplPtr create(); diff --git a/source/MaterialXGenMsl/Nodes/PositionNodeMsl.cpp b/source/MaterialXGenShader/Nodes/HwPositionNode.cpp similarity index 84% rename from source/MaterialXGenMsl/Nodes/PositionNodeMsl.cpp rename to source/MaterialXGenShader/Nodes/HwPositionNode.cpp index 6f45f4364b..df7c11f4e6 100644 --- a/source/MaterialXGenMsl/Nodes/PositionNodeMsl.cpp +++ b/source/MaterialXGenShader/Nodes/HwPositionNode.cpp @@ -3,18 +3,18 @@ // SPDX-License-Identifier: Apache-2.0 // -#include +#include #include MATERIALX_NAMESPACE_BEGIN -ShaderNodeImplPtr PositionNodeMsl::create() +ShaderNodeImplPtr HwPositionNode::create() { - return std::make_shared(); + return std::make_shared(); } -void PositionNodeMsl::createVariables(const ShaderNode& node, GenContext&, Shader& shader) const +void HwPositionNode::createVariables(const ShaderNode& node, GenContext&, Shader& shader) const { ShaderStage vs = shader.getStage(Stage::VERTEX); ShaderStage ps = shader.getStage(Stage::PIXEL); @@ -33,9 +33,9 @@ void PositionNodeMsl::createVariables(const ShaderNode& node, GenContext&, Shade } } -void PositionNodeMsl::emitFunctionCall(const ShaderNode& node, GenContext& context, ShaderStage& stage) const +void HwPositionNode::emitFunctionCall(const ShaderNode& node, GenContext& context, ShaderStage& stage) const { - const MslShaderGenerator& shadergen = static_cast(context.getShaderGenerator()); + const HwShaderGenerator& shadergen = static_cast(context.getShaderGenerator()); const ShaderInput* spaceInput = node.getInput(SPACE); const int space = spaceInput ? spaceInput->getValue()->asA() : OBJECT_SPACE; diff --git a/source/MaterialXGenGlsl/Nodes/BitangentNodeGlsl.h b/source/MaterialXGenShader/Nodes/HwPositionNode.h similarity index 63% rename from source/MaterialXGenGlsl/Nodes/BitangentNodeGlsl.h rename to source/MaterialXGenShader/Nodes/HwPositionNode.h index 905b2808e0..ae2ce5c3f5 100644 --- a/source/MaterialXGenGlsl/Nodes/BitangentNodeGlsl.h +++ b/source/MaterialXGenShader/Nodes/HwPositionNode.h @@ -3,15 +3,15 @@ // SPDX-License-Identifier: Apache-2.0 // -#ifndef MATERIALX_BITANGENTNODEGLSL_H -#define MATERIALX_BITANGENTNODEGLSL_H +#ifndef MATERIALX_HWPOSITIONNODE_H +#define MATERIALX_HWPOSITIONNODE_H -#include +#include MATERIALX_NAMESPACE_BEGIN -/// Bitangent node implementation for GLSL -class MX_GENGLSL_API BitangentNodeGlsl : public GlslImplementation +/// Position node implementation for hardware languages +class MX_GENSHADER_API HwPositionNode : public HwImplementation { public: static ShaderNodeImplPtr create(); diff --git a/source/MaterialXGenGlsl/Nodes/TangentNodeGlsl.cpp b/source/MaterialXGenShader/Nodes/HwTangentNode.cpp similarity index 85% rename from source/MaterialXGenGlsl/Nodes/TangentNodeGlsl.cpp rename to source/MaterialXGenShader/Nodes/HwTangentNode.cpp index daffaf0e2c..6e80537932 100644 --- a/source/MaterialXGenGlsl/Nodes/TangentNodeGlsl.cpp +++ b/source/MaterialXGenShader/Nodes/HwTangentNode.cpp @@ -3,18 +3,18 @@ // SPDX-License-Identifier: Apache-2.0 // -#include +#include #include MATERIALX_NAMESPACE_BEGIN -ShaderNodeImplPtr TangentNodeGlsl::create() +ShaderNodeImplPtr HwTangentNode::create() { - return std::make_shared(); + return std::make_shared(); } -void TangentNodeGlsl::createVariables(const ShaderNode& node, GenContext&, Shader& shader) const +void HwTangentNode::createVariables(const ShaderNode& node, GenContext&, Shader& shader) const { ShaderStage& vs = shader.getStage(Stage::VERTEX); ShaderStage& ps = shader.getStage(Stage::PIXEL); @@ -34,9 +34,9 @@ void TangentNodeGlsl::createVariables(const ShaderNode& node, GenContext&, Shade } } -void TangentNodeGlsl::emitFunctionCall(const ShaderNode& node, GenContext& context, ShaderStage& stage) const +void HwTangentNode::emitFunctionCall(const ShaderNode& node, GenContext& context, ShaderStage& stage) const { - const GlslShaderGenerator& shadergen = static_cast(context.getShaderGenerator()); + const HwShaderGenerator& shadergen = static_cast(context.getShaderGenerator()); const ShaderInput* spaceInput = node.getInput(SPACE); const int space = spaceInput ? spaceInput->getValue()->asA() : OBJECT_SPACE; diff --git a/source/MaterialXGenGlsl/Nodes/NormalNodeGlsl.h b/source/MaterialXGenShader/Nodes/HwTangentNode.h similarity index 64% rename from source/MaterialXGenGlsl/Nodes/NormalNodeGlsl.h rename to source/MaterialXGenShader/Nodes/HwTangentNode.h index acb4d5085d..b36d7f3c56 100644 --- a/source/MaterialXGenGlsl/Nodes/NormalNodeGlsl.h +++ b/source/MaterialXGenShader/Nodes/HwTangentNode.h @@ -3,15 +3,15 @@ // SPDX-License-Identifier: Apache-2.0 // -#ifndef MATERIALX_NORMALNODEGLSL_H -#define MATERIALX_NORMALNODEGLSL_H +#ifndef MATERIALX_HWTANGENTNODE_H +#define MATERIALX_HWTANGENTNODE_H -#include +#include MATERIALX_NAMESPACE_BEGIN -/// Normal node implementation for GLSL -class MX_GENGLSL_API NormalNodeGlsl : public GlslImplementation +/// Tangent node implementation for hardware languages +class MX_GENSHADER_API HwTangentNode : public HwImplementation { public: static ShaderNodeImplPtr create(); diff --git a/source/MaterialXGenShader/Nodes/HwTexCoordNode.cpp b/source/MaterialXGenShader/Nodes/HwTexCoordNode.cpp new file mode 100644 index 0000000000..3e5c5c0a65 --- /dev/null +++ b/source/MaterialXGenShader/Nodes/HwTexCoordNode.cpp @@ -0,0 +1,83 @@ +// +// Copyright Contributors to the MaterialX Project +// SPDX-License-Identifier: Apache-2.0 +// + +#include +#include +#include + +MATERIALX_NAMESPACE_BEGIN + +string HwTexCoordNode::INDEX = "index"; + +ShaderNodeImplPtr HwTexCoordNode::create() +{ + return std::make_shared(); +} + +void HwTexCoordNode::createVariables(const ShaderNode& node, GenContext&, Shader& shader) const +{ + const ShaderOutput* output = node.getOutput(); + const string index = getIndex(node); + + ShaderStage& vs = shader.getStage(Stage::VERTEX); + ShaderStage& ps = shader.getStage(Stage::PIXEL); + + addStageInput(HW::VERTEX_INPUTS, output->getType(), HW::T_IN_TEXCOORD + "_" + index, vs, true); + addStageConnector(HW::VERTEX_DATA, output->getType(), HW::T_TEXCOORD + "_" + index, vs, ps, true); +} + +void HwTexCoordNode::emitFunctionCall(const ShaderNode& node, GenContext& context, ShaderStage& stage) const +{ + const HwShaderGenerator& shadergen = static_cast(context.getShaderGenerator()); + + const string index = getIndex(node); + const string variable = HW::T_TEXCOORD + "_" + index; + const ShaderOutput* output = node.getOutput(); + + DEFINE_SHADER_STAGE(stage, Stage::VERTEX) + { + VariableBlock& vertexData = stage.getOutputBlock(HW::VERTEX_DATA); + const string prefix = shadergen.getVertexDataPrefix(vertexData); + ShaderPort* texcoord = vertexData[variable]; + if (!texcoord->isEmitted()) + { + shadergen.emitLine(prefix + texcoord->getVariable() + " = " + HW::T_IN_TEXCOORD + "_" + index, stage); + texcoord->setEmitted(); + } + } + + DEFINE_SHADER_STAGE(stage, Stage::PIXEL) + { + VariableBlock& vertexData = stage.getInputBlock(HW::VERTEX_DATA); + const string prefix = shadergen.getVertexDataPrefix(vertexData); + ShaderPort* texcoord = vertexData[variable]; + shadergen.emitLineBegin(stage); + shadergen.emitOutput(output, true, false, context, stage); + + // Extract the requested number of components from the texture coordinates (which may be a + // larger datatype than the requested number of texture coordinates, if several texture + // coordinate nodes with different width coexist). + string suffix = EMPTY_STRING; + if (*output->getType() == *Type::VECTOR2) + { + suffix = ".xy"; + } + else if (*output->getType() == *Type::VECTOR3) + { + suffix = ".xyz"; + } + + shadergen.emitString(" = " + prefix + texcoord->getVariable() + suffix, stage); + shadergen.emitLineEnd(stage); + } +} + +string HwTexCoordNode::getIndex(const ShaderNode& node) const +{ + const ShaderInput* input = node.getInput(INDEX); + return input ? input->getValue()->getValueString() : "0"; +} + +MATERIALX_NAMESPACE_END diff --git a/source/MaterialXGenShader/Nodes/HwTexCoordNode.h b/source/MaterialXGenShader/Nodes/HwTexCoordNode.h new file mode 100644 index 0000000000..9aae3d18ce --- /dev/null +++ b/source/MaterialXGenShader/Nodes/HwTexCoordNode.h @@ -0,0 +1,31 @@ +// +// Copyright Contributors to the MaterialX Project +// SPDX-License-Identifier: Apache-2.0 +// + +#ifndef MATERIALX_HWTEXCOORDNODE_H +#define MATERIALX_HWTEXCOORDNODE_H + +#include + +MATERIALX_NAMESPACE_BEGIN + +/// Generic texture coordinate node for hardware languages +class MX_GENSHADER_API HwTexCoordNode : public ShaderNodeImpl +{ + public: + static ShaderNodeImplPtr create(); + + void createVariables(const ShaderNode& node, GenContext& context, Shader& shader) const override; + + void emitFunctionCall(const ShaderNode& node, GenContext& context, ShaderStage& stage) const override; + + protected: + virtual string getIndex(const ShaderNode& node) const; + + static string INDEX; +}; + +MATERIALX_NAMESPACE_END + +#endif diff --git a/source/MaterialXGenMsl/Nodes/TimeNodeMsl.cpp b/source/MaterialXGenShader/Nodes/HwTimeNode.cpp similarity index 72% rename from source/MaterialXGenMsl/Nodes/TimeNodeMsl.cpp rename to source/MaterialXGenShader/Nodes/HwTimeNode.cpp index 0c54861b40..8f802a0764 100644 --- a/source/MaterialXGenMsl/Nodes/TimeNodeMsl.cpp +++ b/source/MaterialXGenShader/Nodes/HwTimeNode.cpp @@ -3,24 +3,24 @@ // SPDX-License-Identifier: Apache-2.0 // -#include +#include #include MATERIALX_NAMESPACE_BEGIN -ShaderNodeImplPtr TimeNodeMsl::create() +ShaderNodeImplPtr HwTimeNode::create() { - return std::make_shared(); + return std::make_shared(); } -void TimeNodeMsl::createVariables(const ShaderNode&, GenContext&, Shader& shader) const +void HwTimeNode::createVariables(const ShaderNode&, GenContext&, Shader& shader) const { ShaderStage& ps = shader.getStage(Stage::PIXEL); addStageUniform(HW::PRIVATE_UNIFORMS, Type::FLOAT, HW::T_FRAME, ps); } -void TimeNodeMsl::emitFunctionCall(const ShaderNode& node, GenContext& context, ShaderStage& stage) const +void HwTimeNode::emitFunctionCall(const ShaderNode& node, GenContext& context, ShaderStage& stage) const { DEFINE_SHADER_STAGE(stage, Stage::PIXEL) { diff --git a/source/MaterialXGenGlsl/Nodes/FrameNodeGlsl.h b/source/MaterialXGenShader/Nodes/HwTimeNode.h similarity index 65% rename from source/MaterialXGenGlsl/Nodes/FrameNodeGlsl.h rename to source/MaterialXGenShader/Nodes/HwTimeNode.h index f3a5197eae..e5e1a2fcd4 100644 --- a/source/MaterialXGenGlsl/Nodes/FrameNodeGlsl.h +++ b/source/MaterialXGenShader/Nodes/HwTimeNode.h @@ -3,15 +3,15 @@ // SPDX-License-Identifier: Apache-2.0 // -#ifndef MATERIALX_FRAMENODEGLSL_H -#define MATERIALX_FRAMENODEGLSL_H +#ifndef MATERIALX_HWTIMENODE_H +#define MATERIALX_HWTIMENODE_H -#include +#include MATERIALX_NAMESPACE_BEGIN -/// Frame node implementation for GLSL -class MX_GENGLSL_API FrameNodeGlsl : public GlslImplementation +/// Time node implementation for hardware languages +class MX_GENSHADER_API HwTimeNode : public HwImplementation { public: static ShaderNodeImplPtr create(); diff --git a/source/MaterialXGenShader/Nodes/HwTransformNode.cpp b/source/MaterialXGenShader/Nodes/HwTransformNode.cpp new file mode 100644 index 0000000000..76394309af --- /dev/null +++ b/source/MaterialXGenShader/Nodes/HwTransformNode.cpp @@ -0,0 +1,110 @@ +// +// Copyright Contributors to the MaterialX Project +// SPDX-License-Identifier: Apache-2.0 +// + +#include +#include +#include + +MATERIALX_NAMESPACE_BEGIN + +const string HwTransformNode::FROM_SPACE = "fromspace"; +const string HwTransformNode::TO_SPACE = "tospace"; +const string HwTransformNode::MODEL = "model"; +const string HwTransformNode::OBJECT = "object"; +const string HwTransformNode::WORLD = "world"; + +void HwTransformNode::createVariables(const ShaderNode& node, GenContext&, Shader& shader) const +{ + const string toSpace = getToSpace(node); + const string fromSpace = getFromSpace(node); + const string& matrix = getMatrix(fromSpace, toSpace); + if (!matrix.empty()) + { + ShaderStage& ps = shader.getStage(Stage::PIXEL); + addStageUniform(HW::PRIVATE_UNIFORMS, Type::MATRIX44, matrix, ps); + } +} + +void HwTransformNode::emitFunctionCall(const ShaderNode& node, GenContext& context, ShaderStage& stage) const +{ + DEFINE_SHADER_STAGE(stage, Stage::PIXEL) + { + const ShaderGenerator& shadergen = context.getShaderGenerator(); + + const ShaderOutput* output = node.getOutput(); + const ShaderInput* inInput = node.getInput("in"); + if (inInput->getType() != Type::VECTOR3 && inInput->getType() != Type::VECTOR4) + { + throw ExceptionShaderGenError("Transform node must have 'in' type of vector3 or vector4."); + } + + shadergen.emitLineBegin(stage); + shadergen.emitOutput(output, true, false, context, stage); + shadergen.emitString(" = (", stage); + + const string toSpace = getToSpace(node); + const string fromSpace = getFromSpace(node); + const string& matrix = getMatrix(fromSpace, toSpace); + if (!matrix.empty()) + { + shadergen.emitString(matrix + " * ", stage); + } + + const string type = shadergen.getSyntax().getTypeName(Type::VECTOR4); + const string input = shadergen.getUpstreamResult(inInput, context); + shadergen.emitString(type + "(" + input + ", " + getHomogeneousCoordinate() + ")).xyz", stage); + shadergen.emitLineEnd(stage); + + if (shouldNormalize()) + { + shadergen.emitLineBegin(stage); + shadergen.emitOutput(output, false, false, context, stage); + shadergen.emitString(" = normalize(" + output->getVariable() + ")", stage); + shadergen.emitLineEnd(stage); + } + } +} + +string HwTransformNode::getFromSpace(const ShaderNode& node) const +{ + const ShaderInput* input = node.getInput(FROM_SPACE); + return input ? input->getValueString() : EMPTY_STRING; +} + +string HwTransformNode::getToSpace(const ShaderNode& node) const +{ + const ShaderInput* input = node.getInput(TO_SPACE); + return input ? input->getValueString() : EMPTY_STRING; +} + +const string& HwTransformNode::getMatrix(const string& fromSpace, const string& toSpace) const +{ + if ((fromSpace == MODEL || fromSpace == OBJECT) && toSpace == WORLD) + { + return getModelToWorldMatrix(); + } + else if (fromSpace == WORLD && (toSpace == MODEL || toSpace == OBJECT)) + { + return getWorldToModelMatrix(); + } + return EMPTY_STRING; +} + +ShaderNodeImplPtr HwTransformVectorNode::create() +{ + return std::make_shared(); +} + +ShaderNodeImplPtr HwTransformPointNode::create() +{ + return std::make_shared(); +} + +ShaderNodeImplPtr HwTransformNormalNode::create() +{ + return std::make_shared(); +} + +MATERIALX_NAMESPACE_END diff --git a/source/MaterialXGenShader/Nodes/HwTransformNode.h b/source/MaterialXGenShader/Nodes/HwTransformNode.h new file mode 100644 index 0000000000..a97e57405c --- /dev/null +++ b/source/MaterialXGenShader/Nodes/HwTransformNode.h @@ -0,0 +1,71 @@ +// +// Copyright Contributors to the MaterialX Project +// SPDX-License-Identifier: Apache-2.0 +// + +#ifndef MATERIALX_HWTRANSFORMNODE_H +#define MATERIALX_HWTRANSFORMNODE_H + +#include + +MATERIALX_NAMESPACE_BEGIN + +/// Generic transformation node for hardware languages +class MX_GENSHADER_API HwTransformNode : public ShaderNodeImpl +{ + public: + void createVariables(const ShaderNode& node, GenContext& context, Shader& shader) const override; + void emitFunctionCall(const ShaderNode& node, GenContext& context, ShaderStage& stage) const override; + + protected: + virtual const string& getMatrix(const string& fromSpace, const string& toSpace) const; + virtual const string& getModelToWorldMatrix() const = 0; + virtual const string& getWorldToModelMatrix() const = 0; + virtual string getHomogeneousCoordinate() const = 0; + virtual bool shouldNormalize() const { return false; } + + virtual string getFromSpace(const ShaderNode&) const; + virtual string getToSpace(const ShaderNode&) const; + + static const string FROM_SPACE; + static const string TO_SPACE; + static const string MODEL; + static const string OBJECT; + static const string WORLD; +}; + +class MX_GENSHADER_API HwTransformVectorNode : public HwTransformNode +{ + public: + static ShaderNodeImplPtr create(); + + protected: + const string& getModelToWorldMatrix() const override { return HW::T_WORLD_MATRIX; } + const string& getWorldToModelMatrix() const override { return HW::T_WORLD_INVERSE_MATRIX; } + string getHomogeneousCoordinate() const override { return "0.0"; } +}; + +class MX_GENSHADER_API HwTransformPointNode : public HwTransformVectorNode +{ + public: + static ShaderNodeImplPtr create(); + + protected: + string getHomogeneousCoordinate() const override { return "1.0"; } +}; + +class MX_GENSHADER_API HwTransformNormalNode : public HwTransformNode +{ + public: + static ShaderNodeImplPtr create(); + + protected: + const string& getModelToWorldMatrix() const override { return HW::T_WORLD_INVERSE_TRANSPOSE_MATRIX; } + const string& getWorldToModelMatrix() const override { return HW::T_WORLD_TRANSPOSE_MATRIX; } + string getHomogeneousCoordinate() const override { return "0.0"; } + bool shouldNormalize() const override { return true; } +}; + +MATERIALX_NAMESPACE_END + +#endif diff --git a/source/MaterialXGenShader/Nodes/HwViewDirectionNode.cpp b/source/MaterialXGenShader/Nodes/HwViewDirectionNode.cpp new file mode 100644 index 0000000000..819ac93029 --- /dev/null +++ b/source/MaterialXGenShader/Nodes/HwViewDirectionNode.cpp @@ -0,0 +1,55 @@ +// +// Copyright Contributors to the MaterialX Project +// SPDX-License-Identifier: Apache-2.0 +// + +#include + +#include + +MATERIALX_NAMESPACE_BEGIN + +ShaderNodeImplPtr HwViewDirectionNode::create() +{ + return std::make_shared(); +} + +void HwViewDirectionNode::createVariables(const ShaderNode&, GenContext&, Shader& shader) const +{ + ShaderStage& vs = shader.getStage(Stage::VERTEX); + ShaderStage& ps = shader.getStage(Stage::PIXEL); + + addStageInput(HW::VERTEX_INPUTS, Type::VECTOR3, HW::T_IN_POSITION, vs); + addStageConnector(HW::VERTEX_DATA, Type::VECTOR3, HW::T_POSITION_WORLD, vs, ps); + addStageUniform(HW::PRIVATE_UNIFORMS, Type::VECTOR3, HW::T_VIEW_POSITION, ps); +} + +void HwViewDirectionNode::emitFunctionCall(const ShaderNode& node, GenContext& context, ShaderStage& stage) const +{ + const HwShaderGenerator& shadergen = static_cast(context.getShaderGenerator()); + + DEFINE_SHADER_STAGE(stage, Stage::VERTEX) + { + VariableBlock& vertexData = stage.getOutputBlock(HW::VERTEX_DATA); + const string prefix = shadergen.getVertexDataPrefix(vertexData); + ShaderPort* position = vertexData[HW::T_POSITION_WORLD]; + if (!position->isEmitted()) + { + position->setEmitted(); + shadergen.emitLine(prefix + position->getVariable() + " = hPositionWorld.xyz", stage); + } + } + + DEFINE_SHADER_STAGE(stage, Stage::PIXEL) + { + VariableBlock& vertexData = stage.getInputBlock(HW::VERTEX_DATA); + const string prefix = shadergen.getVertexDataPrefix(vertexData); + ShaderPort* position = vertexData[HW::T_POSITION_WORLD]; + shadergen.emitLineBegin(stage); + shadergen.emitOutput(node.getOutput(), true, false, context, stage); + shadergen.emitString(" = normalize(" + prefix + position->getVariable() + " - " + HW::T_VIEW_POSITION + ")", stage); + shadergen.emitLineEnd(stage); + } +} + +MATERIALX_NAMESPACE_END diff --git a/source/MaterialXGenShader/Nodes/HwViewDirectionNode.h b/source/MaterialXGenShader/Nodes/HwViewDirectionNode.h new file mode 100644 index 0000000000..143d89d437 --- /dev/null +++ b/source/MaterialXGenShader/Nodes/HwViewDirectionNode.h @@ -0,0 +1,26 @@ +// +// Copyright Contributors to the MaterialX Project +// SPDX-License-Identifier: Apache-2.0 +// + +#ifndef MATERIALX_HWVIEWDIRECTIONNODE_H +#define MATERIALX_HWVIEWDIRECTIONNODE_H + +#include + +MATERIALX_NAMESPACE_BEGIN + +/// ViewDirection node implementation for hardware languages +class MX_GENSHADER_API HwViewDirectionNode : public HwImplementation +{ + public: + static ShaderNodeImplPtr create(); + + void createVariables(const ShaderNode& node, GenContext& context, Shader& shader) const override; + + void emitFunctionCall(const ShaderNode& node, GenContext& context, ShaderStage& stage) const override; +}; + +MATERIALX_NAMESPACE_END + +#endif diff --git a/source/MaterialXGenShader/ShaderGenerator.cpp b/source/MaterialXGenShader/ShaderGenerator.cpp index 177201a9e3..d5f51aed1c 100644 --- a/source/MaterialXGenShader/ShaderGenerator.cpp +++ b/source/MaterialXGenShader/ShaderGenerator.cpp @@ -270,7 +270,7 @@ void ShaderGenerator::registerImplementation(const string& name, CreatorFunction void ShaderGenerator::registerImplementation(const StringVec& nameVec, CreatorFunction creator) { - for(const string& name : nameVec) + for (const string& name : nameVec) { _implFactory.registerClass(name, creator); } diff --git a/source/MaterialXGenShader/ShaderGenerator.h b/source/MaterialXGenShader/ShaderGenerator.h index 8e7f9855de..fa60a4d63e 100644 --- a/source/MaterialXGenShader/ShaderGenerator.h +++ b/source/MaterialXGenShader/ShaderGenerator.h @@ -151,7 +151,7 @@ class MX_GENSHADER_API ShaderGenerator /// Register a shader node implementation for a given implementation element name void registerImplementation(const string& name, CreatorFunction creator); - + /// Register a shader node implementation for a given set of implementation element names void registerImplementation(const StringVec& nameVec, CreatorFunction creator); diff --git a/source/MaterialXGenShader/ShaderGraph.cpp b/source/MaterialXGenShader/ShaderGraph.cpp index e3a0c4a0ec..b95a9471e9 100644 --- a/source/MaterialXGenShader/ShaderGraph.cpp +++ b/source/MaterialXGenShader/ShaderGraph.cpp @@ -93,7 +93,7 @@ void ShaderGraph::createConnectedNodes(const ElementPtr& downstreamElement, ShaderNode* newNode = getNode(newNodeName); if (!newNode) { - newNode = createNode(*upstreamNode, context); + newNode = createNode(upstreamNode, context); } // @@ -443,171 +443,6 @@ ShaderGraphPtr ShaderGraph::create(const ShaderGraph* parent, const NodeGraph& n return graph; } -ShaderGraphPtr ShaderGraph::createSurfaceShader( - const string& name, - const ShaderGraph* parent, - NodePtr node, - GenContext& context, - ElementPtr& root) -{ - NodeDefPtr nodeDef = node->getNodeDef(EMPTY_STRING, true); - if (!nodeDef) - { - throw ExceptionShaderGenError("Could not find a nodedef for shader node '" + node->getName() + - "' with category '" + node->getCategory() + "'"); - } - - ShaderGraphPtr graph = std::make_shared(parent, name, node->getDocument(), context.getReservedWords()); - - // Create input sockets - graph->addInputSockets(*nodeDef, context); - - // Create output sockets - graph->addOutputSockets(*nodeDef); - - // Create this shader node in the graph. - const string& newNodeName = node->getName(); - ShaderNodePtr newNode = ShaderNode::create(graph.get(), newNodeName, *nodeDef, context); - newNode->initialize(*node, *nodeDef, context); - graph->addNode(newNode); - - // Share metadata. - graph->setMetadata(newNode->getMetadata()); - - // Connect it to the graph output - ShaderGraphOutputSocket* outputSocket = graph->getOutputSocket(); - outputSocket->makeConnection(newNode->getOutput()); - outputSocket->setPath(node->getNamePath()); - - ColorManagementSystemPtr colorManagementSystem = context.getShaderGenerator().getColorManagementSystem(); - string targetColorSpace = context.getOptions().targetColorSpaceOverride.empty() ? - node->getDocument()->getColorSpace() : - context.getOptions().targetColorSpaceOverride; - - const string& targetDistanceUnit = context.getOptions().targetDistanceUnit; - UnitSystemPtr unitSystem = context.getShaderGenerator().getUnitSystem(); - - // Set node input values onto graph input sockets - for (const InputPtr& nodeDefInput : nodeDef->getActiveInputs()) - { - ShaderGraphInputSocket* inputSocket = graph->getInputSocket(nodeDefInput->getName()); - ShaderInput* input = newNode->getInput(nodeDefInput->getName()); - if (!inputSocket || !input) - { - throw ExceptionShaderGenError("Shader input '" + nodeDefInput->getName() + "' doesn't match an existing input on graph '" + graph->getName() + "'"); - } - - InputPtr nodeInput = node->getInput(nodeDefInput->getName()); - if (nodeInput) - { - // Copy value from binding - ValuePtr nodeInputValue = nodeInput->getResolvedValue(); - if (nodeInputValue) - { - inputSocket->setValue(nodeInputValue); - input->setBindInput(); - graph->populateColorTransformMap(colorManagementSystem, input, nodeInput, targetColorSpace, true); - graph->populateUnitTransformMap(unitSystem, input, nodeInput, targetDistanceUnit, true); - } - inputSocket->setPath(nodeInput->getNamePath()); - input->setPath(inputSocket->getPath()); - const string& nodeInputUnit = nodeInput->getUnit(); - if (!nodeInputUnit.empty()) - { - inputSocket->setUnit(nodeInputUnit); - input->setUnit(nodeInputUnit); - } - const string& nodeColorspace = nodeInput->getColorSpace(); - if (!nodeColorspace.empty()) - { - inputSocket->setColorSpace(nodeColorspace); - input->setColorSpace(nodeColorspace); - } - } - - // Check if the input is a uniform - bool isUniform = nodeDefInput->getIsUniform(); - if (isUniform) - { - inputSocket->makeConnection(input); - } - else - { - GeomPropDefPtr geomprop = nodeDefInput->getDefaultGeomProp(); - if (geomprop) - { - inputSocket->setGeomProp(geomprop->getName()); - input->setGeomProp(geomprop->getName()); - } - - // If no explicit connection, connect to geometric node if a geomprop is used - // or otherwise to the graph interface. - const string& connection = nodeInput ? nodeInput->getOutputString() : EMPTY_STRING; - if (connection.empty()) - { - if (geomprop) - { - graph->addDefaultGeomNode(input, *geomprop, context); - } - else - { - inputSocket->makeConnection(input); - } - } - } - - // Share metadata. - inputSocket->setMetadata(input->getMetadata()); - } - - // Add shader node paths and unit value - const string& nodePath = node->getNamePath(); - for (auto nodeInput : nodeDef->getActiveInputs()) - { - const string& inputName = nodeInput->getName(); - const string path = nodePath + NAME_PATH_SEPARATOR + inputName; - const string& unit = nodeInput->getUnit(); - const string& colorSpace = nodeInput->getColorSpace(); - ShaderInput* input = newNode->getInput(inputName); - if (input) - { - if (input->getPath().empty()) - { - input->setPath(path); - } - if (input->getUnit().empty() && !unit.empty()) - { - input->setUnit(unit); - } - if (input->getColorSpace().empty() && !colorSpace.empty()) - { - input->setColorSpace(colorSpace); - } - } - ShaderGraphInputSocket* inputSocket = graph->getInputSocket(inputName); - if (inputSocket) - { - if (inputSocket->getPath().empty()) - { - inputSocket->setPath(path); - } - if (inputSocket->getUnit().empty() && !unit.empty()) - { - inputSocket->setUnit(unit); - } - if (inputSocket->getColorSpace().empty() && !colorSpace.empty()) - { - inputSocket->setColorSpace(colorSpace); - } - } - } - - // Start traversal from this shader node - root = node; - - return graph; -} - ShaderGraphPtr ShaderGraph::create(const ShaderGraph* parent, const string& name, ElementPtr element, GenContext& context) { ShaderGraphPtr graph; @@ -674,104 +509,99 @@ ShaderGraphPtr ShaderGraph::create(const ShaderGraph* parent, const string& name else if (element->isA()) { NodePtr node = element->asA(); - - // Handle shader nodes different from other nodes - if (node->getType() == SURFACE_SHADER_TYPE_STRING) + NodeDefPtr nodeDef = node->getNodeDef(); + if (!nodeDef) { - graph = createSurfaceShader(name, parent, node, context, root); + throw ExceptionShaderGenError("Could not find a nodedef for node '" + node->getName() + "'"); } - else - { - NodeDefPtr nodeDef = node->getNodeDef(); - if (!nodeDef) - { - throw ExceptionShaderGenError("Could not find a nodedef for node '" + node->getName() + "'"); - } - graph = std::make_shared(parent, name, element->getDocument(), context.getReservedWords()); + graph = std::make_shared(parent, name, element->getDocument(), context.getReservedWords()); - // Create input sockets - graph->addInputSockets(*nodeDef, context); + // Create input sockets + graph->addInputSockets(*nodeDef, context); - // Create output sockets - graph->addOutputSockets(*nodeDef); + // Create output sockets + graph->addOutputSockets(*nodeDef); - // Create this shader node in the graph. - ShaderNodePtr newNode = ShaderNode::create(graph.get(), node->getName(), *nodeDef, context); - graph->addNode(newNode); + // Create this shader node in the graph. + ShaderNodePtr newNode = ShaderNode::create(graph.get(), node->getName(), *nodeDef, context); + graph->addNode(newNode); - // Share metadata. - graph->setMetadata(newNode->getMetadata()); + // Share metadata. + graph->setMetadata(newNode->getMetadata()); + + // Connect it to the graph outputs + for (size_t i = 0; i < newNode->numOutputs(); ++i) + { + ShaderGraphOutputSocket* outputSocket = graph->getOutputSocket(i); + outputSocket->makeConnection(newNode->getOutput(i)); + outputSocket->setPath(node->getNamePath()); + } - // Connect it to the graph outputs - for (size_t i = 0; i < newNode->numOutputs(); ++i) + // Handle node input ports + for (const InputPtr& nodedefInput : nodeDef->getActiveInputs()) + { + ShaderGraphInputSocket* inputSocket = graph->getInputSocket(nodedefInput->getName()); + ShaderInput* input = newNode->getInput(nodedefInput->getName()); + if (!inputSocket || !input) { - ShaderGraphOutputSocket* outputSocket = graph->getOutputSocket(i); - outputSocket->makeConnection(newNode->getOutput(i)); - outputSocket->setPath(node->getNamePath()); + throw ExceptionShaderGenError("Node input '" + nodedefInput->getName() + "' doesn't match an existing input on graph '" + graph->getName() + "'"); } - // Handle node input ports - for (const InputPtr& nodedefInput : nodeDef->getActiveInputs()) + // Copy data from node element to shadergen representation + InputPtr nodeInput = node->getInput(nodedefInput->getName()); + if (nodeInput) { - ShaderGraphInputSocket* inputSocket = graph->getInputSocket(nodedefInput->getName()); - ShaderInput* input = newNode->getInput(nodedefInput->getName()); - if (!inputSocket || !input) - { - throw ExceptionShaderGenError("Node input '" + nodedefInput->getName() + "' doesn't match an existing input on graph '" + graph->getName() + "'"); - } - - // Copy data from node element to shadergen representation - InputPtr nodeInput = node->getInput(nodedefInput->getName()); - if (nodeInput) + ValuePtr value = nodeInput->getResolvedValue(); + if (value) { - ValuePtr value = nodeInput->getResolvedValue(); - if (value) - { - const string& valueString = value->getValueString(); - std::pair enumResult; - const TypeDesc* type = TypeDesc::get(nodedefInput->getType()); - const string& enumNames = nodedefInput->getAttribute(ValueElement::ENUM_ATTRIBUTE); - if (context.getShaderGenerator().getSyntax().remapEnumeration(valueString, type, enumNames, enumResult)) - { - inputSocket->setValue(enumResult.second); - } - else - { - inputSocket->setValue(value); - } - } - - const string path = nodeInput->getNamePath(); - if (!path.empty()) + const string& valueString = value->getValueString(); + std::pair enumResult; + const TypeDesc* type = TypeDesc::get(nodedefInput->getType()); + const string& enumNames = nodedefInput->getAttribute(ValueElement::ENUM_ATTRIBUTE); + if (context.getShaderGenerator().getSyntax().remapEnumeration(valueString, type, enumNames, enumResult)) { - inputSocket->setPath(path); - input->setPath(path); + inputSocket->setValue(enumResult.second); } - const string& unit = nodeInput->getUnit(); - if (!unit.empty()) - { - inputSocket->setUnit(unit); - input->setUnit(unit); - } - const string& colorSpace = nodeInput->getColorSpace(); - if (!colorSpace.empty()) + else { - inputSocket->setColorSpace(colorSpace); - input->setColorSpace(colorSpace); + inputSocket->setValue(value); } } - // Connect graph socket to the node input - inputSocket->makeConnection(input); - - // Share metadata. - inputSocket->setMetadata(input->getMetadata()); + input->setBindInput(); + const string path = nodeInput->getNamePath(); + if (!path.empty()) + { + inputSocket->setPath(path); + input->setPath(path); + } + const string& unit = nodeInput->getUnit(); + if (!unit.empty()) + { + inputSocket->setUnit(unit); + input->setUnit(unit); + } + const string& colorSpace = nodeInput->getColorSpace(); + if (!colorSpace.empty()) + { + inputSocket->setColorSpace(colorSpace); + input->setColorSpace(colorSpace); + } } - // Set root for upstream dependency traversal - root = node; + // Connect graph socket to the node input + inputSocket->makeConnection(input); + + // Share metadata. + inputSocket->setMetadata(input->getMetadata()); } + + // Apply color and unit transforms to each input. + graph->applyInputTransforms(node, newNode, context); + + // Set root for upstream dependency traversal + root = node; } if (!graph) @@ -790,23 +620,72 @@ ShaderGraphPtr ShaderGraph::create(const ShaderGraph* parent, const string& name return graph; } -ShaderNode* ShaderGraph::createNode(const Node& node, GenContext& context) +void ShaderGraph::applyInputTransforms(ConstNodePtr node, ShaderNodePtr shaderNode, GenContext& context) { - NodeDefPtr nodeDef = node.getNodeDef(); + ColorManagementSystemPtr colorManagementSystem = context.getShaderGenerator().getColorManagementSystem(); + UnitSystemPtr unitSystem = context.getShaderGenerator().getUnitSystem(); + + const string& targetColorSpace = context.getOptions().targetColorSpaceOverride.empty() ? + _document->getActiveColorSpace() : + context.getOptions().targetColorSpaceOverride; + const string& targetDistanceUnit = context.getOptions().targetDistanceUnit; + + for (InputPtr input : node->getInputs()) + { + if (input->hasValue() || input->hasInterfaceName()) + { + string sourceColorSpace = input->getActiveColorSpace(); + if (input->getType() == FILENAME_TYPE_STRING && node->isColorType()) + { + // Adjust the source color space for filename interface names. + if (input->hasInterfaceName()) + { + for (ConstNodePtr parentNode : context.getParentNodes()) + { + if (!parentNode->isColorType()) + { + InputPtr interfaceInput = parentNode->getInput(input->getInterfaceName()); + string interfaceColorSpace = interfaceInput ? interfaceInput->getActiveColorSpace() : EMPTY_STRING; + if (!interfaceColorSpace.empty()) + { + sourceColorSpace = interfaceColorSpace; + } + } + } + } + + ShaderOutput* shaderOutput = shaderNode->getOutput(); + populateColorTransformMap(colorManagementSystem, shaderOutput, sourceColorSpace, targetColorSpace, false); + populateUnitTransformMap(unitSystem, shaderOutput, input, targetDistanceUnit, false); + } + else + { + ShaderInput* shaderInput = shaderNode->getInput(input->getName()); + populateColorTransformMap(colorManagementSystem, shaderInput, sourceColorSpace, targetColorSpace, true); + populateUnitTransformMap(unitSystem, shaderInput, input, targetDistanceUnit, true); + } + } + } +} + +ShaderNode* ShaderGraph::createNode(ConstNodePtr node, GenContext& context) +{ + NodeDefPtr nodeDef = node->getNodeDef(); if (!nodeDef) { - throw ExceptionShaderGenError("Could not find a nodedef for node '" + node.getName() + "'"); + throw ExceptionShaderGenError("Could not find a nodedef for node '" + node->getName() + "'"); } // Create this node in the graph. - const string& name = node.getName(); - ShaderNodePtr newNode = ShaderNode::create(this, name, *nodeDef, context); - newNode->initialize(node, *nodeDef, context); - _nodeMap[name] = newNode; + context.pushParentNode(node); + ShaderNodePtr newNode = ShaderNode::create(this, node->getName(), *nodeDef, context); + newNode->initialize(*node, *nodeDef, context); + _nodeMap[node->getName()] = newNode; _nodeOrder.push_back(newNode.get()); + context.popParentNode(); // Check if any of the node inputs should be connected to the graph interface - for (ValueElementPtr elem : node.getChildrenOfType()) + for (ValueElementPtr elem : node->getChildrenOfType()) { const string& interfaceName = elem->getInterfaceName(); if (!interfaceName.empty()) @@ -829,7 +708,7 @@ ShaderNode* ShaderGraph::createNode(const Node& node, GenContext& context) for (const InputPtr& nodeDefInput : nodeDef->getActiveInputs()) { ShaderInput* input = newNode->getInput(nodeDefInput->getName()); - InputPtr nodeInput = node.getInput(nodeDefInput->getName()); + InputPtr nodeInput = node->getInput(nodeDefInput->getName()); const string& connection = nodeInput ? nodeInput->getNodeName() : EMPTY_STRING; if (connection.empty() && !input->getConnection()) @@ -842,38 +721,8 @@ ShaderNode* ShaderGraph::createNode(const Node& node, GenContext& context) } } - // Handle colorspace and unit conversion if needed. - UnitSystemPtr unitSystem = context.getShaderGenerator().getUnitSystem(); - const string& targetDistanceUnit = context.getOptions().targetDistanceUnit; - - ColorManagementSystemPtr colorManagementSystem = context.getShaderGenerator().getColorManagementSystem(); - string targetColorSpace = context.getOptions().targetColorSpaceOverride.empty() ? - _document->getActiveColorSpace() : - context.getOptions().targetColorSpaceOverride; - - for (InputPtr input : node.getInputs()) - { - if (input->getType() == FILENAME_TYPE_STRING) - { - ShaderOutput* shaderOutput = newNode->getOutput(); - if (shaderOutput) - { - string colorSpace = populateColorTransformMap(colorManagementSystem, shaderOutput, input, targetColorSpace, false); - ShaderInput* shaderInput = newNode->getInput(input->getName()); - if (shaderInput && !colorSpace.empty()) - { - shaderInput->setColorSpace(colorSpace); - } - populateUnitTransformMap(unitSystem, shaderOutput, input, targetDistanceUnit, false); - } - } - else - { - ShaderInput* shaderInput = newNode->getInput(input->getName()); - populateColorTransformMap(colorManagementSystem, shaderInput, input, targetColorSpace, true); - populateUnitTransformMap(unitSystem, shaderInput, input, targetDistanceUnit, true); - } - } + // Apply color and unit transforms to each input. + applyInputTransforms(node, newNode, context); return newNode.get(); } @@ -1046,7 +895,7 @@ void ShaderGraph::optimize(GenContext& context) { // Filename dot nodes must be elided so they do not create extra samplers. ShaderInput* in = node->getInput("in"); - if (in->getChannels().empty() && in->getType() == Type::FILENAME) + if (in->getChannels().empty() && *in->getType() == *Type::FILENAME) { bypass(context, node, 0); ++numEdits; @@ -1246,48 +1095,44 @@ void ShaderGraph::setVariableNames(GenContext& context) } } -string ShaderGraph::populateColorTransformMap(ColorManagementSystemPtr colorManagementSystem, ShaderPort* shaderPort, - ValueElementPtr input, const string& targetColorSpace, bool asInput) +void ShaderGraph::populateColorTransformMap(ColorManagementSystemPtr colorManagementSystem, ShaderPort* shaderPort, + const string& sourceColorSpace, const string& targetColorSpace, bool asInput) { - if (targetColorSpace.empty()) + if (!shaderPort || + sourceColorSpace.empty() || + targetColorSpace.empty() || + sourceColorSpace == targetColorSpace) { - return EMPTY_STRING; + return; } - const string& sourceColorSpace = input->getActiveColorSpace(); - if (shaderPort && !sourceColorSpace.empty()) + if (*(shaderPort->getType()) == *Type::COLOR3 || *(shaderPort->getType()) == *Type::COLOR4) { - if (shaderPort->getType() == Type::COLOR3 || shaderPort->getType() == Type::COLOR4) + // Store the source color space on the shader port. + shaderPort->setColorSpace(sourceColorSpace); + + // Update the color transform map, if a color management system is provided. + if (colorManagementSystem) { - // If we're converting between two identical color spaces than we have no work to do. - if (sourceColorSpace != targetColorSpace) + ColorSpaceTransform transform(sourceColorSpace, targetColorSpace, shaderPort->getType()); + if (colorManagementSystem->supportsTransform(transform)) { - // Cache colorspace on shader port - shaderPort->setColorSpace(sourceColorSpace); - if (colorManagementSystem) + if (asInput) { - ColorSpaceTransform transform(sourceColorSpace, targetColorSpace, shaderPort->getType()); - if (colorManagementSystem->supportsTransform(transform)) - { - if (asInput) - { - _inputColorTransformMap.emplace(static_cast(shaderPort), transform); - } - else - { - _outputColorTransformMap.emplace(static_cast(shaderPort), transform); - } - } - else - { - std::cerr << "Unsupported color space transform from " << - sourceColorSpace << " to " << targetColorSpace << std::endl; - } + _inputColorTransformMap.emplace(static_cast(shaderPort), transform); } + else + { + _outputColorTransformMap.emplace(static_cast(shaderPort), transform); + } + } + else + { + std::cerr << "Unsupported color space transform from " << + sourceColorSpace << " to " << targetColorSpace << std::endl; } } } - return sourceColorSpace; } void ShaderGraph::populateUnitTransformMap(UnitSystemPtr unitSystem, ShaderPort* shaderPort, ValueElementPtr input, const string& globalTargetUnitSpace, bool asInput) @@ -1326,10 +1171,10 @@ void ShaderGraph::populateUnitTransformMap(UnitSystemPtr unitSystem, ShaderPort* // Only support convertion for float and vectors. arrays, matrices are not supported. // TODO: This should be provided by the UnitSystem. - bool supportedType = (shaderPort->getType() == Type::FLOAT || - shaderPort->getType() == Type::VECTOR2 || - shaderPort->getType() == Type::VECTOR3 || - shaderPort->getType() == Type::VECTOR4); + bool supportedType = (*shaderPort->getType() == *Type::FLOAT || + *shaderPort->getType() == *Type::VECTOR2 || + *shaderPort->getType() == *Type::VECTOR3 || + *shaderPort->getType() == *Type::VECTOR4); if (supportedType) { UnitTransform transform(sourceUnitSpace, targetUnitSpace, shaderPort->getType(), unitType); diff --git a/source/MaterialXGenShader/ShaderGraph.h b/source/MaterialXGenShader/ShaderGraph.h index 4117599c27..a96f59edce 100644 --- a/source/MaterialXGenShader/ShaderGraph.h +++ b/source/MaterialXGenShader/ShaderGraph.h @@ -92,8 +92,11 @@ class MX_GENSHADER_API ShaderGraph : public ShaderNode const vector& getInputSockets() const { return _outputOrder; } const vector& getOutputSockets() const { return _inputOrder; } + /// Apply color and unit transforms to each input of a node. + void applyInputTransforms(ConstNodePtr node, ShaderNodePtr shaderNode, GenContext& context); + /// Create a new node in the graph - ShaderNode* createNode(const Node& node, GenContext& context); + ShaderNode* createNode(ConstNodePtr node, GenContext& context); /// Add input/output sockets ShaderGraphInputSocket* addInputSocket(const string& name, const TypeDesc* type); @@ -112,13 +115,6 @@ class MX_GENSHADER_API ShaderGraph : public ShaderNode IdentifierMap& getIdentifierMap() { return _identifiers; } protected: - static ShaderGraphPtr createSurfaceShader( - const string& name, - const ShaderGraph* parent, - NodePtr node, - GenContext& context, - ElementPtr& root); - /// Create node connections corresponding to the connection between a pair of elements. /// @param downstreamElement Element representing the node to connect to. /// @param upstreamElement Element representing the node to connect from @@ -171,9 +167,10 @@ class MX_GENSHADER_API ShaderGraph : public ShaderNode /// to avoid name conflicts during shader generation. void setVariableNames(GenContext& context); - /// Populates the input or output color transform map if the provided input/parameter - /// has a color space attribute and has a type of color3 or color4. - string populateColorTransformMap(ColorManagementSystemPtr colorManagementSystem, ShaderPort* shaderPort, ValueElementPtr element, const string& targetColorSpace, bool asInput); + /// Populate the color transform map for the given shader port, if the provided combination of + /// source and target color spaces are supported for its data type. + void populateColorTransformMap(ColorManagementSystemPtr colorManagementSystem, ShaderPort* shaderPort, + const string& sourceColorSpace, const string& targetColorSpace, bool asInput); /// Populates the appropriate unit transform map if the provided input/parameter or output /// has a unit attribute and is of the supported type diff --git a/source/MaterialXGenShader/ShaderNode.cpp b/source/MaterialXGenShader/ShaderNode.cpp index 04551cb6d2..adcf71566b 100644 --- a/source/MaterialXGenShader/ShaderNode.cpp +++ b/source/MaterialXGenShader/ShaderNode.cpp @@ -32,6 +32,11 @@ string ShaderPort::getFullName() const return (_node->getName() + "_" + _name); } +string ShaderPort::getValueString() const +{ + return getValue() ? getValue()->getValueString() : EMPTY_STRING; +} + // // ShaderInput methods // @@ -224,13 +229,14 @@ ShaderNodePtr ShaderNode::create(const ShaderGraph* parent, const string& name, // First, check for specific output types const ShaderOutput* primaryOutput = newNode->getOutput(); - if (primaryOutput->getType() == Type::MATERIAL) + if (*primaryOutput->getType() == *Type::MATERIAL) { newNode->_classification = Classification::MATERIAL; } - else if (primaryOutput->getType() == Type::SURFACESHADER) + else if (*primaryOutput->getType() == *Type::SURFACESHADER) { - if (nodeDefName == "ND_surface_unlit") + if (nodeDefName == "ND_surface_unlit" || + (stringStartsWith(nodeDefName, "ND_convert_") && stringEndsWith(nodeDefName, "_surfaceshader"))) { newNode->_classification = Classification::SHADER | Classification::SURFACE | Classification::UNLIT; } @@ -239,11 +245,15 @@ ShaderNodePtr ShaderNode::create(const ShaderGraph* parent, const string& name, newNode->_classification = Classification::SHADER | Classification::SURFACE | Classification::CLOSURE; } } - else if (primaryOutput->getType() == Type::LIGHTSHADER) + else if (*primaryOutput->getType() == *Type::VOLUMESHADER) + { + newNode->_classification = Classification::SHADER | Classification::VOLUME | Classification::CLOSURE; + } + else if (*primaryOutput->getType() == *Type::LIGHTSHADER) { newNode->_classification = Classification::LIGHT | Classification::SHADER | Classification::CLOSURE; } - else if (primaryOutput->getType() == Type::BSDF) + else if (*primaryOutput->getType() == *Type::BSDF) { newNode->_classification = Classification::BSDF | Classification::CLOSURE; @@ -273,11 +283,11 @@ ShaderNodePtr ShaderNode::create(const ShaderGraph* parent, const string& name, newNode->_classification |= Classification::THINFILM; } } - else if (primaryOutput->getType() == Type::EDF) + else if (*primaryOutput->getType() == *Type::EDF) { newNode->_classification = Classification::EDF | Classification::CLOSURE; } - else if (primaryOutput->getType() == Type::VDF) + else if (*primaryOutput->getType() == *Type::VDF) { newNode->_classification = Classification::VDF | Classification::CLOSURE; } @@ -285,7 +295,7 @@ ShaderNodePtr ShaderNode::create(const ShaderGraph* parent, const string& name, else if (nodeDef.getNodeString() == CONSTANT) { newNode->_classification = Classification::TEXTURE | Classification::CONSTANT; - } + } else if (nodeDef.getNodeString() == DOT) { newNode->_classification = Classification::TEXTURE | Classification::DOT; diff --git a/source/MaterialXGenShader/ShaderNode.h b/source/MaterialXGenShader/ShaderNode.h index 536e0adc1e..dd74269764 100644 --- a/source/MaterialXGenShader/ShaderNode.h +++ b/source/MaterialXGenShader/ShaderNode.h @@ -170,6 +170,9 @@ class MX_GENSHADER_API ShaderPort : public std::enable_shared_from_thissecond->getType()->getSize() < type->getSize()) + { + it->second->setType(type); + } + } + else if (type != it->second->getType()) + { + throw ExceptionShaderGenError("Trying to add shader port '" + name + "' with type '" + + type->getName() + "', but existing shader port with type '" + + it->second->getType()->getName() + "' was found"); + } return it->second.get(); } diff --git a/source/MaterialXGenShader/ShaderStage.h b/source/MaterialXGenShader/ShaderStage.h index 71004f8e52..a6a5cec0b8 100644 --- a/source/MaterialXGenShader/ShaderStage.h +++ b/source/MaterialXGenShader/ShaderStage.h @@ -113,7 +113,14 @@ class MX_GENSHADER_API VariableBlock ShaderPort* find(const ShaderPortPredicate& predicate); /// Add a new shader port to this block. - ShaderPort* add(const TypeDesc* type, const string& name, ValuePtr value = nullptr); + /// @param type The desired shader port type + /// @param name The shader port name + /// @param value The value to attach to the shader port + /// @param shouldWiden When false, an exception is thrown if the type of the existing port with + /// the same name does not match the requested type. When true, the types can mismatch, and the + /// type of any existing port is widened to match the requested type when necessary. + /// @return A new shader port, or a pre-existing shader port with the same name. + ShaderPort* add(const TypeDesc* type, const string& name, ValuePtr value = nullptr, bool shouldWiden = false); /// Add an existing shader port to this block. void add(ShaderPortPtr port); @@ -339,20 +346,22 @@ inline ShaderPort* addStageUniform(const string& block, inline ShaderPort* addStageInput(const string& block, const TypeDesc* type, const string& name, - ShaderStage& stage) + ShaderStage& stage, + bool shouldWiden = false) { VariableBlock& inputs = stage.getInputBlock(block); - return inputs.add(type, name); + return inputs.add(type, name, {}, shouldWiden); } /// Utility function for adding a new shader port to an output block. inline ShaderPort* addStageOutput(const string& block, const TypeDesc* type, const string& name, - ShaderStage& stage) + ShaderStage& stage, + bool shouldWiden = false) { VariableBlock& outputs = stage.getOutputBlock(block); - return outputs.add(type, name); + return outputs.add(type, name, {}, shouldWiden); } /// Utility function for adding a connector block between stages. @@ -370,10 +379,11 @@ inline void addStageConnector(const string& block, const TypeDesc* type, const string& name, ShaderStage& from, - ShaderStage& to) + ShaderStage& to, + bool shouldWiden = false) { - addStageOutput(block, type, name, from); - addStageInput(block, type, name, to); + addStageOutput(block, type, name, from, shouldWiden); + addStageInput(block, type, name, to, shouldWiden); } MATERIALX_NAMESPACE_END diff --git a/source/MaterialXGenShader/ShaderTranslator.cpp b/source/MaterialXGenShader/ShaderTranslator.cpp index 2d53d14925..8a03c106cb 100644 --- a/source/MaterialXGenShader/ShaderTranslator.cpp +++ b/source/MaterialXGenShader/ShaderTranslator.cpp @@ -52,9 +52,10 @@ void ShaderTranslator::connectTranslationInputs(NodePtr shader, NodeDefPtr trans throw Exception("Shader input has no associated output or value " + shaderInput->getName()); } - if (shaderInput->hasColorSpace()) + string colorSpace = shaderInput->getActiveColorSpace(); + if (!colorSpace.empty()) { - input->setColorSpace(shaderInput->getColorSpace()); + input->setColorSpace(colorSpace); } if (shaderInput->hasUnit()) { diff --git a/source/MaterialXGenShader/Syntax.cpp b/source/MaterialXGenShader/Syntax.cpp index 61deda624e..6e97a56609 100644 --- a/source/MaterialXGenShader/Syntax.cpp +++ b/source/MaterialXGenShader/Syntax.cpp @@ -220,42 +220,42 @@ ValuePtr Syntax::getSwizzledValue(ValuePtr value, const TypeDesc* srcType, const { throw ExceptionShaderGenError("Given channel index: '" + string(1, ch) + "' in channels pattern is incorrect for type '" + srcType->getName() + "'."); } - if (srcType == Type::FLOAT) + if (*srcType == *Type::FLOAT) { float v = value->asA(); ss << std::to_string(v); } - else if (srcType == Type::INTEGER) + else if (*srcType == *Type::INTEGER) { int v = value->asA(); ss << std::to_string(v); } - else if (srcType == Type::BOOLEAN) + else if (*srcType == *Type::BOOLEAN) { bool v = value->asA(); ss << std::to_string(v); } - else if (srcType == Type::COLOR3) + else if (*srcType == *Type::COLOR3) { Color3 v = value->asA(); ss << std::to_string(v[channelIndex]); } - else if (srcType == Type::COLOR4) + else if (*srcType == *Type::COLOR4) { Color4 v = value->asA(); ss << std::to_string(v[channelIndex]); } - else if (srcType == Type::VECTOR2) + else if (*srcType == *Type::VECTOR2) { Vector2 v = value->asA(); ss << std::to_string(v[channelIndex]); } - else if (srcType == Type::VECTOR3) + else if (*srcType == *Type::VECTOR3) { Vector3 v = value->asA(); ss << std::to_string(v[channelIndex]); } - else if (srcType == Type::VECTOR4) + else if (*srcType == *Type::VECTOR4) { Vector4 v = value->asA(); ss << std::to_string(v[channelIndex]); diff --git a/source/MaterialXGenShader/TypeDesc.cpp b/source/MaterialXGenShader/TypeDesc.cpp index 54610d81fe..dbe2504758 100644 --- a/source/MaterialXGenShader/TypeDesc.cpp +++ b/source/MaterialXGenShader/TypeDesc.cpp @@ -39,6 +39,16 @@ TypeDesc::TypeDesc(const string& name, unsigned char basetype, unsigned char sem { } +bool TypeDesc::operator==(const TypeDesc& rhs) const +{ + return (this->_name == rhs._name); +} + +bool TypeDesc::operator!=(const TypeDesc& rhs) const +{ + return !(*this == rhs); +} + const TypeDesc* TypeDesc::registerType(const string& name, unsigned char basetype, unsigned char semantic, size_t size, bool editable, const std::unordered_map& channelMapping) { diff --git a/source/MaterialXGenShader/TypeDesc.h b/source/MaterialXGenShader/TypeDesc.h index 425329c32c..daed87d7e2 100644 --- a/source/MaterialXGenShader/TypeDesc.h +++ b/source/MaterialXGenShader/TypeDesc.h @@ -57,6 +57,12 @@ class MX_GENSHADER_API TypeDesc static const TypeDesc* registerType(const string& name, unsigned char basetype, unsigned char semantic = SEMANTIC_NONE, size_t size = 1, bool editable = true, const ChannelMap& channelMapping = ChannelMap()); + /// Equality operator overload + bool operator==(const TypeDesc& rhs) const; + + /// Inequality operator overload + bool operator!=(const TypeDesc& rhs) const; + /// Get a type descriptor for given name. /// Returns an empty shared pointer if no type with the given name is found. static const TypeDesc* get(const string& name); diff --git a/source/MaterialXGenShader/Util.cpp b/source/MaterialXGenShader/Util.cpp index b37383341c..a9f48b31c4 100644 --- a/source/MaterialXGenShader/Util.cpp +++ b/source/MaterialXGenShader/Util.cpp @@ -210,7 +210,7 @@ bool isTransparentShaderGraph(OutputPtr output, const string& target, NodePtr in if (nodeDef) { const TypeDesc* nodeDefType = TypeDesc::get(nodeDef->getType()); - if (nodeDefType == Type::BSDF) + if (*nodeDefType == *Type::BSDF) { InterfaceElementPtr impl = nodeDef->getImplementation(target); if (impl && impl->isA()) diff --git a/source/MaterialXGraphEditor/CMakeLists.txt b/source/MaterialXGraphEditor/CMakeLists.txt index 1785540bd8..557b134cff 100644 --- a/source/MaterialXGraphEditor/CMakeLists.txt +++ b/source/MaterialXGraphEditor/CMakeLists.txt @@ -9,7 +9,7 @@ if (NOT IS_DIRECTORY "${DEAR_IMGUI_PREFIX}/backends") endif() if(MSVC) - add_compile_options(-wd4100) + add_compile_options(-wd4100 -wd4152 -wd4201 -wd4244 -wd4456) elseif(CMAKE_CXX_COMPILER_ID MATCHES "Clang") add_compile_options(-Wno-unused -Wno-deprecated -Wno-comment -Wno-unused-variable) elseif(CMAKE_CXX_COMPILER_ID MATCHES "GNU") @@ -60,6 +60,9 @@ set(GLFW_BUILD_TESTS OFF) set(GLFW_BUILD_DOCS OFF) set(GLFW_INSTALL OFF) +# Explicitly build GLFW with static libraries, independent of the broader build settings. +set(BUILD_SHARED_LIBS OFF) + add_subdirectory(External/Glfw) if(MSVC) diff --git a/source/MaterialXGraphEditor/External/Glfw/CMakeLists.txt b/source/MaterialXGraphEditor/External/Glfw/CMakeLists.txt index eaae85a825..2ec553856f 100644 --- a/source/MaterialXGraphEditor/External/Glfw/CMakeLists.txt +++ b/source/MaterialXGraphEditor/External/Glfw/CMakeLists.txt @@ -41,7 +41,7 @@ if (BUILD_SHARED_LIBS AND UNIX) # On Unix-like systems, shared libraries can use the soname system. set(GLFW_LIB_NAME glfw) else() - set(GLFW_LIB_NAME glfw3) + set(GLFW_LIB_NAME glfw3_minimal) endif() if (GLFW_VULKAN_STATIC) diff --git a/source/MaterialXGraphEditor/FileDialog.h b/source/MaterialXGraphEditor/FileDialog.h index 49b905f28c..4b6c042ef8 100644 --- a/source/MaterialXGraphEditor/FileDialog.h +++ b/source/MaterialXGraphEditor/FileDialog.h @@ -16,9 +16,9 @@ class FileDialog public: enum Flags { - SelectDirectory = 1 << 0, // select directory instead of regular file - EnterNewFilename = 1 << 1, // allow user to enter new filename when selecting regular file - NoTitleBar = 1 << 2, // hide window title bar + SelectDirectory = 1 << 0, // select directory instead of regular file + EnterNewFilename = 1 << 1, // allow user to enter new filename when selecting regular file + NoTitleBar = 1 << 2, // hide window title bar }; public: diff --git a/source/MaterialXGraphEditor/Graph.cpp b/source/MaterialXGraphEditor/Graph.cpp index 2b28317ee2..9b9426f9d7 100644 --- a/source/MaterialXGraphEditor/Graph.cpp +++ b/source/MaterialXGraphEditor/Graph.cpp @@ -23,6 +23,32 @@ const ImVec2 DEFAULT_NODE_SIZE = ImVec2(138, 116); const int DEFAULT_ALPHA = 255; const int FILTER_ALPHA = 50; +const std::array NODE_GROUP_ORDER = +{ + "texture2d", + "texture3d", + "procedural", + "procedural2d", + "procedural3d", + "geometric", + "translation", + "convolution2d", + "math", + "adjustment", + "compositing", + "conditional", + "channel", + "organization", + "global", + "application", + "material", + "shader", + "pbr", + "light", + "colortransform", + "none" +}; + // Based on ImRect_Expanded function in ImGui Node Editor blueprints-example.cpp ImRect expandImRect(const ImRect& rect, float x, float y) { @@ -80,6 +106,22 @@ std::string getUserNodeDefName(const std::string& val) } // anonymous namespace +// +// Link methods +// + +Link::Link() : + _startAttr(-1), + _endAttr(-1) +{ + static int nextId = 1; + _id = nextId++; +} + +// +// Graph methods +// + Graph::Graph(const std::string& materialFilename, const std::string& meshFilename, const mx::FileSearchPath& searchPath, @@ -174,7 +216,7 @@ void Graph::loadStandardLibraries() } } -mx::DocumentPtr Graph::loadDocument(mx::FilePath filename) +mx::DocumentPtr Graph::loadDocument(const mx::FilePath& filename) { mx::FilePathVec libraryFolders = { "libraries" }; _libraryFolders = libraryFolders; @@ -214,7 +256,7 @@ mx::DocumentPtr Graph::loadDocument(mx::FilePath filename) std::cerr << "*** Validation warnings for " << filename.asString() << " ***" << std::endl; std::cerr << message << std::endl; } - + // Cache the currently loaded file _materialFilename = filename; } @@ -236,9 +278,6 @@ void Graph::addExtraNodes() return; } - // Clear any old nodes, if we previously used tab with another graph doc - _extraNodes.clear(); - // Get all types from the doc std::vector types; std::vector typeDefs = _graphDoc->getTypeDefs(); @@ -252,26 +291,33 @@ void Graph::addExtraNodes() for (const std::string& type : types) { std::string nodeName = "ND_input_" + type; - _extraNodes["Input Nodes"].push_back({ nodeName, type, "input" }); + _nodesToAdd.emplace_back(nodeName, type, "input", "Input Nodes"); nodeName = "ND_output_" + type; - _extraNodes["Output Nodes"].push_back({ nodeName, type, "output" }); + _nodesToAdd.emplace_back(nodeName, type, "output", "Output Nodes"); } // Add group node - std::vector groupNode{ "ND_group", "", "group" }; - _extraNodes["Group Nodes"].push_back(groupNode); + _nodesToAdd.emplace_back("ND_group", "", "group", "Group Nodes"); // Add nodegraph node - std::vector nodeGraph{ "ND_nodegraph", "", "nodegraph" }; - _extraNodes["Node Graph"].push_back(nodeGraph); + _nodesToAdd.emplace_back("ND_nodegraph", "", "nodegraph", "Node Graph"); } ed::PinId Graph::getOutputPin(UiNodePtr node, UiNodePtr upNode, UiPinPtr input) { if (upNode->getNodeGraph() != nullptr) { - // For nodegraph need to get the correct ouput pin accorinding to the names of the output nodes - mx::OutputPtr output = input->_pinNode->getNode() ? input->_pinNode->getNode()->getConnectedOutput(input->_name) : nullptr; + // For nodegraph need to get the correct ouput pin according to the names of the output nodes + mx::OutputPtr output; + if (input->_pinNode->getNode()) + { + output = input->_pinNode->getNode()->getConnectedOutput(input->_name); + } + else if (input->_pinNode->getNodeGraph()) + { + output = input->_pinNode->getNodeGraph()->getConnectedOutput(input->_name); + } + if (output) { std::string outName = output->getName(); @@ -389,7 +435,7 @@ void Graph::connectLinks() { for (Link const& link : _currLinks) { - ed::Link(link.id, link._startAttr, link._endAttr); + ed::Link(link._id, link._startAttr, link._endAttr); } } @@ -398,7 +444,7 @@ int Graph::findLinkPosition(int id) int count = 0; for (size_t i = 0; i < _currLinks.size(); i++) { - if (_currLinks[i].id == id) + if (_currLinks[i]._id == id) { return count; } @@ -409,14 +455,8 @@ int Graph::findLinkPosition(int id) bool Graph::checkPosition(UiNodePtr node) { - if (node->getMxElement() != nullptr) - { - if (node->getMxElement()->getAttribute("xpos") != "") - { - return true; - } - } - return false; + return node->getMxElement() && + !node->getMxElement()->getAttribute("xpos").empty(); } // Calculate the total vertical space the node level takes up @@ -689,23 +729,6 @@ void Graph::setPinColor() _pinColor.insert(std::make_pair("stringarray", ImColor(120, 180, 100))); } -void Graph::selectMaterial(UiNodePtr uiNode) -{ - // Find renderable element that corresponds with material UiNode - std::vector elems = mx::findRenderableElements(_graphDoc); - mx::TypedElementPtr typedElem = nullptr; - for (mx::TypedElementPtr elem : elems) - { - mx::TypedElementPtr renderableElem = elem; - mx::NodePtr node = elem->asA(); - if (node == uiNode->getNode()) - { - typedElem = elem; - } - } - _renderer->setMaterial(typedElem); -} - void Graph::setRenderMaterial(UiNodePtr node) { // For now only surface shaders and materials are considered renderable. @@ -846,7 +869,7 @@ void Graph::setRenderMaterial(UiNodePtr node) } } -void Graph::updateMaterials(mx::InputPtr input, mx::ValuePtr value) +void Graph::updateMaterials(mx::InputPtr input /* = nullptr */, mx::ValuePtr value /* = nullptr */) { std::string renderablePath; if (_currRenderNode) @@ -1224,20 +1247,44 @@ void Graph::setUiNodeInfo(UiNodePtr node, const std::string& type, const std::st void Graph::createNodeUIList(mx::DocumentPtr doc) { _nodesToAdd.clear(); - const std::string EXTRA_GROUP_NAME = "extra"; - for (mx::NodeDefPtr nodeDef : doc->getNodeDefs()) + + auto nodeDefs = doc->getNodeDefs(); + std::unordered_map> groupToNodeDef; + std::vector groupList = std::vector(NODE_GROUP_ORDER.begin(), NODE_GROUP_ORDER.end()); + + for (const auto& nodeDef : nodeDefs) { - // NodeDef is the key for the map std::string group = nodeDef->getNodeGroup(); if (group.empty()) { - group = EXTRA_GROUP_NAME; + group = NODE_GROUP_ORDER.back(); + } + + // If the group is not in the groupList already (seeded by NODE_GROUP_ORDER) then add it. + if (std::find(groupList.begin(), groupList.end(), group) == groupList.end()) + { + groupList.emplace_back(group); } - if (_nodesToAdd.find(group) == _nodesToAdd.end()) + + if (groupToNodeDef.find(group) == groupToNodeDef.end()) { - _nodesToAdd[group] = std::vector(); + groupToNodeDef[group] = std::vector(); + } + groupToNodeDef[group].push_back(nodeDef); + } + + for (const auto& group : groupList) + { + auto it = groupToNodeDef.find(group); + if (it != groupToNodeDef.end()) + { + const auto& groupNodeDefs = it->second; + + for (const auto& nodeDef : groupNodeDefs) + { + _nodesToAdd.emplace_back(nodeDef->getName(), nodeDef->getType(), nodeDef->getNodeString(), group); + } } - _nodesToAdd[group].push_back(nodeDef); } addExtraNodes(); @@ -1304,21 +1351,28 @@ void Graph::buildUiBaseGraph(mx::DocumentPtr doc) { int downNum = -1; int upNum = -1; + mx::string nodeGraphName = input->getNodeGraphString(); mx::NodePtr connectedNode = input->getConnectedNode(); - if (connectedNode) + if (!nodeGraphName.empty()) + { + downNum = findNode(graph->getName(), "nodegraph"); + upNum = findNode(nodeGraphName, "nodegraph"); + } + else if (connectedNode) { downNum = findNode(graph->getName(), "nodegraph"); upNum = findNode(connectedNode->getName(), "node"); - if (upNum > -1) + } + + if (upNum > -1) + { + UiEdge newEdge = UiEdge(_graphNodes[upNum], _graphNodes[downNum], input); + if (!edgeExists(newEdge)) { - UiEdge newEdge = UiEdge(_graphNodes[upNum], _graphNodes[downNum], input); - if (!edgeExists(newEdge)) - { - _graphNodes[downNum]->edges.push_back(newEdge); - _graphNodes[downNum]->setInputNodeNum(1); - _graphNodes[upNum]->setOutputConnection(_graphNodes[downNum]); - _currEdge.push_back(newEdge); - } + _graphNodes[downNum]->edges.push_back(newEdge); + _graphNodes[downNum]->setInputNodeNum(1); + _graphNodes[upNum]->setOutputConnection(_graphNodes[downNum]); + _currEdge.push_back(newEdge); } } } @@ -1983,7 +2037,7 @@ UiPinPtr Graph::getPin(ed::PinId pinId) return nullPin; } -void Graph::drawPinIcon(std::string type, bool connected, int alpha) +void Graph::drawPinIcon(const std::string& type, bool connected, int alpha) { ax::Drawing::IconType iconType = ax::Drawing::IconType::Flow; ImColor color = ImColor(0, 0, 0, 255); @@ -2060,50 +2114,6 @@ bool Graph::readOnly() return _currGraphElem->getActiveSourceUri() != _graphDoc->getActiveSourceUri(); } -mx::InputPtr Graph::findInput(mx::InputPtr nodeInput, const std::string& name) -{ - if (_isNodeGraph) - { - for (UiNodePtr node : _graphNodes) - { - if (node->getNode()) - { - for (mx::InputPtr input : node->getNode()->getActiveInputs()) - { - if (input->getInterfaceInput()) - { - if (input->getInterfaceInput() == nodeInput) - { - return input; - } - } - } - } - } - } - else - { - if (_currUiNode->getNodeGraph()) - { - for (mx::NodePtr node : _currUiNode->getNodeGraph()->getNodes()) - { - for (mx::InputPtr input : node->getActiveInputs()) - { - if (input->getInterfaceInput()) - { - - if (input->getInterfaceName() == name) - { - return input; - } - } - } - } - } - } - return nullptr; -} - void Graph::drawOutputPins(UiNodePtr node, const std::string& longestInputLabel) { std::string longestLabel = longestInputLabel; @@ -2219,6 +2229,7 @@ std::vector Graph::createNodes(bool nodegraph) } upUiNode->outputPins[pinIndex]->addConnection(pin); + pin->addConnection(upUiNode->outputPins[pinIndex]); } pin->setConnected(true); } @@ -2284,6 +2295,7 @@ std::vector Graph::createNodes(bool nodegraph) } } upUiNode->outputPins[pinIndex]->addConnection(pin); + pin->addConnection(upUiNode->outputPins[pinIndex]); } pin->setConnected(true); } @@ -2354,6 +2366,7 @@ std::vector Graph::createNodes(bool nodegraph) } } upUiNode->outputPins[pinIndex]->addConnection(pin); + pin->addConnection(upUiNode->outputPins[pinIndex]); } } @@ -2483,12 +2496,22 @@ void Graph::setDefaults(mx::InputPtr input) } } -void Graph::addLink(ed::PinId inputPinId, ed::PinId outputPinId) +void Graph::addLink(ed::PinId startPinId, ed::PinId endPinId) { - int end_attr = int(outputPinId.Get()); - int start_attr = int(inputPinId.Get()); - UiPinPtr inputPin = getPin(outputPinId); - UiPinPtr outputPin = getPin(inputPinId); + // Prefer to assume left to right - start is an output, end is an input; swap if inaccurate + if (UiPinPtr inputPin = getPin(endPinId); inputPin && inputPin->_kind != ed::PinKind::Input) + { + auto tmp = startPinId; + startPinId = endPinId; + endPinId = tmp; + } + + int end_attr = int(endPinId.Get()); + int start_attr = int(startPinId.Get()); + ed::PinId outputPinId = startPinId; + ed::PinId inputPinId = endPinId; + UiPinPtr outputPin = getPin(outputPinId); + UiPinPtr inputPin = getPin(inputPinId); if (!inputPin || !outputPin) { @@ -2496,7 +2519,7 @@ void Graph::addLink(ed::PinId inputPinId, ed::PinId outputPinId) return; } - // Perform type check + // Perform type check bool typesMatch = (outputPin->_type == inputPin->_type); if (!typesMatch) { @@ -2505,187 +2528,207 @@ void Graph::addLink(ed::PinId inputPinId, ed::PinId outputPinId) return; } - if (inputPin->_connected == false) + // Perform kind check + bool kindsMatch = (outputPin->_kind == inputPin->_kind); + if (kindsMatch) { - int upNode = getNodeId(inputPinId); - int downNode = getNodeId(outputPinId); - UiNodePtr uiDownNode = _graphNodes[downNode]; - UiNodePtr uiUpNode = _graphNodes[upNode]; - if (!uiDownNode || !uiUpNode) - { - ed::RejectNewItem(); - return; - } + ed::RejectNewItem(); + showLabel("Invalid connection due to same input/output kind", ImColor(50, 50, 50, 255)); + return; + } - // make sure there is an implementation for node - const mx::ShaderGenerator& shadergen = _renderer->getGenContext().getShaderGenerator(); + int upNode = getNodeId(outputPinId); + int downNode = getNodeId(inputPinId); + UiNodePtr uiDownNode = _graphNodes[downNode]; + UiNodePtr uiUpNode = _graphNodes[upNode]; + if (!uiDownNode || !uiUpNode) + { + ed::RejectNewItem(); + return; + } - // Prevent direct connecting from input to output - if (uiDownNode->getInput() && uiUpNode->getOutput()) - { - ed::RejectNewItem(); - showLabel("Direct connections between inputs and outputs is invalid", ImColor(50, 50, 50, 255)); - return; - } + // Make sure there is an implementation for node + const mx::ShaderGenerator& shadergen = _renderer->getGenContext().getShaderGenerator(); + + // Prevent direct connecting from input to output + if (uiDownNode->getInput() && uiUpNode->getOutput()) + { + ed::RejectNewItem(); + showLabel("Direct connections between inputs and outputs is invalid", ImColor(50, 50, 50, 255)); + return; + } - // Find the implementation for this nodedef if not an input or output uinode - if (uiDownNode->getInput() && _isNodeGraph) + // Find the implementation for this nodedef if not an input or output uinode + if (uiDownNode->getInput() && _isNodeGraph) + { + ed::RejectNewItem(); + showLabel("Cannot connect to inputs inside of graph", ImColor(50, 50, 50, 255)); + return; + } + else if (uiUpNode->getNode()) + { + mx::ShaderNodeImplPtr impl = shadergen.getImplementation(*_graphNodes[upNode]->getNode()->getNodeDef(), _renderer->getGenContext()); + if (!impl) { ed::RejectNewItem(); - showLabel("Cannot connect to inputs inside of graph", ImColor(50, 50, 50, 255)); + showLabel("Invalid Connection: Node does not have an implementation", ImColor(50, 50, 50, 255)); return; } - else if (uiUpNode->getNode()) + } + + if (ed::AcceptNewItem()) + { + // If the accepting node already has a link, remove it + if (inputPin->_connected) { - mx::ShaderNodeImplPtr impl = shadergen.getImplementation(*_graphNodes[upNode]->getNode()->getNodeDef(), _renderer->getGenContext()); - if (!impl) + for (auto linksItr = _currLinks.begin(); linksItr != _currLinks.end(); linksItr++) { - ed::RejectNewItem(); - showLabel("Invalid Connection: Node does not have an implementation", ImColor(50, 50, 50, 255)); - return; + if (linksItr->_endAttr == end_attr) + { + // Found existing link - remove it; adapted from deleteLink + // note: ed::BreakLinks doesn't work as the order ends up inaccurate + deleteLinkInfo(linksItr->_startAttr, linksItr->_endAttr); + _currLinks.erase(linksItr); + break; + } } } - if (ed::AcceptNewItem()) - { - // Since we accepted new link, lets add one to our list of links. - Link link; - link._startAttr = start_attr; - link._endAttr = end_attr; - _currLinks.push_back(link); - _frameCount = ImGui::GetFrameCount(); - _renderer->setMaterialCompilation(true); + // Since we accepted new link, lets add one to our list of links. + Link link; + link._startAttr = start_attr; + link._endAttr = end_attr; + _currLinks.push_back(link); + _frameCount = ImGui::GetFrameCount(); + _renderer->setMaterialCompilation(true); + + inputPin->addConnection(outputPin); + outputPin->addConnection(inputPin); + outputPin->setConnected(true); + inputPin->setConnected(true); - if (uiDownNode->getNode() || uiDownNode->getNodeGraph()) + if (uiDownNode->getNode() || uiDownNode->getNodeGraph()) + { + mx::InputPtr connectingInput = nullptr; + for (UiPinPtr pin : uiDownNode->inputPins) { - mx::InputPtr connectingInput = nullptr; - for (UiPinPtr pin : uiDownNode->inputPins) + if (pin->_pinId == inputPinId) { - if (pin->_pinId == outputPinId) + addNodeInput(uiDownNode, pin->_input); + + // Update value to be empty + if (uiDownNode->getNode() && uiDownNode->getNode()->getType() == mx::SURFACE_SHADER_TYPE_STRING) { - addNodeInput(uiDownNode, pin->_input); - // update value to be empty - if (uiDownNode->getNode() && uiDownNode->getNode()->getType() == mx::SURFACE_SHADER_TYPE_STRING) + if (uiUpNode->getOutput() != nullptr) { - if (uiUpNode->getOutput() != nullptr) - { - pin->_input->setConnectedOutput(uiUpNode->getOutput()); - } - else if (uiUpNode->getInput() != nullptr) - { - pin->_input->setInterfaceName(uiUpNode->getName()); - } - else + pin->_input->setConnectedOutput(uiUpNode->getOutput()); + } + else if (uiUpNode->getInput() != nullptr) + { + pin->_input->setInterfaceName(uiUpNode->getName()); + } + else + { + if (uiUpNode->getNodeGraph() != nullptr) { - // node graph - if (uiUpNode->getNodeGraph() != nullptr) + for (UiPinPtr outPin : uiUpNode->outputPins) { - for (UiPinPtr outPin : uiUpNode->outputPins) + // Set pin connection to correct output + if (outPin->_pinId == outputPinId) { - // set pin connection to correct output - if (outPin->_pinId == inputPinId) - { - mx::OutputPtr outputs = uiUpNode->getNodeGraph()->getOutput(outPin->_name); - pin->_input->setConnectedOutput(outputs); - } + mx::OutputPtr outputs = uiUpNode->getNodeGraph()->getOutput(outPin->_name); + pin->_input->setConnectedOutput(outputs); } } - else - { - pin->_input->setConnectedNode(uiUpNode->getNode()); - } } + else + { + pin->_input->setConnectedNode(uiUpNode->getNode()); + } + } + } + else + { + if (uiUpNode->getInput()) + { + pin->_input->setInterfaceName(uiUpNode->getName()); } else { - if (uiUpNode->getInput()) + if (uiUpNode->getNode()) { - pin->_input->setInterfaceName(uiUpNode->getName()); - } - else - { - if (uiUpNode->getNode()) + mx::NodePtr upstreamNode = _graphNodes[upNode]->getNode(); + mx::NodeDefPtr upstreamNodeDef = upstreamNode->getNodeDef(); + bool isMultiOutput = upstreamNodeDef ? upstreamNodeDef->getOutputs().size() > 1 : false; + if (!isMultiOutput) { - mx::NodePtr upstreamNode = _graphNodes[upNode]->getNode(); - mx::NodeDefPtr upstreamNodeDef = upstreamNode->getNodeDef(); - bool isMultiOutput = upstreamNodeDef ? upstreamNodeDef->getOutputs().size() > 1 : false; - - // This is purely to avoid adding a reference to an update node only 1 output, - // as currently validation consides adding this an error. Otherwise - // it will add an "output" attribute all the time. - if (!isMultiOutput) - { - pin->_input->setConnectedNode(uiUpNode->getNode()); - } - else + pin->_input->setConnectedNode(uiUpNode->getNode()); + } + else + { + for (UiPinPtr outPin : _graphNodes[upNode]->outputPins) { - for (UiPinPtr outPin : _graphNodes[upNode]->outputPins) + // Set pin connection to correct output + if (outPin->_pinId == outputPinId) { - // set pin connection to correct output - if (outPin->_pinId == inputPinId) + mx::OutputPtr outputs = uiUpNode->getNode()->getOutput(outPin->_name); + if (!outputs) { - mx::OutputPtr outputs = uiUpNode->getNode()->getOutput(outPin->_name); - if (!outputs) - { - outputs = uiUpNode->getNode()->addOutput(outPin->_name, pin->_input->getType()); - } - pin->_input->setConnectedOutput(outputs); + outputs = uiUpNode->getNode()->addOutput(outPin->_name, pin->_input->getType()); } + pin->_input->setConnectedOutput(outputs); } } } - else if (uiUpNode->getNodeGraph()) + } + else if (uiUpNode->getNodeGraph()) + { + for (UiPinPtr outPin : uiUpNode->outputPins) { - for (UiPinPtr outPin : uiUpNode->outputPins) + // Set pin connection to correct output + if (outPin->_pinId == outputPinId) { - // set pin connection to correct output - if (outPin->_pinId == inputPinId) - { - mx::OutputPtr outputs = uiUpNode->getNodeGraph()->getOutput(outPin->_name); - pin->_input->setConnectedOutput(outputs); - } + mx::OutputPtr outputs = uiUpNode->getNodeGraph()->getOutput(outPin->_name); + pin->_input->setConnectedOutput(outputs); } } } } - - pin->setConnected(true); - pin->_input->removeAttribute(mx::ValueElement::VALUE_ATTRIBUTE); - connectingInput = pin->_input; - break; } + + pin->setConnected(true); + pin->_input->removeAttribute(mx::ValueElement::VALUE_ATTRIBUTE); + connectingInput = pin->_input; + break; } - // create new edge and set edge information - createEdge(_graphNodes[upNode], _graphNodes[downNode], connectingInput); } - else if (_graphNodes[downNode]->getOutput() != nullptr) - { - mx::InputPtr connectingInput = nullptr; - _graphNodes[downNode]->getOutput()->setConnectedNode(_graphNodes[upNode]->getNode()); - // create new edge and set edge information - createEdge(_graphNodes[upNode], _graphNodes[downNode], connectingInput); - } - else + // Create new edge and set edge information + createEdge(_graphNodes[upNode], _graphNodes[downNode], connectingInput); + } + else if (_graphNodes[downNode]->getOutput() != nullptr) + { + mx::InputPtr connectingInput = nullptr; + _graphNodes[downNode]->getOutput()->setConnectedNode(_graphNodes[upNode]->getNode()); + + // Create new edge and set edge information + createEdge(_graphNodes[upNode], _graphNodes[downNode], connectingInput); + } + else + { + // Create new edge and set edge info + UiEdge newEdge = UiEdge(_graphNodes[upNode], _graphNodes[downNode], nullptr); + if (!edgeExists(newEdge)) { - // create new edge and set edge info - UiEdge newEdge = UiEdge(_graphNodes[upNode], _graphNodes[downNode], nullptr); - if (!edgeExists(newEdge)) - { - _graphNodes[downNode]->edges.push_back(newEdge); - _currEdge.push_back(newEdge); + _graphNodes[downNode]->edges.push_back(newEdge); + _currEdge.push_back(newEdge); - // update input node num and output connections - _graphNodes[downNode]->setInputNodeNum(1); - _graphNodes[upNode]->setOutputConnection(_graphNodes[downNode]); - } + // Update input node num and output connections + _graphNodes[downNode]->setInputNodeNum(1); + _graphNodes[upNode]->setOutputConnection(_graphNodes[downNode]); } } } - else - { - ed::RejectNewItem(); - } } void Graph::removeEdge(int downNode, int upNode, UiPinPtr pin) @@ -2739,9 +2782,13 @@ void Graph::deleteLinkInfo(int startAttr, int endAttr) setDefaults(_graphNodes[upNode]->getInput()); } + for (UiPinPtr connect : pin->_connections) + { + pin->deleteConnection(connect); + } + // Remove any output reference pin->_input->removeAttribute(mx::PortElement::OUTPUT_ATTRIBUTE); - pin->setConnected(false); // If a value exists update the input with it @@ -2766,6 +2813,10 @@ void Graph::deleteLinkInfo(int startAttr, int endAttr) _graphNodes[downNode]->getNodeGraph()->getInput(pin->_name)->removeAttribute(mx::ValueElement::INTERFACE_NAME_ATTRIBUTE); setDefaults(_graphNodes[upNode]->getInput()); } + for (UiPinPtr connect : pin->_connections) + { + pin->deleteConnection(connect); + } pin->_input->setConnectedNode(nullptr); pin->setConnected(false); setDefaults(pin->_input); @@ -2780,6 +2831,10 @@ void Graph::deleteLinkInfo(int startAttr, int endAttr) { removeEdge(downNode, upNode, pin); _graphNodes[downNode]->getOutput()->removeAttribute("nodename"); + for (UiPinPtr connect : pin->_connections) + { + pin->deleteConnection(connect); + } pin->setConnected(false); } } @@ -2831,10 +2886,10 @@ void Graph::deleteNode(UiNodePtr node) } } - if (node->outputPins.size() > 0) + for (UiPinPtr outputPin : node->outputPins) { // Update downNode info - for (UiPinPtr pin : node->outputPins.front()->getConnections()) + for (UiPinPtr pin : outputPin.get()->getConnections()) { mx::ValuePtr val; if (pin->_pinNode->getNode()) @@ -2849,6 +2904,13 @@ void Graph::deleteNode(UiNodePtr node) { pin->_input->setConnectedNode(nullptr); } + if (node->getInput()) + { + // Remove interface value in order to set the default of the input + pin->_input->removeAttribute(mx::ValueElement::INTERFACE_NAME_ATTRIBUTE); + setDefaults(pin->_input); + setDefaults(node->getInput()); + } } else if (pin->_pinNode->getNodeGraph()) { @@ -3009,7 +3071,7 @@ void Graph::loadGraphFromFile(bool prompt) _fileDialog.open(); } else - { + { _graphDoc = loadDocument(_materialFilename); // Rebuild the UI @@ -3020,7 +3082,7 @@ void Graph::loadGraphFromFile(bool prompt) _renderer->setDocument(_graphDoc); _renderer->updateMaterials(nullptr); - } + } } void Graph::saveGraphToFile() @@ -3157,13 +3219,27 @@ void Graph::graphButtons() // Create two windows using splitter float paneWidth = (leftPaneWidth - 2.0f); - ImGui::BeginChild("Selection", ImVec2(paneWidth, 0)); + + float aspectRatio = _renderer->getPixelRatio(); + ImVec2 screenSize = ImVec2(paneWidth, paneWidth / aspectRatio); + + ImVec2 mousePos = ImGui::GetMousePos(); + ImVec2 tempWindowPos = ImGui::GetCursorPos(); + bool cursorInRenderView = mousePos.x > tempWindowPos.x && mousePos.x < (tempWindowPos.x + screenSize.x) && + mousePos.y > tempWindowPos.y && mousePos.y < (tempWindowPos.y + screenSize.y); + + ImGuiWindowFlags windowFlags = 0; + + if (cursorInRenderView) + { + windowFlags |= ImGuiWindowFlags_NoScrollWithMouse; + } + + ImGui::BeginChild("Selection", ImVec2(paneWidth, 0), false, windowFlags); ImVec2 windowPos = ImGui::GetWindowPos(); // RenderView window ImVec2 wsize = ImVec2((float) _renderer->getViewWidth(), (float) _renderer->getViewHeight()); - float aspectRatio = _renderer->getPixelRatio(); - ImVec2 screenSize = ImVec2(paneWidth, paneWidth / aspectRatio); _renderer->setViewWidth((int) screenSize[0]); _renderer->setViewHeight((int) screenSize[1]); @@ -3183,7 +3259,10 @@ void Graph::graphButtons() ImGui::EndChild(); ImGui::SameLine(0.0f, 12.0f); - handleRenderViewInputs(windowPos, screenSize[0], screenSize[1]); + if (cursorInRenderView) + { + handleRenderViewInputs(); + } } void Graph::propertyEditor() @@ -3205,16 +3284,16 @@ void Graph::propertyEditor() std::string name = _currUiNode->getNode()->getParent()->createValidChildName(temp); std::vector downstreamNodes = _currUiNode->getOutputConnections(); - for (UiNodePtr nodes : downstreamNodes) + for (UiNodePtr uiNode : downstreamNodes) { - if (nodes->getInput() == nullptr) + if (!uiNode->getInput() && uiNode->getNode()) { - for (mx::InputPtr input : nodes->getNode()->getActiveInputs()) + for (mx::InputPtr input : uiNode->getNode()->getActiveInputs()) { if (input->getConnectedNode() == _currUiNode->getNode()) { _currUiNode->getNode()->setName(name); - nodes->getNode()->setConnectedNode(input->getName(), _currUiNode->getNode()); + uiNode->getNode()->setConnectedNode(input->getName(), _currUiNode->getNode()); } } } @@ -3229,13 +3308,13 @@ void Graph::propertyEditor() { std::string name = _currUiNode->getInput()->getParent()->createValidChildName(temp); std::vector downstreamNodes = _currUiNode->getOutputConnections(); - for (UiNodePtr nodes : downstreamNodes) + for (UiNodePtr uiNode : downstreamNodes) { - if (nodes->getInput() == nullptr) + if (uiNode->getInput() == nullptr) { - if (nodes->getNode()) + if (uiNode->getNode()) { - for (mx::InputPtr input : nodes->getNode()->getActiveInputs()) + for (mx::InputPtr input : uiNode->getNode()->getActiveInputs()) { if (input->getInterfaceInput() == _currUiNode->getInput()) { @@ -3248,7 +3327,7 @@ void Graph::propertyEditor() } else { - nodes->getOutput()->setConnectedNode(_currUiNode->getNode()); + uiNode->getOutput()->setConnectedNode(_currUiNode->getNode()); } } } @@ -3566,101 +3645,69 @@ void Graph::addNodePopup(bool cursor) // Input string length // Filter extra nodes - includes inputs, outputs, groups, and node graphs const std::string NODEGRAPH_ENTRY = "Node Graph"; - for (std::unordered_map>>::iterator it = _extraNodes.begin(); it != _extraNodes.end(); ++it) + + // Filter nodedefs and add to menu if matches filter + for (auto node : _nodesToAdd) { // Filter out list of nodes if (subs.size() > 0) { ImGui::SetNextWindowSizeConstraints(ImVec2(250.0f, 300.0f), ImVec2(-1.0f, 500.0f)); - for (size_t i = 0; i < it->second.size(); i++) - { - std::string str(it->second[i][0]); - std::string nodeName = it->second[i][0]; + std::string str(node.getName()); + std::string nodeName = node.getName(); - // Disallow creating nested nodegraphs - if (_isNodeGraph && it->first == NODEGRAPH_ENTRY) - { - continue; - } + // Disallow creating nested nodegraphs + if (_isNodeGraph && node.getGroup() == NODEGRAPH_ENTRY) + { + continue; + } - // Allow spaces to be used to search for node names - std::replace(subs.begin(), subs.end(), ' ', '_'); + // Allow spaces to be used to search for node names + std::replace(subs.begin(), subs.end(), ' ', '_'); - if (str.find(subs) != std::string::npos) + if (str.find(subs) != std::string::npos) + { + if (ImGui::MenuItem(getUserNodeDefName(nodeName).c_str()) || (ImGui::IsItemFocused() && ImGui::IsKeyPressedMap(ImGuiKey_Enter))) { - if (ImGui::MenuItem(getUserNodeDefName(nodeName).c_str()) || (ImGui::IsItemFocused() && ImGui::IsKeyPressedMap(ImGuiKey_Enter))) - { - addNode(it->second[i][2], getUserNodeDefName(nodeName), it->second[i][1]); - _addNewNode = true; - memset(input, '\0', sizeof(input)); - } + addNode(node.getCategory(), getUserNodeDefName(nodeName), node.getType()); + _addNewNode = true; + memset(input, '\0', sizeof(input)); } } } else { ImGui::SetNextWindowSizeConstraints(ImVec2(100, 10), ImVec2(-1, 300)); - if (ImGui::BeginMenu(it->first.c_str())) + if (ImGui::BeginMenu(node.getGroup().c_str())) { ImGui::SetWindowFontScale(_fontScale); - for (size_t j = 0; j < it->second.size(); j++) + std::string name = node.getName(); + std::string prefix = "ND_"; + if (name.compare(0, prefix.size(), prefix) == 0 && name.compare(prefix.size(), std::string::npos, node.getCategory()) == 0) { - std::string name = it->second[j][0]; if (ImGui::MenuItem(getUserNodeDefName(name).c_str()) || (ImGui::IsItemFocused() && ImGui::IsKeyPressedMap(ImGuiKey_Enter))) { - addNode(it->second[j][2], getUserNodeDefName(name), it->second[j][1]); - _addNewNode = true; - } - } - ImGui::EndMenu(); - } - } - } - - // Filter nodedefs and add to menu if matches filter - for (std::unordered_map>::iterator it = _nodesToAdd.begin(); it != _nodesToAdd.end(); ++it) - { - // Filter out list of nodes - if (subs.size() > 0) - { - ImGui::SetNextWindowSizeConstraints(ImVec2(250.0f, 300.0f), ImVec2(-1.0f, 500.0f)); - for (size_t i = 0; i < it->second.size(); i++) - { - std::string str(it->second[i]->getName()); - std::string nodeName = it->second[i]->getName(); - if (str.find(subs) != std::string::npos) - { - std::string val = getUserNodeDefName(nodeName); - if (ImGui::MenuItem(val.c_str()) || (ImGui::IsItemFocused() && ImGui::IsKeyPressedMap(ImGuiKey_Enter))) - { - addNode(it->second[i]->getNodeString(), val, it->second[i]->getType()); + addNode(node.getCategory(), getUserNodeDefName(name), node.getType()); _addNewNode = true; - memset(input, '\0', sizeof(input)); } } - } - } - else - { - ImGui::SetNextWindowSizeConstraints(ImVec2(100, 10), ImVec2(-1, 300)); - if (ImGui::BeginMenu(it->first.c_str())) - { - ImGui::SetWindowFontScale(_fontScale); - for (size_t i = 0; i < it->second.size(); i++) + else { - std::string name = it->second[i]->getName(); - std::string val = getUserNodeDefName(name); - if (ImGui::MenuItem(val.c_str()) || (ImGui::IsItemFocused() && ImGui::IsKeyPressedMap(ImGuiKey_Enter))) + if (ImGui::BeginMenu(node.getCategory().c_str())) { - addNode(it->second[i]->getNodeString(), val, it->second[i]->getType()); - _addNewNode = true; + if (ImGui::MenuItem(getUserNodeDefName(name).c_str()) || (ImGui::IsItemFocused() && ImGui::IsKeyPressedMap(ImGuiKey_Enter))) + { + addNode(node.getCategory(), getUserNodeDefName(name), node.getType()); + _addNewNode = true; + } + ImGui::EndMenu(); } } + ImGui::EndMenu(); } } } - cursor = false; ImGui::EndPopup(); open_AddPopup = false; } @@ -3702,11 +3749,45 @@ void Graph::searchNodePopup(bool cursor) } } } - cursor = false; ImGui::EndPopup(); } } +bool Graph::isPinHovered() +{ + ed::PinId currentPin = ed::GetHoveredPin(); + ed::PinId nullPin = 0; + return currentPin != nullPin; +} + +void Graph::addPinPopup() +{ + // Add a floating popup to pin when hovered + if (isPinHovered()) + { + ed::Suspend(); + UiPinPtr pin = getPin(ed::GetHoveredPin()); + std::string connected; + std::string value; + if (pin->_connected) + { + mx::StringVec connectedNames; + for (UiPinPtr connectedPin : pin->getConnections()) + { + connectedNames.push_back(connectedPin->_name); + } + connected = "\nConnected to " + mx::joinStrings(connectedNames, ", "); + } + else if (pin->_input) + { + value = "\nValue: " + pin->_input->getValueString(); + } + const std::string message("Name: " + pin->_name + "\nType: " + pin->_type + value + connected); + ImGui::SetTooltip("%s", message.c_str()); + ed::Resume(); + } +} + void Graph::readOnlyPopup() { if (_popup) @@ -3741,55 +3822,52 @@ void Graph::shaderPopup() } } -void Graph::handleRenderViewInputs(ImVec2 minValue, float width, float height) +void Graph::handleRenderViewInputs() { ImVec2 mousePos = ImGui::GetMousePos(); - if (mousePos.x > minValue.x && mousePos.x < (minValue.x + width) && mousePos.y > minValue.y && mousePos.y < (minValue.y + height)) + mx::Vector2 mxMousePos = mx::Vector2(mousePos.x, mousePos.y); + float scrollAmt = ImGui::GetIO().MouseWheel; + int button = -1; + bool down = false; + if (ImGui::IsMouseDragging(0) || ImGui::IsMouseDragging(1)) { - mx::Vector2 mxMousePos = mx::Vector2(mousePos.x, mousePos.y); - float scrollAmt = ImGui::GetIO().MouseWheel; - int button = -1; - bool down = false; - if (ImGui::IsMouseDragging(0) || ImGui::IsMouseDragging(1)) - { - _renderer->setMouseMotionEvent(mxMousePos); - } - if (ImGui::IsMouseClicked(0)) - { - button = 0; - down = true; - _renderer->setMouseButtonEvent(button, down, mxMousePos); - } - else if (ImGui::IsMouseClicked(1)) - { - button = 1; - down = true; - _renderer->setMouseButtonEvent(button, down, mxMousePos); - } - else if (ImGui::IsMouseReleased(0)) - { - button = 0; - _renderer->setMouseButtonEvent(button, down, mxMousePos); - } - else if (ImGui::IsMouseReleased(1)) - { - button = 1; - _renderer->setMouseButtonEvent(button, down, mxMousePos); - } - else if (ImGui::IsKeyPressed(ImGuiKey_KeypadAdd)) - { - _renderer->setKeyEvent(ImGuiKey_KeypadAdd); - } - else if (ImGui::IsKeyPressed(ImGuiKey_KeypadSubtract)) - { - _renderer->setKeyEvent(ImGuiKey_KeypadSubtract); - } + _renderer->setMouseMotionEvent(mxMousePos); + } + if (ImGui::IsMouseClicked(0)) + { + button = 0; + down = true; + _renderer->setMouseButtonEvent(button, down, mxMousePos); + } + else if (ImGui::IsMouseClicked(1)) + { + button = 1; + down = true; + _renderer->setMouseButtonEvent(button, down, mxMousePos); + } + else if (ImGui::IsMouseReleased(0)) + { + button = 0; + _renderer->setMouseButtonEvent(button, down, mxMousePos); + } + else if (ImGui::IsMouseReleased(1)) + { + button = 1; + _renderer->setMouseButtonEvent(button, down, mxMousePos); + } + else if (ImGui::IsKeyPressed(ImGuiKey_KeypadAdd)) + { + _renderer->setKeyEvent(ImGuiKey_KeypadAdd); + } + else if (ImGui::IsKeyPressed(ImGuiKey_KeypadSubtract)) + { + _renderer->setKeyEvent(ImGuiKey_KeypadSubtract); + } - // Scrolling not possible if open or save file dialog is open - if (scrollAmt != 0 && !_fileDialogSave.isOpened() && !_fileDialog.isOpened() && !_fileDialogGeom.isOpened()) - { - _renderer->setScrollEvent(scrollAmt); - } + // Scrolling not possible if open or save file dialog is open + if (scrollAmt != 0 && !_fileDialogSave.isOpened() && !_fileDialog.isOpened() && !_fileDialogGeom.isOpened()) + { + _renderer->setScrollEvent(scrollAmt); } } @@ -3823,6 +3901,7 @@ void Graph::drawGraph(ImVec2 mousePos) ImGui::SetNextWindowSizeConstraints(ImVec2(250.0f, 300.0f), ImVec2(-1.0f, 500.0f)); addNodePopup(TextCursor); searchNodePopup(TextCursor); + addPinPopup(); readOnlyPopup(); ImGui::PopStyleVar(); @@ -4045,12 +4124,12 @@ void Graph::drawGraph(ImVec2 mousePos) // Add new link if (ed::BeginCreate()) { - ed::PinId inputPinId, outputPinId, filterPinId; - if (ed::QueryNewLink(&inputPinId, &outputPinId)) + ed::PinId startPinId, endPinId, filterPinId; + if (ed::QueryNewLink(&startPinId, &endPinId)) { if (!readOnly()) { - addLink(inputPinId, outputPinId); + addLink(startPinId, endPinId); } else { @@ -4240,19 +4319,6 @@ int Graph::findNode(int nodeId) return -1; } -std::vector Graph::findLinkId(int id) -{ - std::vector ids; - for (const Link& link : _currLinks) - { - if (link._startAttr == id || link._endAttr == id) - { - ids.push_back(link.id); - } - } - return ids; -} - bool Graph::edgeExists(UiEdge newEdge) { if (_currEdge.size() > 0) diff --git a/source/MaterialXGraphEditor/Graph.h b/source/MaterialXGraphEditor/Graph.h index 8c76f0f68d..f225f5e686 100644 --- a/source/MaterialXGraphEditor/Graph.h +++ b/source/MaterialXGraphEditor/Graph.h @@ -17,19 +17,39 @@ namespace ed = ax::NodeEditor; namespace mx = MaterialX; +class MenuItem +{ + public: + MenuItem(const std::string& name, const std::string& type, const std::string& category, const std::string& group) : + name(name), type(type), category(category), group(group) { } + + // getters + std::string getName() const { return name; } + std::string getType() const { return type; } + std::string getCategory() const { return category; } + std::string getGroup() const { return group; } + + // setters + void setName(const std::string& newName) { this->name = newName; } + void setType(const std::string& newType) { this->type = newType; } + void setCategory(const std::string& newCategory) { this->category = newCategory; } + void setGroup(const std::string& newGroup) { this->group = newGroup; } + + private: + std::string name; + std::string type; + std::string category; + std::string group; +}; + // A link connects two pins and includes a unique id and the ids of the two pins it connects -// Based off Link struct from ImGui Node Editor blueprints-examples.cpp +// Based on the Link struct from ImGui Node Editor blueprints-examples.cpp struct Link { - int id; + Link(); + int _startAttr, _endAttr; - Link() : - _startAttr(-1), - _endAttr(-1) - { - static int _id = 0; - id = ++_id; - } + int _id; }; class Graph @@ -42,7 +62,7 @@ class Graph int viewWidth, int viewHeight); - mx::DocumentPtr loadDocument(mx::FilePath filename); + mx::DocumentPtr loadDocument(const mx::FilePath& filename); void drawGraph(ImVec2 mousePos); RenderViewPtr getRenderer() @@ -82,15 +102,14 @@ class Graph // Find link position in current links vector from link id int findLinkPosition(int id); - // Find link from attribute id - std::vector findLinkId(int attrId); - // Check if link exists in the current link vector bool linkExists(Link newLink); // Add link to nodegraph and set up connections between UiNodes and // MaterialX Nodes to update shader - void addLink(ed::PinId inputPinId, ed::PinId outputPinId); + // startPinId - where the link was initiated + // endPinId - where the link was ended + void addLink(ed::PinId startPinId, ed::PinId endPinId); // Delete link from current link vector and remove any connections in // UiNode or MaterialX Nodes to update shader @@ -113,7 +132,7 @@ class Graph void setPinColor(); // Based on the pin icon function in the ImGui Node Editor blueprints-example.cpp - void drawPinIcon(std::string type, bool connected, int alpha); + void drawPinIcon(const std::string& type, bool connected, int alpha); UiPinPtr getPin(ed::PinId id); void drawInputPin(UiPinPtr pin); @@ -163,7 +182,6 @@ class Graph // Add input pointer to node based on input pin void addNodeInput(UiNodePtr node, mx::InputPtr& input); - mx::InputPtr findInput(mx::InputPtr input, const std::string& name); void upNodeGraph(); // Set the value of the selected node constants in the node property editor @@ -187,6 +205,8 @@ class Graph void addNodePopup(bool cursor); void searchNodePopup(bool cursor); + bool isPinHovered(); + void addPinPopup(); bool readOnly(); void readOnlyPopup(); @@ -194,10 +214,9 @@ class Graph void shaderPopup(); void updateMaterials(mx::InputPtr input = nullptr, mx::ValuePtr value = nullptr); - void selectMaterial(UiNodePtr node); // Allow for camera manipulation of render view window - void handleRenderViewInputs(ImVec2 minValue, float width, float height); + void handleRenderViewInputs(); // Set the node to display in render view based on selected node or nodegraph void setRenderMaterial(UiNodePtr node); @@ -246,8 +265,7 @@ class Graph std::vector _currGraphName; // for adding new nodes - std::unordered_map> _nodesToAdd; - std::unordered_map>> _extraNodes; + std::vector _nodesToAdd; // stacks to dive into and out of node graphs std::stack> _graphStack; diff --git a/source/MaterialXGraphEditor/Main.cpp b/source/MaterialXGraphEditor/Main.cpp index 754d766798..5bbcbdad66 100644 --- a/source/MaterialXGraphEditor/Main.cpp +++ b/source/MaterialXGraphEditor/Main.cpp @@ -23,44 +23,6 @@ static void errorCallback(int error, const char* description) fprintf(stderr, "Glfw Error %d: %s\n", error, description); } -mx::FilePath getConfigPath() -{ - mx::FilePath configPath; - auto xdgConfigHome = mx::getEnviron("XDG_CONFIG_HOME"); - auto homeDirectory = mx::getEnviron("HOME"); - if (!xdgConfigHome.empty()) - { - configPath = mx::FilePath(xdgConfigHome); - } - else if (!homeDirectory.empty()) - { -#if defined(__APPLE__) - configPath = mx::FilePath(homeDirectory) / "Library" / "Preferences"; -#else - configPath = mx::FilePath(homeDirectory) / ".config"; - if (!configPath.exists()) - { - configPath.createDirectory(); - } -#endif - } - else - { - return {}; - } - - configPath = configPath / "MaterialX"; - configPath.createDirectory(); - - if (!configPath.exists()) - { - std::cerr << "Failed to create MaterialX config directory at " << configPath.asString() << std::endl; - return {}; - } - - return configPath / "GraphEditor.imgui.ini"; -} - const std::string options = " Options: \n" " --material [FILENAME] Specify the filename of the MTLX document to be displayed in the graph editor\n" @@ -197,13 +159,14 @@ int main(int argc, char* const argv[]) IMGUI_CHECKVERSION(); ImGui::CreateContext(); ImGuiIO& io = ImGui::GetIO(); - io.Fonts->AddFontDefault(); - mx::FilePath configPath = getConfigPath(); - if (!configPath.isEmpty()) - { - io.IniFilename = configPath.asString().c_str(); - } + // Set ini and log filename to NULL. This will prevent the automatic creation of imgui.ini + // in the same folder as the saved material. + // TODO: Consider setting the ini and log file paths to an application directory. + io.IniFilename = NULL; + io.LogFilename = NULL; + + io.Fonts->AddFontDefault(); // Setup Dear ImGui style ImGui::StyleColorsDark(); diff --git a/source/MaterialXGraphEditor/RenderView.cpp b/source/MaterialXGraphEditor/RenderView.cpp index 176014ba65..3c2e01dff9 100644 --- a/source/MaterialXGraphEditor/RenderView.cpp +++ b/source/MaterialXGraphEditor/RenderView.cpp @@ -82,26 +82,6 @@ void applyModifiers(mx::DocumentPtr doc, const DocumentModifiers& modifiers) } } - // Remap references to unimplemented shader nodedefs. - for (mx::NodePtr materialNode : doc->getMaterialNodes()) - { - for (mx::NodePtr shader : getShaderNodes(materialNode)) - { - mx::NodeDefPtr nodeDef = shader->getNodeDef(); - if (nodeDef && !nodeDef->getImplementation()) - { - std::vector altNodeDefs = doc->getMatchingNodeDefs(nodeDef->getNodeString()); - for (mx::NodeDefPtr altNodeDef : altNodeDefs) - { - if (altNodeDef->getImplementation()) - { - shader->setNodeDefString(altNodeDef->getName()); - } - } - } - } - } - // Remap unsupported texture coordinate indices. for (mx::ElementPtr elem : doc->traverseTree()) { @@ -319,7 +299,7 @@ void RenderView::loadMesh(const mx::FilePath& filename) _cameraTarget = mx::Vector3(); initCamera(); - + if (_shadowMap) { _imageHandler->releaseRenderResources(_shadowMap); @@ -868,7 +848,7 @@ void RenderView::initCamera() { _viewCamera->setViewportSize(mx::Vector2((float) _viewWidth, (float) _viewHeight)); - if ( _geometryHandler->getMeshes().empty()) + if (_geometryHandler->getMeshes().empty()) { return; } diff --git a/source/MaterialXGraphEditor/UiNode.h b/source/MaterialXGraphEditor/UiNode.h index c03ae43219..06d0281676 100644 --- a/source/MaterialXGraphEditor/UiNode.h +++ b/source/MaterialXGraphEditor/UiNode.h @@ -95,6 +95,29 @@ class UiPin _connections.push_back(pin); } + void deleteConnection(UiPinPtr pin) + { + for (size_t i = 0; i < _connections.size(); i++) + { + if (_connections[i]->_pinId == pin->_pinId) + { + _connections.erase(_connections.begin() + i); + } + } + for (size_t i = 0; i < pin->_connections.size(); i++) + { + if (pin->_connections[i]->_pinId == _pinId) + { + pin->_connections.erase(pin->_connections.begin() + i); + } + } + if (pin->_connections.size() == 0) + { + pin->setConnected(false); + } + return; + } + const std::vector& getConnections() { return _connections; diff --git a/source/MaterialXRender/CMakeLists.txt b/source/MaterialXRender/CMakeLists.txt index 52d07e688e..654a9648bb 100644 --- a/source/MaterialXRender/CMakeLists.txt +++ b/source/MaterialXRender/CMakeLists.txt @@ -18,6 +18,9 @@ assign_source_group("Header Files" ${materialx_headers}) if(UNIX) add_compile_options(-Wno-unused-function) + if(CMAKE_CXX_COMPILER_ID MATCHES "GNU") + add_compile_options(-Wno-stringop-overflow) + endif() endif() add_library(${MATERIALX_MODULE_NAME} ${materialx_source} ${materialx_headers} ${materialx_inlined}) diff --git a/source/MaterialXRender/Camera.cpp b/source/MaterialXRender/Camera.cpp index 6464246e3a..7b9579376c 100644 --- a/source/MaterialXRender/Camera.cpp +++ b/source/MaterialXRender/Camera.cpp @@ -23,8 +23,8 @@ Matrix44 Camera::createViewMatrix(const Vector3& eye, } Matrix44 Camera::createPerspectiveMatrixZP(float left, float right, - float bottom, float top, - float nearP, float farP) + float bottom, float top, + float nearP, float farP) { return Matrix44( (2.0f * nearP) / (right - left), 0.0f, (right + left) / (right - left), 0.0f, @@ -34,8 +34,8 @@ Matrix44 Camera::createPerspectiveMatrixZP(float left, float right, } Matrix44 Camera::createOrthographicMatrixZP(float left, float right, - float bottom, float top, - float nearP, float farP) + float bottom, float top, + float nearP, float farP) { return Matrix44( 2.0f / (right - left), 0.0f, 0.0f, 0.0f, diff --git a/source/MaterialXRender/Camera.h b/source/MaterialXRender/Camera.h index a20c0f0e70..3135904b5a 100644 --- a/source/MaterialXRender/Camera.h +++ b/source/MaterialXRender/Camera.h @@ -163,17 +163,17 @@ class MX_RENDER_API Camera static Matrix44 createOrthographicMatrix(float left, float right, float bottom, float top, float nearP, float farP); - + /// Create a perpective projection matrix given a set of clip planes with [0,1] projected Z. static Matrix44 createPerspectiveMatrixZP(float left, float right, - float bottom, float top, - float nearP, float farP); + float bottom, float top, + float nearP, float farP); /// Create an orthographic projection matrix given a set of clip planes with [0,1] projected Z. static Matrix44 createOrthographicMatrixZP(float left, float right, - float bottom, float top, - float nearP, float farP); - + float bottom, float top, + float nearP, float farP); + /// Apply a perspective transform to the given 3D point, performing a /// homogeneous divide on the transformed result. static Vector3 transformPointPerspective(const Matrix44& m, const Vector3& v) @@ -185,7 +185,7 @@ class MX_RENDER_API Camera /// @} protected: - // Transform matrices + // Transform matrices Matrix44 _worldMatrix; Matrix44 _viewMatrix; Matrix44 _projectionMatrix; diff --git a/source/MaterialXRender/CgltfLoader.cpp b/source/MaterialXRender/CgltfLoader.cpp index 1c8ec598a6..fcc8831732 100644 --- a/source/MaterialXRender/CgltfLoader.cpp +++ b/source/MaterialXRender/CgltfLoader.cpp @@ -59,7 +59,7 @@ void computeMeshMatrices(GLTFMeshMatrixList& meshMatrices, cgltf_node* cnode) } // Iterate over all children. Note that the existence of a mesh - // does not imply that this is a leaf node so traversal should + // does not imply that this is a leaf node so traversal should // continue even when a mesh is encountered. for (cgltf_size i = 0; i < cnode->children_count; i++) { @@ -76,7 +76,7 @@ using GLTFMeshPathList = std::unordered_map; void computeMeshPaths(GLTFMeshPathList& meshPaths, cgltf_node* cnode, FilePath path, size_t nodeCount, size_t meshCount) { string cnodeName = cnode->name ? string(cnode->name) : DEFAULT_NODE_PREFIX + std::to_string(nodeCount++); - path = path / ( createValidName(cnodeName) + "/" ); + path = path / (createValidName(cnodeName) + "/"); cgltf_mesh* cmesh = cnode->mesh; if (cmesh) @@ -92,7 +92,7 @@ void computeMeshPaths(GLTFMeshPathList& meshPaths, cgltf_node* cnode, FilePath p } // Iterate over all children. Note that the existence of a mesh - // does not imply that this is a leaf node so traversal should + // does not imply that this is a leaf node so traversal should // continue even when a mesh is encountered. for (cgltf_size i = 0; i < cnode->children_count; i++) { @@ -220,11 +220,11 @@ bool CgltfLoader::load(const FilePath& filePath, MeshList& meshList, bool texcoo } // Iterate through all parent transform - for (size_t mtx=0; mtx < positionMatrices.size(); mtx++) + for (size_t mtx = 0; mtx < positionMatrices.size(); mtx++) { const Matrix44& positionMatrix = positionMatrices[mtx]; const Matrix44 normalMatrix = positionMatrix.getInverse().getTranspose(); - + for (cgltf_size primitiveIndex = 0; primitiveIndex < cmesh->primitives_count; ++primitiveIndex) { cgltf_primitive* primitive = &cmesh->primitives[primitiveIndex]; @@ -347,8 +347,7 @@ bool CgltfLoader::load(const FilePath& filePath, MeshList& meshList, bool texcoo else { if (_debugLevel > 0) - std::cout << "Unknown stream type: " << std::to_string(attribute->type) - << std::endl; + std::cout << "Unknown stream type: " << std::to_string(attribute->type) << std::endl; } // Fill in stream diff --git a/source/MaterialXRender/CgltfLoader.h b/source/MaterialXRender/CgltfLoader.h index 4f4a7145ba..fb63cb6102 100644 --- a/source/MaterialXRender/CgltfLoader.h +++ b/source/MaterialXRender/CgltfLoader.h @@ -6,7 +6,7 @@ #ifndef MATERIALX_CGLTFLOADER_H #define MATERIALX_CGLTFLOADER_H -/// @file +/// @file /// GLTF format loader using the Cgltf library #include @@ -32,7 +32,7 @@ class MX_RENDER_API CgltfLoader : public GeometryLoader static CgltfLoaderPtr create() { return std::make_shared(); } /// Load geometry from file path - bool load(const FilePath& filePath, MeshList& meshList, bool texcoordVerticalFlip=false) override; + bool load(const FilePath& filePath, MeshList& meshList, bool texcoordVerticalFlip = false) override; private: unsigned int _debugLevel; diff --git a/source/MaterialXRender/GeometryHandler.cpp b/source/MaterialXRender/GeometryHandler.cpp index e2c974a767..dfea0b2ceb 100644 --- a/source/MaterialXRender/GeometryHandler.cpp +++ b/source/MaterialXRender/GeometryHandler.cpp @@ -89,7 +89,7 @@ bool GeometryHandler::loadGeometry(const FilePath& filePath, bool texcoordVertic bool loaded = false; - std::pair range; + std::pair range; string extension = filePath.getExtension(); range = _geometryLoaders.equal_range(extension); GeometryLoaderMap::iterator first = --range.second; @@ -140,19 +140,17 @@ MeshPtr GeometryHandler::createQuadMesh(const Vector2& uvMin, const Vector2& uvM quadTexCoords->setStride(MeshStream::STRIDE_2D); if (!flipTexCoordsHorizontally) { - quadTexCoords->getData().assign({ - uvMax[0], uvMax[1], - uvMax[0], uvMin[1], - uvMin[0], uvMin[1], - uvMin[0], uvMax[1] }); + quadTexCoords->getData().assign({ uvMax[0], uvMax[1], + uvMax[0], uvMin[1], + uvMin[0], uvMin[1], + uvMin[0], uvMax[1] }); } else { - quadTexCoords->getData().assign({ - uvMax[0], uvMin[1], - uvMax[0], uvMax[1], - uvMin[0], uvMax[1], - uvMin[0], uvMin[1] }); + quadTexCoords->getData().assign({ uvMax[0], uvMin[1], + uvMax[0], uvMax[1], + uvMin[0], uvMax[1], + uvMin[0], uvMin[1] }); } MeshPartitionPtr quadIndices = MeshPartition::create(); quadIndices->getIndices().assign({ 0, 1, 3, 1, 2, 3 }); @@ -161,7 +159,7 @@ MeshPtr GeometryHandler::createQuadMesh(const Vector2& uvMin, const Vector2& uvM quadMesh->addStream(quadPositions); quadMesh->addStream(quadTexCoords); quadMesh->addPartition(quadIndices); - + return quadMesh; } diff --git a/source/MaterialXRender/GeometryHandler.h b/source/MaterialXRender/GeometryHandler.h index 0022487602..5dfc561e0e 100644 --- a/source/MaterialXRender/GeometryHandler.h +++ b/source/MaterialXRender/GeometryHandler.h @@ -121,7 +121,7 @@ class MX_RENDER_API GeometryHandler static MeshPtr createQuadMesh(const Vector2& uvMin = Vector2(0.0f, 0.0f), const Vector2& uvMax = Vector2(1.0f, 1.0f), bool flipTexCoordsHorizontally = false); - + protected: // Recompute bounds for all stored geometry void computeBounds(); diff --git a/source/MaterialXRender/Harmonics.cpp b/source/MaterialXRender/Harmonics.cpp index daf6a59d10..3d5c9d0a1d 100644 --- a/source/MaterialXRender/Harmonics.cpp +++ b/source/MaterialXRender/Harmonics.cpp @@ -9,7 +9,8 @@ MATERIALX_NAMESPACE_BEGIN -namespace { +namespace +{ const double PI = std::acos(-1.0); diff --git a/source/MaterialXRender/Harmonics.h b/source/MaterialXRender/Harmonics.h index 10d5f81e49..f51991361a 100644 --- a/source/MaterialXRender/Harmonics.h +++ b/source/MaterialXRender/Harmonics.h @@ -27,7 +27,8 @@ template class ShCoeffs public: ShCoeffs() = default; - explicit ShCoeffs(const std::array& arr) : _arr(arr) { } + explicit ShCoeffs(const std::array& arr) : + _arr(arr) { } /// @name Comparison Operators /// @{ diff --git a/source/MaterialXRender/Image.cpp b/source/MaterialXRender/Image.cpp index e3b0e4365c..eec4461aea 100644 --- a/source/MaterialXRender/Image.cpp +++ b/source/MaterialXRender/Image.cpp @@ -112,11 +112,13 @@ unsigned int Image::getBaseStride() const return 4; } if (_baseType == BaseType::HALF || - _baseType == BaseType::UINT16) + _baseType == BaseType::UINT16 || + _baseType == BaseType::INT16) { return 2; } - if (_baseType == BaseType::UINT8) + if (_baseType == BaseType::UINT8 || + _baseType == BaseType::INT8) { return 1; } @@ -164,6 +166,14 @@ void Image::setTexelColor(unsigned int x, unsigned int y, const Color4& color) data[c] = (uint16_t) std::round(color[c] * (float) std::numeric_limits::max()); } } + else if (_baseType == BaseType::INT16) + { + int16_t* data = static_cast(_resourceBuffer) + (y * _width + x) * _channelCount; + for (unsigned int c = 0; c < writeChannels; c++) + { + data[c] = (int16_t) std::round(color[c] * (float) std::numeric_limits::max()); + } + } else if (_baseType == BaseType::UINT8) { uint8_t* data = static_cast(_resourceBuffer) + (y * _width + x) * _channelCount; @@ -172,6 +182,14 @@ void Image::setTexelColor(unsigned int x, unsigned int y, const Color4& color) data[c] = (uint8_t) std::round(color[c] * (float) std::numeric_limits::max()); } } + else if (_baseType == BaseType::INT8) + { + int8_t* data = static_cast(_resourceBuffer) + (y * _width + x) * _channelCount; + for (unsigned int c = 0; c < writeChannels; c++) + { + data[c] = (int8_t) std::round(color[c] * (float) std::numeric_limits::max()); + } + } else { throw Exception("Unsupported base type in setTexelColor"); @@ -263,6 +281,32 @@ Color4 Image::getTexelColor(unsigned int x, unsigned int y) const throw Exception("Unsupported channel count in getTexelColor"); } } + else if (_baseType == BaseType::INT16) + { + int16_t* data = static_cast(_resourceBuffer) + (y * _width + x) * _channelCount; + const float MAX_VALUE = (float) std::numeric_limits::max(); + if (_channelCount == 4) + { + return Color4(data[0] / MAX_VALUE, data[1] / MAX_VALUE, data[2] / MAX_VALUE, data[3] / MAX_VALUE); + } + else if (_channelCount == 3) + { + return Color4(data[0] / MAX_VALUE, data[1] / MAX_VALUE, data[2] / MAX_VALUE, 1.0f); + } + else if (_channelCount == 2) + { + return Color4(data[0] / MAX_VALUE, data[1] / MAX_VALUE, 0.0f, 1.0f); + } + else if (_channelCount == 1) + { + float scalar = data[0] / MAX_VALUE; + return Color4(scalar, scalar, scalar, 1.0f); + } + else + { + throw Exception("Unsupported channel count in getTexelColor"); + } + } else if (_baseType == BaseType::UINT8) { uint8_t* data = static_cast(_resourceBuffer) + (y * _width + x) * _channelCount; @@ -289,6 +333,32 @@ Color4 Image::getTexelColor(unsigned int x, unsigned int y) const throw Exception("Unsupported channel count in getTexelColor"); } } + else if (_baseType == BaseType::INT8) + { + int8_t* data = static_cast(_resourceBuffer) + (y * _width + x) * _channelCount; + const float MAX_VALUE = (float) std::numeric_limits::max(); + if (_channelCount == 4) + { + return Color4(data[0] / MAX_VALUE, data[1] / MAX_VALUE, data[2] / MAX_VALUE, data[3] / MAX_VALUE); + } + else if (_channelCount == 3) + { + return Color4(data[0] / MAX_VALUE, data[1] / MAX_VALUE, data[2] / MAX_VALUE, 1.0f); + } + else if (_channelCount == 2) + { + return Color4(data[0] / MAX_VALUE, data[1] / MAX_VALUE, 0.0f, 1.0f); + } + else if (_channelCount == 1) + { + float scalar = data[0] / MAX_VALUE; + return Color4(scalar, scalar, scalar, 1.0f); + } + else + { + throw Exception("Unsupported channel count in getTexelColor"); + } + } else { throw Exception("Unsupported base type in getTexelColor"); diff --git a/source/MaterialXRender/Image.h b/source/MaterialXRender/Image.h index e5857d2af8..43bbbed123 100644 --- a/source/MaterialXRender/Image.h +++ b/source/MaterialXRender/Image.h @@ -47,10 +47,12 @@ class MX_RENDER_API Image public: enum class BaseType { - UINT8 = 0, - UINT16 = 1, - HALF = 2, - FLOAT = 3 + UINT8, + INT8, + UINT16, + INT16, + HALF, + FLOAT }; public: diff --git a/source/MaterialXRender/ImageHandler.cpp b/source/MaterialXRender/ImageHandler.cpp index d54a18fedd..71721c4775 100644 --- a/source/MaterialXRender/ImageHandler.cpp +++ b/source/MaterialXRender/ImageHandler.cpp @@ -165,7 +165,7 @@ void ImageHandler::unbindImages() } } -bool ImageHandler::createRenderResources(ImagePtr, bool) +bool ImageHandler::createRenderResources(ImagePtr, bool, bool) { return false; } @@ -184,11 +184,10 @@ ImageVec ImageHandler::getReferencedImages(ConstDocumentPtr doc) continue; } - NodePtr node = elem->asA(); - InputPtr file = node ? node->getInput("file") : nullptr; - if (file) + InputPtr input = elem->asA(); + if (input && input->getType() == FILENAME_TYPE_STRING) { - ImagePtr image = acquireImage(file->getResolvedValueString()); + ImagePtr image = acquireImage(input->getResolvedValueString()); if (image) { imageVec.push_back(image); @@ -306,12 +305,11 @@ void ImageSamplingProperties::setProperties(const string& fileNameUniform, bool ImageSamplingProperties::operator==(const ImageSamplingProperties& r) const { - return - (enableMipmaps == r.enableMipmaps && - uaddressMode == r.uaddressMode && - vaddressMode == r.vaddressMode && - filterType == r.filterType && - defaultColor == r.defaultColor) ; + return (enableMipmaps == r.enableMipmaps && + uaddressMode == r.uaddressMode && + vaddressMode == r.vaddressMode && + filterType == r.filterType && + defaultColor == r.defaultColor); } MATERIALX_NAMESPACE_END diff --git a/source/MaterialXRender/ImageHandler.h b/source/MaterialXRender/ImageHandler.h index c744eb2f6a..e5d2082f8d 100644 --- a/source/MaterialXRender/ImageHandler.h +++ b/source/MaterialXRender/ImageHandler.h @@ -35,7 +35,7 @@ using ImageHandlerPtr = std::shared_ptr; using ImageLoaderPtr = std::shared_ptr; /// Map from strings to vectors of image loaders -using ImageLoaderMap = std::unordered_map< string, std::vector >; +using ImageLoaderMap = std::unordered_map>; /// @class ImageSamplingProperties /// Interface to describe sampling properties for images. @@ -48,16 +48,16 @@ class MX_RENDER_API ImageSamplingProperties /// @param uniformBlock Block containing sampler uniforms void setProperties(const string& fileNameUniform, const VariableBlock& uniformBlock); - + bool operator==(const ImageSamplingProperties& r) const; /// Address mode options. Matches enumerations allowed for image address /// modes, except UNSPECIFIED which indicates no explicit mode was defined. enum class AddressMode : int - { + { UNSPECIFIED = -1, CONSTANT = 0, - CLAMP = 1, + CLAMP = 1, PERIODIC = 2, MIRROR = 3 }; @@ -186,7 +186,10 @@ class MX_RENDER_API ImageHandler /// Acquire an image from the cache or file system. If the image is not /// found in the cache, then each image loader will be applied in turn. + /// If the image cannot be found by any loader, then a uniform image of the + /// given default color will be returned. /// @param filePath File path of the image. + /// @param defaultColor Default color to use as a fallback for missing images. /// @return On success, a shared pointer to the acquired image. ImagePtr acquireImage(const FilePath& filePath, const Color4& defaultColor = Color4(0.0f)); @@ -227,7 +230,7 @@ class MX_RENDER_API ImageHandler } /// Create rendering resources for the given image. - virtual bool createRenderResources(ImagePtr image, bool generateMipMaps); + virtual bool createRenderResources(ImagePtr image, bool generateMipMaps, bool useAsRenderTarget = false); /// Release rendering resources for the given image, or for all cached images /// if no image pointer is specified. diff --git a/source/MaterialXRender/LightHandler.cpp b/source/MaterialXRender/LightHandler.cpp index cc96d979c7..1daef328dd 100644 --- a/source/MaterialXRender/LightHandler.cpp +++ b/source/MaterialXRender/LightHandler.cpp @@ -42,7 +42,7 @@ void LightHandler::findLights(DocumentPtr doc, vector& lights) for (NodePtr node : doc->getNodes()) { const TypeDesc* type = TypeDesc::get(node->getType()); - if (type == Type::LIGHTSHADER) + if (*type == *Type::LIGHTSHADER) { lights.push_back(node); } @@ -51,7 +51,7 @@ void LightHandler::findLights(DocumentPtr doc, vector& lights) void LightHandler::registerLights(DocumentPtr doc, const vector& lights, GenContext& context) { - // Clear context light user data which is set when bindLightShader() + // Clear context light user data which is set when bindLightShader() // is called. This is necessary in case the light types have already been // registered. HwShaderGenerator::unbindLightShaders(context); @@ -71,7 +71,7 @@ void LightHandler::registerLights(DocumentPtr doc, const vector& lights } // Make sure max light count is large enough - const unsigned int lightCount = (unsigned int)lights.size(); + const unsigned int lightCount = (unsigned int) lights.size(); if (lightCount > context.getOptions().hwMaxActiveLightSources) { context.getOptions().hwMaxActiveLightSources = lightCount; diff --git a/source/MaterialXRender/LightHandler.h b/source/MaterialXRender/LightHandler.h index 666edd34a1..056b0c5cbb 100644 --- a/source/MaterialXRender/LightHandler.h +++ b/source/MaterialXRender/LightHandler.h @@ -37,6 +37,8 @@ class MX_RENDER_API LightHandler _lightTransform(Matrix44::IDENTITY), _directLighting(true), _indirectLighting(true), + _usePrefilteredMap(false), + _envLightIntensity(1.0f), _envSampleCount(DEFAULT_ENV_SAMPLE_COUNT), _refractionTwoSided(false) { @@ -48,7 +50,7 @@ class MX_RENDER_API LightHandler /// @name Global State /// @{ - + /// Set the light transform. void setLightTransform(const Matrix44& mat) { @@ -101,6 +103,30 @@ class MX_RENDER_API LightHandler return _envRadianceMap; } + /// Set the environment radiance map for the prefiltered environment lighting model. + void setEnvPrefilteredMap(ImagePtr map) + { + _envPrefilteredMap = map; + } + + /// Return the environment radiance map for the prefiltered environment lighting model. + ImagePtr getEnvPrefilteredMap() const + { + return _envPrefilteredMap; + } + + /// Set whether to use the prefiltered environment lighting model. + void setUsePrefilteredMap(bool val) + { + _usePrefilteredMap = val; + } + + /// Return whether to use the prefiltered environment lighting model. + bool getUsePrefilteredMap() + { + return _usePrefilteredMap; + } + /// Set the environment irradiance map void setEnvIrradianceMap(ImagePtr map) { @@ -125,6 +151,18 @@ class MX_RENDER_API LightHandler return _envSampleCount; } + /// Set the environment light intensity. + void setEnvLightIntensity(const float intensity) + { + _envLightIntensity = intensity; + } + + /// Return the environment light intensity. + float getEnvLightIntensity() + { + return _envLightIntensity; + } + /// Set the two-sided refraction property. void setRefractionTwoSided(bool enable) { @@ -216,9 +254,12 @@ class MX_RENDER_API LightHandler Matrix44 _lightTransform; bool _directLighting; bool _indirectLighting; + bool _usePrefilteredMap; ImagePtr _envRadianceMap; + ImagePtr _envPrefilteredMap; ImagePtr _envIrradianceMap; + float _envLightIntensity; int _envSampleCount; bool _refractionTwoSided; diff --git a/source/MaterialXRender/Mesh.cpp b/source/MaterialXRender/Mesh.cpp index 110829cd21..bfa7dedd13 100644 --- a/source/MaterialXRender/Mesh.cpp +++ b/source/MaterialXRender/Mesh.cpp @@ -18,7 +18,8 @@ const string MeshStream::BITANGENT_ATTRIBUTE("bitangent"); const string MeshStream::COLOR_ATTRIBUTE("color"); const string MeshStream::GEOMETRY_PROPERTY_ATTRIBUTE("geomprop"); -namespace { +namespace +{ const float MAX_FLOAT = std::numeric_limits::max(); const size_t FACE_VERTEX_COUNT = 3; @@ -266,7 +267,7 @@ void Mesh::splitByUdims() // MeshStream methods // -void MeshStream::transform(const Matrix44 &matrix) +void MeshStream::transform(const Matrix44& matrix) { unsigned int stride = getStride(); size_t numElements = _data.size() / getStride(); @@ -274,17 +275,17 @@ void MeshStream::transform(const Matrix44 &matrix) getType() == MeshStream::TEXCOORD_ATTRIBUTE || getType() == MeshStream::GEOMETRY_PROPERTY_ATTRIBUTE) { - for (size_t i=0; i @@ -31,9 +31,15 @@ bool OiioImageLoader::saveImage(const FilePath& filePath, case Image::BaseType::UINT8: format = OIIO::TypeDesc::UINT8; break; + case Image::BaseType::INT8: + format = OIIO::TypeDesc::INT8; + break; case Image::BaseType::UINT16: format = OIIO::TypeDesc::UINT16; break; + case Image::BaseType::INT16: + format = OIIO::TypeDesc::INT16; + break; case Image::BaseType::HALF: format = OIIO::TypeDesc::HALF; break; @@ -90,9 +96,15 @@ ImagePtr OiioImageLoader::loadImage(const FilePath& filePath) case OIIO::TypeDesc::UINT8: baseType = Image::BaseType::UINT8; break; + case OIIO::TypeDesc::INT8: + baseType = Image::BaseType::INT8; + break; case OIIO::TypeDesc::UINT16: baseType = Image::BaseType::UINT16; break; + case OIIO::TypeDesc::INT16: + baseType = Image::BaseType::INT16; + break; case OIIO::TypeDesc::HALF: baseType = Image::BaseType::HALF; break; diff --git a/source/MaterialXRender/OiioImageLoader.h b/source/MaterialXRender/OiioImageLoader.h index 6619c85bb2..38781dad9e 100644 --- a/source/MaterialXRender/OiioImageLoader.h +++ b/source/MaterialXRender/OiioImageLoader.h @@ -7,7 +7,7 @@ #define MATERIALX_OIIOIMAGELOADER_H /// @file -/// Image loader wrapper using OpenImageIO +/// Image loader wrapper using OpenImageIO #include @@ -21,7 +21,7 @@ using OiioImageLoaderPtr = std::shared_ptr; class MX_RENDER_API OiioImageLoader : public ImageLoader { public: - OiioImageLoader() + OiioImageLoader() { // Set all extensions supported by OpenImageIO _extensions.insert(BMP_EXTENSION); @@ -40,7 +40,7 @@ class MX_RENDER_API OiioImageLoader : public ImageLoader _extensions.insert(TXT_EXTENSION); _extensions.insert(TXR_EXTENSION); } - virtual ~OiioImageLoader() { } + virtual ~OiioImageLoader() { } /// Create a new OpenImageIO image loader static OiioImageLoaderPtr create() { return std::make_shared(); } diff --git a/source/MaterialXRender/ShaderMaterial.cpp b/source/MaterialXRender/ShaderMaterial.cpp index d51efa54af..c61c6d3c04 100644 --- a/source/MaterialXRender/ShaderMaterial.cpp +++ b/source/MaterialXRender/ShaderMaterial.cpp @@ -8,8 +8,8 @@ MATERIALX_NAMESPACE_BEGIN -ShaderMaterial::ShaderMaterial() : _hasTransparency(false) {} -ShaderMaterial::~ShaderMaterial() {} +ShaderMaterial::ShaderMaterial() : _hasTransparency(false) { } +ShaderMaterial::~ShaderMaterial() { } void ShaderMaterial::setDocument(DocumentPtr doc) { @@ -62,9 +62,9 @@ bool ShaderMaterial::hasTransparency() const } bool ShaderMaterial::generateEnvironmentShader(GenContext& context, - const FilePath& filename, - DocumentPtr stdLib, - const FilePath& imagePath) + const FilePath& filename, + DocumentPtr stdLib, + const FilePath& imagePath) { // Read in the environment nodegraph. DocumentPtr doc = createDocument(); @@ -73,7 +73,7 @@ bool ShaderMaterial::generateEnvironmentShader(GenContext& context, readFromXmlFile(envDoc, filename); doc->importLibrary(envDoc); - NodeGraphPtr envGraph = doc->getNodeGraph("environmentDraw"); + NodeGraphPtr envGraph = doc->getNodeGraph("envMap"); if (!envGraph) { return false; diff --git a/source/MaterialXRender/ShaderMaterial.h b/source/MaterialXRender/ShaderMaterial.h index cf500463e4..f29b6f763c 100644 --- a/source/MaterialXRender/ShaderMaterial.h +++ b/source/MaterialXRender/ShaderMaterial.h @@ -74,7 +74,7 @@ class MX_RENDER_API ShaderMaterial /// Generate a shader from our currently stored element and /// the given generator context. virtual bool generateShader(GenContext& context) = 0; - + /// Copies shader and API specific generated program from ShaderMaterial to this one. virtual void copyShader(MaterialPtr ShaderMaterial) = 0; @@ -86,7 +86,7 @@ class MX_RENDER_API ShaderMaterial const FilePath& filename, DocumentPtr stdLib, const FilePath& imagePath); - + /// Return the underlying hardware shader. ShaderPtr getShader() const; diff --git a/source/MaterialXRender/ShaderRenderer.h b/source/MaterialXRender/ShaderRenderer.h index c1cfbecfa0..829a0252c1 100644 --- a/source/MaterialXRender/ShaderRenderer.h +++ b/source/MaterialXRender/ShaderRenderer.h @@ -34,7 +34,7 @@ class MX_RENDER_API ShaderRenderer enum class MatrixConvention { OpenGL = 0, - Metal = 1 + Metal = 1 }; /// A map with name and source code for each shader stage. using StageMap = StringMap; @@ -133,7 +133,7 @@ class MX_RENDER_API ShaderRenderer protected: ShaderRenderer(unsigned int width, unsigned int height, Image::BaseType baseType, - MatrixConvention matrixConvention = MatrixConvention::OpenGL); + MatrixConvention matrixConvention = MatrixConvention::OpenGL); protected: unsigned int _width; @@ -167,7 +167,7 @@ class MX_RENDER_API ExceptionRenderError : public Exception { } - ExceptionRenderError& operator=(const ExceptionRenderError& e) + ExceptionRenderError& operator=(const ExceptionRenderError& e) { Exception::operator=(e); _errorLog = e._errorLog; diff --git a/source/MaterialXRender/StbImageLoader.cpp b/source/MaterialXRender/StbImageLoader.cpp index d8747b75ad..b367bf741c 100644 --- a/source/MaterialXRender/StbImageLoader.cpp +++ b/source/MaterialXRender/StbImageLoader.cpp @@ -7,9 +7,9 @@ #if defined(_MSC_VER) #pragma warning(push) - #pragma warning(disable: 4100) - #pragma warning(disable: 4505) - #pragma warning(disable: 4996) + #pragma warning(disable : 4100) + #pragma warning(disable : 4505) + #pragma warning(disable : 4996) #endif #define STB_IMAGE_IMPLEMENTATION @@ -96,7 +96,7 @@ ImagePtr StbImageLoader::loadImage(const FilePath& filePath) int height = 0; int channelCount = 0; Image::BaseType baseType = Image::BaseType::UINT8; - void *buffer = nullptr; + void* buffer = nullptr; // Select standard or float reader based on file extension. string extension = filePath.getExtension(); diff --git a/source/MaterialXRender/StbImageLoader.h b/source/MaterialXRender/StbImageLoader.h index dabbb8ca9e..f9d91fbcc7 100644 --- a/source/MaterialXRender/StbImageLoader.h +++ b/source/MaterialXRender/StbImageLoader.h @@ -34,7 +34,7 @@ class MX_RENDER_API StbImageLoader : public ImageLoader _extensions.insert(PSD_EXTENSION); _extensions.insert(TGA_EXTENSION); } - virtual ~StbImageLoader() { } + virtual ~StbImageLoader() { } /// Create a new stb image loader static StbImageLoaderPtr create() { return std::make_shared(); } diff --git a/source/MaterialXRender/TextureBaker.h b/source/MaterialXRender/TextureBaker.h index 54b1016451..656bb63c1d 100644 --- a/source/MaterialXRender/TextureBaker.h +++ b/source/MaterialXRender/TextureBaker.h @@ -27,7 +27,7 @@ using BakedDocumentVec = std::vector>; /// A helper class for baking procedural material content to textures. /// TODO: Add support for graphs containing geometric nodes such as position /// and normal. -template +template class TextureBaker : public Renderer { public: @@ -112,7 +112,7 @@ class TextureBaker : public Renderer /// Set the name of the baked graph element. void setBakedGraphName(const string& name) { - _bakedGraphName= name; + _bakedGraphName = name; } /// Return the name of the baked graph element. @@ -218,13 +218,13 @@ class TextureBaker : public Renderer void optimizeBakedTextures(NodePtr shader); /// Bake material to document in memory and write baked textures to disk. - DocumentPtr bakeMaterialToDoc(DocumentPtr doc, const FileSearchPath& searchPath, const string& materialPath, + DocumentPtr bakeMaterialToDoc(DocumentPtr doc, const FileSearchPath& searchPath, const string& materialPath, const StringVec& udimSet, std::string& documentName); /// Bake materials in the given document and write them to disk. If multiple documents are written, /// then the given output filename will be used as a template. void bakeAllMaterials(DocumentPtr doc, const FileSearchPath& searchPath, const FilePath& outputFileName); - + /// Set whether to write a separate document per material when calling bakeAllMaterials. /// By default separate documents are written. void writeDocumentPerMaterial(bool value) @@ -295,7 +295,7 @@ class TextureBaker : public Renderer StringMap _bakedInputMap; std::unordered_map _worldSpaceNodes; - + bool _flipSavedImage; bool _writeDocumentPerMaterial; diff --git a/source/MaterialXRender/TextureBaker.inl b/source/MaterialXRender/TextureBaker.inl index bcc9401210..ff05cb49e7 100644 --- a/source/MaterialXRender/TextureBaker.inl +++ b/source/MaterialXRender/TextureBaker.inl @@ -13,17 +13,17 @@ MATERIALX_NAMESPACE_BEGIN -namespace { +namespace +{ const string SRGB_TEXTURE = "srgb_texture"; const string LIN_REC709 = "lin_rec709"; -const string BAKED_POSTFIX = "_baked"; const string SHADER_PREFIX = "SR_"; const string DEFAULT_UDIM_PREFIX = "_"; } // anonymous namespace -template +template string TextureBaker::getValueStringFromColor(const Color4& color, const string& type) { if (type == "color4" || type == "vector4") @@ -45,7 +45,7 @@ string TextureBaker::getValueStringFromColor(const Color4& return EMPTY_STRING; } -template +template TextureBaker::TextureBaker(unsigned int width, unsigned int height, Image::BaseType baseType, bool flipSavedImage) : Renderer(width, height, baseType), _distanceUnit("meter"), @@ -97,7 +97,7 @@ TextureBaker::TextureBaker(unsigned int width, unsigned int _frameCaptureImage->createResourceBuffer(); } -template +template size_t TextureBaker::findVarInTemplate(const string& filename, const string& var, size_t start) { size_t i = filename.find(var, start); @@ -112,17 +112,15 @@ size_t TextureBaker::findVarInTemplate(const string& filena return i; } -template +template FilePath TextureBaker::generateTextureFilename(const StringMap& filenameTemplateMap) { string bakedImageName = _textureFilenameTemplate; for (auto& pair : filenameTemplateMap) { - string replacement = (_texTemplateOverrides.count(pair.first)) ? - _texTemplateOverrides[pair.first] : pair.second; - replacement = (filenameTemplateMap.at("$UDIM").empty() && pair.first == "$UDIMPREFIX") ? - EMPTY_STRING : replacement; + string replacement = (_texTemplateOverrides.count(pair.first)) ? _texTemplateOverrides[pair.first] : pair.second; + replacement = (filenameTemplateMap.at("$UDIM").empty() && pair.first == "$UDIMPREFIX") ? EMPTY_STRING : replacement; for (size_t i = 0; (i = findVarInTemplate(bakedImageName, pair.first, i)) != string::npos; i++) { @@ -140,7 +138,7 @@ FilePath TextureBaker::generateTextureFilename(const String return _outputImagePath / bakedImageName; } -template +template StringMap TextureBaker::initializeFileTemplateMap(InputPtr input, NodePtr shader, const string& udim) { FilePath assetPath = FilePath(shader->getActiveSourceUri()); @@ -156,7 +154,7 @@ StringMap TextureBaker::initializeFileTemplateMap(InputPtr return filenameTemplateMap; } -template +template bool TextureBaker::writeBakedImage(const BakedImage& baked, ImagePtr image) { if (!Renderer::_imageHandler->saveImage(baked.filename, image, _flipSavedImage)) @@ -176,11 +174,11 @@ bool TextureBaker::writeBakedImage(const BakedImage& baked, return true; } -template +template void TextureBaker::bakeShaderInputs(NodePtr material, NodePtr shader, GenContext& context, const string& udim) { _material = material; - + if (!shader) { return; @@ -216,16 +214,15 @@ void TextureBaker::bakeShaderInputs(NodePtr material, NodeP Renderer::_imageHandler->clearImageCache(); } -template +template void TextureBaker::bakeGraphOutput(OutputPtr output, GenContext& context, const StringMap& filenameTemplateMap) { if (!output) { return; } - - bool encodeSrgb = _colorSpace == SRGB_TEXTURE && - (output->getType() == "color3" || output->getType() == "color4"); + + bool encodeSrgb = _colorSpace == SRGB_TEXTURE && output->isColorType(); Renderer::getFramebuffer()->setEncodeSrgb(encodeSrgb); ShaderPtr shader = _generator->generate("BakingShader", output, context); @@ -258,7 +255,7 @@ void TextureBaker::bakeGraphOutput(OutputPtr output, GenCon } } -template +template void TextureBaker::optimizeBakedTextures(NodePtr shader) { if (!shader) @@ -320,7 +317,7 @@ void TextureBaker::optimizeBakedTextures(NodePtr shader) } } -template +template DocumentPtr TextureBaker::generateNewDocumentFromShader(NodePtr shader, const StringVec& udimSet) { if (!shader) @@ -354,13 +351,13 @@ DocumentPtr TextureBaker::generateNewDocumentFromShader(Nod } // Create a shader node. - NodePtr bakedShader = _bakedTextureDoc->addNode(shader->getCategory(), shader->getName() + BAKED_POSTFIX, shader->getType()); + NodePtr bakedShader = _bakedTextureDoc->addNode(shader->getCategory(), shader->getName(), shader->getType()); // Optionally create a material node, connecting it to the new shader node. if (_material) { - string materialName = (_texTemplateOverrides.count("$MATERIAL"))? _texTemplateOverrides["$MATERIAL"] : _material->getName(); - NodePtr bakedMaterial = _bakedTextureDoc->addNode(_material->getCategory(), materialName + BAKED_POSTFIX, _material->getType()); + string materialName = (_texTemplateOverrides.count("$MATERIAL")) ? _texTemplateOverrides["$MATERIAL"] : _material->getName(); + NodePtr bakedMaterial = _bakedTextureDoc->addNode(_material->getCategory(), materialName, _material->getType()); for (auto sourceMaterialInput : _material->getInputs()) { const string& sourceMaterialInputName = sourceMaterialInput->getName(); @@ -413,7 +410,7 @@ DocumentPtr TextureBaker::generateNewDocumentFromShader(Nod Color4 uniformColor = _bakedConstantMap[output].color; string uniformColorString = getValueStringFromColor(uniformColor, bakedInput->getType()); bakedInput->setValueString(uniformColorString); - if (bakedInput->getType() == "color3" || bakedInput->getType() == "color4") + if (bakedInput->isColorType()) { bakedInput->setColorSpace(_colorSpace); } @@ -423,7 +420,7 @@ DocumentPtr TextureBaker::generateNewDocumentFromShader(Nod if (!_bakedImageMap.empty()) { // Add the image node. - NodePtr bakedImage = bakedNodeGraph->addNode("image", sourceName + BAKED_POSTFIX, sourceType); + NodePtr bakedImage = bakedNodeGraph->addNode("image", sourceName, sourceType); InputPtr input = bakedImage->addInput("file", "filename"); StringMap filenameTemplateMap = initializeFileTemplateMap(bakedInput, shader, udimSet.empty() ? EMPTY_STRING : UDIM_TOKEN); input->setValueString(generateTextureFilename(filenameTemplateMap)); @@ -435,7 +432,7 @@ DocumentPtr TextureBaker::generateNewDocumentFromShader(Nod NodePtr origWorldSpaceNode = worldSpacePair->second; if (origWorldSpaceNode) { - NodePtr newWorldSpaceNode = bakedNodeGraph->addNode(origWorldSpaceNode->getCategory(), sourceName + BAKED_POSTFIX + "_map", sourceType); + NodePtr newWorldSpaceNode = bakedNodeGraph->addNode(origWorldSpaceNode->getCategory(), sourceName + "_map", sourceType); newWorldSpaceNode->copyContentFrom(origWorldSpaceNode); InputPtr mapInput = newWorldSpaceNode->getInput("in"); if (mapInput) @@ -483,9 +480,9 @@ DocumentPtr TextureBaker::generateNewDocumentFromShader(Nod return _bakedTextureDoc; } -template +template DocumentPtr TextureBaker::bakeMaterialToDoc(DocumentPtr doc, const FileSearchPath& searchPath, const string& materialPath, - const StringVec& udimSet, string& documentName) + const StringVec& udimSet, string& documentName) { if (_outputStream) { @@ -551,7 +548,7 @@ DocumentPtr TextureBaker::bakeMaterialToDoc(DocumentPtr doc return generateNewDocumentFromShader(shaderNode, udimSet); } -template +template void TextureBaker::bakeAllMaterials(DocumentPtr doc, const FileSearchPath& searchPath, const FilePath& outputFilename) { if (_outputImagePath.isEmpty()) @@ -593,31 +590,31 @@ void TextureBaker::bakeAllMaterials(DocumentPtr doc, const if (_writeDocumentPerMaterial) { - // Write documents in memory to disk. - size_t bakeCount = bakedDocuments.size(); - for (size_t i = 0; i < bakeCount; i++) - { - if (bakedDocuments[i].second) + // Write documents in memory to disk. + size_t bakeCount = bakedDocuments.size(); + for (size_t i = 0; i < bakeCount; i++) { - FilePath writeFilename = outputFilename; - - // Add additional filename decorations if there are multiple documents. - if (bakedDocuments.size() > 1) + if (bakedDocuments[i].second) { - const string extension = writeFilename.getExtension(); - writeFilename.removeExtension(); - string filenameSeparator = writeFilename.isDirectory()? EMPTY_STRING : "_"; - writeFilename = FilePath(writeFilename.asString() + filenameSeparator + bakedDocuments[i].first + "." + extension); - } + FilePath writeFilename = outputFilename; - writeToXmlFile(bakedDocuments[i].second, writeFilename); - if (_outputStream) - { - *_outputStream << "Wrote baked document: " << writeFilename.asString() << std::endl; + // Add additional filename decorations if there are multiple documents. + if (bakedDocuments.size() > 1) + { + const string extension = writeFilename.getExtension(); + writeFilename.removeExtension(); + string filenameSeparator = writeFilename.isDirectory() ? EMPTY_STRING : "_"; + writeFilename = FilePath(writeFilename.asString() + filenameSeparator + bakedDocuments[i].first + "." + extension); + } + + writeToXmlFile(bakedDocuments[i].second, writeFilename); + if (_outputStream) + { + *_outputStream << "Wrote baked document: " << writeFilename.asString() << std::endl; + } } } } -} else if (_bakedTextureDoc) { writeToXmlFile(_bakedTextureDoc, outputFilename); @@ -628,7 +625,7 @@ void TextureBaker::bakeAllMaterials(DocumentPtr doc, const } } -template +template void TextureBaker::setupUnitSystem(DocumentPtr unitDefinitions) { UnitTypeDefPtr distanceTypeDef = unitDefinitions ? unitDefinitions->getUnitTypeDef("distance") : nullptr; diff --git a/source/MaterialXRender/TinyObjLoader.cpp b/source/MaterialXRender/TinyObjLoader.cpp index 324a1df3e7..b01af1ebf9 100644 --- a/source/MaterialXRender/TinyObjLoader.cpp +++ b/source/MaterialXRender/TinyObjLoader.cpp @@ -23,7 +23,8 @@ MATERIALX_NAMESPACE_BEGIN -namespace { +namespace +{ const float MAX_FLOAT = std::numeric_limits::max(); const size_t FACE_VERTEX_COUNT = 3; @@ -32,9 +33,10 @@ class VertexVector : public VectorN { public: using VectorN::VectorN; - VertexVector(const Vector3& p, const Vector3& n, const Vector2& t) : VectorN(Uninit{}) + VertexVector(const Vector3& p, const Vector3& n, const Vector2& t) : + VectorN(Uninit{}) { - _arr = {p[0], p[1], p[2], n[0], n[1], n[2], t[0], t[1]}; + _arr = { p[0], p[1], p[2], n[0], n[1], n[2], t[0], t[1] }; } }; diff --git a/source/MaterialXRender/TinyObjLoader.h b/source/MaterialXRender/TinyObjLoader.h index 8cfb80762b..e3934f9e41 100644 --- a/source/MaterialXRender/TinyObjLoader.h +++ b/source/MaterialXRender/TinyObjLoader.h @@ -6,7 +6,7 @@ #ifndef MATERIALX_TINYOBJLOADER_H #define MATERIALX_TINYOBJLOADER_H -/// @file +/// @file /// OBJ geometry format loader using the TinyObj library #include diff --git a/source/MaterialXRender/Types.h b/source/MaterialXRender/Types.h index 6af59b9122..b3c15c9f8b 100644 --- a/source/MaterialXRender/Types.h +++ b/source/MaterialXRender/Types.h @@ -65,7 +65,7 @@ class MX_RENDER_API Vector3d : public VectorN Vector3d() = default; Vector3d(double x, double y, double z) : VectorN(Uninit{}) { - _arr = {x, y, z}; + _arr = { x, y, z }; } }; @@ -78,7 +78,7 @@ class MX_RENDER_API Vector4d : public VectorN Vector4d() = default; Vector4d(double x, double y, double z, double w) : VectorN(Uninit{}) { - _arr = {x, y, z, w}; + _arr = { x, y, z, w }; } }; @@ -91,7 +91,7 @@ class MX_RENDER_API Color3d : public VectorN Color3d() = default; Color3d(double r, double g, double b) : VectorN(Uninit{}) { - _arr = {r, g, b}; + _arr = { r, g, b }; } }; diff --git a/source/MaterialXRender/Util.cpp b/source/MaterialXRender/Util.cpp index e8ec0f7c48..f33c67173e 100644 --- a/source/MaterialXRender/Util.cpp +++ b/source/MaterialXRender/Util.cpp @@ -76,6 +76,26 @@ ShaderPtr createAlbedoTableShader(GenContext& context, return shader; } +ShaderPtr createEnvPrefilterShader(GenContext& context, + DocumentPtr stdLib, + const string& shaderName) +{ + // Construct a dummy nodegraph. + DocumentPtr doc = createDocument(); + doc->importLibrary(stdLib); + NodeGraphPtr nodeGraph = doc->addNodeGraph(); + NodePtr constant = nodeGraph->addNode("constant"); + OutputPtr output = nodeGraph->addOutput(); + output->setConnectedNode(constant); + + // Generate the shader + GenContext tableContext = context; + tableContext.getOptions().hwWriteEnvPrefilter = true; + ShaderPtr shader = createShader(shaderName, tableContext, output); + + return shader; +} + ShaderPtr createBlurShader(GenContext& context, DocumentPtr stdLib, const string& shaderName, diff --git a/source/MaterialXRender/Util.h b/source/MaterialXRender/Util.h index 10799cfd33..bf1a3d543c 100644 --- a/source/MaterialXRender/Util.h +++ b/source/MaterialXRender/Util.h @@ -31,28 +31,33 @@ MX_RENDER_API ShaderPtr createShader(const string& shaderName, GenContext& conte /// Create a shader with a constant color output, using the given standard libraries /// for code generation. MX_RENDER_API ShaderPtr createConstantShader(GenContext& context, - DocumentPtr stdLib, - const string& shaderName, - const Color3& color); + DocumentPtr stdLib, + const string& shaderName, + const Color3& color); /// Create a shader with depth value output, using the given standard libraries /// for code generation. MX_RENDER_API ShaderPtr createDepthShader(GenContext& context, - DocumentPtr stdLib, - const string& shaderName); + DocumentPtr stdLib, + const string& shaderName); /// Create a shader that generates a look-up table for directional albedo, using /// the given standard libraries for code generation. MX_RENDER_API ShaderPtr createAlbedoTableShader(GenContext& context, - DocumentPtr stdLib, - const string& shaderName); + DocumentPtr stdLib, + const string& shaderName); + +/// Create a shader that generates a prefiltered environment map. +MX_RENDER_API ShaderPtr createEnvPrefilterShader(GenContext& context, + DocumentPtr stdLib, + const string& shaderName); /// Create a blur shader, using the given standard libraries for code generation. MX_RENDER_API ShaderPtr createBlurShader(GenContext& context, - DocumentPtr stdLib, - const string& shaderName, - const string& filterType, - float filterSize); + DocumentPtr stdLib, + const string& shaderName, + const string& filterType, + float filterSize); /// @} /// @name User Interface Utilities diff --git a/source/MaterialXRenderGlsl/CMakeLists.txt b/source/MaterialXRenderGlsl/CMakeLists.txt index cb2f3c27c2..1748b70190 100644 --- a/source/MaterialXRenderGlsl/CMakeLists.txt +++ b/source/MaterialXRenderGlsl/CMakeLists.txt @@ -27,6 +27,10 @@ elseif(UNIX) message(FATAL_ERROR "Error in building MaterialXRenderGlsl: Xt was not found") endif() + if(SKBUILD) + set(OpenGL_GL_PREFERENCE LEGACY) + endif() + find_package(OpenGL REQUIRED) include_directories(${X11_INCLUDE_DIR}) endif() @@ -50,7 +54,8 @@ if(MATERIALX_BUILD_SHARED_LIBS) target_compile_definitions(${MATERIALX_MODULE_NAME} PUBLIC GLAD_GLAPI_EXPORT PRIVATE GLAD_GLAPI_EXPORT_BUILD) endif() -set(COMMON_LIBRARIES +target_link_libraries( + ${MATERIALX_MODULE_NAME} MaterialXRenderHw MaterialXGenGlsl ${CMAKE_DL_LIBS}) @@ -59,30 +64,26 @@ if(WIN32) if(MSVC) target_link_libraries( ${MATERIALX_MODULE_NAME} - ${COMMON_LIBRARIES} Opengl32) elseif(MINGW) target_link_libraries( ${MATERIALX_MODULE_NAME} - ${COMMON_LIBRARIES} Opengl32 gdi32) endif() elseif(APPLE) target_link_libraries( ${MATERIALX_MODULE_NAME} - ${COMMON_LIBRARIES} - ${OPENGL_LIBRARIES} + "-framework OpenGL" "-framework Foundation" "-framework Cocoa" "-framework Metal") elseif(UNIX) target_link_libraries( ${MATERIALX_MODULE_NAME} - ${COMMON_LIBRARIES} - ${OPENGL_LIBRARIES} - ${X11_LIBRARIES} - ${X11_Xt_LIB}) + OpenGL::GL + X11::X11 + X11::Xt) endif() set_target_properties( diff --git a/source/MaterialXRenderGlsl/GLFramebuffer.cpp b/source/MaterialXRenderGlsl/GLFramebuffer.cpp index bb8e567c58..9516e9ad43 100644 --- a/source/MaterialXRenderGlsl/GLFramebuffer.cpp +++ b/source/MaterialXRenderGlsl/GLFramebuffer.cpp @@ -75,33 +75,33 @@ GLFramebuffer::GLFramebuffer(unsigned int width, unsigned int height, unsigned i string errorMessage; switch (status) { - case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT: - errorMessage = "GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT"; - break; - case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT: - errorMessage = "GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT"; - break; - case GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER: - errorMessage = "GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER"; - break; - case GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER: - errorMessage = "GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER"; - break; - case GL_FRAMEBUFFER_UNSUPPORTED: - errorMessage = "GL_FRAMEBUFFER_UNSUPPORTED"; - break; - case GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE: - errorMessage = "GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE"; - break; - case GL_FRAMEBUFFER_UNDEFINED: - errorMessage = "GL_FRAMEBUFFER_UNDEFINED"; - break; - case GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS: - errorMessage = "GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS"; - break; - default: - errorMessage = std::to_string(status); - break; + case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT: + errorMessage = "GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT"; + break; + case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT: + errorMessage = "GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT"; + break; + case GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER: + errorMessage = "GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER"; + break; + case GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER: + errorMessage = "GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER"; + break; + case GL_FRAMEBUFFER_UNSUPPORTED: + errorMessage = "GL_FRAMEBUFFER_UNSUPPORTED"; + break; + case GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE: + errorMessage = "GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE"; + break; + case GL_FRAMEBUFFER_UNDEFINED: + errorMessage = "GL_FRAMEBUFFER_UNDEFINED"; + break; + case GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS: + errorMessage = "GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS"; + break; + default: + errorMessage = std::to_string(status); + break; } throw ExceptionRenderError("Frame buffer object setup failed: " + errorMessage); diff --git a/source/MaterialXRenderGlsl/GLTextureHandler.cpp b/source/MaterialXRenderGlsl/GLTextureHandler.cpp index 314a78c257..cd130654f6 100644 --- a/source/MaterialXRenderGlsl/GLTextureHandler.cpp +++ b/source/MaterialXRenderGlsl/GLTextureHandler.cpp @@ -91,7 +91,7 @@ bool GLTextureHandler::unbindImage(ImagePtr image) return false; } -bool GLTextureHandler::createRenderResources(ImagePtr image, bool generateMipMaps) +bool GLTextureHandler::createRenderResources(ImagePtr image, bool generateMipMaps, bool) { if (image->getResourceId() == GlslProgram::UNDEFINED_OPENGL_RESOURCE_ID) { @@ -230,9 +230,9 @@ void GLTextureHandler::mapTextureFormatToGL(Image::BaseType baseType, unsigned i default: throw Exception("Unsupported channel count in mapTextureFormatToGL"); } - if (baseType == Image::BaseType::UINT8) + if (baseType == Image::BaseType::UINT8 || baseType == Image::BaseType::INT8) { - glType = GL_UNSIGNED_BYTE; + glType = baseType == Image::BaseType::UINT8 ? GL_UNSIGNED_BYTE : GL_BYTE; switch (channelCount) { case 4: glInternalFormat = srgb ? GL_SRGB8_ALPHA8 : GL_RGBA8; break; @@ -242,9 +242,9 @@ void GLTextureHandler::mapTextureFormatToGL(Image::BaseType baseType, unsigned i default: throw Exception("Unsupported channel count in mapTextureFormatToGL"); } } - else if (baseType == Image::BaseType::UINT16) + else if (baseType == Image::BaseType::UINT16 || baseType == Image::BaseType::INT16) { - glType = GL_UNSIGNED_SHORT; + glType = baseType == Image::BaseType::UINT16 ? GL_UNSIGNED_SHORT : GL_SHORT; switch (channelCount) { case 4: glInternalFormat = GL_RGBA16; break; diff --git a/source/MaterialXRenderGlsl/GLTextureHandler.h b/source/MaterialXRenderGlsl/GLTextureHandler.h index 4485ab98eb..13eaab098f 100644 --- a/source/MaterialXRenderGlsl/GLTextureHandler.h +++ b/source/MaterialXRenderGlsl/GLTextureHandler.h @@ -33,11 +33,11 @@ class MX_RENDERGLSL_API GLTextureHandler : public ImageHandler /// will fail if there are not enough available image units to bind to. bool bindImage(ImagePtr image, const ImageSamplingProperties& samplingProperties) override; - /// Unbind an image. + /// Unbind an image. bool unbindImage(ImagePtr image) override; /// Create rendering resources for the given image. - bool createRenderResources(ImagePtr image, bool generateMipMaps) override; + bool createRenderResources(ImagePtr image, bool generateMipMaps, bool useAsRenderTarget = false) override; /// Release rendering resources for the given image, or for all cached images /// if no image pointer is specified. diff --git a/source/MaterialXRenderGlsl/GlslMaterial.cpp b/source/MaterialXRenderGlsl/GlslMaterial.cpp index ce4582d44f..84668d2d0a 100644 --- a/source/MaterialXRenderGlsl/GlslMaterial.cpp +++ b/source/MaterialXRenderGlsl/GlslMaterial.cpp @@ -38,7 +38,7 @@ bool GlslMaterial::loadSource(const FilePath& vertexShaderFile, const FilePath& } // TODO: - // Here we set new source code on the _glProgram without rebuilding + // Here we set new source code on the _glProgram without rebuilding // the _hwShader instance. So the _hwShader is not in sync with the // _glProgram after this operation. _glProgram = GlslProgram::create(); diff --git a/source/MaterialXRenderGlsl/GlslMaterial.h b/source/MaterialXRenderGlsl/GlslMaterial.h index 1e3d0f7f3b..1ae945867a 100644 --- a/source/MaterialXRenderGlsl/GlslMaterial.h +++ b/source/MaterialXRenderGlsl/GlslMaterial.h @@ -24,7 +24,8 @@ using GlslMaterialPtr = std::shared_ptr; class MX_RENDERGLSL_API GlslMaterial : public ShaderMaterial { public: - GlslMaterial() : ShaderMaterial() + GlslMaterial() : + ShaderMaterial() { } ~GlslMaterial() { } @@ -45,7 +46,7 @@ class MX_RENDERGLSL_API GlslMaterial : public ShaderMaterial /// Generate a shader from the given hardware shader. bool generateShader(ShaderPtr hwShader) override; - + /// Copy shader from one material to this one void copyShader(MaterialPtr material) override { diff --git a/source/MaterialXRenderGlsl/GlslProgram.cpp b/source/MaterialXRenderGlsl/GlslProgram.cpp index 900cac0ef1..54f2ba1ca3 100644 --- a/source/MaterialXRenderGlsl/GlslProgram.cpp +++ b/source/MaterialXRenderGlsl/GlslProgram.cpp @@ -59,7 +59,7 @@ void GlslProgram::setStages(ShaderPtr shader) // Extract out the shader code per stage _shader = shader; - for (size_t i =0; inumStages(); ++i) + for (size_t i = 0; i < shader->numStages(); ++i) { const ShaderStage& stage = shader->getStage(i); addStage(stage.getName(), stage.getSourceCode()); @@ -101,7 +101,7 @@ void GlslProgram::build() // Compile vertex shader, if any GLuint vertexShaderId = UNDEFINED_OPENGL_RESOURCE_ID; - const string &vertexShaderSource = _stages[Stage::VERTEX]; + const string& vertexShaderSource = _stages[Stage::VERTEX]; if (!vertexShaderSource.empty()) { vertexShaderId = glCreateShader(GL_VERTEX_SHADER); @@ -138,7 +138,7 @@ void GlslProgram::build() fragmentShaderId = glCreateShader(GL_FRAGMENT_SHADER); // Compile fragment shader - const char *fragmentChar = fragmentShaderSource.c_str(); + const char* fragmentChar = fragmentShaderSource.c_str(); glShaderSource(fragmentShaderId, 1, &fragmentChar, nullptr); glCompileShader(fragmentShaderId); @@ -324,7 +324,7 @@ void GlslProgram::bindPartition(MeshPartitionPtr part) void GlslProgram::bindMesh(MeshPtr mesh) { - _enabledStreamLocations.clear(); + _enabledStreamLocations.clear(); if (_programId == UNDEFINED_OPENGL_RESOURCE_ID) { @@ -547,7 +547,7 @@ void GlslProgram::bindTextures(ImageHandlerPtr imageHandler) // Always bind a texture unless it is a lighting texture. // Lighting textures are handled in the bindLighting() call. - // If no texture can be loaded then the default color defined in + // If no texture can be loaded then the default color defined in // "samplingProperties" will be used to create a fallback texture. if (fileName != HW::ENV_RADIANCE && fileName != HW::ENV_IRRADIANCE) @@ -578,9 +578,21 @@ void GlslProgram::bindLighting(LightHandlerPtr lightHandler, ImageHandlerPtr ima Matrix44 envRotation = Matrix44::createRotationY(PI) * lightHandler->getLightTransform().getTranspose(); bindUniform(HW::ENV_MATRIX, Value::createValue(envRotation), false); bindUniform(HW::ENV_RADIANCE_SAMPLES, Value::createValue(lightHandler->getEnvSampleCount()), false); + bindUniform(HW::ENV_LIGHT_INTENSITY, Value::createValue(lightHandler->getEnvLightIntensity()), false); + ImagePtr envRadiance = nullptr; + if (lightHandler->getIndirectLighting()) + { + envRadiance = lightHandler->getUsePrefilteredMap() ? + lightHandler->getEnvPrefilteredMap() : + lightHandler->getEnvRadianceMap(); + } + else + { + envRadiance = imageHandler->getZeroImage(); + } ImageMap envImages = { - { HW::ENV_RADIANCE, lightHandler->getIndirectLighting() ? lightHandler->getEnvRadianceMap() : imageHandler->getZeroImage() }, + { HW::ENV_RADIANCE, envRadiance }, { HW::ENV_IRRADIANCE, lightHandler->getIndirectLighting() ? lightHandler->getEnvIrradianceMap() : imageHandler->getZeroImage() } }; for (const auto& env : envImages) @@ -903,7 +915,7 @@ const GlslProgram::InputMap& GlslProgram::updateUniformsList() // Process constants const VariableBlock& constants = ps.getConstantBlock(); - for (size_t i=0; i< constants.size(); ++i) + for (size_t i = 0; i < constants.size(); ++i) { const ShaderPort* v = constants[i]; // There is no way to match with an unnamed variable @@ -1027,11 +1039,11 @@ const GlslProgram::InputMap& GlslProgram::updateUniformsList() int GlslProgram::mapTypeToOpenGLType(const TypeDesc* type) { - if (type == Type::INTEGER) + if (*type == *Type::INTEGER) return GL_INT; - else if (type == Type::BOOLEAN) + else if (*type == *Type::BOOLEAN) return GL_BOOL; - else if (type == Type::FLOAT) + else if (*type == *Type::FLOAT) return GL_FLOAT; else if (type->isFloat2()) return GL_FLOAT_VEC2; @@ -1039,11 +1051,11 @@ int GlslProgram::mapTypeToOpenGLType(const TypeDesc* type) return GL_FLOAT_VEC3; else if (type->isFloat4()) return GL_FLOAT_VEC4; - else if (type == Type::MATRIX33) + else if (*type == *Type::MATRIX33) return GL_FLOAT_MAT3; - else if (type == Type::MATRIX44) + else if (*type == *Type::MATRIX44) return GL_FLOAT_MAT4; - else if (type == Type::FILENAME) + else if (*type == *Type::FILENAME) { // A "filename" is not indicative of type, so just return a 2d sampler. return GL_SAMPLER_2D; @@ -1197,9 +1209,9 @@ void GlslProgram::printUniforms(std::ostream& outputStream) string colorspace = input.second->colorspace; bool isConstant = input.second->isConstant; outputStream << "Program Uniform: \"" << input.first - << "\". Location:" << location - << ". GLtype: " << std::hex << gltype - << ". Size: " << std::dec << size; + << "\". Location:" << location + << ". GLtype: " << std::hex << gltype + << ". Size: " << std::dec << size; if (!type.empty()) outputStream << ". TypeString: \"" << type << "\""; if (!value.empty()) @@ -1217,7 +1229,6 @@ void GlslProgram::printUniforms(std::ostream& outputStream) } } - void GlslProgram::printAttributes(std::ostream& outputStream) { updateAttributesList(); @@ -1229,9 +1240,9 @@ void GlslProgram::printAttributes(std::ostream& outputStream) string type = input.second->typeString; string value = input.second->value ? input.second->value->getValueString() : EMPTY_STRING; outputStream << "Program Attribute: \"" << input.first - << "\". Location:" << location - << ". GLtype: " << std::hex << gltype - << ". Size: " << std::dec << size; + << "\". Location:" << location + << ". GLtype: " << std::hex << gltype + << ". Size: " << std::dec << size; if (!type.empty()) outputStream << ". TypeString: \"" << type << "\""; if (!value.empty()) diff --git a/source/MaterialXRenderGlsl/GlslProgram.h b/source/MaterialXRenderGlsl/GlslProgram.h index 2538c63fcb..e90853eedb 100644 --- a/source/MaterialXRenderGlsl/GlslProgram.h +++ b/source/MaterialXRenderGlsl/GlslProgram.h @@ -109,7 +109,7 @@ class MX_RENDERGLSL_API GlslProgram string path; /// Unit string unit; - /// Colorspace + /// Colorspace string colorspace; /// Program input constructor diff --git a/source/MaterialXRenderGlsl/GlslRenderer.h b/source/MaterialXRenderGlsl/GlslRenderer.h index 9ea121aec9..bdf16b44b3 100644 --- a/source/MaterialXRenderGlsl/GlslRenderer.h +++ b/source/MaterialXRenderGlsl/GlslRenderer.h @@ -50,7 +50,7 @@ class MX_RENDERGLSL_API GlslRenderer : public ShaderRenderer { return GLTextureHandler::create(imageLoader); } - + /// Destructor virtual ~GlslRenderer() { } diff --git a/source/MaterialXRenderGlsl/TextureBaker.h b/source/MaterialXRenderGlsl/TextureBaker.h index be1f713cd6..c084b00a1a 100644 --- a/source/MaterialXRenderGlsl/TextureBaker.h +++ b/source/MaterialXRenderGlsl/TextureBaker.h @@ -37,7 +37,7 @@ class MX_RENDERGLSL_API TextureBakerGlsl : public TextureBaker; /// @class SimpleWindow /// A platform-independent window class. -/// +/// /// Plaform-specific resources are encapsulated by a WindowWrapper instance. class MX_RENDERHW_API SimpleWindow { @@ -30,7 +30,7 @@ class MX_RENDERHW_API SimpleWindow virtual ~SimpleWindow(); /// Window initialization - bool initialize(const char* title, unsigned int width, unsigned int height, void *applicationShell); + bool initialize(const char* title, unsigned int width, unsigned int height, void* applicationShell); /// Return our platform-specific resource wrapper WindowWrapperPtr getWindowWrapper() diff --git a/source/MaterialXRenderHw/SimpleWindowLinux.cpp b/source/MaterialXRenderHw/SimpleWindowLinux.cpp index 23779bd92b..5a14a51aba 100644 --- a/source/MaterialXRenderHw/SimpleWindowLinux.cpp +++ b/source/MaterialXRenderHw/SimpleWindowLinux.cpp @@ -26,7 +26,7 @@ SimpleWindow::SimpleWindow() : bool SimpleWindow::initialize(const char* title, unsigned int width, unsigned int height, - void *applicationShell) + void* applicationShell) { int n = 0; @@ -49,13 +49,13 @@ bool SimpleWindow::initialize(const char* title, else { // Reuse existing application shell; - shell = (Widget)applicationShell; + shell = (Widget) applicationShell; } if (!shell) { _id = 0; - return false;; + return false; } Arg args[6]; diff --git a/source/MaterialXRenderHw/SimpleWindowWindows.cpp b/source/MaterialXRenderHw/SimpleWindowWindows.cpp index de5cf48fc1..070950e682 100644 --- a/source/MaterialXRenderHw/SimpleWindowWindows.cpp +++ b/source/MaterialXRenderHw/SimpleWindowWindows.cpp @@ -30,19 +30,19 @@ LRESULT CALLBACK NoOpProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) { switch (msg) { - case WM_CLOSE: - case WM_DESTROY: - break; - default: - return DefWindowProc(hWnd, msg, wParam, lParam); - break; + case WM_CLOSE: + case WM_DESTROY: + break; + default: + return DefWindowProc(hWnd, msg, wParam, lParam); + break; } return 0; } bool SimpleWindow::initialize(const char* title, unsigned int width, unsigned int height, - void * /*applicationShell*/) + void* /*applicationShell*/) { HINSTANCE hInstance = GetModuleHandle(NULL); @@ -50,14 +50,14 @@ bool SimpleWindow::initialize(const char* title, // WNDCLASS wc; wc.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC; - wc.lpfnWndProc = (WNDPROC)NoOpProc; + wc.lpfnWndProc = (WNDPROC) NoOpProc; wc.cbClsExtra = 0; wc.cbWndExtra = 0; wc.hInstance = hInstance; // Set the instance to this application wc.hIcon = LoadIcon(NULL, IDI_WINLOGO); wc.hCursor = LoadCursor(NULL, IDC_ARROW); wc.hbrBackground = NULL; // No background required - wc.lpszMenuName = NULL; // No menu required + wc.lpszMenuName = NULL; // No menu required wc.lpszClassName = _windowClassName; if (!RegisterClass(&wc)) @@ -73,10 +73,10 @@ bool SimpleWindow::initialize(const char* title, // Set the rectangle of the client area. RECT WindowRect; - WindowRect.left = (long)0; - WindowRect.top = (long)0; - WindowRect.right = (long)width; - WindowRect.bottom = (long)height; + WindowRect.left = (long) 0; + WindowRect.top = (long) 0; + WindowRect.right = (long) width; + WindowRect.bottom = (long) height; // Calculate the exact window size (including border) so that the // client area has the desired dimensions. @@ -86,13 +86,13 @@ bool SimpleWindow::initialize(const char* title, // Attempt to create the window. HWND hWnd = CreateWindowEx(dwExStyle, _windowClassName, title, dwStyle | WS_CLIPSIBLINGS | WS_CLIPCHILDREN, - 0, 0, // Window position - WindowRect.right - WindowRect.left, // Window width (including borders) - WindowRect.bottom - WindowRect.top, // Window height (including borders/title bar) - NULL, // No parent window - NULL, // No menu - hInstance, // Instance - NULL); // Don't pass anything To WM_CREATE + 0, 0, // Window position + WindowRect.right - WindowRect.left, // Window width (including borders) + WindowRect.bottom - WindowRect.top, // Window height (including borders/title bar) + NULL, // No parent window + NULL, // No menu + hInstance, // Instance + NULL); // Don't pass anything To WM_CREATE if (!hWnd) { diff --git a/source/MaterialXRenderMsl/CMakeLists.txt b/source/MaterialXRenderMsl/CMakeLists.txt index 4d5e286463..3d980fa44b 100644 --- a/source/MaterialXRenderMsl/CMakeLists.txt +++ b/source/MaterialXRenderMsl/CMakeLists.txt @@ -42,36 +42,33 @@ add_library(${MATERIALX_MODULE_NAME} ${materialx_source} ${materialx_headers}) add_definitions(-DMATERIALX_RENDERMSL_EXPORTS) -set(COMMON_LIBRARIES +target_link_libraries( + ${MATERIALX_MODULE_NAME} MaterialXRenderHw MaterialXGenMsl ${CMAKE_DL_LIBS}) - -if(APPLE AND NOT MATERIALX_BUILD_IOS) -set(COMMON_LIBRARIES - ${COMMON_LIBRARIES} - "-framework Cocoa") -endif() if(MSVC) target_link_libraries( ${MATERIALX_MODULE_NAME} - ${COMMON_LIBRARIES} Opengl32) elseif(APPLE) + if(NOT MATERIALX_BUILD_IOS) + target_link_libraries( + ${MATERIALX_MODULE_NAME} + "-framework Cocoa" + "-framework OpenGL") + endif() target_link_libraries( ${MATERIALX_MODULE_NAME} - ${COMMON_LIBRARIES} - ${OPENGL_LIBRARIES} "-framework Foundation" "-framework Metal") elseif(UNIX) target_link_libraries( ${MATERIALX_MODULE_NAME} - ${COMMON_LIBRARIES} - ${OPENGL_LIBRARIES} - ${X11_LIBRARIES} - ${X11_Xt_LIB}) + OpenGL::GL + X11::X11 + X11::Xt) endif() set_target_properties( diff --git a/source/MaterialXRenderMsl/MetalTextureHandler.h b/source/MaterialXRenderMsl/MetalTextureHandler.h index 4c329f3f6d..c78469a4ce 100644 --- a/source/MaterialXRenderMsl/MetalTextureHandler.h +++ b/source/MaterialXRenderMsl/MetalTextureHandler.h @@ -57,7 +57,7 @@ class MX_RENDERMSL_API MetalTextureHandler : public ImageHandler id getMTLSamplerStateForImage(unsigned int index); /// Create rendering resources for the given image. - bool createRenderResources(ImagePtr image, bool generateMipMaps) override; + bool createRenderResources(ImagePtr image, bool generateMipMaps, bool useAsRenderTarget = false) override; /// Release rendering resources for the given image, or for all cached images /// if no image pointer is specified. diff --git a/source/MaterialXRenderMsl/MetalTextureHandler.mm b/source/MaterialXRenderMsl/MetalTextureHandler.mm index 745019ac92..ab8da46f1f 100644 --- a/source/MaterialXRenderMsl/MetalTextureHandler.mm +++ b/source/MaterialXRenderMsl/MetalTextureHandler.mm @@ -128,7 +128,7 @@ return false; } -bool MetalTextureHandler::createRenderResources(ImagePtr image, bool generateMipMaps) +bool MetalTextureHandler::createRenderResources(ImagePtr image, bool generateMipMaps, bool useAsRenderTarget) { id texture = nil; @@ -149,9 +149,7 @@ texDesc.height = image->getHeight(); texDesc.mipmapLevelCount = generateMipMaps ? image->getMaxMipCount() : 1; texDesc.usage = MTLTextureUsageShaderRead | - // For now, we set generate mip maps flag off, - // when we want to use the texture as render target - (!generateMipMaps ? MTLTextureUsageRenderTarget : 0); + (useAsRenderTarget ? MTLTextureUsageRenderTarget : 0); texDesc.resourceOptions = MTLResourceStorageModePrivate; texDesc.pixelFormat = pixelFormat; if(generateMipMaps) diff --git a/source/MaterialXRenderMsl/MslPipelineStateObject.mm b/source/MaterialXRenderMsl/MslPipelineStateObject.mm index 4f8378ae46..6e5c2764e1 100644 --- a/source/MaterialXRenderMsl/MslPipelineStateObject.mm +++ b/source/MaterialXRenderMsl/MslPipelineStateObject.mm @@ -594,7 +594,7 @@ int GetStrideOfMetalType(MTLDataType type) // Bind environment lights. ImageMap envLights = { - { HW::ENV_RADIANCE, lightHandler->getEnvRadianceMap() }, + { HW::ENV_RADIANCE, lightHandler->getUsePrefilteredMap() ? lightHandler->getEnvPrefilteredMap() : lightHandler->getEnvRadianceMap() }, { HW::ENV_IRRADIANCE, lightHandler->getEnvIrradianceMap() } }; for (const auto& env : envLights) @@ -706,6 +706,7 @@ int GetStrideOfMetalType(MTLDataType type) Matrix44 envRotation = Matrix44::createRotationY(PI) * lightHandler->getLightTransform().getTranspose(); bindUniform(HW::ENV_MATRIX, Value::createValue(envRotation), false); bindUniform(HW::ENV_RADIANCE_SAMPLES, Value::createValue(lightHandler->getEnvSampleCount()), false); + bindUniform(HW::ENV_LIGHT_INTENSITY, Value::createValue(lightHandler->getEnvLightIntensity()), false); ImageMap envLights = { { HW::ENV_RADIANCE, lightHandler->getEnvRadianceMap() }, diff --git a/source/MaterialXTest/CMakeLists.txt b/source/MaterialXTest/CMakeLists.txt index e66db4bd2e..9d2bd578dd 100644 --- a/source/MaterialXTest/CMakeLists.txt +++ b/source/MaterialXTest/CMakeLists.txt @@ -98,6 +98,9 @@ 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) + add_custom_command(TARGET MaterialXTest POST_BUILD + COMMAND ${CMAKE_COMMAND} -E rename + ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/libraries/pbrlib/genosl/mx39_pbrlib_genosl_impl.legacy ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/libraries/pbrlib/genosl/mx39_pbrlib_genosl_impl.mtlx) endif() if(MATERIALX_BUILD_GEN_MDL) @@ -121,6 +124,10 @@ set_target_properties( VERSION "${MATERIALX_LIBRARY_VERSION}" SOVERSION "${MATERIALX_MAJOR_VERSION}") +if(MATERIALX_BUILD_BENCHMARK_TESTS) + target_compile_definitions(MaterialXTest PRIVATE -DCATCH_CONFIG_ENABLE_BENCHMARKING) +endif() + target_link_libraries( MaterialXTest ${CMAKE_DL_LIBS}) diff --git a/source/MaterialXTest/External/Catch/catch.hpp b/source/MaterialXTest/External/Catch/catch.hpp index d2a12427b2..9b309bddc6 100644 --- a/source/MaterialXTest/External/Catch/catch.hpp +++ b/source/MaterialXTest/External/Catch/catch.hpp @@ -1,6 +1,6 @@ /* - * Catch v2.13.9 - * Generated: 2022-04-12 22:37:23.260201 + * Catch v2.13.10 + * Generated: 2022-10-16 11:01:23.452308 * ---------------------------------------------------------- * This file has been merged from multiple headers. Please don't edit it directly * Copyright (c) 2022 Two Blue Cubes Ltd. All rights reserved. @@ -15,7 +15,7 @@ #define CATCH_VERSION_MAJOR 2 #define CATCH_VERSION_MINOR 13 -#define CATCH_VERSION_PATCH 9 +#define CATCH_VERSION_PATCH 10 #ifdef __clang__ # pragma clang system_header @@ -7395,8 +7395,6 @@ namespace Catch { template struct ObjectStorage { - using TStorage = typename std::aligned_storage::value>::type; - ObjectStorage() : data() {} ObjectStorage(const ObjectStorage& other) @@ -7439,7 +7437,7 @@ namespace Catch { return *static_cast(static_cast(&data)); } - TStorage data; + struct { alignas(T) unsigned char data[sizeof(T)]; } data; }; } @@ -7949,7 +7947,7 @@ namespace Catch { #if defined(__i386__) || defined(__x86_64__) #define CATCH_TRAP() __asm__("int $3\n" : : ) /* NOLINT */ #elif defined(__aarch64__) - #define CATCH_TRAP() __asm__(".inst 0xd4200000") + #define CATCH_TRAP() __asm__(".inst 0xd43e0000") #endif #elif defined(CATCH_PLATFORM_IPHONE) @@ -13558,7 +13556,7 @@ namespace Catch { // Handle list request if( Option listed = list( m_config ) ) - return static_cast( *listed ); + return (std::min) (MaxExitCode, static_cast(*listed)); TestGroup tests { m_config }; auto const totals = tests.execute(); @@ -15391,7 +15389,7 @@ namespace Catch { } Version const& libraryVersion() { - static Version version( 2, 13, 9, "", 0 ); + static Version version( 2, 13, 10, "", 0 ); return version; } @@ -17526,12 +17524,20 @@ namespace Catch { #ifndef __OBJC__ +#ifndef CATCH_INTERNAL_CDECL +#ifdef _MSC_VER +#define CATCH_INTERNAL_CDECL __cdecl +#else +#define CATCH_INTERNAL_CDECL +#endif +#endif + #if defined(CATCH_CONFIG_WCHAR) && defined(CATCH_PLATFORM_WINDOWS) && defined(_UNICODE) && !defined(DO_NOT_USE_WMAIN) // Standard C/C++ Win32 Unicode wmain entry point -extern "C" int wmain (int argc, wchar_t * argv[], wchar_t * []) { +extern "C" int CATCH_INTERNAL_CDECL wmain (int argc, wchar_t * argv[], wchar_t * []) { #else // Standard C/C++ main entry point -int main (int argc, char * argv[]) { +int CATCH_INTERNAL_CDECL main (int argc, char * argv[]) { #endif return Catch::Session().run( argc, argv ); diff --git a/source/MaterialXTest/MaterialXCore/Document.cpp b/source/MaterialXTest/MaterialXCore/Document.cpp index 29092071cf..9670c54283 100644 --- a/source/MaterialXTest/MaterialXCore/Document.cpp +++ b/source/MaterialXTest/MaterialXCore/Document.cpp @@ -23,6 +23,7 @@ TEST_CASE("Document", "[document]") constant->setInputValue("value", mx::Color3(0.5f)); mx::OutputPtr output = nodeGraph->addOutput(); output->setConnectedNode(constant); + REQUIRE(output->isColorType()); REQUIRE(doc->validate()); // Create and test a type mismatch in a connection. @@ -108,108 +109,3 @@ TEST_CASE("Document", "[document]") // Validate the combined document. REQUIRE(doc->validate()); } - -TEST_CASE("Version", "[document]") -{ - mx::FileSearchPath searchPath = mx::getDefaultDataSearchPath(); - mx::DocumentPtr stdlib = mx::createDocument(); - mx::loadLibraries({ "libraries" }, searchPath, stdlib); - searchPath.append(searchPath.find("resources/Materials/TestSuite/stdlib/upgrade")); - - // 1.36 to 1.37 - { - mx::DocumentPtr doc = mx::createDocument(); - mx::readFromXmlFile(doc, "1_36_to_1_37.mtlx", searchPath); - doc->importLibrary(stdlib); - REQUIRE(doc->validate()); - - mx::XmlWriteOptions writeOptions; - writeOptions.writeXIncludeEnable = true; - std::string xmlString = mx::writeToXmlString(doc, &writeOptions); - - mx::DocumentPtr doc2 = mx::createDocument(); - mx::readFromXmlString(doc2, xmlString); - REQUIRE(doc2->validate()); - - // Check conversion to desired types occurred - std::unordered_map convertSet = - { - { "invertmatrix", 2}, - { "rotate2d", 1}, - { "rotate3d", 1}, - { "transformmatrix", 7}, - { "ifgreatereq", 7}, - { "separate2", 1}, - { "separate3", 1}, - { "separate4", 1}, - { "combine2", 1}, - { "combine3", 1}, - { "combine4", 1} - }; - for (mx::NodePtr node : doc2->getNodes()) - { - auto convertItem = convertSet.find(node->getCategory()); - if (convertItem != convertSet.end()) - { - convertItem->second--; - } - } - for (auto convertItem : convertSet) - { - REQUIRE((convertItem.second == 0)); - } - } - - // 1.37 to 1.38 - { - mx::DocumentPtr doc = mx::createDocument(); - mx::readFromXmlFile(doc, "1_37_to_1_38.mtlx", searchPath); - doc->importLibrary(stdlib); - REQUIRE(doc->validate()); - - mx::XmlWriteOptions writeOptions; - writeOptions.writeXIncludeEnable = false; - std::string xmlString = mx::writeToXmlString(doc, &writeOptions); - - mx::DocumentPtr doc2 = mx::createDocument(); - mx::readFromXmlString(doc2, xmlString); - REQUIRE(doc2->validate()); - - // atan2 test - const std::string ATAN2 = "atan2"; - mx::StringMap ATAN2_MAP; - ATAN2_MAP["in1"] = "in2"; - ATAN2_MAP["in2"] = "in1"; - - for (mx::ElementPtr elem : doc->traverseTree()) - { - mx::NodePtr node = elem->asA(); - if (!node) - { - continue; - } - const std::string& nodeCategory = node->getCategory(); - if (nodeCategory == ATAN2) - { - const std::string &nodePath = node->getNamePath(); - for (auto in : ATAN2_MAP) - { - mx::ElementPtr input = node->getChild(in.first); - if (input) - { - mx::ElementPtr newNode = doc2->getDescendant(nodePath); - REQUIRE((newNode && newNode->getChild(in.second))); - } - } - } - } - - mx::NodeGraphPtr testNodeGraph = doc2->getNodeGraph("NG_Test"); - REQUIRE(!testNodeGraph->getNode("add")); - REQUIRE(testNodeGraph->getNode("add1")); - REQUIRE(testNodeGraph->getNode("add2")); - REQUIRE(testNodeGraph->getNode("add2")->getInput("in1")->getInterfaceName() == "add"); - REQUIRE(testNodeGraph->getNode("add1")->getInput("in1")->getNodeName() == "add2"); - } -} - diff --git a/source/MaterialXTest/MaterialXCore/Element.cpp b/source/MaterialXTest/MaterialXCore/Element.cpp index fc4939a74f..3865934ccb 100644 --- a/source/MaterialXTest/MaterialXCore/Element.cpp +++ b/source/MaterialXTest/MaterialXCore/Element.cpp @@ -54,6 +54,9 @@ TEST_CASE("Element", "[element]") REQUIRE(*doc2 != *doc); doc2->setChildIndex("elem1", doc2->getChildIndex("elem2")); REQUIRE(*doc2 == *doc); + REQUIRE_THROWS_AS(doc2->setChildIndex("elem1", -100), mx::Exception); + REQUIRE_THROWS_AS(doc2->setChildIndex("elem1", -1), mx::Exception); + REQUIRE_THROWS_AS(doc2->setChildIndex("elem1", 2), mx::Exception); REQUIRE_THROWS_AS(doc2->setChildIndex("elem1", 100), mx::Exception); REQUIRE(*doc2 == *doc); diff --git a/source/MaterialXTest/MaterialXCore/Geom.cpp b/source/MaterialXTest/MaterialXCore/Geom.cpp index 46a9531006..2457d4e524 100644 --- a/source/MaterialXTest/MaterialXCore/Geom.cpp +++ b/source/MaterialXTest/MaterialXCore/Geom.cpp @@ -11,6 +11,21 @@ namespace mx = MaterialX; TEST_CASE("Geom strings", "[geom]") { + // Test conversion between geometry strings and paths. + mx::StringVec geomStrings = + { + "", + "/", + "/robot1", + "/robot1/left_arm" + }; + for (const std::string& geomString : geomStrings) + { + mx::GeomPath geomPath(geomString); + std::string newGeomString(geomPath); + REQUIRE(newGeomString == geomString); + } + // Test for overlapping paths. REQUIRE(mx::geomStringsMatch("/", "/robot1")); REQUIRE(mx::geomStringsMatch("/robot1", "/robot1/left_arm")); diff --git a/source/MaterialXTest/MaterialXCore/Look.cpp b/source/MaterialXTest/MaterialXCore/Look.cpp index 4106bf2eb3..006538891c 100644 --- a/source/MaterialXTest/MaterialXCore/Look.cpp +++ b/source/MaterialXTest/MaterialXCore/Look.cpp @@ -75,6 +75,7 @@ TEST_CASE("Look", "[look]") // Create an inherited look. mx::LookPtr look2 = doc->addLook(); look2->setInheritsFrom(look); + REQUIRE(look2->getActiveMaterialAssigns().size() == 2); REQUIRE(look2->getActivePropertySetAssigns().size() == 1); REQUIRE(look2->getActiveVisibilities().size() == 1); @@ -86,6 +87,7 @@ TEST_CASE("Look", "[look]") // Disconnect the inherited look. look2->setInheritsFrom(nullptr); + REQUIRE(look2->getActiveMaterialAssigns().empty()); REQUIRE(look2->getActivePropertySetAssigns().empty()); REQUIRE(look2->getActiveVisibilities().empty()); } diff --git a/source/MaterialXTest/MaterialXFormat/XmlIo.cpp b/source/MaterialXTest/MaterialXFormat/XmlIo.cpp index 1336a080c4..495712381e 100644 --- a/source/MaterialXTest/MaterialXFormat/XmlIo.cpp +++ b/source/MaterialXTest/MaterialXFormat/XmlIo.cpp @@ -6,7 +6,6 @@ #include #include -#include #include #include @@ -262,6 +261,51 @@ TEST_CASE("Comments and newlines", "[xmlio]") REQUIRE(origXml == newXml); } +TEST_CASE("Fuzz testing", "[xmlio]") +{ + mx::FileSearchPath searchPath = mx::getDefaultDataSearchPath(); + mx::FilePath examplesPath = searchPath.find("resources/Materials/Examples/StandardSurface"); + + std::mt19937 rng(0); + std::uniform_int_distribution randChar(0, 255); + + for (const mx::FilePath& filename : examplesPath.getFilesInDirectory(mx::MTLX_EXTENSION)) + { + // Read the example file into an XML string buffer. + const std::string origString = mx::readFile(examplesPath / filename); + REQUIRE(origString.size() > 0); + std::uniform_int_distribution randPos(0, origString.size() - 1); + + // Iterate over test runs. + for (size_t testRun = 0; testRun < 256; testRun++) + { + std::string editString = origString; + + // Iterate over string edits. + for (size_t editIndex = 0; editIndex < 32; editIndex++) + { + // Randomly alter one character in the document. + size_t charIndex = randPos(rng); + size_t newChar = randChar(rng); + editString[charIndex] = (char) newChar; + + // Attempt to interpret the edited string as a document, allowing only MaterialX exceptions. + mx::DocumentPtr doc = mx::createDocument(); + try + { + mx::readFromXmlString(doc, editString, searchPath); + doc->validate(); + } + catch (const mx::Exception&) + { + // On a MaterialX exception, proceed to the next test run. + break; + } + } + } + } +} + TEST_CASE("Locale region testing", "[xmlio]") { // In the United States, the thousands separator is a comma, while in Germany it is a period. diff --git a/source/MaterialXTest/MaterialXGenGlsl/GenGlsl.cpp b/source/MaterialXTest/MaterialXGenGlsl/GenGlsl.cpp index 339d3853cb..e2857f1eb2 100644 --- a/source/MaterialXTest/MaterialXGenGlsl/GenGlsl.cpp +++ b/source/MaterialXTest/MaterialXGenGlsl/GenGlsl.cpp @@ -119,6 +119,17 @@ TEST_CASE("GenShader: Bind Light Shaders", "[genglsl]") REQUIRE_NOTHROW(mx::HwShaderGenerator::bindLightShader(*spotLightShader, 66, context)); } +#ifdef MATERIALX_BUILD_BENCHMARK_TESTS +TEST_CASE("GenShader: Performance Test", "[genglsl]") +{ + mx::GenContext context(mx::GlslShaderGenerator::create()); + BENCHMARK("Load documents, validate and generate shader") + { + return GenShaderUtil::shaderGenPerformanceTest(context); + }; +} +#endif + enum class GlslType { Glsl400, @@ -147,6 +158,7 @@ static void generateGlslCode(GlslType type = GlslType::Glsl400) 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/OpenPbr")); const mx::FilePath logPath("genglsl_" + GlslTypeToString(type) + "_generate_test.txt"); diff --git a/source/MaterialXTest/MaterialXGenMdl/GenMdl.cpp b/source/MaterialXTest/MaterialXGenMdl/GenMdl.cpp index 1a3e127cde..2cd48dd4c4 100644 --- a/source/MaterialXTest/MaterialXGenMdl/GenMdl.cpp +++ b/source/MaterialXTest/MaterialXGenMdl/GenMdl.cpp @@ -288,7 +288,10 @@ void MdlShaderGeneratorTester::compileSource(const std::vector& so std::string iblFile = (rootPath / "resources/lights/san_giuseppe_bridge.hdr").asString(); renderCommand += " --hdr \"" + iblFile + "\" --hdr_rotate 90"; // set scene - renderCommand += " --uv_scale 0.5 1.0 --uv_offset 0.0 0.0 --uv_repeat --uv_flip"; + renderCommand += " --uv_scale 0.5 1.0 --uv_offset 0.0 0.0 --uv_repeat"; + renderCommand += " --uv_flip"; // this will flip the v coordinate of the vertices, which flips all the + // UV operations. In contrast, the fileTextureVerticalFlip option will + // only flip the image access nodes. renderCommand += " --camera 0 0 3 0 0 0 --fov 45"; // set the material @@ -324,11 +327,11 @@ void MdlShaderGeneratorTester::compileSource(const std::vector& so mx::FilePath outputImageName = moduleToTestPath / (imageFilename + extension); renderCommand += " -o " + outputImageName.asString(); - mx::FilePath logFile = moduleToTestPath / (moduleToTest + ".mdl_render_errors.txt"); - renderCommand += " > " + logFile.asString() + " 2>&1"; - + mx::FilePath logFile = moduleToTestPath / (moduleToTest + ".mdl_render_log.txt"); + renderCommand += " --log_file " + logFile.asString(); + mx::FilePath errorLogFile = moduleToTestPath / (moduleToTest + ".mdl_render_errors.txt"); int returnValue = std::system(renderCommand.c_str()); - std::ifstream logStream(logFile); + std::ifstream logStream(errorLogFile); mx::StringVec result; std::string line; bool writeLogCode = false; @@ -354,6 +357,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/OpenPbr")); const mx::FilePath logPath("genmdl_mdl_generate_test.txt"); @@ -365,6 +369,25 @@ TEST_CASE("GenShader: MDL Shader Generation", "[genmdl]") mx::GenOptions genOptions; genOptions.targetColorSpaceOverride = "lin_rec709"; + + // Flipping the texture lookups for the test renderer only. + // This is because OSL testrender does not allow to change the UV layout of their sphere (yet) and the MaterialX test suite + // adopts the OSL behavior in order to produce comparable results. This means that raw texture coordinates, or procedurals + // that use the texture coordinates, do not match what might be expected when reading the MaterialX spec: + // "[...] the image is mapped onto the geometry based on geometry UV coordinates, with the lower-left corner of an image + // mapping to the (0,0) UV coordinate [...]" + // This means for MDL: here, and only here in the test suite, we flip the UV coordinates of mesh using the `--uv_flip` option + // of the renderer, and to correct the image orientation, we apply `fileTextureVerticalFlip`. + // In regular MDL integrations this is not needed because MDL and MaterialX define the texture space equally with the origin + // at the bottom left. + genOptions.fileTextureVerticalFlip = true; + mx::FilePath optionsFilePath = searchPath.find("resources/Materials/TestSuite/_options.mtlx"); + + // Specify the MDL target version to be the latest which is also the default. + mx::GenMdlOptionsPtr genMdlOptions = std::make_shared(); + genMdlOptions->targetVersion = mx::GenMdlOptions::MdlVersion::MDL_LATEST; + tester.addUserData(mx::GenMdlOptions::GEN_CONTEXT_USER_DATA_KEY, genMdlOptions); + tester.validate(genOptions, optionsFilePath); } diff --git a/source/MaterialXTest/MaterialXGenMsl/GenMsl.cpp b/source/MaterialXTest/MaterialXGenMsl/GenMsl.cpp index 03dbcbde69..62c108deca 100644 --- a/source/MaterialXTest/MaterialXGenMsl/GenMsl.cpp +++ b/source/MaterialXTest/MaterialXGenMsl/GenMsl.cpp @@ -124,6 +124,7 @@ static void generateMslCode() 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/OpenPbr")); const mx::FilePath logPath("genmsl_msl23_layout_generate_test.txt"); diff --git a/source/MaterialXTest/MaterialXGenOsl/GenOsl.cpp b/source/MaterialXTest/MaterialXGenOsl/GenOsl.cpp index 13a8b5ffdf..28156a41fe 100644 --- a/source/MaterialXTest/MaterialXGenOsl/GenOsl.cpp +++ b/source/MaterialXTest/MaterialXGenOsl/GenOsl.cpp @@ -183,6 +183,7 @@ static void generateOslCode() 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/OpenPbr")); const mx::FilePath logPath("genosl_vanilla_generate_test.txt"); diff --git a/source/MaterialXTest/MaterialXGenShader/GenShaderUtil.cpp b/source/MaterialXTest/MaterialXGenShader/GenShaderUtil.cpp index 863cd1af05..3ed23848e6 100644 --- a/source/MaterialXTest/MaterialXGenShader/GenShaderUtil.cpp +++ b/source/MaterialXTest/MaterialXGenShader/GenShaderUtil.cpp @@ -314,6 +314,85 @@ void testUniqueNames(mx::GenContext& context, const std::string& stage) REQUIRE(sgNode1->getOutput()->getVariable() == "unique_names_out"); } +// Test ShaderGen performance +void shaderGenPerformanceTest(mx::GenContext& context) +{ + mx::DocumentPtr nodeLibrary = mx::createDocument(); + mx::FilePath currentPath = mx::FilePath::getCurrentPath(); + const mx::FileSearchPath libSearchPath(currentPath); + + // Load the standard libraries. + loadLibraries({ "libraries" }, libSearchPath, nodeLibrary); + context.registerSourceCodeSearchPath(libSearchPath); + + // Enable Color Management + mx::ColorManagementSystemPtr colorManagementSystem = + mx::DefaultColorManagementSystem::create(context.getShaderGenerator().getTarget()); + + REQUIRE(colorManagementSystem); + if (colorManagementSystem) + { + context.getShaderGenerator().setColorManagementSystem(colorManagementSystem); + colorManagementSystem->loadLibrary(nodeLibrary); + } + + // Enable Unit System + mx::UnitSystemPtr unitSystem = mx::UnitSystem::create(context.getShaderGenerator().getTarget()); + REQUIRE(unitSystem); + if (unitSystem) + { + context.getShaderGenerator().setUnitSystem(unitSystem); + unitSystem->loadLibrary(nodeLibrary); + // Setup Unit converters + unitSystem->setUnitConverterRegistry(mx::UnitConverterRegistry::create()); + mx::UnitTypeDefPtr distanceTypeDef = nodeLibrary->getUnitTypeDef("distance"); + unitSystem->getUnitConverterRegistry()->addUnitConverter(distanceTypeDef, mx::LinearUnitConverter::create(distanceTypeDef)); + mx::UnitTypeDefPtr angleTypeDef = nodeLibrary->getUnitTypeDef("angle"); + unitSystem->getUnitConverterRegistry()->addUnitConverter(angleTypeDef, mx::LinearUnitConverter::create(angleTypeDef)); + context.getOptions().targetDistanceUnit = "meter"; + } + + // Read mtlx documents + mx::FilePathVec testRootPaths; + testRootPaths.push_back("resources/Materials/Examples/StandardSurface"); + testRootPaths.push_back("resources/Materials/Examples/OpenPbr"); + + std::vector loadedDocuments; + mx::StringVec documentsPaths; + mx::StringVec errorLog; + + for (const auto& testRoot : testRootPaths) + { + mx::loadDocuments(testRoot, libSearchPath, {}, {}, loadedDocuments, documentsPaths, + nullptr, &errorLog); + } + + REQUIRE(loadedDocuments.size() > 0); + REQUIRE(loadedDocuments.size() == documentsPaths.size()); + + // Shuffle the order of documents and perform document library import validatation and shadergen + std::mt19937 rng(0); + std::shuffle(loadedDocuments.begin(), loadedDocuments.end(), rng); + for (const auto& doc : loadedDocuments) + { + doc->importLibrary(nodeLibrary); + std::vector elements = mx::findRenderableElements(doc); + + REQUIRE(elements.size() > 0); + + std::string message; + bool docValid = doc->validate(&message); + + REQUIRE(docValid == true); + + mx::StringVec sourceCode; + mx::ShaderPtr shader = nullptr; + shader = context.getShaderGenerator().generate(elements[0]->getName(), elements[0], context); + + REQUIRE(shader != nullptr); + REQUIRE(shader->getSourceCode(mx::Stage::PIXEL).length() > 0); + } +} void ShaderGeneratorTester::checkImplementationUsage(const mx::StringSet& usedImpls, const mx::GenContext& context, @@ -480,27 +559,6 @@ void ShaderGeneratorTester::setupDependentLibraries() loadLibraries({ "libraries" }, _searchPath, _dependLib, _skipLibraryFiles); } -void ShaderGeneratorTester::addSkipFiles() -{ - _skipFiles.insert("_options.mtlx"); - _skipFiles.insert("light_rig_test_1.mtlx"); - _skipFiles.insert("light_rig_test_2.mtlx"); - _skipFiles.insert("light_compound_test.mtlx"); - _skipFiles.insert("xinclude_search_path.mtlx"); - _skipFiles.insert("1_38_parameter_to_input.mtlx"); - _skipFiles.insert("1_36_to_1_37.mtlx"); - _skipFiles.insert("1_37_to_1_38.mtlx"); - _skipFiles.insert("material_element_to_surface_material.mtlx"); -} - -void ShaderGeneratorTester::addSkipNodeDefs() -{ -} - -void ShaderGeneratorTester::addSkipLibraryFiles() -{ -} - LightIdMap ShaderGeneratorTester::computeLightIdMap(const std::vector& nodes) { std::unordered_map idMap; @@ -648,6 +706,7 @@ void ShaderGeneratorTester::validate(const mx::GenOptions& generateOptions, cons { // Apply optional preprocessing. preprocessDocument(doc); + _shaderGenerator->registerShaderMetadata(doc, context); // For each new file clear the implementation cache. // Since the new file might contain implementations with names @@ -907,8 +966,6 @@ bool TestSuiteOptions::readOptions(const std::string& optionFile) const std::string EXTRA_LIBRARY_PATHS("extraLibraryPaths"); const std::string RENDER_TEST_PATHS("renderTestPaths"); const std::string ENABLE_REFERENCE_QUALITY("enableReferenceQuality"); - const std::string WEDGE_SETTING("wedgerender"); - const std::string BAKER_SETTINGS("baker"); overrideFiles.clear(); dumpGeneratedCode = false; @@ -925,70 +982,6 @@ bool TestSuiteOptions::readOptions(const std::string& optionFile) mx::NodeDefPtr optionDefs = doc->getNodeDef(RENDER_TEST_OPTIONS_STRING); if (optionDefs) { - // Read Wedge Render Settings - for (mx::ElementPtr p : optionDefs->getChildrenOfType(WEDGE_SETTING)) - { - WedgeSetting setting; - for (auto child : p->getChildren()) - { - mx::InputPtr input = child->asA(); - const std::string& name = input->getName(); - mx::ValuePtr val = input->getValue(); - - if (name == "file") - { - setting.wedgeFile = val->asA(); - } - else if (name == "parameter") - { - setting.parameter = val->asA(); - } - else if (name == "range") - { - setting.range = val->asA(); - } - else if (name == "steps") - { - setting.steps = val->asA(); - } - } - wedgeSettings.push_back(setting); - } - - // Read Baker Settings - for (mx::ElementPtr p : optionDefs->getChildrenOfType(BAKER_SETTINGS)) - { - BakeSetting setting; - for (auto child : p->getChildren()) - { - mx::InputPtr input = child->asA(); - const std::string& name = input->getName(); - mx::ValuePtr val = input->getValue(); - - if (name == "file") - { - setting.bakeFile = val->asA(); - } - else if (name == "resolution") - { - setting.resolution = val->asA(); - } - else if (name == "hdr") - { - setting.hdr = val->asA(); - } - else if (name == "uvmin") - { - setting.uvmin = val->asA(); - } - else if (name == "uvmax") - { - setting.uvmax = val->asA(); - } - } - bakeSettings.push_back(setting); - } - for (auto p : optionDefs->getInputs()) { const std::string& name = p->getName(); diff --git a/source/MaterialXTest/MaterialXGenShader/GenShaderUtil.h b/source/MaterialXTest/MaterialXGenShader/GenShaderUtil.h index 7be195e9de..2bac14e435 100644 --- a/source/MaterialXTest/MaterialXGenShader/GenShaderUtil.h +++ b/source/MaterialXTest/MaterialXGenShader/GenShaderUtil.h @@ -52,6 +52,9 @@ void checkImplementations(mx::GenContext& context, // Utility test to check unique name generation on a shader generator void testUniqueNames(mx::GenContext& context, const std::string& stage); +// Utility to perfrom simple performance test to load, validate and generate shaders +void shaderGenPerformanceTest(mx::GenContext& context); + // // Render validation options. Reflects the _options.mtlx // file in the test suite area. @@ -128,16 +131,6 @@ class TestSuiteOptions // Enable reference quality rendering. Default is false. bool enableReferenceQuality; - // Wedge parameters - struct WedgeSetting - { - std::string wedgeFile; - std::string parameter; - mx::Vector2 range; - int steps; - }; - std::vector wedgeSettings; - // Bake parameters struct BakeSetting { @@ -180,13 +173,13 @@ class ShaderGeneratorTester virtual void setTestStages() = 0; // Add files in to not examine - virtual void addSkipFiles(); + virtual void addSkipFiles() { }; // Add nodedefs to not examine - virtual void addSkipNodeDefs(); + virtual void addSkipNodeDefs() { }; // Add files to be skipped while loading libraries - virtual void addSkipLibraryFiles(); + virtual void addSkipLibraryFiles() { }; // Add color management virtual void addColorManagement(); @@ -268,8 +261,6 @@ class ShaderGeneratorTester mx::StringSet _usedImplementations; }; - - } // namespace GenShaderUtil #endif diff --git a/source/MaterialXTest/MaterialXRender/RenderUtil.cpp b/source/MaterialXTest/MaterialXRender/RenderUtil.cpp index af392a9a05..cabcaca9a4 100644 --- a/source/MaterialXTest/MaterialXRender/RenderUtil.cpp +++ b/source/MaterialXTest/MaterialXRender/RenderUtil.cpp @@ -76,19 +76,6 @@ void ShaderRenderTester::loadDependentLibraries(GenShaderUtil::TestSuiteOptions loadAdditionalLibraries(dependLib, options); } -void ShaderRenderTester::addSkipFiles() -{ - _skipFiles.insert("_options.mtlx"); - _skipFiles.insert("light_rig_test_1.mtlx"); - _skipFiles.insert("light_rig_test_2.mtlx"); - _skipFiles.insert("light_compound_test.mtlx"); - _skipFiles.insert("xinclude_search_path.mtlx"); - _skipFiles.insert("1_38_parameter_to_input.mtlx"); - _skipFiles.insert("1_36_to_1_37.mtlx"); - _skipFiles.insert("1_37_to_1_38.mtlx"); - _skipFiles.insert("material_element_to_surface_material.mtlx"); -} - bool ShaderRenderTester::validate(const mx::FilePath optionsFilePath) { #ifdef LOG_TO_FILE @@ -144,9 +131,6 @@ bool ShaderRenderTester::validate(const mx::FilePath optionsFilePath) } ioTimer.endTimer(); - // Add files to skip - addSkipFiles(); - // Load in the library dependencies once // This will be imported in each test document below ioTimer.startTimer(); @@ -215,11 +199,6 @@ bool ShaderRenderTester::validate(const mx::FilePath optionsFilePath) for (const mx::FilePath& file : files) { - if (_skipFiles.count(file)) - { - continue; - } - ioTimer.startTimer(); // Check if a file override set is used and ignore all files // not part of the override set @@ -277,22 +256,6 @@ bool ShaderRenderTester::validate(const mx::FilePath optionsFilePath) mx::FilePath outputPath = mx::FilePath(dir) / file; outputPath.removeExtension(); - // Perform bake and use that file for rendering - if (canBake()) - { - for (auto& doctoBake : options.bakeSettings) - { - mx::FilePath outputBakeFile = file; - if (doctoBake.bakeFile == outputBakeFile.asString()) - { - outputBakeFile.removeExtension(); - outputBakeFile = outputPath / (outputBakeFile.asString() + "_baked.mtlx"); - runBake(doc, imageSearchPath, outputBakeFile, doctoBake, log); - break; - } - } - } - renderableSearchTimer.startTimer(); std::vector elements; try @@ -308,116 +271,8 @@ bool ShaderRenderTester::validate(const mx::FilePath optionsFilePath) for (const auto& element : elements) { - const mx::string elementName = mx::createValidName(mx::replaceSubstrings(element->getNamePath(), pathMap)); - - auto it = std::find_if(options.wedgeSettings.begin(), options.wedgeSettings.end(), - [&file] (const GenShaderUtil::TestSuiteOptions::WedgeSetting& setting) { - return (file.asString() == setting.wedgeFile); - }); - - const bool performWedge = (it != options.wedgeSettings.end()) ? true : false; - if (!performWedge) - { - runRenderer(elementName, element, context, doc, log, options, profileTimes, imageSearchPath, outputPath, nullptr); - } - else - { - for (auto &wedgesetting: options.wedgeSettings) - { - mx::ImageVec imageVec; - - const std::string& wedgeFile = wedgesetting.wedgeFile; - if (wedgeFile != file.asString()) - { - continue; - } - - // Make this a utility - std::string parameterPath = wedgesetting.parameter; - mx::ElementPtr uniformElement = doc->getDescendant(parameterPath); - if (!uniformElement) - { - std::string nodePath = mx::parentNamePath(parameterPath); - mx::ElementPtr uniformParent = doc->getDescendant(nodePath); - if (uniformParent) - { - mx::NodePtr uniformNode = uniformParent->asA(); - if (uniformNode) - { - mx::StringVec pathVec = mx::splitNamePath(parameterPath); - uniformNode->addInputFromNodeDef(pathVec[pathVec.size() - 1]); - } - } - } - uniformElement = doc->getDescendant(parameterPath); - mx::ValueElementPtr valueElement = uniformElement ? uniformElement->asA() : nullptr; - if (!valueElement) - { - continue; - } - - mx::ValuePtr origPropertyValue(valueElement ? valueElement->getValue() : nullptr); - mx::ValuePtr newValue = valueElement->getValue(); - - float wedgePropertyMin = wedgesetting.range[0]; - float wedgePropertyMax = wedgesetting.range[1]; - int wedgeImageCount = std::max(wedgesetting.steps, 2); - - float wedgePropertyStep = (wedgePropertyMax - wedgePropertyMin) / (wedgeImageCount - 1); - for (int w = 0; w < wedgeImageCount; w++) - { - bool setValue = false; - float propertyValue = (w == wedgeImageCount - 1) ? wedgePropertyMax : wedgePropertyMin + wedgePropertyStep * w; - if (origPropertyValue->isA()) - { - valueElement->setValue(static_cast(propertyValue)); - setValue = true; - } - else if (origPropertyValue->isA()) - { - valueElement->setValue(propertyValue); - setValue = true; - } - else if (origPropertyValue->isA()) - { - mx::Vector2 val(propertyValue, propertyValue); - valueElement->setValue(val); - setValue = true; - } - else if (origPropertyValue->isA() || - origPropertyValue->isA()) - { - mx::Vector3 val(propertyValue, propertyValue, propertyValue); - valueElement->setValue(val); - setValue = true; - } - else if (origPropertyValue->isA() || - origPropertyValue->isA()) - { - mx::Vector4 val(propertyValue, propertyValue, propertyValue, origPropertyValue->isA() ? 1.0f : propertyValue); - valueElement->setValue(val); - setValue = true; - } - - if (setValue) - { - runRenderer(elementName, element, context, doc, log, options, profileTimes, imageSearchPath, outputPath, &imageVec); - } - } - - if (!imageVec.empty()) - { - mx::ImagePtr wedgeImage = mx::createImageStrip(imageVec); - if (wedgeImage) - { - std::string wedgeFileName = mx::createValidName(mx::replaceSubstrings(parameterPath, pathMap)); - wedgeFileName += "_" + _shaderGenerator->getTarget() + ".bmp"; - mx::FilePath wedgePath = outputPath / wedgeFileName; - saveImage(wedgePath, wedgeImage, true); - } - } - } - } + mx::string elementName = mx::createValidName(mx::replaceSubstrings(element->getNamePath(), pathMap)); + runRenderer(elementName, element, context, doc, log, options, profileTimes, imageSearchPath, outputPath, nullptr); } } } diff --git a/source/MaterialXTest/MaterialXRender/RenderUtil.h b/source/MaterialXTest/MaterialXRender/RenderUtil.h index 9f892569de..15eb5778f6 100644 --- a/source/MaterialXTest/MaterialXRender/RenderUtil.h +++ b/source/MaterialXTest/MaterialXRender/RenderUtil.h @@ -114,9 +114,6 @@ class ShaderRenderTester } #endif - // Add files to skip - void addSkipFiles(); - // Load dependencies void loadDependentLibraries(GenShaderUtil::TestSuiteOptions options, mx::FileSearchPath searchPath, mx::DocumentPtr& dependLib); @@ -168,10 +165,6 @@ class ShaderRenderTester std::ostream& stream, mx::DocumentPtr dependLib); - virtual bool canBake() const { return false; } - virtual void runBake(mx::DocumentPtr /*doc*/, const mx::FileSearchPath& /*codeSearchPath*/, const mx::FilePath& /*outputFilename*/, - const GenShaderUtil::TestSuiteOptions::BakeSetting& /*bakeOptions*/, std::ostream& /*log*/) {}; - // If these streams don't exist add them for testing purposes void addAdditionalTestStreams(mx::MeshPtr mesh); @@ -181,9 +174,6 @@ class ShaderRenderTester bool _resolveImageFilenames; mx::StringResolverPtr _customFilenameResolver; - // Files to skip - mx::StringSet _skipFiles; - // Color management information mx::ColorManagementSystemPtr _colorManagementSystem; mx::FilePath _colorManagementConfigFile; diff --git a/source/MaterialXTest/MaterialXRenderGlsl/RenderGlsl.cpp b/source/MaterialXTest/MaterialXRenderGlsl/RenderGlsl.cpp index 719914a62e..01e0875727 100644 --- a/source/MaterialXTest/MaterialXRenderGlsl/RenderGlsl.cpp +++ b/source/MaterialXTest/MaterialXRenderGlsl/RenderGlsl.cpp @@ -9,7 +9,6 @@ #include #include #include -#include #include #include @@ -54,14 +53,6 @@ class GlslShaderRenderTester : public RenderUtil::ShaderRenderTester bool saveImage(const mx::FilePath& filePath, mx::ConstImagePtr image, bool verticalFlip) const override; - bool canBake() const override - { - return true; - } - - void runBake(mx::DocumentPtr doc, const mx::FileSearchPath& imageSearchPath, const mx::FilePath& outputFilename, - const GenShaderUtil::TestSuiteOptions::BakeSetting& bakeOptions, std::ostream& log) override; - mx::GlslRendererPtr _renderer; mx::LightHandlerPtr _lightHandler; }; @@ -421,35 +412,6 @@ bool GlslShaderRenderTester::runRenderer(const std::string& shaderName, return true; } -void GlslShaderRenderTester::runBake(mx::DocumentPtr doc, const mx::FileSearchPath& imageSearchPath, const mx::FilePath& outputFileName, - const GenShaderUtil::TestSuiteOptions::BakeSetting& bakeOptions, std::ostream& log) -{ - mx::ImageVec imageVec = _renderer->getImageHandler()->getReferencedImages(doc); - auto maxImageSize = mx::getMaxDimensions(imageVec); - const unsigned bakeWidth = std::max(bakeOptions.resolution, maxImageSize.first); - const unsigned bakeHeight = std::max(bakeOptions.resolution, maxImageSize.second); - - mx::Image::BaseType baseType = bakeOptions.hdr ? mx::Image::BaseType::FLOAT : mx::Image::BaseType::UINT8; - mx::TextureBakerPtr baker = mx::TextureBakerGlsl::create(bakeWidth, bakeHeight, baseType); - baker->setupUnitSystem(doc); - baker->setImageHandler(_renderer->getImageHandler()); - baker->setOptimizeConstants(true); - baker->setHashImageNames(true); - baker->setTextureSpaceMin(bakeOptions.uvmin); - baker->setTextureSpaceMax(bakeOptions.uvmax); - - try - { - baker->setOutputStream(&log); - baker->bakeAllMaterials(doc, imageSearchPath, outputFileName); - } - catch (mx::Exception& e) - { - const mx::FilePath& sourceUri = doc->getSourceUri(); - log << sourceUri.asString() + " failed baking process: " + e.what() << std::endl; - } -} - TEST_CASE("Render: GLSL TestSuite", "[renderglsl]") { mx::FileSearchPath searchPath = mx::getDefaultDataSearchPath(); diff --git a/source/MaterialXTest/MaterialXRenderMsl/RenderMsl.mm b/source/MaterialXTest/MaterialXRenderMsl/RenderMsl.mm index 248d458542..be5b8aa616 100644 --- a/source/MaterialXTest/MaterialXRenderMsl/RenderMsl.mm +++ b/source/MaterialXTest/MaterialXRenderMsl/RenderMsl.mm @@ -17,7 +17,6 @@ #endif #include -#include #include @@ -58,14 +57,6 @@ bool runRenderer(const std::string& shaderName, bool saveImage(const mx::FilePath& filePath, mx::ConstImagePtr image, bool verticalFlip) const override; - bool canBake() const override - { - return true; - } - - void runBake(mx::DocumentPtr doc, const mx::FileSearchPath& imageSearchPath, const mx::FilePath& outputFilename, - const GenShaderUtil::TestSuiteOptions::BakeSetting& bakeOptions, std::ostream& log) override; - mx::MslRendererPtr _renderer; mx::LightHandlerPtr _lightHandler; id _device; @@ -427,35 +418,6 @@ void runBake(mx::DocumentPtr doc, const mx::FileSearchPath& imageSearchPath, con return true; } -void MslShaderRenderTester::runBake(mx::DocumentPtr doc, const mx::FileSearchPath& imageSearchPath, const mx::FilePath& outputFileName, - const GenShaderUtil::TestSuiteOptions::BakeSetting& bakeOptions, std::ostream& log) -{ - mx::ImageVec imageVec = _renderer->getImageHandler()->getReferencedImages(doc); - auto maxImageSize = mx::getMaxDimensions(imageVec); - const unsigned bakeWidth = std::max(bakeOptions.resolution, maxImageSize.first); - const unsigned bakeHeight = std::max(bakeOptions.resolution, maxImageSize.second); - - mx::Image::BaseType baseType = bakeOptions.hdr ? mx::Image::BaseType::FLOAT : mx::Image::BaseType::UINT8; - mx::TextureBakerPtr baker = mx::TextureBakerMsl::create(bakeWidth, bakeHeight, baseType); - baker->setupUnitSystem(doc); - baker->setImageHandler(_renderer->getImageHandler()); - baker->setOptimizeConstants(true); - baker->setHashImageNames(true); - baker->setTextureSpaceMin(bakeOptions.uvmin); - baker->setTextureSpaceMax(bakeOptions.uvmax); - - try - { - baker->setOutputStream(&log); - baker->bakeAllMaterials(doc, imageSearchPath, outputFileName); - } - catch (mx::Exception& e) - { - const mx::FilePath& sourceUri = doc->getSourceUri(); - log << sourceUri.asString() + " failed baking process: " + e.what() << std::endl; - } -} - TEST_CASE("Render: MSL TestSuite", "[rendermsl]") { mx::FileSearchPath searchPath = mx::getDefaultDataSearchPath(); diff --git a/source/MaterialXView/CMakeLists.txt b/source/MaterialXView/CMakeLists.txt index 1d9a329e46..e3e81a4b09 100644 --- a/source/MaterialXView/CMakeLists.txt +++ b/source/MaterialXView/CMakeLists.txt @@ -70,7 +70,7 @@ else() elseif(CMAKE_CXX_COMPILER_ID MATCHES "Clang") add_compile_options(-Wno-deprecated) elseif(CMAKE_CXX_COMPILER_ID MATCHES "GNU") - add_compile_options(-Wno-format-truncation -Wno-use-after-free) + add_compile_options(-Wno-format-truncation -Wno-stringop-overflow -Wno-use-after-free) endif() # Disable NanoGUI compiler modifications for Clang diff --git a/source/MaterialXView/Editor.cpp b/source/MaterialXView/Editor.cpp index ff91f0f129..090937d6e5 100644 --- a/source/MaterialXView/Editor.cpp +++ b/source/MaterialXView/Editor.cpp @@ -18,14 +18,13 @@ namespace class EditorColorPicker : public ng::ColorPicker { public: - EditorColorPicker(ng::Widget *parent, const ng::Color& color) : + EditorColorPicker(ng::Widget* parent, const ng::Color& color) : ng::ColorPicker(parent, color) { - ng::Popup *popup = this->popup(); - ng::Widget *floatGroup = new ng::Widget(popup); - auto layout = - new ng::GridLayout(ng::Orientation::Horizontal, 2, - ng::Alignment::Middle, 2, 2); + ng::Popup* popup = this->popup(); + ng::Widget* 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 }); layout->set_spacing(1, 1); floatGroup->set_layout(layout); @@ -51,7 +50,8 @@ class EditorColorPicker : public ng::ColorPicker // The color wheel does not handle alpha properly, so only // overwrite RGB in the callback. - m_callback = [this](const ng::Color &value) { + m_callback = [this](const ng::Color& value) + { _colorWidgets[0]->set_value(value[0]); _colorWidgets[1]->set_value(value[1]); _colorWidgets[2]->set_value(value[2]); @@ -110,7 +110,7 @@ void PropertyEditor::create(Viewer& parent) _window->set_position(previousPosition); _window->set_visible(_visible); - ng::VScrollPanel *scroll_panel = new ng::VScrollPanel(_window); + ng::VScrollPanel* 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)); @@ -122,7 +122,7 @@ void PropertyEditor::create(Viewer& parent) // 3 cell layout for label plus widget value pair. _gridLayout3 = new ng::GridLayout(ng::Orientation::Horizontal, 3, - ng::Alignment::Minimum, 2, 2); + ng::Alignment::Minimum, 2, 2); _gridLayout3->set_col_alignment({ ng::Alignment::Minimum, ng::Alignment::Maximum, ng::Alignment::Maximum }); } @@ -150,7 +150,7 @@ void PropertyEditor::addItemToForm(const mx::UIPropertyItem& item, const std::st { ng::Widget* twoColumns = new ng::Widget(container); twoColumns->set_layout(_gridLayout2); - ng::Label* groupLabel = new ng::Label(twoColumns, group); + ng::Label* groupLabel = new ng::Label(twoColumns, group); groupLabel->set_font_size(20); groupLabel->set_font("sans-bold"); new ng::Label(twoColumns, ""); @@ -163,7 +163,7 @@ void PropertyEditor::addItemToForm(const mx::UIPropertyItem& item, const std::st auto indexInEnumeration = [&value, &enumValues, &enumeration]() { size_t index = 0; - for (auto& enumValue: enumValues) + for (auto& enumValue : enumValues) { if (value->getValueString() == enumValue->getValueString()) { @@ -172,7 +172,7 @@ void PropertyEditor::addItemToForm(const mx::UIPropertyItem& item, const std::st index++; } index = 0; - for (auto& enumName: enumeration) + for (auto& enumName : enumeration) { if (value->getValueString() == enumName) { @@ -191,7 +191,7 @@ void PropertyEditor::addItemToForm(const mx::UIPropertyItem& item, const std::st twoColumns->set_layout(_gridLayout2); new ng::Label(twoColumns, label); - ng::ComboBox* comboBox = new ng::ComboBox(twoColumns, {""}); + ng::ComboBox* comboBox = new ng::ComboBox(twoColumns, { "" }); comboBox->set_enabled(editable); comboBox->set_items(enumeration); comboBox->set_selected_index(static_cast(valueIndex)); @@ -259,7 +259,7 @@ void PropertyEditor::addItemToForm(const mx::UIPropertyItem& item, const std::st mx::MaterialPtr material = viewer->getSelectedMaterial(); if (material) { - material->modifyUniform(path, mx::Value::createValue(value)); + material->modifyUniform(path, mx::Value::createValue(value)); } }); floatBox->set_fixed_size(ng::Vector2i(100, 20)); @@ -333,12 +333,12 @@ void PropertyEditor::addItemToForm(const mx::UIPropertyItem& item, const std::st { mx::Color3 v = value->asA(); ng::Color c(v[0], v[1], v[2], 1.0); - + new ng::Label(twoColumns, label); auto colorVar = new EditorColorPicker(twoColumns, c); colorVar->set_fixed_size({ 100, 20 }); colorVar->set_font_size(15); - colorVar->set_final_callback([path, viewer](const ng::Color &c) + colorVar->set_final_callback([path, viewer](const ng::Color& c) { mx::MaterialPtr material = viewer->getSelectedMaterial(); if (material) @@ -362,7 +362,7 @@ void PropertyEditor::addItemToForm(const mx::UIPropertyItem& item, const std::st auto colorVar = new EditorColorPicker(twoColumns, c); colorVar->set_fixed_size({ 100, 20 }); colorVar->set_font_size(15); - colorVar->set_final_callback([path, viewer](const ng::Color &c) + colorVar->set_final_callback([path, viewer](const ng::Color& c) { mx::MaterialPtr material = viewer->getSelectedMaterial(); if (material) @@ -583,10 +583,10 @@ 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::TextBox* 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) + stringVar->set_callback([path, viewer](const std::string& v) { mx::MaterialPtr material = viewer->getSelectedMaterial(); mx::ShaderPort* uniform = material ? material->findUniform(path) : nullptr; @@ -646,7 +646,7 @@ void PropertyEditor::updateContents(Viewer* viewer) mx::UIPropertyGroup groups; mx::UIPropertyGroup unnamedGroups; const std::string pathSeparator(":"); - mx::createUIPropertyGroups(elem->getDocument(), *publicUniforms, groups, unnamedGroups, pathSeparator); + mx::createUIPropertyGroups(elem->getDocument(), *publicUniforms, groups, unnamedGroups, pathSeparator); // First add items with named groups. std::string previousFolder; @@ -691,7 +691,7 @@ ng::FloatBox* createFloatWidget(ng::Widget* parent, const std::string& la { new ng::Label(parent, label); - ng::Slider *slider = new ng::Slider(parent); + ng::Slider* slider = new ng::Slider(parent); slider->set_value(value); ng::FloatBox* box = new ng::FloatBox(parent, value); @@ -732,7 +732,7 @@ ng::FloatBox* createFloatWidget(ng::Widget* parent, const std::string& la } } - slider->set_callback([box, callback](float value) + slider->set_callback([box, callback](float value) { box->set_value(value); callback(value); @@ -747,12 +747,12 @@ ng::FloatBox* createFloatWidget(ng::Widget* parent, const std::string& la } ng::IntBox* createIntWidget(ng::Widget* parent, const std::string& label, int value, - const mx::UIProperties* ui, std::function callback) + const mx::UIProperties* ui, std::function callback) { new ng::Label(parent, label); - ng::Slider *slider = new ng::Slider(parent); - slider->set_value((float)value); + ng::Slider* slider = new ng::Slider(parent); + slider->set_value((float) value); ng::IntBox* box = new ng::IntBox(parent, value); box->set_fixed_width(60); @@ -781,7 +781,7 @@ ng::IntBox* createIntWidget(ng::Widget* parent, const std::string& label, i } if (range.first != range.second) { - std::pair float_range((float)range.first, (float)range.second); + std::pair float_range((float) range.first, (float) range.second); slider->set_range(float_range); } if (ui->uiStep) @@ -794,12 +794,12 @@ ng::IntBox* createIntWidget(ng::Widget* parent, const std::string& label, i slider->set_callback([box, callback](float value) { - box->set_value((int)value); - callback((int)value); + box->set_value((int) value); + callback((int) value); }); box->set_callback([slider, callback](int value) { - slider->set_value((float)value); + slider->set_value((float) value); callback(value); }); diff --git a/source/MaterialXView/Editor.h b/source/MaterialXView/Editor.h index 8e74ca987d..b1fb4a3ade 100644 --- a/source/MaterialXView/Editor.h +++ b/source/MaterialXView/Editor.h @@ -19,7 +19,7 @@ namespace ng = nanogui; class Viewer; -class PropertyEditor +class PropertyEditor { public: PropertyEditor(); @@ -58,7 +58,7 @@ class PropertyEditor }; ng::FloatBox* createFloatWidget(ng::Widget* parent, const std::string& label, float value, - const mx::UIProperties*ui, std::function callback = nullptr); + 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); diff --git a/source/MaterialXView/Main.cpp b/source/MaterialXView/Main.cpp index 99104f7fa2..b2a9403f0f 100644 --- a/source/MaterialXView/Main.cpp +++ b/source/MaterialXView/Main.cpp @@ -13,40 +13,41 @@ NANOGUI_FORCE_DISCRETE_GPU(); -const std::string options = -" Options: \n" -" --material [FILENAME] Specify the filename of the MTLX document to be displayed in the viewer\n" -" --mesh [FILENAME] Specify the filename of the OBJ mesh to be displayed in the viewer\n" -" --meshRotation [VECTOR3] Specify the rotation of the displayed mesh as three comma-separated floats, representing rotations in degrees about the X, Y, and Z axes (defaults to 0,0,0)\n" -" --meshScale [FLOAT] Specify the uniform scale of the displayed mesh\n" -" --enableTurntable[BOOLEAN] Specify whether to enable turntable rendering of the scene\n" -" --turntableSteps [INTEGER] Specify the number of steps for a complete turntable rotation. Defaults to 360\n" -" --cameraPosition [VECTOR3] Specify the position of the camera as three comma-separated floats (defaults to 0,0,5)\n" -" --cameraTarget [VECTOR3] Specify the position of the camera target as three comma-separated floats (defaults to 0,0,0)\n" -" --cameraViewAngle [FLOAT] Specify the view angle of the camera, or zero for an orthographic projection (defaults to 45)\n" -" --cameraZoom [FLOAT] Specify the zoom factor for the camera, implemented as a mesh scale multiplier (defaults to 1)\n" -" --envRad [FILENAME] Specify the filename of the environment light to display, stored as HDR environment radiance in the latitude-longitude format\n" -" --envMethod [INTEGER] Specify the environment lighting method (0 = filtered importance sampling, 1 = prefiltered environment maps, defaults to 0)\n" -" --envSampleCount [INTEGER] Specify the environment sample count (defaults to 16)\n" -" --lightRotation [FLOAT] Specify the rotation in degrees of the lighting environment about the Y axis (defaults to 0)\n" -" --shadowMap [BOOLEAN] Specify whether shadow mapping is enabled (defaults to true)\n" -" --path [FILEPATH] Specify an additional data search path location (e.g. '/projects/MaterialX'). This absolute path will be queried when locating data libraries, XInclude references, and referenced images.\n" -" --library [FILEPATH] Specify an additional data library folder (e.g. 'vendorlib', 'studiolib'). This relative path will be appended to each location in the data search path when loading data libraries.\n" -" --screenWidth [INTEGER] Specify the width of the screen image in pixels (defaults to 1280)\n" -" --screenHeight [INTEGER] Specify the height of the screen image in pixels (defaults to 960)\n" -" --screenColor [VECTOR3] Specify the background color of the viewer as three comma-separated floats (defaults to 0.3,0.3,0.32)\n" -" --drawEnvironment [BOOLEAN] Specify whether to render the environment as the background (defaults to false)\n" -" --captureFilename [FILENAME] Specify the filename to which the first rendered frame should be written\n" -" --bakeWidth [INTEGER] Specify the target width for texture baking (defaults to maximum image width of the source document)\n" -" --bakeHeight [INTEGER] Specify the target height for texture baking (defaults to maximum image height of the source document)\n" -" --bakeFilename [STRING] Specify the output document filename for texture baking\n" -" --refresh [FLOAT] Specify the refresh period for the viewer in milliseconds (defaults to 50, set to -1 to disable)\n" -" --remap [TOKEN1:TOKEN2] Specify the remapping from one token to another when MaterialX document is loaded\n" -" --skip [NAME] Specify to skip elements matching the given name attribute\n" -" --terminator [STRING] Specify to enforce the given terminator string for file prefixes\n" -" --help Display the complete list of command-line options\n"; +const std::string options = + " Options: \n" + " --material [FILENAME] Specify the filename of the MTLX document to be displayed in the viewer\n" + " --mesh [FILENAME] Specify the filename of the OBJ mesh to be displayed in the viewer\n" + " --meshRotation [VECTOR3] Specify the rotation of the displayed mesh as three comma-separated floats, representing rotations in degrees about the X, Y, and Z axes (defaults to 0,0,0)\n" + " --meshScale [FLOAT] Specify the uniform scale of the displayed mesh\n" + " --enableTurntable[BOOLEAN] Specify whether to enable turntable rendering of the scene\n" + " --turntableSteps [INTEGER] Specify the number of steps for a complete turntable rotation. Defaults to 360\n" + " --cameraPosition [VECTOR3] Specify the position of the camera as three comma-separated floats (defaults to 0,0,5)\n" + " --cameraTarget [VECTOR3] Specify the position of the camera target as three comma-separated floats (defaults to 0,0,0)\n" + " --cameraViewAngle [FLOAT] Specify the view angle of the camera, or zero for an orthographic projection (defaults to 45)\n" + " --cameraZoom [FLOAT] Specify the zoom factor for the camera, implemented as a mesh scale multiplier (defaults to 1)\n" + " --envRad [FILENAME] Specify the filename of the environment light to display, stored as HDR environment radiance in the latitude-longitude format\n" + " --envMethod [INTEGER] Specify the environment lighting method (0 = filtered importance sampling, 1 = prefiltered environment maps, defaults to 0)\n" + " --envSampleCount [INTEGER] Specify the environment sample count (defaults to 16)\n" + " --envLightIntensity [FLOAT] Specify the environment light intensity (defaults to 1)\n" + " --lightRotation [FLOAT] Specify the rotation in degrees of the lighting environment about the Y axis (defaults to 0)\n" + " --shadowMap [BOOLEAN] Specify whether shadow mapping is enabled (defaults to true)\n" + " --path [FILEPATH] Specify an additional data search path location (e.g. '/projects/MaterialX'). This absolute path will be queried when locating data libraries, XInclude references, and referenced images.\n" + " --library [FILEPATH] Specify an additional data library folder (e.g. 'vendorlib', 'studiolib'). This relative path will be appended to each location in the data search path when loading data libraries.\n" + " --screenWidth [INTEGER] Specify the width of the screen image in pixels (defaults to 1280)\n" + " --screenHeight [INTEGER] Specify the height of the screen image in pixels (defaults to 960)\n" + " --screenColor [VECTOR3] Specify the background color of the viewer as three comma-separated floats (defaults to 0.3,0.3,0.32)\n" + " --drawEnvironment [BOOLEAN] Specify whether to render the environment as the background (defaults to false)\n" + " --captureFilename [FILENAME] Specify the filename to which the first rendered frame should be written\n" + " --bakeWidth [INTEGER] Specify the target width for texture baking (defaults to maximum image width of the source document)\n" + " --bakeHeight [INTEGER] Specify the target height for texture baking (defaults to maximum image height of the source document)\n" + " --bakeFilename [STRING] Specify the output document filename for texture baking\n" + " --refresh [FLOAT] Specify the refresh period for the viewer in milliseconds (defaults to 50, set to -1 to disable)\n" + " --remap [TOKEN1:TOKEN2] Specify the remapping from one token to another when MaterialX document is loaded\n" + " --skip [NAME] Specify to skip elements matching the given name attribute\n" + " --terminator [STRING] Specify to enforce the given terminator string for file prefixes\n" + " --help Display the complete list of command-line options\n"; -template void parseToken(std::string token, std::string type, T& res) +template void parseToken(std::string token, std::string type, T& res) { if (token.empty()) { @@ -64,14 +65,14 @@ template void parseToken(std::string token, std::string type, T& res) } int main(int argc, char* const argv[]) -{ +{ std::vector tokens; for (int i = 1; i < argc; i++) { tokens.emplace_back(argv[i]); } - std::string materialFilename = "resources/Materials/Examples/StandardSurface/standard_surface_default.mtlx"; + std::string materialFilename = "resources/Materials/Examples/OpenPbr/open_pbr_default.mtlx"; std::string meshFilename = "resources/Geometry/shaderball.glb"; std::string envRadianceFilename = "resources/Lights/san_giuseppe_bridge_split.hdr"; mx::FileSearchPath searchPath = mx::getDefaultDataSearchPath(); @@ -87,6 +88,7 @@ int main(int argc, char* const argv[]) float cameraZoom(DEFAULT_CAMERA_ZOOM); mx::HwSpecularEnvironmentMethod specularEnvironmentMethod = mx::SPECULAR_ENVIRONMENT_FIS; int envSampleCount = mx::DEFAULT_ENV_SAMPLE_COUNT; + float envLightIntensity = 1.0f; float lightRotation = 0.0f; bool shadowMap = true; DocumentModifiers modifiers; @@ -131,7 +133,7 @@ int main(int argc, char* const argv[]) else if (token == "--turntableSteps") { parseToken(nextToken, "integer", turntableSteps); - turntableSteps = std::clamp(turntableSteps, 2, 360);; + turntableSteps = std::clamp(turntableSteps, 2, 360); } else if (token == "--cameraPosition") { @@ -159,7 +161,11 @@ int main(int argc, char* const argv[]) else if (token == "--envSampleCount") { parseToken(nextToken, "integer", envSampleCount); - } + } + else if (token == "--envLightIntensity") + { + parseToken(nextToken, "float", envLightIntensity); + } else if (token == "--lightRotation") { parseToken(nextToken, "float", lightRotation); @@ -278,6 +284,7 @@ int main(int argc, char* const argv[]) viewer->setCameraZoom(cameraZoom); viewer->setSpecularEnvironmentMethod(specularEnvironmentMethod); viewer->setEnvSampleCount(envSampleCount); + viewer->setEnvLightIntensity(envLightIntensity); viewer->setLightRotation(lightRotation); viewer->setShadowMapEnable(shadowMap); viewer->setDrawEnvironment(drawEnvironment); diff --git a/source/MaterialXView/RenderPipeline.h b/source/MaterialXView/RenderPipeline.h index 82f5990513..3b7e7a48b7 100644 --- a/source/MaterialXView/RenderPipeline.h +++ b/source/MaterialXView/RenderPipeline.h @@ -44,16 +44,17 @@ class RenderPipeline virtual ~RenderPipeline() { } virtual void initialize(void* device, void* command_queue) = 0; - + virtual mx::ImageHandlerPtr createImageHandler() = 0; - virtual mx::MaterialPtr createMaterial() = 0; + virtual mx::MaterialPtr createMaterial() = 0; virtual void bakeTextures() = 0; - + virtual void updateAlbedoTable(int tableSize) = 0; + virtual void updatePrefilteredMap() = 0; virtual std::shared_ptr createTextureBaker(unsigned int width, unsigned int height, mx::Image::BaseType baseType) = 0; - + virtual void renderFrame(void* color_texture, int shadowMapSize, const char* dirLightNodeCat) = 0; virtual void initFramebuffer(int width, int height, @@ -62,9 +63,9 @@ class RenderPipeline void* color_texture) = 0; virtual mx::ImagePtr getShadowMap(int shadowMapSize) = 0; - + virtual mx::ImagePtr getFrameImage() = 0; - + public: Viewer* _viewer; }; diff --git a/source/MaterialXView/RenderPipelineGL.cpp b/source/MaterialXView/RenderPipelineGL.cpp index f08704d0a3..a41a4c1c4e 100644 --- a/source/MaterialXView/RenderPipelineGL.cpp +++ b/source/MaterialXView/RenderPipelineGL.cpp @@ -110,6 +110,100 @@ void GLRenderPipeline::updateAlbedoTable(int tableSize) glDrawBuffer(GL_BACK); } +void GLRenderPipeline::updatePrefilteredMap() +{ + auto& genContext = _viewer->_genContext; + auto& lightHandler = _viewer->_lightHandler; + auto& imageHandler = _viewer->_imageHandler; + + if (lightHandler->getEnvPrefilteredMap()) + { + return; + } + + // Create the prefilter shader. + mx::GlslMaterialPtr material = nullptr; + try + { + mx::ShaderPtr hwShader = mx::createEnvPrefilterShader(genContext, _viewer->_stdLib, "__ENV_PREFILTER__"); + material = mx::GlslMaterial::create(); + material->generateShader(hwShader); + } + catch (std::exception& e) + { + new ng::MessageDialog(_viewer, ng::MessageDialog::Type::Warning, "Failed to generate prefilter shader", e.what()); + } + + mx::ImagePtr srcTex = lightHandler->getEnvRadianceMap(); + + int w = srcTex->getWidth(); + int h = srcTex->getHeight(); + int numMips = srcTex->getMaxMipCount(); + + // Create texture to hold the prefiltered environment. + mx::GLTextureHandlerPtr glImageHandler = std::dynamic_pointer_cast(imageHandler); + mx::ImagePtr outTex = mx::Image::create(w, h, 3, mx::Image::BaseType::HALF); + glImageHandler->createRenderResources(outTex, true, true); + + mx::GlslProgramPtr program = material->getProgram(); + + try + { + int i = 0; + while (w > 0 && h > 0) + { + // Create framebuffer + unsigned int framebuffer; + glGenFramebuffers(1, &framebuffer); + glBindFramebuffer(GL_FRAMEBUFFER, framebuffer); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, outTex->getResourceId(), i); + glViewport(0, 0, w, h); + material->bindShader(); + + // Bind the source texture + mx::ImageSamplingProperties samplingProperties; + samplingProperties.uaddressMode = mx::ImageSamplingProperties::AddressMode::PERIODIC; + samplingProperties.vaddressMode = mx::ImageSamplingProperties::AddressMode::CLAMP; + samplingProperties.filterType = mx::ImageSamplingProperties::FilterType::LINEAR; + imageHandler->bindImage(srcTex, samplingProperties); + int textureLocation = glImageHandler->getBoundTextureLocation(srcTex->getResourceId()); + assert(textureLocation >= 0); + material->getProgram()->bindUniform(mx::HW::ENV_RADIANCE, mx::Value::createValue(textureLocation)); + // Bind other uniforms + program->bindUniform(mx::HW::ENV_PREFILTER_MIP, mx::Value::createValue(i)); + const mx::Matrix44 yRotationPI = mx::Matrix44::createScale(mx::Vector3(-1, 1, -1)); + program->bindUniform(mx::HW::ENV_MATRIX, mx::Value::createValue(yRotationPI)); + program->bindUniform(mx::HW::ENV_RADIANCE_MIPS, mx::Value::createValue(numMips)); + + _viewer->renderScreenSpaceQuad(material); + + glDeleteFramebuffers(1, &framebuffer); + + w /= 2; + h /= 2; + i++; + } + } + catch (mx::ExceptionRenderError& e) + { + for (const std::string& error : e.errorLog()) + { + std::cerr << error << std::endl; + } + new ng::MessageDialog(_viewer, ng::MessageDialog::Type::Warning, "Failed to render prefiltered environment", e.what()); + } + catch (std::exception& e) + { + new ng::MessageDialog(_viewer, ng::MessageDialog::Type::Warning, "Failed to render prefiltered environment", e.what()); + } + + // Clean up. + glViewport(0, 0, _viewer->m_fbsize[0], _viewer->m_fbsize[1]); + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); + + lightHandler->setEnvPrefilteredMap(outTex); +} + mx::ImagePtr GLRenderPipeline::getShadowMap(int shadowMapSize) { auto& genContext = _viewer->_genContext; @@ -219,7 +313,13 @@ void GLRenderPipeline::renderFrame(void*, int shadowMapSize, const char* dirLigh float lightRotation = _viewer->_lightRotation; auto& searchPath = _viewer->_searchPath; auto& geometryHandler = _viewer->_geometryHandler; - + + // Update prefiltered environment. + if (lightHandler->getUsePrefilteredMap() && !_viewer->_materialAssignments.empty()) + { + updatePrefilteredMap(); + } + // Initialize OpenGL state glDisable(GL_BLEND); glEnable(GL_DEPTH_TEST); @@ -267,6 +367,9 @@ void GLRenderPipeline::renderFrame(void*, int shadowMapSize, const char* dirLigh float longitudeOffset = (lightRotation / 360.0f) + 0.5f; envMaterial->modifyUniform("longitude/in2", mx::Value::createValue(longitudeOffset)); + // Apply light intensity to the environment shader. + envMaterial->modifyUniform("envImageAdjusted/in2", mx::Value::createValue(lightHandler->getEnvLightIntensity())); + // Render the environment mesh. glDepthMask(GL_FALSE); envMaterial->bindShader(); diff --git a/source/MaterialXView/RenderPipelineGL.h b/source/MaterialXView/RenderPipelineGL.h index fcb64a6436..00ebcbc6eb 100644 --- a/source/MaterialXView/RenderPipelineGL.h +++ b/source/MaterialXView/RenderPipelineGL.h @@ -31,6 +31,7 @@ class GLRenderPipeline : public RenderPipeline mx::ImageHandlerPtr createImageHandler() override; mx::MaterialPtr createMaterial() override; void updateAlbedoTable(int tableSize) override; + void updatePrefilteredMap() override; std::shared_ptr createTextureBaker(unsigned int width, unsigned int height, mx::Image::BaseType baseType) override; diff --git a/source/MaterialXView/RenderPipelineMetal.h b/source/MaterialXView/RenderPipelineMetal.h index 1ed8c063bd..9cd2b2f6b3 100644 --- a/source/MaterialXView/RenderPipelineMetal.h +++ b/source/MaterialXView/RenderPipelineMetal.h @@ -40,6 +40,7 @@ class MetalRenderPipeline : public RenderPipeline mx::ImageHandlerPtr createImageHandler() override; mx::MaterialPtr createMaterial() override; void updateAlbedoTable(int tableSize) override; + void updatePrefilteredMap() override; void renderFrame(void* color_texture, int shadowMapSize, const char* dirLightNodeCat) override; void bakeTextures() override; mx::ImagePtr getFrameImage() override; @@ -50,6 +51,7 @@ class MetalRenderPipeline : public RenderPipeline protected: mx::ImagePtr getShadowMap(int shadowMapSize) override; mx::MetalFramebufferPtr _shadowMapFramebuffer; + mx::MetalFramebufferPtr _prefilterFramebuffer; mx::ImagePtr _shadowMap[SHADOWMAP_TEX_COUNT]; }; diff --git a/source/MaterialXView/RenderPipelineMetal.mm b/source/MaterialXView/RenderPipelineMetal.mm index 026e35720a..9ced3b1669 100644 --- a/source/MaterialXView/RenderPipelineMetal.mm +++ b/source/MaterialXView/RenderPipelineMetal.mm @@ -155,6 +155,96 @@ } } +void MetalRenderPipeline::updatePrefilteredMap() +{ + auto& genContext = _viewer->_genContext; + auto& lightHandler = _viewer->_lightHandler; + auto& imageHandler = _viewer->_imageHandler; + + if (lightHandler->getEnvPrefilteredMap()) + { + return; + } + + mx::ImagePtr srcTex = lightHandler->getEnvRadianceMap(); + int w = srcTex->getWidth(); + int h = srcTex->getHeight(); + + mx::MetalTextureHandlerPtr mtlImageHandler = std::dynamic_pointer_cast(imageHandler); + mx::ImagePtr outTex = mx::Image::create(w, h, 3, mx::Image::BaseType::HALF); + mtlImageHandler->createRenderResources(outTex, true, true); + id metalTex = mtlImageHandler->getAssociatedMetalTexture(outTex); + + // Create framebuffer. + _prefilterFramebuffer = mx::MetalFramebuffer::create( + MTL(device), + w, h, + 4, + mx::Image::BaseType::HALF, + metalTex + ); + + MTL_PUSH_FRAMEBUFFER(_prefilterFramebuffer); + + // Create shader. + mx::ShaderPtr hwShader = mx::createEnvPrefilterShader(genContext, _viewer->_stdLib, "__ENV_PREFILTER__"); + mx::MslMaterialPtr material = mx::MslMaterial::create(); + try + { + material->generateShader(hwShader); + } + catch (std::exception& e) + { + new ng::MessageDialog(_viewer, ng::MessageDialog::Type::Warning, "Failed to generate convolution shader", e.what()); + } + + int i = 0; + + while (w > 0 && h > 0) + { + MTL(beginCommandBuffer()); + MTLRenderPassDescriptor* desc = [MTLRenderPassDescriptor new]; + [desc.colorAttachments[0] setTexture:metalTex]; + [desc.colorAttachments[0] setLevel:i]; + [desc.colorAttachments[0] setLoadAction:MTLLoadActionDontCare]; + [desc.colorAttachments[0] setStoreAction:MTLStoreActionStore]; + [desc.depthAttachment setTexture:_prefilterFramebuffer->getDepthTexture()]; + [desc.depthAttachment setLoadAction:MTLLoadActionDontCare]; + [desc.depthAttachment setStoreAction:MTLStoreActionDontCare]; + [desc setStencilAttachment:nil]; + + MTL(beginEncoder(desc)); + [MTL(renderCmdEncoder) setDepthStencilState:MTL_DEPTHSTENCIL_STATE(opaque)]; + + _prefilterFramebuffer->bind(desc); + material->bindShader(); + material->getProgram()->bindUniform(mx::HW::ENV_PREFILTER_MIP, mx::Value::createValue(i)); + + bool prevValue = lightHandler->getUsePrefilteredMap(); + lightHandler->setUsePrefilteredMap(false); + material->getProgram()->prepareUsedResources( + MTL(renderCmdEncoder), + _viewer->_identityCamera, + nullptr, + imageHandler, + lightHandler); + lightHandler->setUsePrefilteredMap(prevValue); + + _viewer->renderScreenSpaceQuad(material); + + MTL(endCommandBuffer()); + [desc release]; + + w /= 2; + h /= 2; + i++; + } + + MTL_POP_FRAMEBUFFER(); + + lightHandler->setEnvPrefilteredMap(outTex); +} + mx::ImagePtr MetalRenderPipeline::getShadowMap(int shadowMapSize) { auto& genContext = _viewer->_genContext; @@ -175,7 +265,7 @@ !mtlImageHandler->getAssociatedMetalTexture(_shadowMap[i])) { _shadowMap[i] = mx::Image::create(shadowMapSize, shadowMapSize, 2, mx::Image::BaseType::FLOAT); - _viewer->_imageHandler->createRenderResources(_shadowMap[i], false); + _viewer->_imageHandler->createRenderResources(_shadowMap[i], false, true); } shadowMapTex[i] = @@ -315,6 +405,12 @@ auto& searchPath = _viewer->_searchPath; auto& geometryHandler = _viewer->_geometryHandler; + // Update prefiltered environment. + if (lightHandler->getUsePrefilteredMap() && !_viewer->_materialAssignments.empty()) + { + updatePrefilteredMap(); + } + // Update lighting state. lightHandler->setLightTransform(mx::Matrix44::createRotationY(lightRotation / 180.0f * M_PI)); @@ -394,6 +490,9 @@ float longitudeOffset = (lightRotation / 360.0f) + 0.5f; envMaterial->modifyUniform("longitude/in2", mx::Value::createValue(longitudeOffset)); + // Apply light intensity to the environment shader. + envMaterial->modifyUniform("envImageAdjusted/in2", mx::Value::createValue(lightHandler->getEnvLightIntensity())); + // Render the environment mesh. [MTL(renderCmdEncoder) setCullMode:MTLCullModeNone]; envMaterial->bindShader(); diff --git a/source/MaterialXView/Viewer.cpp b/source/MaterialXView/Viewer.cpp index 6346658d07..7cd70d6c7f 100644 --- a/source/MaterialXView/Viewer.cpp +++ b/source/MaterialXView/Viewer.cpp @@ -121,26 +121,6 @@ void applyModifiers(mx::DocumentPtr doc, const DocumentModifiers& modifiers) } } - // Remap references to unimplemented shader nodedefs. - for (mx::NodePtr materialNode : doc->getMaterialNodes()) - { - for (mx::NodePtr shader : getShaderNodes(materialNode)) - { - mx::NodeDefPtr nodeDef = shader->getNodeDef(); - if (nodeDef && !nodeDef->getImplementation()) - { - std::vector altNodeDefs = doc->getMatchingNodeDefs(nodeDef->getNodeString()); - for (mx::NodeDefPtr altNodeDef : altNodeDefs) - { - if (altNodeDef->getImplementation()) - { - shader->setNodeDefString(altNodeDef->getName()); - } - } - } - } - } - // Remap unsupported texture coordinate indices. for (mx::ElementPtr elem : doc->traverseTree()) { @@ -157,55 +137,6 @@ void applyModifiers(mx::DocumentPtr doc, const DocumentModifiers& modifiers) } } -// ViewDir implementation for GLSL -// as needed for the environment shader. -template -class ViewDir : public NodeGraphImpl -{ -public: - static mx::ShaderNodeImplPtr create() - { - return std::make_shared(); - } - - void createVariables(const mx::ShaderNode&, mx::GenContext&, mx::Shader& shader) const override - { - mx::ShaderStage& vs = shader.getStage(mx::Stage::VERTEX); - mx::ShaderStage& ps = shader.getStage(mx::Stage::PIXEL); - addStageInput(mx::HW::VERTEX_INPUTS, mx::Type::VECTOR3, mx::HW::T_IN_POSITION, vs); - addStageConnector(mx::HW::VERTEX_DATA, mx::Type::VECTOR3, mx::HW::T_POSITION_WORLD, vs, ps); - addStageUniform(mx::HW::PRIVATE_UNIFORMS, mx::Type::VECTOR3, mx::HW::T_VIEW_POSITION, ps); - } - - void emitFunctionCall(const mx::ShaderNode& node, mx::GenContext& context, mx::ShaderStage& stage) const override - { - const mx::ShaderGenerator& shadergen = context.getShaderGenerator(); - - DEFINE_SHADER_STAGE(stage, mx::Stage::VERTEX) - { - mx::VariableBlock& vertexData = stage.getOutputBlock(mx::HW::VERTEX_DATA); - const mx::string prefix = vertexData.getInstance() + "."; - mx::ShaderPort* position = vertexData[mx::HW::T_POSITION_WORLD]; - if (!position->isEmitted()) - { - position->setEmitted(); - shadergen.emitLine(prefix + position->getVariable() + " = hPositionWorld.xyz", stage); - } - } - - DEFINE_SHADER_STAGE(stage, mx::Stage::PIXEL) - { - mx::VariableBlock& vertexData = stage.getInputBlock(mx::HW::VERTEX_DATA); - const mx::string prefix = vertexData.getInstance() + "."; - mx::ShaderPort* position = vertexData[mx::HW::T_POSITION_WORLD]; - shadergen.emitLineBegin(stage); - shadergen.emitOutput(node.getOutput(), true, false, context, stage); - shadergen.emitString(" = normalize(" + prefix + position->getVariable() + " - " + mx::HW::T_VIEW_POSITION + ")", stage); - shadergen.emitLineEnd(stage); - } - } -}; - } // anonymous namespace // @@ -317,10 +248,8 @@ Viewer::Viewer(const std::string& materialFilename, _renderPipeline = MetalRenderPipeline::create(this); _renderPipeline->initialize(ng::metal_device(), ng::metal_command_queue()); - _genContext.getShaderGenerator().registerImplementation("IM_viewdir_vector3_" + _genContext.getShaderGenerator().getTarget(), ViewDir::create); #else _renderPipeline = GLRenderPipeline::create(this); - _genContext.getShaderGenerator().registerImplementation("IM_viewdir_vector3_" + _genContext.getShaderGenerator().getTarget(), ViewDir::create); // Set Essl generator options _genContextEssl.getOptions().targetColorSpaceOverride = "lin_rec709"; @@ -337,7 +266,6 @@ Viewer::Viewer(const std::string& materialFilename, _genContextMdl.getOptions().targetColorSpaceOverride = "lin_rec709"; _genContextMdl.getOptions().fileTextureVerticalFlip = false; #endif - // Register the API Spcefic implementation for used by the environment shader. } void Viewer::initialize() @@ -474,7 +402,7 @@ void Viewer::loadEnvironmentLight() } // Look for an irradiance map using an expected filename convention. - mx::ImagePtr envIrradianceMap = _imageHandler->getZeroImage(); + mx::ImagePtr envIrradianceMap; if (!_normalizeEnvironment && !_splitDirectLight) { mx::FilePath envIrradiancePath = _envRadianceFilename.getParentPath() / IRRADIANCE_MAP_FOLDER / _envRadianceFilename.getBaseName(); @@ -482,7 +410,7 @@ void Viewer::loadEnvironmentLight() } // If not found, then generate an irradiance map via spherical harmonics. - if (envIrradianceMap == _imageHandler->getZeroImage()) + if (!envIrradianceMap || envIrradianceMap->getWidth() == 1) { if (_generateReferenceIrradiance) { @@ -505,9 +433,12 @@ void Viewer::loadEnvironmentLight() // Release any existing environment maps and store the new ones. _imageHandler->releaseRenderResources(_lightHandler->getEnvRadianceMap()); + _imageHandler->releaseRenderResources(_lightHandler->getEnvPrefilteredMap()); _imageHandler->releaseRenderResources(_lightHandler->getEnvIrradianceMap()); + _lightHandler->setEnvRadianceMap(envRadianceMap); _lightHandler->setEnvIrradianceMap(envIrradianceMap); + _lightHandler->setEnvPrefilteredMap(nullptr); // Look for a light rig using an expected filename convention. if (!_splitDirectLight) @@ -766,12 +697,14 @@ void Viewer::createAdvancedSettings(Widget* parent) ng::CheckBox* importanceSampleBox = new ng::CheckBox(advancedPopup, "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) { _genContext.getOptions().hwSpecularEnvironmentMethod = enable ? mx::SPECULAR_ENVIRONMENT_FIS : mx::SPECULAR_ENVIRONMENT_PREFILTER; #ifndef MATERIALXVIEW_METAL_BACKEND _genContextEssl.getOptions().hwSpecularEnvironmentMethod = _genContext.getOptions().hwSpecularEnvironmentMethod; #endif + _lightHandler->setUsePrefilteredMap(!enable); reloadShaders(); }); @@ -812,7 +745,24 @@ void Viewer::createAdvancedSettings(Widget* parent) { _genContext.getOptions().hwDirectionalAlbedoMethod = (mx::HwDirectionalAlbedoMethod) index; reloadShaders(); - _renderPipeline->updateAlbedoTable(ALBEDO_TABLE_SIZE); + try + { + _renderPipeline->updateAlbedoTable(ALBEDO_TABLE_SIZE); + } + catch (mx::ExceptionRenderError& e) + { + for (const std::string& error : e.errorLog()) + { + std::cerr << error << std::endl; + } + new ng::MessageDialog(this, ng::MessageDialog::Type::Warning, "Shader generation error", e.what()); + _materialAssignments.clear(); + } + catch (std::exception& e) + { + new ng::MessageDialog(this, ng::MessageDialog::Type::Warning, "Failed to update albedo table", e.what()); + _materialAssignments.clear(); + } }); Widget* sampleGroup = new Widget(advancedPopup); @@ -1395,7 +1345,7 @@ void Viewer::loadDocument(const mx::FilePath& filename, mx::DocumentPtr librarie // with later assignments superseding earlier ones. for (mx::LookPtr look : doc->getLooks()) { - for (mx::MaterialAssignPtr matAssign : look->getMaterialAssigns()) + for (mx::MaterialAssignPtr matAssign : look->getActiveMaterialAssigns()) { const std::string& activeGeom = matAssign->getActiveGeom(); for (mx::MeshPartitionPtr part : _geometryList) @@ -2410,7 +2360,7 @@ mx::MaterialPtr Viewer::getEnvironmentMaterial() { if (!_envMaterial) { - mx::FilePath envFilename = _searchPath.find(mx::FilePath("resources/Lights/envmap_shader.mtlx")); + mx::FilePath envFilename = _searchPath.find(mx::FilePath("resources/Lights/environment_map.mtlx")); try { _envMaterial = _renderPipeline->createMaterial(); diff --git a/source/MaterialXView/Viewer.h b/source/MaterialXView/Viewer.h index ff0827d12a..cab8efb95b 100644 --- a/source/MaterialXView/Viewer.h +++ b/source/MaterialXView/Viewer.h @@ -109,6 +109,12 @@ class Viewer : public ng::Screen _lightHandler->setEnvSampleCount(count); } + // Set the environment light intensity. + void setEnvLightIntensity(float intensity) + { + _lightHandler->setEnvLightIntensity(intensity); + } + // Set the rotation of the lighting environment about the Y axis. void setLightRotation(float rotation) { diff --git a/source/PyMaterialX/CMakeLists.txt b/source/PyMaterialX/CMakeLists.txt index eda1ba0db4..2bbe2c9506 100644 --- a/source/PyMaterialX/CMakeLists.txt +++ b/source/PyMaterialX/CMakeLists.txt @@ -44,7 +44,7 @@ endif() add_subdirectory(PyMaterialXCore) add_subdirectory(PyMaterialXFormat) -if (MATERIALX_BUILD_GEN_GLSL OR MATERIALX_BUILD_GEN_OSL OR MATERIALX_BUILD_GEN_MDL) +if (MATERIALX_BUILD_GEN_GLSL OR MATERIALX_BUILD_GEN_OSL OR MATERIALX_BUILD_GEN_MDL OR MATERIALX_BUILD_GEN_MSL) add_subdirectory(PyMaterialXGenShader) if (MATERIALX_BUILD_GEN_GLSL) add_subdirectory(PyMaterialXGenGlsl) diff --git a/source/PyMaterialX/PyMaterialX.h b/source/PyMaterialX/PyMaterialX.h index 7af67ac4bd..1e7bc7ff87 100644 --- a/source/PyMaterialX/PyMaterialX.h +++ b/source/PyMaterialX/PyMaterialX.h @@ -16,4 +16,16 @@ #include #include +// Define a macro to import a PyMaterialX module, e.g. `PyMaterialXCore`, +// either within the `MaterialX` Python package, e.g. in `installed/python/`, +// or as a standalone module, e.g. in `lib/` +#define PYMATERIALX_IMPORT_MODULE(MODULE_NAME) \ + try \ + { \ + pybind11::module::import("MaterialX." #MODULE_NAME); \ + } \ + catch (const py::error_already_set&) \ + { \ + pybind11::module::import(#MODULE_NAME); \ + } #endif diff --git a/source/PyMaterialX/PyMaterialXCore/PyElement.cpp b/source/PyMaterialX/PyMaterialXCore/PyElement.cpp index d89cbc81a4..6e846c120e 100644 --- a/source/PyMaterialX/PyMaterialXCore/PyElement.cpp +++ b/source/PyMaterialX/PyMaterialXCore/PyElement.cpp @@ -124,6 +124,7 @@ void bindPyElement(py::module& mod) .def("setType", &mx::TypedElement::setType) .def("hasType", &mx::TypedElement::hasType) .def("getType", &mx::TypedElement::getType) + .def("isColorType", &mx::TypedElement::isColorType) .def("isMultiOutputType", &mx::TypedElement::isMultiOutputType) .def("getTypeDef", &mx::TypedElement::getTypeDef) .def_readonly_static("TYPE_ATTRIBUTE", &mx::TypedElement::TYPE_ATTRIBUTE); diff --git a/source/PyMaterialX/PyMaterialXFormat/PyModule.cpp b/source/PyMaterialX/PyMaterialXFormat/PyModule.cpp index 842087d24f..3965f48753 100644 --- a/source/PyMaterialX/PyMaterialXFormat/PyModule.cpp +++ b/source/PyMaterialX/PyMaterialXFormat/PyModule.cpp @@ -15,6 +15,9 @@ PYBIND11_MODULE(PyMaterialXFormat, mod) { mod.doc() = "Module containing Python bindings for the MaterialXFormat library"; + // PyMaterialXFormat depends on types defined in PyMaterialXCore + PYMATERIALX_IMPORT_MODULE(PyMaterialXCore); + bindPyFile(mod); bindPyXmlIo(mod); bindPyUtil(mod); diff --git a/source/PyMaterialX/PyMaterialXGenGlsl/PyGlslShaderGenerator.cpp b/source/PyMaterialX/PyMaterialXGenGlsl/PyGlslShaderGenerator.cpp index ba4a9c981e..f26d4f2aee 100644 --- a/source/PyMaterialX/PyMaterialXGenGlsl/PyGlslShaderGenerator.cpp +++ b/source/PyMaterialX/PyMaterialXGenGlsl/PyGlslShaderGenerator.cpp @@ -12,8 +12,6 @@ #include #include -#include - namespace py = pybind11; namespace mx = MaterialX; diff --git a/source/PyMaterialX/PyMaterialXGenGlsl/PyModule.cpp b/source/PyMaterialX/PyMaterialXGenGlsl/PyModule.cpp index a36b815d32..9ab46e514d 100644 --- a/source/PyMaterialX/PyMaterialXGenGlsl/PyModule.cpp +++ b/source/PyMaterialX/PyMaterialXGenGlsl/PyModule.cpp @@ -16,6 +16,9 @@ PYBIND11_MODULE(PyMaterialXGenGlsl, mod) { mod.doc() = "Module containing Python bindings for the MaterialXGenGlsl library"; + // PyMaterialXGenGlsl depends on types defined in PyMaterialXGenShader + PYMATERIALX_IMPORT_MODULE(PyMaterialXGenShader); + bindPyGlslShaderGenerator(mod); bindPyGlslResourceBindingContext(mod); diff --git a/source/PyMaterialX/PyMaterialXGenMdl/PyMdlShaderGenerator.cpp b/source/PyMaterialX/PyMaterialXGenMdl/PyMdlShaderGenerator.cpp index d06e6f5ba7..d0702cfff0 100644 --- a/source/PyMaterialX/PyMaterialXGenMdl/PyMdlShaderGenerator.cpp +++ b/source/PyMaterialX/PyMaterialXGenMdl/PyMdlShaderGenerator.cpp @@ -8,12 +8,9 @@ #include #include -#include - namespace py = pybind11; namespace mx = MaterialX; - void bindPyMdlShaderGenerator(py::module& mod) { py::class_(mod, "MdlShaderGenerator") diff --git a/source/PyMaterialX/PyMaterialXGenMdl/PyModule.cpp b/source/PyMaterialX/PyMaterialXGenMdl/PyModule.cpp index 020c944e63..a34b28a729 100644 --- a/source/PyMaterialX/PyMaterialXGenMdl/PyModule.cpp +++ b/source/PyMaterialX/PyMaterialXGenMdl/PyModule.cpp @@ -13,5 +13,8 @@ PYBIND11_MODULE(PyMaterialXGenMdl, mod) { mod.doc() = "Module containing Python bindings for the MaterialXGenMdl library"; + // PyMaterialXGenMdl depends on types defined in PyMaterialXGenShader + PYMATERIALX_IMPORT_MODULE(PyMaterialXGenShader); + bindPyMdlShaderGenerator(mod); }; diff --git a/source/PyMaterialX/PyMaterialXGenMsl/PyModule.cpp b/source/PyMaterialX/PyMaterialXGenMsl/PyModule.cpp index 6eda44871b..b3dcdb10a8 100644 --- a/source/PyMaterialX/PyMaterialXGenMsl/PyModule.cpp +++ b/source/PyMaterialX/PyMaterialXGenMsl/PyModule.cpp @@ -14,6 +14,9 @@ PYBIND11_MODULE(PyMaterialXGenMsl, mod) { mod.doc() = "Module containing Python bindings for the MaterialXGenMsl library"; + // PyMaterialXGenMsl depends on types defined in PyMaterialXGenShader + PYMATERIALX_IMPORT_MODULE(PyMaterialXGenShader); + bindPyMslShaderGenerator(mod); bindPyMslResourceBindingContext(mod); } diff --git a/source/PyMaterialX/PyMaterialXGenMsl/PyMslShaderGenerator.cpp b/source/PyMaterialX/PyMaterialXGenMsl/PyMslShaderGenerator.cpp index 870b9bc02c..48259cad07 100644 --- a/source/PyMaterialX/PyMaterialXGenMsl/PyMslShaderGenerator.cpp +++ b/source/PyMaterialX/PyMaterialXGenMsl/PyMslShaderGenerator.cpp @@ -10,8 +10,6 @@ #include #include -#include - namespace py = pybind11; namespace mx = MaterialX; diff --git a/source/PyMaterialX/PyMaterialXGenOsl/PyModule.cpp b/source/PyMaterialX/PyMaterialXGenOsl/PyModule.cpp index d772d18b6a..54d7d2439a 100644 --- a/source/PyMaterialX/PyMaterialXGenOsl/PyModule.cpp +++ b/source/PyMaterialX/PyMaterialXGenOsl/PyModule.cpp @@ -13,5 +13,8 @@ PYBIND11_MODULE(PyMaterialXGenOsl, mod) { mod.doc() = "Module containing Python bindings for the MaterialXGenOsl library"; + // PyMaterialXGenOsl depends on types defined in PyMaterialXGenShader + PYMATERIALX_IMPORT_MODULE(PyMaterialXGenShader); + bindPyOslShaderGenerator(mod); } diff --git a/source/PyMaterialX/PyMaterialXGenOsl/PyOslShaderGenerator.cpp b/source/PyMaterialX/PyMaterialXGenOsl/PyOslShaderGenerator.cpp index 39082c28f5..7c53002669 100644 --- a/source/PyMaterialX/PyMaterialXGenOsl/PyOslShaderGenerator.cpp +++ b/source/PyMaterialX/PyMaterialXGenOsl/PyOslShaderGenerator.cpp @@ -9,8 +9,6 @@ #include #include -#include - namespace py = pybind11; namespace mx = MaterialX; diff --git a/source/PyMaterialX/PyMaterialXGenShader/PyGenOptions.cpp b/source/PyMaterialX/PyMaterialXGenShader/PyGenOptions.cpp index 75b5fb11bb..c40728ad26 100644 --- a/source/PyMaterialX/PyMaterialXGenShader/PyGenOptions.cpp +++ b/source/PyMaterialX/PyMaterialXGenShader/PyGenOptions.cpp @@ -38,6 +38,7 @@ void bindPyGenOptions(py::module& mod) .def_readwrite("hwNormalizeUdimTexCoords", &mx::GenOptions::hwNormalizeUdimTexCoords) .def_readwrite("hwAmbientOcclusion", &mx::GenOptions::hwAmbientOcclusion) .def_readwrite("hwWriteAlbedoTable", &mx::GenOptions::hwWriteAlbedoTable) + .def_readwrite("hwWriteEnvPrefilter", &mx::GenOptions::hwWriteEnvPrefilter) .def_readwrite("hwImplicitBitangents", &mx::GenOptions::hwImplicitBitangents) .def_readwrite("emitColorTransforms", &mx::GenOptions::emitColorTransforms) .def(py::init<>()); diff --git a/source/PyMaterialX/PyMaterialXGenShader/PyHwShaderGenerator.cpp b/source/PyMaterialX/PyMaterialXGenShader/PyHwShaderGenerator.cpp index d13b2ad133..286021cb90 100644 --- a/source/PyMaterialX/PyMaterialXGenShader/PyHwShaderGenerator.cpp +++ b/source/PyMaterialX/PyMaterialXGenShader/PyHwShaderGenerator.cpp @@ -9,8 +9,6 @@ #include #include -#include - namespace py = pybind11; namespace mx = MaterialX; diff --git a/source/PyMaterialX/PyMaterialXGenShader/PyShaderPort.cpp b/source/PyMaterialX/PyMaterialXGenShader/PyShaderPort.cpp index 343442e071..146674c222 100644 --- a/source/PyMaterialX/PyMaterialXGenShader/PyShaderPort.cpp +++ b/source/PyMaterialX/PyMaterialXGenShader/PyShaderPort.cpp @@ -24,6 +24,7 @@ void bindPyShaderPort(py::module& mod) .def("getSemantic", &mx::ShaderPort::getSemantic) .def("setValue", &mx::ShaderPort::setValue) .def("getValue", &mx::ShaderPort::getValue) + .def("getValueString", &mx::ShaderPort::getValueString) .def("setGeomProp", &mx::ShaderPort::setGeomProp) .def("getGeomProp", &mx::ShaderPort::getGeomProp) .def("setPath", &mx::ShaderPort::setPath) diff --git a/source/PyMaterialX/PyMaterialXRender/PyModule.cpp b/source/PyMaterialX/PyMaterialXRender/PyModule.cpp index 1c60142346..bbf9688403 100644 --- a/source/PyMaterialX/PyMaterialXRender/PyModule.cpp +++ b/source/PyMaterialX/PyMaterialXRender/PyModule.cpp @@ -25,6 +25,9 @@ PYBIND11_MODULE(PyMaterialXRender, mod) { mod.doc() = "Module containing Python bindings for the MaterialXRender library"; + // PyMaterialXRender depends on types defined in PyMaterialXCore + PYMATERIALX_IMPORT_MODULE(PyMaterialXCore); + bindPyMesh(mod); bindPyGeometryHandler(mod); bindPyLightHandler(mod); diff --git a/source/PyMaterialX/PyMaterialXRenderGlsl/PyModule.cpp b/source/PyMaterialX/PyMaterialXRenderGlsl/PyModule.cpp index 32fb79239d..d0ef04158d 100644 --- a/source/PyMaterialX/PyMaterialXRenderGlsl/PyModule.cpp +++ b/source/PyMaterialX/PyMaterialXRenderGlsl/PyModule.cpp @@ -16,6 +16,9 @@ PYBIND11_MODULE(PyMaterialXRenderGlsl, mod) { mod.doc() = "Module containing Python bindings for the MaterialXRenderGlsl library"; + // PyMaterialXRenderGlsl depends on types defined in PyMaterialXRender + PYMATERIALX_IMPORT_MODULE(PyMaterialXRender); + bindPyGlslProgram(mod); bindPyGlslRenderer(mod); bindPyGLTextureHandler(mod); diff --git a/source/PyMaterialX/PyMaterialXRenderMsl/PyModule.mm b/source/PyMaterialX/PyMaterialXRenderMsl/PyModule.mm index 10b440d21c..f4d0dbeaeb 100644 --- a/source/PyMaterialX/PyMaterialXRenderMsl/PyModule.mm +++ b/source/PyMaterialX/PyMaterialXRenderMsl/PyModule.mm @@ -16,6 +16,9 @@ { mod.doc() = "Module containing Python bindings for the MaterialXRenderMsl library"; + // PyMaterialXRenderMsl depends on types defined in PyMaterialXRender + PYMATERIALX_IMPORT_MODULE(PyMaterialXRender); + bindPyMslProgram(mod); bindPyMslRenderer(mod); bindPyMetalTextureHandler(mod); diff --git a/source/PyMaterialX/PyMaterialXRenderOsl/PyModule.cpp b/source/PyMaterialX/PyMaterialXRenderOsl/PyModule.cpp index 15610066f3..4019d364ab 100644 --- a/source/PyMaterialX/PyMaterialXRenderOsl/PyModule.cpp +++ b/source/PyMaterialX/PyMaterialXRenderOsl/PyModule.cpp @@ -13,5 +13,8 @@ PYBIND11_MODULE(PyMaterialXRenderOsl, mod) { mod.doc() = "Module containing Python bindings for the MaterialXRenderOsl library"; + // PyMaterialXRenderOsl depends on types defined in PyMaterialXRender + PYMATERIALX_IMPORT_MODULE(PyMaterialXRender); + bindPyOslRenderer(mod); }