├── .bash_profile ├── .gitignore ├── LICENSE-APACHE ├── LICENSE-MIT ├── Makefile ├── README.md ├── katana ├── Macros │ └── Material_v2_NMC.macro └── UIPlugins │ └── ShadingNodeMenu.py ├── osl ├── Makefile ├── include │ ├── ikaConstants.h │ └── ikaFunctions.h └── material │ ├── v2_Displacement.h │ ├── v2_Displacement.osl │ ├── v2_PxrSurface.h │ ├── v2_PxrSurface.osl │ ├── v2_PxrSurfaceAdapter.h │ ├── v2_PxrSurfaceAdapter.osl │ └── v2_PxrSurfaceModify.osl ├── ris ├── Makefile ├── displace │ ├── Args │ │ └── SetP.args │ └── SetP.cpp └── displayfilter │ ├── Annotate.cpp │ └── Args │ └── Annotate.args ├── scene ├── Teapot.katana └── Teapot_Annotated.katana └── wiki_images ├── Annotate.params.png ├── Annotate.png ├── Material_v2_NMC.macro.png ├── Material_v2_NMC.params.png ├── Material_v2_Shaders.png ├── Teapot.katana.jpg ├── material_v2_PxrSurface.params.expanded.png ├── material_v2_PxrSurface.params.png └── material_v2_PxrSurface.png /.bash_profile: -------------------------------------------------------------------------------- 1 | # Shading-library installation location. 2 | export SHADING_LIBRARY="${HOME}/shading-library" 3 | 4 | # Pixar installation location. 5 | export PIXAR_ROOT="/opt/pixar" 6 | 7 | # RenderMan version. 8 | export RMAN_MAJOR="23" 9 | export RMAN_MINOR="2" 10 | export RMAN_MICRO="" 11 | export RMAN_VERSION="${RMAN_MAJOR}.${RMAN_MINOR}${RMAN_MICRO}" 12 | 13 | # Katana version. 14 | export KATANA_MAJOR="3" 15 | export KATANA_MINOR="2" 16 | export KATANA_MICRO="v4" 17 | export KATANA_SHORT_VERSION="${KATANA_MAJOR}.${KATANA_MINOR}" 18 | 19 | # RenderMan and shading-library software locations. 20 | export RMANTREE="${PIXAR_ROOT}/RenderManProServer-${RMAN_VERSION}" 21 | export RFK_LOCATION="${PIXAR_ROOT}/RenderManForKatana-${RMAN_VERSION}-katana${KATANA_SHORT_VERSION}" 22 | export RMAN_SHADERPATH="${SHADING_LIBRARY}/build:${RMANTREE}/lib/plugins:${RMANTREE}/lib/shaders" 23 | export RMAN_RIXPLUGINPATH="${SHADING_LIBRARY}/build:${RMANTREE}/lib/plugins" 24 | 25 | # Katana resource locations. 26 | export KATANA_RESOURCES="${RFK_LOCATION}/plugins/Resources/PRMan${RMAN_MAJOR}:${SHADING_LIBRARY}/katana" 27 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.o 2 | *.so 3 | *.oso 4 | *.swp 5 | *.pyc 6 | /build -------------------------------------------------------------------------------- /LICENSE-APACHE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright(c) 2018 Laika, LLC 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /LICENSE-MIT: -------------------------------------------------------------------------------- 1 | Copyright(c) Laika, LLC 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a 4 | copy of this software and associated documentation files (the "Software"), 5 | to deal in the Software without restriction, including without limitation 6 | the rights to use, copy, modify, merge, publish, distribute, sublicense, 7 | and/or sell copies of the Software, and to permit persons to whom the 8 | Software is furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in 11 | all copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 16 | THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | THE SOFTWARE. 20 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | # 2 | # RMANTREE points to the RenderManProServer directory. 3 | # Set it if it's not already set in the environment. 4 | # 5 | RMANTREE ?= /opt/pixar/RenderManProServer-23.2 6 | export RMANTREE 7 | 8 | # 9 | # BUILD_DIR is where the built files will go. 10 | # Set it if it's not already set in the environment. 11 | # 12 | SRC_DIR ?= $(CURDIR) 13 | BUILD_DIR ?= $(SRC_DIR)/build 14 | 15 | # 16 | # Base command for copying files to the build directory. 17 | # 18 | COPY = rsync -rum --include "*/" 19 | 20 | # 21 | # Control variables. 22 | # These subdirectories will be built using their own Makefile. 23 | # 24 | SUBDIRS := osl ris 25 | 26 | # 27 | # Targets and prerequisites. 28 | # clean is the list of (phony) targets for cleaning the SUBDIRS directory contents. 29 | # install contains the (phony) targets for installing the SUBDIRS directory contents. 30 | # 31 | clean := $(patsubst %,%.clean,$(SUBDIRS)) 32 | install := $(patsubst %,%.install,$(SUBDIRS)) 33 | 34 | .PHONY : $(SUBDIRS) build 35 | 36 | build : $(SUBDIRS) install 37 | 38 | # 39 | # Rules. 40 | # 41 | clean : $(clean) 42 | -$(shell rm -rf $(BUILD_DIR)) 43 | 44 | %.clean : 45 | $(MAKE) -C $(subst .clean,,$@) clean 46 | 47 | $(SUBDIRS) : 48 | $(MAKE) -C $@ 49 | 50 | install : $(install) 51 | -$(shell mkdir -p $(BUILD_DIR)) 52 | -$(COPY) --include="*.katana" --exclude="*" scene $(BUILD_DIR) 53 | -$(COPY) --include="*.macro" --exclude="*" katana $(BUILD_DIR) 54 | -$(COPY) --include="*.py" --exclude="*" katana $(BUILD_DIR) 55 | 56 | %.install : $(SUBDIRS) 57 | -$(COPY) --include="*.oso" --include="*.so" --include="*.args" --exclude="*" $(subst .install,,$@) $(BUILD_DIR) 58 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Production Shading Library 2 | 3 | [![](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](LICENSE-APACHE) 4 | [![](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE-MIT) 5 | 6 | The Production Shading Library refers to [Laika's](https://www.laika.com) entire collection of VFX production shading capabilities. This repository will contain those portions of Laika's Production Shading Library that have been released as open source. 7 | 8 | This release contains a set of shading nodes based on [Pixar's](https://www.pixar.com) [RenderMan](https://renderman.pixar.com/product) that provide: 9 | 10 | - [Material Layering System](https://github.com/LaikaStudios/shading-library/wiki/prman_23.Home) 11 | - [Annotate displayfilter](https://github.com/LaikaStudios/shading-library/wiki/prman_23.Home) 12 | 13 | Please use the Discussions tab to provide any feedback or to initiate any other dialog about this repository. 14 | 15 | # Requirements 16 | * [Pixar's](https://www.pixar.com/renderman) [RenderMan 23](https://rmanwiki.pixar.com/display/REN23/RenderMan) 17 |

18 | * [Foundry's](https://www.foundry.com) [Katana](https://www.foundry.com/products/katana) 19 | * [Pixar's](https://www.pixar.com/renderman) [RenderMan 23 for Katana 3 or 4](https://rmanwiki.pixar.com/display/RFK23/RenderMan+23+for+Katana) 20 |

21 | * A c++14 compatible compiler (clang++ is specified in the [ris/Makefile](https://github.com/LaikaStudios/shading-library/blob/prman_23/ris/Makefile)) 22 | 23 | # Documentation 24 | Documentation is on the [wiki page](https://github.com/LaikaStudios/shading-library/wiki/prman_23.Home). 25 | 26 | # Building Instructions 27 | The Production Shading Library at Laika is developed in a [Linux](https://en.wikipedia.org/wiki/Linux) environment. 28 | Specifically, [Fedora](https://getfedora.org). This initial release does not contain any facilities for building in other operating system environments. 29 | That said, as long as the necessary `c++` compatible compiler and `make` and `rsync` commands are available, 30 | it should be trivial to build the shading-library code on other platforms. 31 | 32 | To build the contents, execute 33 | 34 | make clean; make 35 | 36 | in your local checkout directory of the shading-library. This will put the built contents into a `build` sub-directory. 37 | 38 | # Environment 39 | Assuming you checked out this git repository to `~/shading-library` and have built it, katana's execution environment should have the following environment variables set. Make any alterations necessary for your specific set of software. 40 | 41 | Using `bash` shell: 42 | 43 | # Shading-library installation location. 44 | export SHADING_LIBRARY="${HOME}/shading-library" 45 | 46 | # Pixar installation location. 47 | export PIXAR_ROOT="/opt/pixar" 48 | 49 | # RenderMan version. 50 | export RMAN_MAJOR="23" 51 | export RMAN_MINOR="2" 52 | export RMAN_MICRO="" 53 | export RMAN_VERSION="${RMAN_MAJOR}.${RMAN_MINOR}${RMAN_MICRO}" 54 | 55 | # Katana version. 56 | export KATANA_MAJOR="3" 57 | export KATANA_MINOR="2" 58 | export KATANA_MICRO="v4" 59 | export KATANA_SHORT_VERSION="${KATANA_MAJOR}.${KATANA_MINOR}" 60 | 61 | # RenderMan and shading-library software locations. 62 | export RMANTREE="${PIXAR_ROOT}/RenderManProServer-${RMAN_VERSION}" 63 | export RFK_LOCATION="${PIXAR_ROOT}/RenderManForKatana-${RMAN_VERSION}-katana${KATANA_SHORT_VERSION}" 64 | export RMAN_RIXPLUGINPATH="${SHADING_LIBRARY}/build:${RMANTREE}/lib/plugins" 65 | export RMAN_SHADERPATH="${SHADING_LIBRARY}/build:${RMANTREE}/lib/plugins:${RMANTREE}/lib/shaders" 66 | 67 | # Katana resource locations. 68 | export KATANA_RESOURCES="${RFK_LOCATION}/plugins/Resources/PRMan${RMAN_MAJOR}:${SHADING_LIBRARY}/katana" 69 | 70 | # License 71 | Licensed under either of 72 | 73 | * Apache License, Version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or http://www.apache.org/licenses/LICENSE-2.0) 74 | * MIT license ([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT) 75 | 76 | at your option. 77 | -------------------------------------------------------------------------------- /katana/Macros/Material_v2_NMC.macro: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LaikaStudios/shading-library/b9032f49cf034746645fe3e4a97a6b5ea2f0268c/katana/Macros/Material_v2_NMC.macro -------------------------------------------------------------------------------- /katana/UIPlugins/ShadingNodeMenu.py: -------------------------------------------------------------------------------- 1 | # From katana plugins/Src/Resources/Examples/UIPlugins/CustomLayeredMenuExample.py 2 | # Modified for use with Laika Shading Library. 3 | 4 | """ 5 | Alt+P shading node menu. 6 | Generates a sorted and searchable list of shading nodes in the Node Graph. 7 | """ 8 | 9 | from Katana import UI4, NodegraphAPI, LayeredMenuAPI, RenderingAPI, DrawingModule 10 | from RenderingAPI import RenderPlugins 11 | 12 | 13 | # A list of shading nodes that exist, but that are legacy'd or we otherwise want to hide. 14 | excludeList = [ 15 | 'osl/material/v2_PxrSurfaceAdapter', 16 | 'ris/displace/SetP' 17 | ] 18 | 19 | # A list of shading nodes that should not typically be used. 20 | # Flag them with a yellow color in the displayed list. 21 | yellowList = [] 22 | 23 | # The list of shading nodes that are preferred replacements for existing shading nodes. 24 | # Typically, these replace those in the yellow list. 25 | blueList = [] 26 | 27 | # Color dict. 28 | # Sets the node color per shader category. 29 | # 'integrator' :[ 0.00, 0.00, 0.00 ], 30 | # 'lightfilter' :[ 0.00, 0.00, 0.00 ], 31 | colorDict = { 32 | 'bxdf' :[ 0.2380, 0.3196, 0.4420 ], 33 | 'convert' :[ 0.3900, 0.2910, 0.2100 ], 34 | 'data' :[ 0.2139, 0.3773, 0.4061 ], 35 | 'displace' :[ 0.2482, 0.2380, 0.4420 ], 36 | 'displayfilter':[ 0.3000, 0.3900, 0.2100 ], 37 | 'manifold' :[ 0.3968, 0.2232, 0.2232 ], 38 | 'material' :[ 0.3918, 0.2324, 0.4316 ], 39 | 'parameter' :[ 0.2821, 0.2170, 0.4030 ], 40 | 'pattern' :[ 0.2100, 0.3900, 0.3360 ], 41 | 'samplefilter' :[ 0.3900, 0.2100, 0.3180 ], 42 | 'string' :[ 0.3810, 0.3900, 0.2100 ], 43 | 'texture' :[ 0.2100, 0.3900, 0.2280 ], 44 | 'utility' :[ 0.3900, 0.3450, 0.2100 ], 45 | 'vector' :[ 0.4030, 0.2170, 0.3286 ] 46 | } 47 | 48 | 49 | def IkaPopulateCallback( layeredMenu ): 50 | """ 51 | Callback for the layered menu, which adds entries to the given 52 | C{layeredMenu} based on the available shading nodes. 53 | 54 | @type layeredMenu: L{LayeredMenuAPI.LayeredMenu} 55 | @param layeredMenu: The layered menu to add entries to. 56 | """ 57 | # Obtain a list of names of available PRMan shaders from the PRMan renderer info plug-in. 58 | rendererInfoPlugin = RenderPlugins.GetInfoPlugin( 'prman' ) 59 | shaderType = RenderingAPI.RendererInfo.kRendererObjectTypeShader 60 | shaderNames = rendererInfoPlugin.getRendererObjectNames( shaderType ) 61 | 62 | # Iterate over the names of shaders and add a menu entry for each of them to the given layered menu. 63 | # Note: Can set text to whatever I want the user to see when selecting a shading node. 64 | for shaderName in shaderNames: 65 | if( shaderName in excludeList ): continue 66 | 67 | if( shaderName.lower().find( 'lightfilter' ) != -1 ): continue 68 | if( shaderName.startswith( 'Pxr' ) and shaderName.endswith( 'Light' )): continue 69 | 70 | if( shaderName in yellowList ): 71 | layeredMenu.addEntry( shaderName, text=shaderName, color=(0.7, 0.7, 0.1) ) 72 | 73 | elif( shaderName in blueList ): 74 | layeredMenu.addEntry( shaderName, text=shaderName, color=(0.4, 0.4, 1.0) ) 75 | 76 | elif( shaderName.startswith( 'osl' )): 77 | layeredMenu.addEntry( shaderName, text=shaderName, color=(0.3, 0.77, 0.57) ) 78 | 79 | elif( shaderName.startswith( 'ris' )): 80 | layeredMenu.addEntry( shaderName, text=shaderName, color=(0.3, 0.65, 0.73) ) 81 | 82 | else: 83 | layeredMenu.addEntry( shaderName, text=shaderName, color=(0.7, 0.3, 0.3) ) 84 | 85 | 86 | def ActionCallback( value ): 87 | """ 88 | Callback for the layered menu, which creates a PrmanShadingNode node and 89 | sets its B{nodeType} parameter to the given C{value}, which is the name of 90 | a PRMan shader as set for the menu entry in L{IkaPopulateCallback()}. 91 | 92 | @type value: C{str} 93 | @rtype: C{object} 94 | @param value: An arbitrary object that the menu entry that was chosen 95 | represents. In our case here, this is the name of a PRMan shader as 96 | passed to the L{LayeredMenuAPI.LayeredMenu.addEntry()} function in 97 | L{IkaPopulateCallback()}. 98 | @return: An arbitrary object. In our case here, we return the created 99 | PrmanShadingNode node, which is then placed in the B{Node Graph} tab 100 | because it is a L{NodegraphAPI.Node} instance. 101 | """ 102 | 103 | # Remove ris/ or osl/ prefix from the node name. 104 | if( value.find( 'ris/' ) == 0 or value.find( 'osl/' ) == 0 ): 105 | name = value[ 4: ] 106 | else: 107 | name = value 108 | 109 | # Create a node containing the chosen type. 110 | if( name.find( 'integrator' ) == 0 ): 111 | node = NodegraphAPI.CreateNode( 'PrmanIntegratorSettings', NodegraphAPI.GetRootNode() ) 112 | 113 | else: 114 | node = NodegraphAPI.CreateNode( 'PrmanShadingNode', NodegraphAPI.GetRootNode() ) 115 | node.getParameter( 'nodeType' ).setValue( value, 0 ) 116 | 117 | # Set the node's name. 118 | node.setName( name ) 119 | node.getParameter( 'name' ).setValue( node.getName(), 0 ) 120 | 121 | # Set the node's color based on its shader category. 122 | for category in colorDict: 123 | if( category in name ): 124 | color = colorDict[ category ] 125 | DrawingModule.SetCustomNodeColor( node, color[0], color[1], color[2] ) 126 | break 127 | 128 | # Update the Node Graph. 129 | for tab in UI4.App.Tabs.GetTabsByType( 'Node Graph' ): 130 | tab.update() 131 | 132 | return node 133 | 134 | 135 | # Laika Shading Nodes 136 | ikaLayeredMenu = LayeredMenuAPI.LayeredMenu( IkaPopulateCallback, ActionCallback, 'Alt+P', 137 | alwaysPopulate = False, 138 | onlyMatchWordStart = False 139 | ) 140 | LayeredMenuAPI.RegisterLayeredMenu( ikaLayeredMenu, 'Shading Nodes' ) 141 | -------------------------------------------------------------------------------- /osl/Makefile: -------------------------------------------------------------------------------- 1 | # 2 | # RMANTREE points to the RenderManProServer directory. 3 | # Set it if it's not already set in the environment. 4 | # 5 | RMANTREE ?= /opt/pixar/RenderManProServer-23.2 6 | 7 | # 8 | # Compiler settings. 9 | # 10 | CC = ${RMANTREE}/bin/oslc 11 | CFLAGS = 12 | INCLUDE = -I. -I./include 13 | 14 | # 15 | # Control variables. 16 | # These subdirectories will be searched for .osl files, which will then be built into .oso files. 17 | # 18 | SUBDIRS := material 19 | 20 | # These shaders won't be built. Use 'subdirectory/basename'. 21 | EXCLUDE := 22 | 23 | # 24 | # Make functionality. 25 | # src will be the list of .osl files to build from. 26 | # obj will be the list of .oso files to build. 27 | # 28 | src := $(foreach dir,$(SUBDIRS),$(wildcard $(dir)/*.osl)) 29 | 30 | EXCLUDE := $(basename $(EXCLUDE)) 31 | EXCLUDE := $(addsuffix .osl, $(EXCLUDE)) 32 | 33 | src := $(filter-out $(EXCLUDE), $(src)) 34 | obj := $(src:%.osl=%.oso) 35 | 36 | # 37 | # Targets and prerequisites. 38 | # 39 | all: $(obj) 40 | 41 | # 42 | # Rules. 43 | # 44 | clean: 45 | -$(shell rm -f $(shell find . -name "*.oso" -print)) 46 | 47 | show_src: 48 | @echo $(src) 49 | 50 | show_obj: 51 | @echo $(obj) 52 | 53 | # 54 | # Build rules. 55 | # 56 | %.oso : %.osl 57 | $(CC) $(CFLAGS) $(INCLUDE) -o $@ $< 58 | -------------------------------------------------------------------------------- /osl/include/ikaConstants.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 Laika, LLC. Authored by Mitch Prater. 3 | * 4 | * Licensed under the Apache License Version 2.0 http://apache.org/licenses/LICENSE-2.0, 5 | * or the MIT license http://opensource.org/licenses/MIT, at your option. 6 | * 7 | * This program may not be copied, modified, or distributed except according to those terms. 8 | */ 9 | #ifndef IKA_CONSTANTS_H 10 | #define IKA_CONSTANTS_H 11 | 12 | //---------------------------------------------------------------------- 13 | // Constants 14 | //---------------------------------------------------------------------- 15 | #define IKA_MAXDIST 1.0e30 16 | #define IKA_EPSILON 1.0e-6 17 | 18 | #define IKA_PI 3.141592653589793 19 | #define IKA_INVPI 0.318309886183791 20 | #define IKA_INVPISQ 0.101321183642338 21 | #define IKA_TWOPI 6.283185307179586 22 | #define IKA_INVTWOPI 0.159154943091895 23 | #define IKA_HALFPI 1.570796326794897 24 | #define IKA_SQRTPI 1.772453850905516 25 | #define IKA_SQRT2 1.414213562373095 26 | #define IKA_SQRT3 1.732050807568877 27 | #define IKA_INVSQRT2 0.707106781186547 28 | #define IKA_INVSQRT3 0.577350269189626 29 | #define IKA_SQRTTWOPI 2.506628274631000 30 | 31 | #define IKA_UNITVECTOR vector( IKA_INVSQRT3 ) 32 | 33 | #endif 34 | -------------------------------------------------------------------------------- /osl/include/ikaFunctions.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018-2019 Laika, LLC. Authored by Mitch Prater. 3 | * 4 | * Licensed under the Apache License Version 2.0 http://apache.org/licenses/LICENSE-2.0, 5 | * or the MIT license http://opensource.org/licenses/MIT, at your option. 6 | * 7 | * This program may not be copied, modified, or distributed except according to those terms. 8 | */ 9 | #ifndef IKA_FUNCTIONS_H 10 | #define IKA_FUNCTIONS_H 11 | 12 | #include "ikaConstants.h" 13 | 14 | //---------------------------------------------------------------------- 15 | // Macros 16 | //---------------------------------------------------------------------- 17 | #define IKA_DEGREES(R) degrees(R) 18 | #define IKA_RADIANS(D) radians(D) 19 | 20 | 21 | //---------------------------------------------------------------------- 22 | // bumped normal compensation 23 | // 24 | // If a bump makes a front facing N back facing, those surfaces would not 25 | // be visible in a displaced surface; but they are with a bumped normal, 26 | // which typically produces a black response. 27 | // This function prevents the normal from becoming backfacing along I, 28 | // but allows it to rotate around I, maintaining its curvature 29 | // perpendicular to I, thus preserving its appearance. 30 | // Based on RixAdjustNormal(). 31 | // Note: back facing normals that becoming front facing are not visible. 32 | //---------------------------------------------------------------------- 33 | normal ikaBumpCompensation( normal n ) 34 | { 35 | normal Nb = n; 36 | 37 | if( dot( I,N ) < 0.0 ) // Front facing surface. 38 | { 39 | vector In = normalize( I ); 40 | float IdotN = dot( In, n ); 41 | if( IdotN > 0.0 ) 42 | { 43 | Nb -= 1.001*IdotN * In; // Make Nb roughly perpendicular to I. 44 | Nb = normalize( Nb ); 45 | } 46 | } 47 | 48 | return Nb; 49 | } 50 | 51 | 52 | //---------------------------------------------------------------------- 53 | // CreateOrthonormalBasis from RiTypesHelper.h 54 | // Based on the paper Building an Orthonormal Basis, Revisited in 55 | // the Journal of Computer Graphics Techniques Vol. 6, No. 1, 2017 56 | // http://jcgt.org/published/0006/01/01/ 57 | //---------------------------------------------------------------------- 58 | void ikaCreateOrthonormalBasis( 59 | vector Nn, 60 | output vector Tn, 61 | output vector Bn 62 | ) 63 | { 64 | float sign = select( -1.0, 1.0, Nn[2] >= 0.0 ); 65 | float a = -1.0 / ( sign + Nn[2] ); 66 | 67 | Bn = vector( Nn[0]*Nn[1]*a, sign + Nn[1]*Nn[1]*a, -Nn[1] ); 68 | Tn = vector( 1.0 + sign*Nn[0]*Nn[0]*a, sign*Bn[0], -sign*Nn[0] ); 69 | } 70 | 71 | 72 | //---------------------------------------------------------------------- 73 | // max 74 | //---------------------------------------------------------------------- 75 | color ikaMax( float a, color b ) 76 | { 77 | return max( color(a), b ); 78 | } 79 | 80 | color ikaMax( color a, float b ) 81 | { 82 | return max( a, color(b) ); 83 | } 84 | 85 | #endif 86 | -------------------------------------------------------------------------------- /osl/material/v2_Displacement.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018-2019 Laika, LLC. Authored by Mitch Prater. 3 | * 4 | * Licensed under the Apache License Version 2.0 http://apache.org/licenses/LICENSE-2.0, 5 | * or the MIT license http://opensource.org/licenses/MIT, at your option. 6 | * 7 | * This program may not be copied, modified, or distributed except according to those terms. 8 | */ 9 | #ifndef MATERIAL_V2_DISPLACEMENT_H 10 | #define MATERIAL_V2_DISPLACEMENT_H 11 | 12 | #define DISPLACE_FLOAT_UI_DECLARE(NAME) \ 13 | int Displacement_Float_On ## NAME = 0 \ 14 | [[ \ 15 | int connectable = 0, \ 16 | string page = "Displacement.Float", \ 17 | string label = "On " #NAME, \ 18 | string widget = "mapper", \ 19 | string options = "Off:0|On:1|Invert Input:-1", \ 20 | string help = \ 21 | "Turns the use of the Input " #NAME " displacement On, " \ 22 | "Off, or can Invert the Input value before " \ 23 | "it's used: Input -> 1-Input. " \ 24 | ]], \ 25 | float Displacement_Float_Input ## NAME = 0.5 \ 26 | [[ \ 27 | string page = "Displacement.Float", \ 28 | string label = "Input " #NAME, \ 29 | string help = \ 30 | "A (0,1) ranged value that determines this displacement's pattern. " \ 31 | "Combined with the Position and Magnitude " \ 32 | "(and optionally Mask), " \ 33 | "it determines the location and amount of displacement along the surface normal. " \ 34 | ]], \ 35 | float Displacement_Float_Position ## NAME = 0.0 \ 36 | [[ \ 37 | string page = "Displacement.Float", \ 38 | string label = "Position " #NAME, \ 39 | int slider = 1, float slidermin = -1.0, float slidermax = 1.0, \ 40 | string help = \ 41 | "Position sets the vertical location of this displacement relative to the " \ 42 | "existing surface. This will allow it to produce only peaks, a combination of peaks and valleys, " \ 43 | "or just valleys. " \ 44 | "

" \ 45 | "With a Position of 1, this will result in the Input (0,1) " \ 46 | "values creating displacement only above the current surface. " \ 47 | "

" \ 48 | "A Position of 0 will result in the Input " \ 49 | "values (adjusted to the range -.5,+.5) producing displacement peaks above, and valleys below, " \ 50 | "the current surface. " \ 51 | "

" \ 52 | "A Position of -1 will shift the Input values (to -1,0) " \ 53 | "so they will only create valleys below the current surface. " \ 54 | ]], \ 55 | float Displacement_Float_Magnitude ## NAME = 1.0 \ 56 | [[ \ 57 | string page = "Displacement.Float", \ 58 | string label = "Magnitude " #NAME, \ 59 | int slider = 1, float slidermin = 0.0, float slidermax = 10.0, float slidercenter = 1.0, \ 60 | string help = \ 61 | "The peak-to-valley distance produced by this displacement. " \ 62 | "

" \ 63 | "The assumption is that the Input pattern will range from 0 to 1; " \ 64 | "so this parameter controls the actual displacement amount (in displacement " \ 65 | "Mag Space units). " \ 66 | "

" \ 67 | "Note: you can use a negative value here to invert the Input pattern " \ 68 | "and displacement direction (to -N). " \ 69 | ]], \ 70 | float Displacement_Float_Mask ## NAME = 1.0 \ 71 | [[ \ 72 | string page = "Displacement.Float", \ 73 | string label = "Mask " #NAME, \ 74 | int slider = 1, float slidermin = 0, float slidermax = 1, \ 75 | string help = \ 76 | "Controls how this displacement combines/composites " \ 77 | "with the other Input displacements. " \ 78 | "

" \ 79 | "For example, if you want this displacement to exist only in the peaks " \ 80 | "or valleys of another, you can connect a function of the other displacement's " \ 81 | "Input here. " \ 82 | "

" \ 83 | "Alternatively, Mask values > 1 can be used to accentuate this " \ 84 | "displacement in the desired areas. " \ 85 | "Negative Mask values will invert this displacement. " \ 86 | "

" \ 87 | "Note: Mask values > 1 may result in displacements larger than " \ 88 | "the Magnitude value. " \ 89 | ]] 90 | 91 | 92 | #define DISPLACE_VECTOR_UI_DECLARE(NAME) \ 93 | int Displacement_Vector_On ## NAME = 0 \ 94 | [[ \ 95 | int connectable = 0, \ 96 | string page = "Displacement.Vector", \ 97 | string label = "On " #NAME, \ 98 | string widget = "checkBox", \ 99 | string help = \ 100 | "Turns the use of the Input " #NAME " displacement On or Off. " \ 101 | ]], \ 102 | vector Displacement_Vector_Input ## NAME = vector(0.0) \ 103 | [[ \ 104 | string page = "Displacement.Vector", \ 105 | string label = "Input " #NAME, \ 106 | string help = \ 107 | "A vector value that determines this displacement's direction and amount. " \ 108 | "Typically, vectors have (-1,1) ranged component values. " \ 109 | "Combined with the Mode and Magnitude " \ 110 | "(and optionally Mask), " \ 111 | "it determines how the surface is displaced. " \ 112 | ]], \ 113 | int Displacement_Vector_Mode ## NAME = 1 \ 114 | [[ \ 115 | int connectable = 0, \ 116 | string page = "Displacement.Vector", \ 117 | string label = "Mode " #NAME, \ 118 | string widget = "mapper", \ 119 | string options = "+:1|-:-1|+/-:0", \ 120 | string help = \ 121 | "+ mode displaces in the Input vector direction. " \ 122 | "

" \ 123 | "- mode displaces in the opposite direction (-Input). " \ 124 | "

" \ 125 | "+/- takes an Input vector with (0,1) ranged values " \ 126 | "and remaps them to (-1,+1). " \ 127 | "

" \ 128 | "Note: +/- Mode produces double the displacement range " \ 129 | "of that produced by + or - for the same " \ 130 | "Input data. " \ 131 | ]], \ 132 | float Displacement_Vector_Magnitude ## NAME = 1.0 \ 133 | [[ \ 134 | string page = "Displacement.Vector", \ 135 | string label = "Magnitude " #NAME, \ 136 | int slider = 1, float slidermin = 0.0, float slidermax = 10.0, float slidercenter = 1.0, \ 137 | string help = \ 138 | "The magnitude (vector length scale) of the displacement. " \ 139 | "

" \ 140 | "The assumption is that the Input vector will have a maximum length " \ 141 | "of 1; so this parameter controls the actual displacement amount (in displacement " \ 142 | "Mag Space units). " \ 143 | ]], \ 144 | float Displacement_Vector_Mask ## NAME = 1.0 \ 145 | [[ \ 146 | string page = "Displacement.Vector", \ 147 | string label = "Mask " #NAME, \ 148 | int slider = 1, float slidermin = 0, float slidermax = 1, \ 149 | string help = \ 150 | "Controls how this displacement combines/composites " \ 151 | "with the other Input displacements. " \ 152 | "

" \ 153 | "For example, if you want this displacement to exist only in the peaks " \ 154 | "or valleys of another, you can connect a function of the other displacement's " \ 155 | "Input here. " \ 156 | "

" \ 157 | "Alternatively, Mask values > 1 can be used to accentuate this " \ 158 | "displacement in the desired areas. " \ 159 | "Negative Mask values will invert this displacement. " \ 160 | "

" \ 161 | "Note: Mask magnitudes > 1 may result in displacements larger than " \ 162 | "the Magnitude value. " \ 163 | ]] 164 | 165 | 166 | float displace_float_pattern( 167 | int mode, // 0=Off, 1=On, -1=Invert 168 | float input, 169 | float magnitude, 170 | float mask 171 | ) 172 | { 173 | float result = 0.0; 174 | 175 | if( mode == 1 ) result = input*magnitude*mask; 176 | else if( mode == -1 ) result = ( 1.0-input )*magnitude*mask; 177 | 178 | return result; 179 | } 180 | 181 | float displace_float_amount( 182 | int mode, // 0=Off, 1=On, -1=Invert 183 | float input, 184 | float position, 185 | float magnitude, 186 | float mask 187 | ) 188 | { 189 | float result = 0.0; 190 | 191 | if( mode == 1 ) result = ( input + mix( -0.5, 0.0, position ))*magnitude*mask; 192 | else if( mode == -1 ) result = (( 1.0-input ) + mix( -0.5, 0.0, position ))*magnitude*mask; 193 | 194 | return result; 195 | } 196 | 197 | #define DISPLACE_FLOAT_MAG(NAME) \ 198 | (( Displacement_Float_On ## NAME ) ? abs( Displacement_Float_Magnitude ## NAME ) : 0.0 ) 199 | 200 | #define DISPLACE_FLOAT_PATTERN(NAME) \ 201 | displace_float_pattern( \ 202 | Displacement_Float_On ## NAME, \ 203 | Displacement_Float_Input ## NAME, \ 204 | Displacement_Float_Magnitude ## NAME, \ 205 | Displacement_Float_Mask ## NAME \ 206 | ) 207 | 208 | #define DISPLACE_FLOAT_AMOUNT(NAME) \ 209 | displace_float_amount( \ 210 | Displacement_Float_On ## NAME, \ 211 | Displacement_Float_Input ## NAME, \ 212 | Displacement_Float_Position ## NAME, \ 213 | Displacement_Float_Magnitude ## NAME, \ 214 | Displacement_Float_Mask ## NAME \ 215 | ) 216 | 217 | 218 | // Computes a common space displacement vector with 219 | // the given orientation and directional magnitude. 220 | vector displace_vector( 221 | vector input, 222 | int mode, // -1=Negate, 1=None, 0=Expand 223 | string directionSpace, 224 | string magnitudeSpace, 225 | float magnitude, 226 | float mask 227 | ) 228 | { 229 | vector in = input; 230 | 231 | // Remapping modes. 232 | // in = select( in, mix( vector(-1.0), vector(1.0), in ), mode > 1 ); // Expand. 233 | // in = select( in, -in, mode == 1 || mode == 3 ); // Negate. 234 | if( mode == -1 ) 235 | { 236 | in = -in; 237 | } 238 | else if( mode == 0 ) 239 | { 240 | in = mix( vector(-1.0), vector(1.0), in ); 241 | } 242 | 243 | // Determine the Magnitude Space scale relative to a common space vector. 244 | // Note: must use a vector transform to get the proper orienation, 245 | // and a normal transform to get the proper scale. 246 | normal Vmag = normalize( transform( directionSpace, "common", in )); // vector 247 | float magScale = length( transform( "common", magnitudeSpace, Vmag )); // normal 248 | 249 | // Common space displacement vector with the original vector length. 250 | vector Vdir = Vmag * length( in ); 251 | 252 | // Apply the Magnitude Space scaling, plus the unitless UI controls. 253 | vector result = Vdir * magScale * magnitude * mask; 254 | 255 | // Done. 256 | return result; 257 | } 258 | 259 | 260 | #define DISPLACE_VECTOR_MAG(NAME) \ 261 | (( Displacement_Vector_On ## NAME ) ? length( Displacement_Vector_Input ## NAME ) * Displacement_Vector_Magnitude ## NAME * Displacement_Vector_Mask ## NAME : 0.0 ) 262 | 263 | #define DISPLACE_VECTOR_PATTERN(NAME) \ 264 | (( Displacement_Vector_On ## NAME ) ? 0.5*(dot( N, Displacement_Vector_Input ## NAME )+1.0) * Displacement_Vector_Magnitude ## NAME * Displacement_Vector_Mask ## NAME : 0.0 ) 265 | 266 | #define DISPLACE_VECTOR_AMOUNT(NAME,DIRSPACE,MAGSPACE) ( \ 267 | Displacement_Vector_On ## NAME \ 268 | ? displace_vector( \ 269 | Displacement_Vector_Input ## NAME, \ 270 | Displacement_Vector_Mode ## NAME, \ 271 | DIRSPACE, \ 272 | MAGSPACE, \ 273 | Displacement_Vector_Magnitude ## NAME, \ 274 | Displacement_Vector_Mask ## NAME \ 275 | ) \ 276 | : vector(0.0) \ 277 | ) 278 | 279 | #endif 280 | -------------------------------------------------------------------------------- /osl/material/v2_Displacement.osl: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018-2020 Laika, LLC. Authored by Mitch Prater. 3 | * 4 | * Licensed under the Apache License Version 2.0 http://apache.org/licenses/LICENSE-2.0, 5 | * or the MIT license http://opensource.org/licenses/MIT, at your option. 6 | * 7 | * This program may not be copied, modified, or distributed except according to those terms. 8 | */ 9 | /* 10 | Duplicate material displacement only. 11 | */ 12 | #include "ikaConstants.h" 13 | #include "material/v2_Displacement.h" 14 | #include "material/v2_PxrSurface.h" 15 | 16 | shader v2_Displacement 17 | [[ 18 | int rfm_nodeid = 1234002, 19 | string rfm_classification = "rendernode/RenderMan/pattern/material", 20 | string help = 21 | "Creates a Material layer that has only Displacement. " 22 | "

" 23 | "Note: Displacements will affect other Material " 24 | "layer displacements based on their layer order, Thickness, " 25 | "and Mask values. " 26 | ]] 27 | ( 28 | string Notes = "" 29 | [[ 30 | int connectable = 0, 31 | string help = 32 | "Creates a Material layer that has only Displacement. " 33 | "

" 34 | "Note: Displacements will affect other Material " 35 | "layer displacements based on their layer order, Thickness, " 36 | "and Mask values. " 37 | "

" 38 | ]], 39 | 40 | /* 41 | * The Input Material data set. 42 | * 43 | * This consists of a vstruct parameter, a material struct parameter, and a set 44 | * of enable parameters for each response. The material struct and response enable 45 | * parameters are members of the vstruct parameter. 46 | */ 47 | // The vstruct parameter. This is the single material connection point 48 | // for all the material parameters in the material struct. 49 | PXRSURFACE_MATERIAL_VSTRUCT( MaterialInput, Material Input, 50 | The connected Material Input layers OVER this one: 51 | connect a PxrSurface Material Output here to 52 | layer it OVER this material. 53 | ), 54 | 55 | // The material struct parameter. 56 | PXRSURFACE_MATERIAL_STRUCT( MaterialInput, MatIn ), 57 | 58 | // The response Enable parameters. These are linked to a vstructmember of the vstruct parameter. 59 | ALL_ENABLE_PARAMS( MaterialInput, ClearCoat ), 60 | ALL_ENABLE_PARAMS( MaterialInput, PrimarySpecular ), 61 | ALL_ENABLE_PARAMS( MaterialInput, SecondarySpecular ), 62 | RESPONSE_ENABLE_PARAM( MaterialInput, Iridescence ), 63 | SHADINGNORMAL_ENABLE_PARAM( MaterialInput, Iridescence ), 64 | ANISOTROPYDIRECTION_ENABLE_PARAM( MaterialInput, Iridescence ), 65 | RESPONSE_ENABLE_PARAM( MaterialInput, Fuzz ), 66 | SHADINGNORMAL_ENABLE_PARAM( MaterialInput, Fuzz ), 67 | RESPONSE_ENABLE_PARAM( MaterialInput, Diffuse ), 68 | SHADINGNORMAL_ENABLE_PARAM( MaterialInput, Diffuse ), 69 | RESPONSE_ENABLE_PARAM( MaterialInput, Scatter ), 70 | RESPONSE_ENABLE_PARAM( MaterialInput, Subsurface ), 71 | RESPONSE_ENABLE_PARAM( MaterialInput, Glass ), 72 | SHADINGNORMAL_ENABLE_PARAM( MaterialInput, Glass ), 73 | ANISOTROPYDIRECTION_ENABLE_PARAM( MaterialInput, Glass ), 74 | RESPONSE_ENABLE_PARAM( MaterialInput, Glow ), 75 | 76 | /* 77 | * This material's user interface parameters. 78 | */ 79 | int Enable = 1 80 | [[ 81 | int connectable = 0, 82 | string label = "Enable", 83 | string widget = "checkBox", 84 | string help = 85 | "Turns the computation of this Displacement On/Off. " 86 | ]], 87 | 88 | float Mask = 1.0 89 | [[ 90 | string label = "Mask", 91 | int slider = 1, float slidermin = 0.0, float slidermax = 1.0, 92 | string help = 93 | "This material Mask (a.k.a. Opacity, Alpha, Matte, Presence, etc.) " 94 | "determines the distribution of this material layer: where it is versus where it isn't. " 95 | "Specifically, it controls the blend between this material and the material " 96 | "composited UNDER it. " 97 | ]], 98 | 99 | // 100 | // Displacement parameters start here. 101 | // 102 | float Displacement_Thickness = 0.0 103 | [[ 104 | string page = "Displacement", 105 | string label = "Thickness", 106 | int slider = 1, float slidermin = 0.0, float slidermax = 1.0, 107 | string help = 108 | "Thickness determines the degree to which this material will " 109 | "cover over the displacement of the underlying material (the one connected to " 110 | "Material Output). " 111 | "

" 112 | "When 0, this material has no thickness, so it will be applied directly " 113 | "to, and exactly follow, the underlying material's displaced surface. " 114 | "

" 115 | "When 1, this material is completely 'thick', so it will be applied to the underlying " 116 | "material's smooth Covering Height surface. " 117 | ]], 118 | 119 | float Displacement_BumpPercent = 1.0 120 | [[ 121 | string page = "Displacement", 122 | string label = "Bump Percent", 123 | int slider = 1, float slidermin = 0.0, float slidermax = 2.0, 124 | string help = 125 | "How much of the displaced surface normal is used in shading? " 126 | "

" 127 | "Values greater than 1 accentuate the shading effects of the displacement. " 128 | "

" 129 | "Values less than 1 diminish the shading effects of any displacement. " 130 | "The result of this can be used as a simple substitute for subsurface scattering effects. " 131 | "

" 132 | "Note: any time the shading normal doesn't match the geometry's normal " 133 | "(Bump Percent ≠ 1), there is the possibility " 134 | "of artifacts in the shaded result - particularly when Bump Percent > 1. " 135 | "You've been warned. " 136 | ]], 137 | 138 | float Displacement_CoveringHeight = 0.0 139 | [[ 140 | string page = "Displacement", 141 | string label = "Covering Height", 142 | int slider = 1, float slidermin = 0.0, float slidermax = 5.0, float slidercenter = 0.5, 143 | string help = 144 | "Sets the height (in Mag Space) of a uniformly displaced surface that's " 145 | "produced when this material is completely covered by an overlying material: i.e. when that " 146 | "material's Thickness = 1. " 147 | "

" 148 | "It is the height of a level surface that's intended to cover the peaks of this " 149 | "material's displacement. " 150 | "A good starting number is (0.25 + 0.5*Position)*(Magnitude), or, assuming Position=0, " 151 | "0.25*Magnitude. " 152 | "

" 153 | "If Covering Height is left at 0, the original geometric surface is used. " 154 | ]], 155 | 156 | string Displacement_MagSpace = "world" 157 | [[ 158 | int connectable = 0, 159 | string page = "Displacement", 160 | string label = "Mag Space", 161 | string widget = "popup", int editable = 1, 162 | string options = "common|world|object", 163 | string help = 164 | "Selects the Space in which the Displacement Covering Height " 165 | "and Float and Vector Magnitude units are specified. " 166 | ]], 167 | 168 | float Displacement_MagScale = 1.0 169 | [[ 170 | string page = "Displacement", 171 | string label = "Mag Scale", 172 | int slider = 1, float slidermin = 0.0, float slidermax = 10.0, float slidercenter = 1.0, 173 | string help = 174 | "An overall Scale applied to all the Input Float " 175 | "and Vector Magnitudes. " 176 | ]], 177 | 178 | // Float displacements. 179 | normal Displacement_Float_Nn = normal(0.0) 180 | [[ 181 | string page = "Displacement.Float", 182 | string label = "Nn", 183 | string help = 184 | "Use this common space surface normal for the Float displacement " 185 | "directions. Defaults to the surface normal N if left un-connected. " 186 | "

" 187 | "Note: this must be connected to set it: " 188 | "manually entering values will not work. " 189 | ]], 190 | 191 | DISPLACE_FLOAT_UI_DECLARE(0), 192 | DISPLACE_FLOAT_UI_DECLARE(1), 193 | DISPLACE_FLOAT_UI_DECLARE(2), 194 | DISPLACE_FLOAT_UI_DECLARE(3), 195 | DISPLACE_FLOAT_UI_DECLARE(4), 196 | 197 | // Vector displacements. 198 | string Displacement_Vector_DirSpace = "Mag Space Value" 199 | [[ 200 | int connectable = 0, 201 | string page = "Displacement.Vector", 202 | string label = "Dir Space", 203 | string widget = "popup", int editable = 1, 204 | string options = "Mag Space Value|common|world|object", 205 | string help = 206 | "The coordinate system in which the Vector Input Directions are specified. " 207 | "You may also enter the name of your own coordinate system. " 208 | "

" 209 | "Note: it is assumed the Input vectors have a maximum length of 1. " 210 | "Mag Space and Magnitude therefore determine their " 211 | "amount of displacement. " 212 | "

" 213 | "Dir Space however, specifies their orientation (direction): " 214 | "vector direction and magnitude are separate characteristics. " 215 | ]], 216 | 217 | DISPLACE_VECTOR_UI_DECLARE(0), 218 | DISPLACE_VECTOR_UI_DECLARE(1), 219 | DISPLACE_VECTOR_UI_DECLARE(2), 220 | DISPLACE_VECTOR_UI_DECLARE(3), 221 | DISPLACE_VECTOR_UI_DECLARE(4), 222 | 223 | // Utility socket. 224 | int Socket = 0 225 | [[ 226 | string help = 227 | "Connect a shading node's Plug output here in order to execute that node and " 228 | "any shading tree connected to it. " 229 | ]], 230 | 231 | /* 232 | * The Output Material data set. 233 | * 234 | * This consists of a vstruct parameter, a material struct parameter, and a set 235 | * of enable parameters for each response. The material struct and response enable 236 | * parameters are members of the vstruct parameter. 237 | */ 238 | output PXRSURFACE_MATERIAL_VSTRUCT( MaterialOutput, Material Output, 239 | Connect this to a PxrSurface Material shader's Material Input 240 | to layer this OVER it. 241 |

242 | If this is the last Material in the layer chain connect this to a 243 | PxrSurface_Material node. 244 | ), 245 | 246 | // The struct parameter. 247 | output PXRSURFACE_MATERIAL_STRUCT( MaterialOutput, MatOut ), 248 | 249 | // Set the output vstruct Enable parameters based on the input Enable value and user parameter settings. 250 | SET_ALL_ENABLE_PARAMS( MaterialOutput, MaterialInput, ClearCoat ), 251 | SET_ALL_ENABLE_PARAMS( MaterialOutput, MaterialInput, PrimarySpecular ), 252 | SET_ALL_ENABLE_PARAMS( MaterialOutput, MaterialInput, SecondarySpecular ), 253 | SET_RESPONSE_ENABLE_PARAM( MaterialOutput, MaterialInput, Iridescence ), 254 | SET_SHADINGNORMAL_ENABLE_PARAM( MaterialOutput, MaterialInput, Iridescence ), 255 | SET_ANISOTROPYDIRECTION_ENABLE_PARAM( MaterialOutput, MaterialInput, Iridescence ), 256 | SET_RESPONSE_ENABLE_PARAM( MaterialOutput, MaterialInput, Fuzz ), 257 | SET_SHADINGNORMAL_ENABLE_PARAM( MaterialOutput, MaterialInput, Fuzz ), 258 | SET_RESPONSE_ENABLE_PARAM( MaterialOutput, MaterialInput, Diffuse ), 259 | SET_SHADINGNORMAL_ENABLE_PARAM( MaterialOutput, MaterialInput, Diffuse ), 260 | SET_RESPONSE_ENABLE_PARAM( MaterialOutput, MaterialInput, Scatter ), 261 | SET_RESPONSE_ENABLE_PARAM( MaterialOutput, MaterialInput, Subsurface ), 262 | SET_RESPONSE_ENABLE_PARAM( MaterialOutput, MaterialInput, Glass ), 263 | SET_SHADINGNORMAL_ENABLE_PARAM( MaterialOutput, MaterialInput, Glass ), 264 | SET_ANISOTROPYDIRECTION_ENABLE_PARAM( MaterialOutput, MaterialInput, Glass ), 265 | SET_RESPONSE_ENABLE_PARAM( MaterialOutput, MaterialInput, Glow ), 266 | 267 | // This material's masks, as possibly modified by a pattern ramp. 268 | output float dispMask = 1.0 [[ string widget = "null" ]] 269 | ) 270 | /* 271 | * Material functionality: Output = Input OVER this. 272 | */ 273 | { 274 | // Pull on the Socket to make sure it's evaluated. 275 | MatOut.socket = Socket; 276 | 277 | // Bxdf data is passed through. 278 | MatOut = MatIn; 279 | 280 | // Short-circuit this material. 281 | if( Enable != 0 ) 282 | { 283 | 284 | // Initialize this material's mask values. 285 | dispMask = Mask; // this_dispMask 286 | 287 | 288 | // 289 | // Displacement. 290 | // 291 | vector this_deltaP; 292 | vector this_coverV; 293 | 294 | // The covering height surface offset vector for this material. 295 | // Nmag is common space direction with length relative to Mag Space. 296 | // Note: must use a normal transform to get the proper scale. 297 | normal Nn = normalize(N); 298 | normal Nmag = Nn * length( transform( "common", Displacement_MagSpace, Nn )); // normal 299 | 300 | this_coverV = Nmag * Displacement_CoveringHeight; 301 | 302 | // Float displacements. 303 | if( isconnected( Displacement_Float_Nn )) 304 | { 305 | Nn = Displacement_Float_Nn; 306 | Nmag = Nn * length( transform( "common", Displacement_MagSpace, Nn )); // normal 307 | } 308 | 309 | // Add float displacements to the deltaP displacement vector. 310 | float floatDisp = DISPLACE_FLOAT_AMOUNT(0) 311 | + DISPLACE_FLOAT_AMOUNT(1) 312 | + DISPLACE_FLOAT_AMOUNT(2) 313 | + DISPLACE_FLOAT_AMOUNT(3) 314 | + DISPLACE_FLOAT_AMOUNT(4); 315 | 316 | this_deltaP = Nmag * floatDisp; 317 | 318 | // Vector displacements. 319 | // Magnitude and Direction are handled separately. 320 | string directionSpace = ( Displacement_Vector_DirSpace != "Mag Space Value" ) 321 | ? Displacement_Vector_DirSpace : Displacement_MagSpace; 322 | 323 | // Add vector displacements to the deltaP displacement vector. 324 | vector vectorDisp = DISPLACE_VECTOR_AMOUNT( 0, directionSpace, Displacement_MagSpace ) 325 | + DISPLACE_VECTOR_AMOUNT( 1, directionSpace, Displacement_MagSpace ) 326 | + DISPLACE_VECTOR_AMOUNT( 2, directionSpace, Displacement_MagSpace ) 327 | + DISPLACE_VECTOR_AMOUNT( 3, directionSpace, Displacement_MagSpace ) 328 | + DISPLACE_VECTOR_AMOUNT( 4, directionSpace, Displacement_MagSpace ); 329 | 330 | this_deltaP += vectorDisp; 331 | 332 | // Globally scale the displacement. Displacement_MagScale is unitless. 333 | this_deltaP *= Displacement_MagScale; 334 | 335 | // Pre-multiply by the displacement mask. 336 | this_deltaP *= dispMask; 337 | this_coverV *= dispMask; 338 | 339 | // Note: coverV is not composited. It is only communicated 340 | // with the immediately overlying material layer. 341 | MatOut.coverV = this_coverV; 342 | 343 | // Displacement compositing. 344 | // Note: displacement is NOT Porter-Duff OVER operation composited. 345 | MatOut.deltaP = MatIn.deltaP + mix( 346 | this_deltaP, 347 | this_coverV, 348 | MatIn.thickness 349 | ); 350 | 351 | // Thickness accumulates through all the layers, since layer displacements all accumulate. 352 | // Any overlying layer's thickness will apply to all layers below it, so always pass on the 353 | // largest thickness value. 354 | MatOut.thickness = max( MatIn.thickness, Displacement_Thickness*dispMask ); 355 | 356 | // Handle BumpPercent. Just use dispMask - no need for all the bxdfMask controls. 357 | PARAM_OVER( MatOut, MatIn, Displacement, BumpPercent, dispMask ); 358 | 359 | } 360 | } 361 | -------------------------------------------------------------------------------- /osl/material/v2_PxrSurface.osl: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018-2020 Laika, LLC. Authored by Mitch Prater. 3 | * 4 | * Licensed under the Apache License Version 2.0 http://apache.org/licenses/LICENSE-2.0, 5 | * or the MIT license http://opensource.org/licenses/MIT, at your option. 6 | * 7 | * This program may not be copied, modified, or distributed except according to those terms. 8 | */ 9 | /* 10 | Material: a single node that combines bxdf and displacement controls. 11 | Each material node has a Material Input connection which is composited OVER 12 | this material's parameter settings, and the result is returned in Material Output. 13 | */ 14 | #include "ikaConstants.h" 15 | 16 | #include "material/v2_Displacement.h" 17 | #include "material/v2_PxrSurface.h" 18 | 19 | shader v2_PxrSurface 20 | [[ 21 | int rfm_nodeid = 1234034, 22 | string rfm_classification = "rendernode/RenderMan/pattern/material", 23 | string help = 24 | "A Material " 25 | "defines its response to light, its surface displacement, and its presence. " 26 | "Other materials of the same type can be composited together to produce a single layered material. " 27 | "The composited result is returned as a Material Output. " 28 | "

" 29 | "Note: a material that's connected to this one's Material Input " 30 | "is composited OVER this one. " 31 | "

" 32 | "Material Input
" 33 | "          
" 34 | "  This Material
" 35 | "          
" 36 | "Material Output" 37 | "

" 38 | "The output of the final Material node in the chain is connected to a " 39 | "Material_v2_Shaders Shading Group, which produces a " 40 | "prmanBxdf and a prmanDisplacement output. " 41 | ]] 42 | ( 43 | string Notes = "" 44 | [[ 45 | int connectable = 0, 46 | string help = 47 | "A Material " 48 | "defines its response to light, its surface displacement, and its presence. " 49 | "Other materials of the same type can be composited together to produce a single layered material. " 50 | "The composited result is returned as a Material Output. " 51 | "

" 52 | "Note: a material that's connected to this one's Material Input " 53 | "is composited OVER this one. " 54 | "

" 55 | "Material Input
" 56 | "          
" 57 | "  This Material
" 58 | "          
" 59 | "Material Output" 60 | "

" 61 | "The output of the final Material node in the chain is connected to a " 62 | "Material_v2_Shaders Shading Group, which produces a " 63 | "prmanBxdf and a prmanDisplacement output. " 64 | ]], 65 | 66 | /* 67 | * The Input Material data set. 68 | * 69 | * This consists of a vstruct parameter, a material struct parameter, and a set 70 | * of enable parameters for each response. The material struct and response enable 71 | * parameters are members of the vstruct parameter. 72 | */ 73 | // The vstruct parameter. This is the single material connection point 74 | // for all the material parameters in the material struct. 75 | PXRSURFACE_MATERIAL_VSTRUCT( MaterialInput, Material Input, 76 | The connected Material Input layers OVER this one: 77 | connect a v2_PxrSurface Material Output here to 78 | layer it OVER this material. 79 | ), 80 | 81 | // The material struct parameter. 82 | PXRSURFACE_MATERIAL_STRUCT( MaterialInput, MatIn ), 83 | 84 | // The response Enable parameters. These are linked to a vstructmember of the vstruct parameter. 85 | ALL_ENABLE_PARAMS( MaterialInput, ClearCoat ), 86 | ALL_ENABLE_PARAMS( MaterialInput, PrimarySpecular ), 87 | ALL_ENABLE_PARAMS( MaterialInput, SecondarySpecular ), 88 | RESPONSE_ENABLE_PARAM( MaterialInput, Iridescence ), 89 | SHADINGNORMAL_ENABLE_PARAM( MaterialInput, Iridescence ), 90 | ANISOTROPYDIRECTION_ENABLE_PARAM( MaterialInput, Iridescence ), 91 | RESPONSE_ENABLE_PARAM( MaterialInput, Fuzz ), 92 | SHADINGNORMAL_ENABLE_PARAM( MaterialInput, Fuzz ), 93 | RESPONSE_ENABLE_PARAM( MaterialInput, Diffuse ), 94 | SHADINGNORMAL_ENABLE_PARAM( MaterialInput, Diffuse ), 95 | RESPONSE_ENABLE_PARAM( MaterialInput, Scatter ), 96 | RESPONSE_ENABLE_PARAM( MaterialInput, Subsurface ), 97 | RESPONSE_ENABLE_PARAM( MaterialInput, Glass ), 98 | SHADINGNORMAL_ENABLE_PARAM( MaterialInput, Glass ), 99 | ANISOTROPYDIRECTION_ENABLE_PARAM( MaterialInput, Glass ), 100 | RESPONSE_ENABLE_PARAM( MaterialInput, Glow ), 101 | 102 | /* 103 | * This material's user interface parameters. 104 | */ 105 | int Enable = 1 106 | [[ 107 | int connectable = 0, 108 | string label = "Enable", 109 | string widget = "checkBox", 110 | string help = 111 | "Turns the computation of this Material On/Off. " 112 | "When disabled, this material will not be included in any layered set of materials: its " 113 | "Material Input will be copied directly to its Material Output. " 114 | ]], 115 | 116 | float Mask = 1.0 117 | [[ 118 | string label = "Mask", 119 | int slider = 1, float slidermin = 0.0, float slidermax = 1.0, 120 | string help = 121 | "This material Mask (a.k.a. Opacity, Alpha, Matte, Presence, etc.) " 122 | "determines the distribution of this material layer: where it is versus where it isn't. " 123 | "Specifically, it controls the blend between this material and the material " 124 | "composited UNDER it. " 125 | ]], 126 | 127 | // 128 | // Bxdf parameters start here. 129 | // 130 | normal Global_ShadingNormal = normal( 0.0 ) 131 | [[ 132 | string page = "Global", 133 | string label = "Shading Normal", 134 | string help = 135 | "An alternate shading normal to use for all responses. " 136 | "If an individual response specifies its own shading normal values, " 137 | "they will override these settings. " 138 | ]], 139 | 140 | float Global_UseShadingNormal = 1.0 141 | [[ 142 | string page = "Global", 143 | string label = "Use Shading Normal", 144 | int slider = 1, float slidermin = 0.0, float slidermax = 1.0, 145 | string help = 146 | "How much of the connected Shading Normal is used? " 147 | "This is a mix between the regular (potentially displaced) shading normal N, " 148 | "and the connected Shading Normal value. " 149 | "

" 150 | "Note: this has no effect if the Shading Normal is unconnected. " 151 | ]], 152 | 153 | color Global_ShadowColor = color( 0.0 ) 154 | [[ 155 | string page = "Global", 156 | string label = "Shadow Color", 157 | string help = 158 | "Sets the color of the shadows cast by this material. " 159 | ]], 160 | 161 | color Global_UserColor = color( 0.0 ) 162 | [[ 163 | string page = "Global", 164 | string label = "User Color", 165 | string help = 166 | "User Color is output in LPE user lobe 4: U4 " 167 | ]], 168 | 169 | // Clearcoat response. 170 | CLEARCOAT_UI_DECLARE( Clear Coat, ClearCoat, 171 | Clear Coat represents a clear specular layer applied over all the other 172 | responses. It can be truly clear. Or it can optionally absorb colored light from the layers 173 | below it to tint the overall response. 174 | , ClearCoat_RoughnessUIDefault ), 175 | 176 | // Primary specular response. 177 | SPECULAR_UI_DECLARE( Primary Specular, PrimarySpecular, 178 | Primary Specular is the first of two 'standard' specular responses. 179 | It is capable of producing a broad range of response types from artistic 180 | to physically based and dielectric to metallic. 181 | , PrimarySpecular_RoughnessUIDefault ), 182 | 183 | // Secondary specular response. 184 | SPECULAR_UI_DECLARE( Secondary Specular, SecondarySpecular, 185 | Secondary Specular is the second of two 'standard' specular responses. 186 | It is capable of producing a broad range of response types from artistic 187 | to physically based and dielectric to metallic. 188 | , SecondarySpecular_RoughnessUIDefault ), 189 | 190 | // Iridescence response. 191 | IRIDESCENCE_UI_DECLARE( 192 | Iridescence is a special type of specular response. 193 | It produces the effects of thin-film interference and can be controlled 194 | using Artistic or Physically based controls. 195 | ), 196 | 197 | // Fuzz response. 198 | FUZZ_UI_DECLARE( 199 | Fuzz produces scattering of the illumination in 200 | a boundry layer on the surface. It is implemented as a Marschner 201 | hair primary reflection response (R component) where the hair fibers 202 | are oriented in the direction of the shading normal. 203 | ), 204 | 205 | // Diffuse response. 206 | DIFFUSE_UI_DECLARE( 207 | Diffuse uses an Oren-Nayar response model employing 208 | a Roughness parameter to control the deviation of micro-facet normals. 209 | ), 210 | 211 | // Scatter response. 212 | SCATTER_UI_DECLARE( 213 | Scatter produces (single) scattering through the interior 214 | of an object. It has many controls for altering the physical and artistic 215 | characteristics of the response. 216 | Its main feature is the ability to alter the directionality of the scattering 217 | from forward to backward to isotropic. 218 | ), 219 | 220 | // Subsurface response. 221 | SUBSURFACE_UI_DECLARE( 222 | Subsurface produces multiple scattering through the interior 223 | of an object. It has many controls for altering the physical and artistic 224 | characteristics of the response. 225 | ), 226 | 227 | // Scatter & Subsurface controls. 228 | color ScatterAndSubsurface_IlluminationTint = color( 1.0 ) 229 | [[ 230 | string page = "Scatter And Subsurface", 231 | string label = "Illumination Tint", 232 | string help = 233 | "Tints the incoming illumination prior to being used in the " 234 | "Scatter and Subsurface response computations. " 235 | "In light linear space. " 236 | ]], 237 | 238 | float ScatterAndSubsurface_Roughness = 0.0 239 | [[ 240 | string page = "Scatter And Subsurface", 241 | string label = "Roughness", 242 | int slider = 1, float slidermin = 0.0, float slidermax = 1.0, 243 | string help = 244 | "Controls the diffuse micro-facet surface roughness used in the " 245 | "Scatter and Subsurface response computations. " 246 | "Increasing Roughness causes the rays penetrating into " 247 | "the material to have an increasingly broader range of directions than lower " 248 | "Roughness values. This tends to slightly darken the overall response, " 249 | "as the light is more widely dispersed prior to entering the material. " 250 | ]], 251 | 252 | // Glass response. 253 | GLASS_UI_DECLARE( 254 | Glass produces a physically-based glass that 255 | includes Reflection and Refraction. 256 | It has many controls for altering the physical properties of the glass 257 | including its interior. 258 | ), 259 | 260 | 261 | // Glow response. 262 | EGC_UI_DECLARE( Glow, Glow, 263 | Glow can make an object appear to emit light. 264 |

265 | Note: this is not an efficient way to illuminate a scene and would require 266 | indirect bounces to be at least 2 to be effective. This should instead be 267 | used simply as a shading effect and not for actual lighting. 268 | ), 269 | 270 | // 271 | // Displacement parameters start here. 272 | // 273 | float Displacement_Thickness = 0.0 274 | [[ 275 | string page = "Displacement", 276 | string label = "Thickness", 277 | int slider = 1, float slidermin = 0.0, float slidermax = 1.0, 278 | string help = 279 | "Thickness determines the degree to which this material will " 280 | "cover over the displacement of the underlying material (the one connected to " 281 | "Material Output). " 282 | "

" 283 | "When 0, this material has no thickness, so it will be applied directly " 284 | "to, and exactly follow, the underlying material's displaced surface. " 285 | "

" 286 | "When 1, this material is completely 'thick', so it will be applied to the underlying " 287 | "material's smooth Covering Height surface. " 288 | ]], 289 | 290 | float Displacement_BumpPercent = 1.0 291 | [[ 292 | string page = "Displacement", 293 | string label = "Bump Percent", 294 | int slider = 1, float slidermin = 0.0, float slidermax = 2.0, 295 | string help = 296 | "How much of the displaced surface normal is used in shading? " 297 | "

" 298 | "Values greater than 1 accentuate the shading effects of the displacement. " 299 | "

" 300 | "Values less than 1 diminish the shading effects of any displacement. " 301 | "The result of this can be used as a simple substitute for subsurface scattering effects. " 302 | "

" 303 | "Note: any time the shading normal doesn't match the geometry's normal " 304 | "(Bump Percent ≠ 1), there is the possibility " 305 | "of artifacts in the shaded result - particularly when Bump Percent > 1. " 306 | "You've been warned. " 307 | ]], 308 | 309 | float Displacement_CoveringHeight = 0.0 310 | [[ 311 | string page = "Displacement", 312 | string label = "Covering Height", 313 | int slider = 1, float slidermin = 0.0, float slidermax = 5.0, float slidercenter = 0.5, 314 | string help = 315 | "Sets the height (in Mag Space) of a uniformly displaced surface that's " 316 | "produced when this material is completely covered by an overlying material: i.e. when that " 317 | "material's Thickness = 1. " 318 | "

" 319 | "It is the height of a level surface that's intended to cover the peaks of this " 320 | "material's displacement. " 321 | "A good starting number is (0.25 + 0.5*Position)*(Magnitude), or, assuming Position=0, " 322 | "0.25*Magnitude. " 323 | "

" 324 | "If Covering Height is left at 0, the original geometric surface is used. " 325 | ]], 326 | 327 | string Displacement_MagSpace = "world" 328 | [[ 329 | int connectable = 0, 330 | string page = "Displacement", 331 | string label = "Mag Space", 332 | string widget = "popup", int editable = 1, 333 | string options = "common|world|object", 334 | string help = 335 | "Selects the Space in which the Displacement Covering Height " 336 | "and Float and Vector Magnitude units are specified. " 337 | ]], 338 | 339 | float Displacement_MagScale = 1.0 340 | [[ 341 | string page = "Displacement", 342 | string label = "Mag Scale", 343 | int slider = 1, float slidermin = 0.0, float slidermax = 10.0, float slidercenter = 1.0, 344 | string help = 345 | "An overall Scale applied to all the Input Float " 346 | "and Vector Magnitudes. " 347 | ]], 348 | 349 | // Float displacements. 350 | normal Displacement_Float_Nn = normal(0.0) 351 | [[ 352 | string page = "Displacement.Float", 353 | string label = "Nn", 354 | string help = 355 | "Use this common space surface normal for the Float displacement " 356 | "directions. Defaults to the surface normal N if left un-connected. " 357 | "

" 358 | "Note: this must be connected to set it: " 359 | "manually entering values will not work. " 360 | ]], 361 | 362 | DISPLACE_FLOAT_UI_DECLARE(0), 363 | DISPLACE_FLOAT_UI_DECLARE(1), 364 | DISPLACE_FLOAT_UI_DECLARE(2), 365 | DISPLACE_FLOAT_UI_DECLARE(3), 366 | DISPLACE_FLOAT_UI_DECLARE(4), 367 | 368 | // Vector displacements. 369 | string Displacement_Vector_DirSpace = "Mag Space Value" 370 | [[ 371 | int connectable = 0, 372 | string page = "Displacement.Vector", 373 | string label = "Dir Space", 374 | string widget = "popup", int editable = 1, 375 | string options = "Mag Space Value|common|world|object", 376 | string help = 377 | "The coordinate system in which the Vector Input Directions are specified. " 378 | "You may also enter the name of your own coordinate system. " 379 | "

" 380 | "Note: it is assumed the Input vectors have a maximum length of 1. " 381 | "Mag Space and Magnitude therefore determine their " 382 | "amount of displacement. " 383 | "

" 384 | "Dir Space however, specifies their orientation (direction): " 385 | "vector direction and magnitude are separate characteristics. " 386 | ]], 387 | 388 | DISPLACE_VECTOR_UI_DECLARE(0), 389 | DISPLACE_VECTOR_UI_DECLARE(1), 390 | DISPLACE_VECTOR_UI_DECLARE(2), 391 | DISPLACE_VECTOR_UI_DECLARE(3), 392 | DISPLACE_VECTOR_UI_DECLARE(4), 393 | 394 | // Utility socket. 395 | int Socket = 0 396 | [[ 397 | string help = 398 | "Connect a shading node's Plug output here in order to execute that node and " 399 | "any shading tree connected to it. " 400 | ]], 401 | 402 | /* 403 | * The Output Material data set. 404 | * 405 | * This consists of a vstruct parameter, a material struct parameter, and a set 406 | * of enable parameters for each response. The material struct and response enable 407 | * parameters are members of the vstruct parameter. 408 | */ 409 | output PXRSURFACE_MATERIAL_VSTRUCT( MaterialOutput, Material Output, 410 | Connect this to another v2_PxrSurface material shader's Material Input 411 | to layer this OVER it. 412 |

413 | If this is the last in the material layering chain - connect it to a 414 | v2_PxrSurfaceAdapter node. 415 | ), 416 | 417 | // The struct parameter. 418 | output PXRSURFACE_MATERIAL_STRUCT( MaterialOutput, MatOut ), 419 | 420 | // Set the output vstruct Enable parameters based on the input Enable value and user parameter settings. 421 | SET_ALL_ENABLE_PARAMS( MaterialOutput, MaterialInput, ClearCoat ), 422 | SET_ALL_ENABLE_PARAMS( MaterialOutput, MaterialInput, PrimarySpecular ), 423 | SET_ALL_ENABLE_PARAMS( MaterialOutput, MaterialInput, SecondarySpecular ), 424 | SET_RESPONSE_ENABLE_PARAM( MaterialOutput, MaterialInput, Iridescence ), 425 | SET_SHADINGNORMAL_ENABLE_PARAM( MaterialOutput, MaterialInput, Iridescence ), 426 | SET_ANISOTROPYDIRECTION_ENABLE_PARAM( MaterialOutput, MaterialInput, Iridescence ), 427 | SET_RESPONSE_ENABLE_PARAM( MaterialOutput, MaterialInput, Fuzz ), 428 | SET_SHADINGNORMAL_ENABLE_PARAM( MaterialOutput, MaterialInput, Fuzz ), 429 | SET_RESPONSE_ENABLE_PARAM( MaterialOutput, MaterialInput, Diffuse ), 430 | SET_SHADINGNORMAL_ENABLE_PARAM( MaterialOutput, MaterialInput, Diffuse ), 431 | SET_RESPONSE_ENABLE_PARAM( MaterialOutput, MaterialInput, Scatter ), 432 | SET_RESPONSE_ENABLE_PARAM( MaterialOutput, MaterialInput, Subsurface ), 433 | SET_RESPONSE_ENABLE_PARAM( MaterialOutput, MaterialInput, Glass ), 434 | SET_SHADINGNORMAL_ENABLE_PARAM( MaterialOutput, MaterialInput, Glass ), 435 | SET_ANISOTROPYDIRECTION_ENABLE_PARAM( MaterialOutput, MaterialInput, Glass ), 436 | SET_RESPONSE_ENABLE_PARAM( MaterialOutput, MaterialInput, Glow ) 437 | ) 438 | /* 439 | * Material functionality: Output = Input OVER this. 440 | */ 441 | { 442 | // Pull on the Socket to make sure it's evaluated. 443 | MatOut.socket = Socket; 444 | 445 | // Short-circuit this material. 446 | if( Enable == 0 ) 447 | { 448 | MatOut = MatIn; 449 | } 450 | 451 | // Note: using a return statement in the if case above breaks functionality, 452 | // so must use this else clause. 453 | // My guess is the osl optimizer is mucking with the proper behavior. 454 | else 455 | { 456 | 457 | // Max of all active material Mask values. 458 | MatOut.maxMask = max( Mask, MatIn.maxMask ); 459 | 460 | // Initialize this material's mask values. 461 | float bxdfMask = Mask; // this_bxdfMask 462 | float dispMask = Mask; // this_dispMask 463 | 464 | // 465 | // Displacement. 466 | // 467 | vector this_deltaP; 468 | vector this_coverV; 469 | 470 | // The covering height surface offset vector for this material. 471 | // Nmag is common space direction with length relative to Mag Space. 472 | // Note: must use a normal transform to get the proper scale. 473 | normal Nn = normalize(N); 474 | normal Nmag = Nn * length( transform( "common", Displacement_MagSpace, Nn )); // normal 475 | 476 | this_coverV = Nmag * Displacement_CoveringHeight; 477 | 478 | // Float displacements. 479 | if( isconnected( Displacement_Float_Nn )) 480 | { 481 | Nn = Displacement_Float_Nn; 482 | Nmag = Nn * length( transform( "common", Displacement_MagSpace, Nn )); // normal 483 | } 484 | 485 | // Add float displacements to the deltaP displacement vector. 486 | float floatDisp = DISPLACE_FLOAT_AMOUNT(0) 487 | + DISPLACE_FLOAT_AMOUNT(1) 488 | + DISPLACE_FLOAT_AMOUNT(2) 489 | + DISPLACE_FLOAT_AMOUNT(3) 490 | + DISPLACE_FLOAT_AMOUNT(4); 491 | 492 | this_deltaP = Nmag * floatDisp; 493 | 494 | // Vector displacements. 495 | // Magnitude and Direction are handled separately. 496 | string directionSpace = ( Displacement_Vector_DirSpace != "Mag Space Value" ) 497 | ? Displacement_Vector_DirSpace : Displacement_MagSpace; 498 | 499 | // Add vector displacements to the deltaP displacement vector. 500 | vector vectorDisp = DISPLACE_VECTOR_AMOUNT( 0, directionSpace, Displacement_MagSpace ) 501 | + DISPLACE_VECTOR_AMOUNT( 1, directionSpace, Displacement_MagSpace ) 502 | + DISPLACE_VECTOR_AMOUNT( 2, directionSpace, Displacement_MagSpace ) 503 | + DISPLACE_VECTOR_AMOUNT( 3, directionSpace, Displacement_MagSpace ) 504 | + DISPLACE_VECTOR_AMOUNT( 4, directionSpace, Displacement_MagSpace ); 505 | 506 | this_deltaP += vectorDisp; 507 | 508 | // Globally scale the displacement. Displacement_MagScale is unitless. 509 | this_deltaP *= Displacement_MagScale; 510 | 511 | // Pre-multiply by the displacement mask. 512 | this_deltaP *= dispMask; 513 | this_coverV *= dispMask; 514 | 515 | // Note: coverV is not composited. It is only communicated 516 | // with the immediately overlying material layer. 517 | MatOut.coverV = this_coverV; 518 | 519 | // Displacement compositing. 520 | // Note: displacement is NOT Porter-Duff OVER operation composited. 521 | MatOut.deltaP = MatIn.deltaP + mix( 522 | this_deltaP, 523 | this_coverV, 524 | MatIn.thickness 525 | ); 526 | 527 | // Thickness accumulates through all the layers, since layer displacements all accumulate. 528 | // Any overlying layer's thickness will apply to all layers below it, so always pass on the 529 | // largest thickness value. 530 | MatOut.thickness = max( MatIn.thickness, Displacement_Thickness*dispMask ); 531 | 532 | // Composite the dispMask. 533 | MatOut.dispMask = MatIn.dispMask + dispMask*( 1.0 - MatIn.dispMask ); 534 | 535 | 536 | // 537 | // Bxdf shader parameters start here. 538 | // Note: Gain = 1.0, and Color = Gain*Color. This eliminates false 539 | // colors resulting from interpolating these parameters separately. 540 | // 541 | // Porter-Duff pre-multiplied alpha(mask) compositing OVER operation. 542 | // Out = In over Ui: 543 | // Out = In*In_Mask*1 + Ui*Ui_Mask*(1 - In_Mask) 544 | // Out_Mask = In_Mask*1 + Ui_Mask*(1 - In_Mask) 545 | // 546 | // Composited output mask defines where the input material and this material exist. 547 | MatOut.bxdfMask = MatIn.bxdfMask + bxdfMask*( 1.0 - MatIn.bxdfMask ); 548 | 549 | PARAM_OVER( MatOut, MatIn, Displacement, BumpPercent, bxdfMask ); 550 | PARAM_OVER( MatOut, MatIn, Global, ShadowColor, bxdfMask ); 551 | PARAM_OVER( MatOut, MatIn, Global, UserColor, bxdfMask ); 552 | PARAM_OVER( MatOut, MatIn, Global, ShadingNormal, bxdfMask ); 553 | 554 | // This material's Global_UseShadingNormal value is 0 if its Global_ShadingNormal is not connected. 555 | float useShadingNormal = isconnected( Global_ShadingNormal ) ? Global_UseShadingNormal : 0.0; 556 | MatOut.Global_UseShadingNormal = MatIn.Global_UseShadingNormal 557 | + useShadingNormal*bxdfMask*( 1.0 - MatIn.bxdfMask ); 558 | 559 | // ClearCoat 560 | if( ClearCoat_Enable ) 561 | { 562 | MatOut.ClearCoat_CG = MatIn.ClearCoat_CG 563 | + ( ClearCoat_Gain*ClearCoat_Color*bxdfMask )*( 1.0 - MatIn.bxdfMask ); 564 | 565 | MatOut.ClearCoat_FaceCG = MatIn.ClearCoat_FaceCG 566 | + ( ClearCoat_Gain*ClearCoat_FaceColor*bxdfMask )*( 1.0 - MatIn.bxdfMask ); 567 | 568 | MatOut.ClearCoat_RefractionCI = MatIn.ClearCoat_RefractionCI 569 | + ( ClearCoat_RefractionIndex*ClearCoat_RefractionColor*bxdfMask )*( 1.0 - MatIn.bxdfMask ); 570 | 571 | PARAM_OVER( MatOut, MatIn, ClearCoat, FresnelExponent, bxdfMask ); 572 | PARAM_OVER( MatOut, MatIn, ClearCoat, LayerThickness, bxdfMask ); 573 | PARAM_OVER( MatOut, MatIn, ClearCoat, LayerColor, bxdfMask ); 574 | PARAM_OVER( MatOut, MatIn, ClearCoat, Roughness, bxdfMask ); 575 | PARAM_OVER( MatOut, MatIn, ClearCoat, Anisotropy, bxdfMask ); 576 | PARAM_OVER( MatOut, MatIn, ClearCoat, AnisotropyDirection, bxdfMask ); 577 | PARAM_OVER( MatOut, MatIn, ClearCoat, ShadingNormal, bxdfMask ); 578 | 579 | float useAnisotropyDirection = isconnected( ClearCoat_AnisotropyDirection ) ? 1.0 : 0.0; 580 | MatOut.ClearCoat_UseAnisotropyDirection = MatIn.ClearCoat_UseAnisotropyDirection 581 | + useAnisotropyDirection*bxdfMask*( 1.0 - MatIn.bxdfMask ); 582 | 583 | float useShadingNormal = isconnected( ClearCoat_ShadingNormal ) ? ClearCoat_UseShadingNormal : 0.0; 584 | MatOut.ClearCoat_UseShadingNormal = MatIn.ClearCoat_UseShadingNormal 585 | + useShadingNormal*bxdfMask*( 1.0 - MatIn.bxdfMask ); 586 | } 587 | else 588 | { 589 | CLEARCOAT_COPY( MatOut, MatIn, ClearCoat ); 590 | } 591 | 592 | // PrimarySpecular 593 | if( PrimarySpecular_Enable ) 594 | { 595 | MatOut.PrimarySpecular_CG = MatIn.PrimarySpecular_CG 596 | + ( PrimarySpecular_Gain*PrimarySpecular_Color*bxdfMask )*( 1.0 - MatIn.bxdfMask ); 597 | 598 | MatOut.PrimarySpecular_FaceCG = MatIn.PrimarySpecular_FaceCG 599 | + ( PrimarySpecular_Gain*PrimarySpecular_FaceColor*bxdfMask )*( 1.0 - MatIn.bxdfMask ); 600 | 601 | MatOut.PrimarySpecular_RefractionCI = MatIn.PrimarySpecular_RefractionCI 602 | + ( PrimarySpecular_RefractionIndex*PrimarySpecular_RefractionColor*bxdfMask )*( 1.0 - MatIn.bxdfMask ); 603 | 604 | MatOut.PrimarySpecular_ExtinctionCC = MatIn.PrimarySpecular_ExtinctionCC 605 | + ( PrimarySpecular_ExtinctionCoeff*PrimarySpecular_ExtinctionColor*bxdfMask )*( 1.0 - MatIn.bxdfMask ); 606 | 607 | PARAM_OVER( MatOut, MatIn, PrimarySpecular, FresnelExponent, bxdfMask ); 608 | PARAM_OVER( MatOut, MatIn, PrimarySpecular, Roughness, bxdfMask ); 609 | PARAM_OVER( MatOut, MatIn, PrimarySpecular, Anisotropy, bxdfMask ); 610 | PARAM_OVER( MatOut, MatIn, PrimarySpecular, AnisotropyDirection, bxdfMask ); 611 | PARAM_OVER( MatOut, MatIn, PrimarySpecular, ShadingNormal, bxdfMask ); 612 | 613 | float useAnisotropyDirection = isconnected( PrimarySpecular_AnisotropyDirection ) ? 1.0 : 0.0; 614 | MatOut.PrimarySpecular_UseAnisotropyDirection = MatIn.PrimarySpecular_UseAnisotropyDirection 615 | + useAnisotropyDirection*bxdfMask*( 1.0 - MatIn.bxdfMask ); 616 | 617 | float useShadingNormal = isconnected( PrimarySpecular_ShadingNormal ) ? PrimarySpecular_UseShadingNormal : 0.0; 618 | MatOut.PrimarySpecular_UseShadingNormal = MatIn.PrimarySpecular_UseShadingNormal 619 | + useShadingNormal*bxdfMask*( 1.0 - MatIn.bxdfMask ); 620 | } 621 | else 622 | { 623 | SPECULAR_COPY( MatOut, MatIn, PrimarySpecular ); 624 | } 625 | 626 | // SecondarySpecular 627 | if( SecondarySpecular_Enable ) 628 | { 629 | MatOut.SecondarySpecular_CG = MatIn.SecondarySpecular_CG 630 | + ( SecondarySpecular_Gain*SecondarySpecular_Color*bxdfMask )*( 1.0 - MatIn.bxdfMask ); 631 | 632 | MatOut.SecondarySpecular_FaceCG = MatIn.SecondarySpecular_FaceCG 633 | + ( SecondarySpecular_Gain*SecondarySpecular_FaceColor*bxdfMask )*( 1.0 - MatIn.bxdfMask ); 634 | 635 | MatOut.SecondarySpecular_RefractionCI = MatIn.SecondarySpecular_RefractionCI 636 | + ( SecondarySpecular_RefractionIndex*SecondarySpecular_RefractionColor*bxdfMask )*( 1.0 - MatIn.bxdfMask ); 637 | 638 | MatOut.SecondarySpecular_ExtinctionCC = MatIn.SecondarySpecular_ExtinctionCC 639 | + ( SecondarySpecular_ExtinctionCoeff*SecondarySpecular_ExtinctionColor*bxdfMask )*( 1.0 - MatIn.bxdfMask ); 640 | 641 | PARAM_OVER( MatOut, MatIn, SecondarySpecular, FresnelExponent, bxdfMask ); 642 | PARAM_OVER( MatOut, MatIn, SecondarySpecular, Roughness, bxdfMask ); 643 | PARAM_OVER( MatOut, MatIn, SecondarySpecular, Anisotropy, bxdfMask ); 644 | PARAM_OVER( MatOut, MatIn, SecondarySpecular, AnisotropyDirection, bxdfMask ); 645 | PARAM_OVER( MatOut, MatIn, SecondarySpecular, ShadingNormal, bxdfMask ); 646 | 647 | float useAnisotropyDirection = isconnected( SecondarySpecular_AnisotropyDirection ) ? 1.0 : 0.0; 648 | MatOut.SecondarySpecular_UseAnisotropyDirection = MatIn.SecondarySpecular_UseAnisotropyDirection 649 | + useAnisotropyDirection*bxdfMask*( 1.0 - MatIn.bxdfMask ); 650 | 651 | float useShadingNormal = isconnected( SecondarySpecular_ShadingNormal ) ? SecondarySpecular_UseShadingNormal : 0.0; 652 | MatOut.SecondarySpecular_UseShadingNormal = MatIn.SecondarySpecular_UseShadingNormal 653 | + useShadingNormal*bxdfMask*( 1.0 - MatIn.bxdfMask ); 654 | } 655 | else 656 | { 657 | SPECULAR_COPY( MatOut, MatIn, SecondarySpecular ); 658 | } 659 | 660 | // Iridescence 661 | if( Iridescence_Enable ) 662 | { 663 | PARAM_OVER( MatOut, MatIn, Iridescence, Gain, bxdfMask ); 664 | PARAM_OVER( MatOut, MatIn, Iridescence, FaceColor, bxdfMask ); 665 | PARAM_OVER( MatOut, MatIn, Iridescence, EdgeColor, bxdfMask ); 666 | PARAM_OVER( MatOut, MatIn, Iridescence, Exponent, bxdfMask ); 667 | PARAM_OVER( MatOut, MatIn, Iridescence, Repetitions, bxdfMask ); 668 | PARAM_OVER( MatOut, MatIn, Iridescence, Thickness, bxdfMask ); 669 | PARAM_OVER( MatOut, MatIn, Iridescence, Roughness, bxdfMask ); 670 | PARAM_OVER( MatOut, MatIn, Iridescence, Anisotropy, bxdfMask ); 671 | PARAM_OVER( MatOut, MatIn, Iridescence, AnisotropyDirection, bxdfMask ); 672 | PARAM_OVER( MatOut, MatIn, Iridescence, ShadingNormal, bxdfMask ); 673 | 674 | float useAnisotropyDirection = isconnected( Iridescence_AnisotropyDirection ) ? 1.0 : 0.0; 675 | MatOut.Iridescence_UseAnisotropyDirection = MatIn.Iridescence_UseAnisotropyDirection 676 | + useAnisotropyDirection*bxdfMask*( 1.0 - MatIn.bxdfMask ); 677 | 678 | float useShadingNormal = isconnected( Iridescence_ShadingNormal ) ? Iridescence_UseShadingNormal : 0.0; 679 | MatOut.Iridescence_UseShadingNormal = MatIn.Iridescence_UseShadingNormal 680 | + useShadingNormal*bxdfMask*( 1.0 - MatIn.bxdfMask ); 681 | } 682 | else 683 | { 684 | IRIDESCENCE_COPY( MatOut, MatIn, Iridescence ); 685 | } 686 | 687 | // Fuzz 688 | if( Fuzz_Enable ) 689 | { 690 | MatOut.Fuzz_CG = MatIn.Fuzz_CG 691 | + ( Fuzz_Gain*Fuzz_Color*bxdfMask )*( 1.0 - MatIn.bxdfMask ); 692 | 693 | PARAM_OVER( MatOut, MatIn, Fuzz, ConeAngle, bxdfMask ); 694 | PARAM_OVER( MatOut, MatIn, Fuzz, ShadingNormal, bxdfMask ); 695 | 696 | float useShadingNormal = isconnected( Fuzz_ShadingNormal ) ? Fuzz_UseShadingNormal : 0.0; 697 | MatOut.Fuzz_UseShadingNormal = MatIn.Fuzz_UseShadingNormal 698 | + useShadingNormal*bxdfMask*( 1.0 - MatIn.bxdfMask ); 699 | } 700 | else 701 | { 702 | FUZZ_COPY( MatOut, MatIn, Fuzz ); 703 | } 704 | 705 | // Diffuse 706 | if( Diffuse_Enable ) 707 | { 708 | MatOut.Diffuse_CG = MatIn.Diffuse_CG 709 | + ( Diffuse_Gain*Diffuse_Color*bxdfMask )*( 1.0 - MatIn.bxdfMask ); 710 | 711 | MatOut.Diffuse_BackfaceCG = MatIn.Diffuse_BackfaceCG 712 | + ( Diffuse_BackfaceGain*Diffuse_BackfaceColor*bxdfMask )*( 1.0 - MatIn.bxdfMask ); 713 | 714 | MatOut.Diffuse_TransmitCG = MatIn.Diffuse_TransmitCG 715 | + ( Diffuse_TransmitGain*Diffuse_TransmitColor*bxdfMask )*( 1.0 - MatIn.bxdfMask ); 716 | 717 | PARAM_OVER( MatOut, MatIn, Diffuse, Roughness, bxdfMask ); 718 | PARAM_OVER( MatOut, MatIn, Diffuse, Exponent, bxdfMask ); 719 | PARAM_OVER( MatOut, MatIn, Diffuse, ShadingNormal, bxdfMask ); 720 | 721 | float useShadingNormal = isconnected( Diffuse_ShadingNormal ) ? Diffuse_UseShadingNormal : 0.0; 722 | MatOut.Diffuse_UseShadingNormal = MatIn.Diffuse_UseShadingNormal 723 | + useShadingNormal*bxdfMask*( 1.0 - MatIn.bxdfMask ); 724 | } 725 | else 726 | { 727 | DIFFUSE_COPY( MatOut, MatIn, Diffuse ); 728 | } 729 | 730 | // Scatter 731 | if( Scatter_Enable ) 732 | { 733 | MatOut.Scatter_CG = MatIn.Scatter_CG 734 | + ( Scatter_Gain*Scatter_Color*bxdfMask )*( 1.0 - MatIn.bxdfMask ); 735 | 736 | // Backside_CG = (Backside) IlluminationGain * (Backside) IlluminationTint 737 | MatOut.Scatter_BacksideCG = MatIn.Scatter_BacksideCG 738 | + ( Scatter_IlluminationGain*Scatter_IlluminationTint*bxdfMask )*( 1.0 - MatIn.bxdfMask ); 739 | 740 | PARAM_OVER( MatOut, MatIn, Scatter, PathLength, bxdfMask ); 741 | PARAM_OVER( MatOut, MatIn, Scatter, PathColor, bxdfMask ); 742 | PARAM_OVER( MatOut, MatIn, Scatter, Direction, bxdfMask ); 743 | PARAM_OVER( MatOut, MatIn, Scatter, Roughness, bxdfMask ); 744 | PARAM_OVER( MatOut, MatIn, Scatter, RefractionIndex, bxdfMask ); 745 | } 746 | else 747 | { 748 | SCATTER_COPY( MatOut, MatIn, Scatter ); 749 | } 750 | 751 | // Subsurface 752 | if( Subsurface_Enable ) 753 | { 754 | PARAM_OVER( MatOut, MatIn, Subsurface, Gain, bxdfMask ); 755 | PARAM_OVER( MatOut, MatIn, Subsurface, Color, bxdfMask ); 756 | PARAM_OVER( MatOut, MatIn, Subsurface, PathLength, bxdfMask ); 757 | PARAM_OVER( MatOut, MatIn, Subsurface, PathColor, bxdfMask ); 758 | PARAM_OVER( MatOut, MatIn, Subsurface, PostTint, bxdfMask ); 759 | PARAM_OVER( MatOut, MatIn, Subsurface, TransmitGain, bxdfMask ); 760 | PARAM_OVER( MatOut, MatIn, Subsurface, ShortGain, bxdfMask ); 761 | PARAM_OVER( MatOut, MatIn, Subsurface, ShortColor, bxdfMask ); 762 | PARAM_OVER( MatOut, MatIn, Subsurface, ShortLength, bxdfMask ); 763 | PARAM_OVER( MatOut, MatIn, Subsurface, LongGain, bxdfMask ); 764 | PARAM_OVER( MatOut, MatIn, Subsurface, LongColor, bxdfMask ); 765 | PARAM_OVER( MatOut, MatIn, Subsurface, LongLength, bxdfMask ); 766 | PARAM_OVER( MatOut, MatIn, Subsurface, Directionality, bxdfMask ); 767 | // XXX PARAM_OVER( MatOut, MatIn, Subsurface, DiffuseBlend, bxdfMask ); 768 | PARAM_OVER( MatOut, MatIn, Subsurface, Bleed, bxdfMask ); 769 | } 770 | else 771 | { 772 | SUBSURFACE_COPY( MatOut, MatIn, Subsurface ); 773 | } 774 | 775 | // Scatter & Subsurface 776 | if( Scatter_Enable || Subsurface_Enable ) 777 | { 778 | PARAM_OVER( MatOut, MatIn, ScatterAndSubsurface, IlluminationTint, bxdfMask ); 779 | PARAM_OVER( MatOut, MatIn, ScatterAndSubsurface, Roughness, bxdfMask ); 780 | } 781 | else 782 | { 783 | MatOut.ScatterAndSubsurface_IlluminationTint = MatIn.ScatterAndSubsurface_IlluminationTint; 784 | MatOut.ScatterAndSubsurface_Roughness = MatIn.ScatterAndSubsurface_Roughness; 785 | } 786 | 787 | // Glass 788 | if( Glass_Enable ) 789 | { 790 | PARAM_OVER( MatOut, MatIn, Glass, ReflectionGain, bxdfMask ); 791 | PARAM_OVER( MatOut, MatIn, Glass, Roughness, bxdfMask ); 792 | PARAM_OVER( MatOut, MatIn, Glass, Anisotropy, bxdfMask ); 793 | PARAM_OVER( MatOut, MatIn, Glass, AnisotropyDirection, bxdfMask ); 794 | PARAM_OVER( MatOut, MatIn, Glass, ShadingNormal, bxdfMask ); 795 | 796 | float useAnisotropyDirection = isconnected( Glass_AnisotropyDirection ) ? 1.0 : 0.0; 797 | MatOut.Glass_UseAnisotropyDirection = MatIn.Glass_UseAnisotropyDirection 798 | + useAnisotropyDirection*bxdfMask*( 1.0 - MatIn.bxdfMask ); 799 | 800 | float useShadingNormal = isconnected( Glass_ShadingNormal ) ? Glass_UseShadingNormal : 0.0; 801 | MatOut.Glass_UseShadingNormal = MatIn.Glass_UseShadingNormal 802 | + useShadingNormal*bxdfMask*( 1.0 - MatIn.bxdfMask ); 803 | 804 | // Refraction. 805 | MatOut.Glass_RefractionCG = MatIn.Glass_RefractionCG 806 | + ( Glass_RefractionGain*Glass_RefractionColor*bxdfMask )*( 1.0 - MatIn.bxdfMask ); 807 | 808 | MatOut.Glass_ExtinctionCC = MatIn.Glass_ExtinctionCC 809 | + ( Glass_ExtinctionCoeff*Glass_ExtinctionColor*bxdfMask )*( 1.0 - MatIn.bxdfMask ); 810 | 811 | PARAM_OVER( MatOut, MatIn, Glass, RefractionIndex, bxdfMask ); 812 | PARAM_OVER( MatOut, MatIn, Glass, ScatterColor, bxdfMask ); 813 | PARAM_OVER( MatOut, MatIn, Glass, ManifoldExplorationIOR, bxdfMask ); 814 | } 815 | else 816 | { 817 | GLASS_COPY( MatOut, MatIn, Glass ); 818 | } 819 | 820 | // Glow 821 | if( Glow_Enable ) 822 | { 823 | MatOut.Glow_CG = MatIn.Glow_CG 824 | + ( Glow_Gain*Glow_Color*bxdfMask )*( 1.0 - MatIn.bxdfMask ); 825 | } 826 | else 827 | { 828 | GLOW_COPY( MatOut, MatIn, Glow ); 829 | } 830 | 831 | // This bxdfMask is only where this material is. 832 | bxdfMask = bxdfMask*( 1.0 - MatIn.bxdfMask ); 833 | 834 | } 835 | } 836 | -------------------------------------------------------------------------------- /osl/material/v2_PxrSurfaceAdapter.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018-2020 Laika, LLC. Authored by Mitch Prater. 3 | * 4 | * Licensed under the Apache License Version 2.0 http://apache.org/licenses/LICENSE-2.0, 5 | * or the MIT license http://opensource.org/licenses/MIT, at your option. 6 | * 7 | * This program may not be copied, modified, or distributed except according to those terms. 8 | */ 9 | /* 10 | Defines the vstruct connection made with the PxrSurface bxdf. 11 | */ 12 | #ifndef MATERIAL_V2_PXRSURFACEADAPTOR_H 13 | #define MATERIAL_V2_PXRSURFACEADAPTOR_H 14 | 15 | #include "material/v2_PxrSurface.h" 16 | 17 | 18 | // 19 | // Copy input struct member to the corresponding output parameter. 20 | // 21 | #define COPY_PARAM(VSTRUCTIN,PREFIX,NAME) \ 22 | PREFIX##_##NAME = VSTRUCTIN.PREFIX##_##NAME 23 | 24 | /************************************************************************************************** 25 | * vstruct Output Parameters 26 | **************************************************************************************************/ 27 | 28 | // 29 | // These macros examine the vstruct Enable parameters to determine what is connected 30 | // to the bxdf node. 31 | // 32 | #define PARAM_OUTPUT(VSTRUCTIN,VSTRUCTOUT,PREFIX,TYPE,PARAM,VSTRUCTMEMBER) \ 33 | output TYPE PREFIX##_##PARAM = TYPE(0.0) \ 34 | [[ \ 35 | string widget = "null", \ 36 | string vstructmember = #VSTRUCTOUT "." #VSTRUCTMEMBER, \ 37 | string vstructConditionalExpr = "connect if " #VSTRUCTIN "_" #PREFIX "_Enable == 1" \ 38 | ]] 39 | 40 | #define PARAM_OUTPUT_ENABLE(VSTRUCTIN,VSTRUCTOUT,PREFIX,TYPE,PARAM,VSTRUCTMEMBER) \ 41 | output TYPE PREFIX##_##PARAM = TYPE(0.0) \ 42 | [[ \ 43 | string widget = "null", \ 44 | string vstructmember = #VSTRUCTOUT "." #VSTRUCTMEMBER, \ 45 | string vstructConditionalExpr = "connect if " #VSTRUCTIN "_" #PREFIX "_" #PARAM "_Enable == 1" \ 46 | ]] 47 | 48 | // 49 | // Gain parameters are set to 1 or 0 depending on whether the response is enabled or not. 50 | // Their corresponding color value is used to control the actual response intensity. 51 | // This is done to avoid hue aliasing when two material layers are blended and one has 52 | // a low gain value. 53 | // 54 | #define PARAM_OUTPUT_SET_GAIN(VSTRUCTIN,VSTRUCTOUT,PREFIX,PARAM,VSTRUCTMEMBER) \ 55 | output float PREFIX##_##PARAM = 0.0 \ 56 | [[ \ 57 | string widget = "null", \ 58 | string vstructmember = #VSTRUCTOUT "." #VSTRUCTMEMBER, \ 59 | string vstructConditionalExpr = "set 1.0 if " #VSTRUCTIN "_" #PREFIX "_Enable == 1 else set 0.0" \ 60 | ]] 61 | 62 | 63 | #define CLEARCOAT_OUTPUT_PARAMS(VSTRUCTIN,VSTRUCTOUT,PREFIX) \ 64 | PARAM_OUTPUT( VSTRUCTIN, VSTRUCTOUT, PREFIX, color, CG, clearcoatEdgeColor ), \ 65 | PARAM_OUTPUT( VSTRUCTIN, VSTRUCTOUT, PREFIX, color, FaceCG, clearcoatFaceColor ), \ 66 | PARAM_OUTPUT( VSTRUCTIN, VSTRUCTOUT, PREFIX, float, FresnelExponent, clearcoatFresnelShape ), \ 67 | PARAM_OUTPUT( VSTRUCTIN, VSTRUCTOUT, PREFIX, color, RefractionCI, clearcoatIor ), \ 68 | PARAM_OUTPUT( VSTRUCTIN, VSTRUCTOUT, PREFIX, float, LayerThickness, clearcoatThickness ), \ 69 | PARAM_OUTPUT( VSTRUCTIN, VSTRUCTOUT, PREFIX, color, LayerColor, clearcoatAborptionTint ), \ 70 | PARAM_OUTPUT( VSTRUCTIN, VSTRUCTOUT, PREFIX, float, Roughness, clearcoatRoughness ), \ 71 | PARAM_OUTPUT( VSTRUCTIN, VSTRUCTOUT, PREFIX, float, Anisotropy, clearcoatAnisotropy ), \ 72 | PARAM_OUTPUT_ENABLE( VSTRUCTIN, VSTRUCTOUT, PREFIX, normal, ShadingNormal, clearcoatBumpNormal ), \ 73 | PARAM_OUTPUT_ENABLE( VSTRUCTIN, VSTRUCTOUT, PREFIX, vector, AnisotropyDirection, clearcoatAnisotropyDirection ) 74 | 75 | #define PRIMARYSPECULAR_OUTPUT_PARAMS(VSTRUCTIN,VSTRUCTOUT,PREFIX) \ 76 | PARAM_OUTPUT( VSTRUCTIN, VSTRUCTOUT, PREFIX, color, CG, specularEdgeColor ), \ 77 | PARAM_OUTPUT( VSTRUCTIN, VSTRUCTOUT, PREFIX, color, FaceCG, specularFaceColor ), \ 78 | PARAM_OUTPUT( VSTRUCTIN, VSTRUCTOUT, PREFIX, float, FresnelExponent, specularFresnelShape ), \ 79 | PARAM_OUTPUT( VSTRUCTIN, VSTRUCTOUT, PREFIX, color, RefractionCI, specularIor ), \ 80 | PARAM_OUTPUT( VSTRUCTIN, VSTRUCTOUT, PREFIX, color, ExtinctionCC, specularExtinctionCoeff ), \ 81 | PARAM_OUTPUT( VSTRUCTIN, VSTRUCTOUT, PREFIX, float, Roughness, specularRoughness ), \ 82 | PARAM_OUTPUT( VSTRUCTIN, VSTRUCTOUT, PREFIX, float, Anisotropy, specularAnisotropy ), \ 83 | PARAM_OUTPUT_ENABLE( VSTRUCTIN, VSTRUCTOUT, PREFIX, normal, ShadingNormal, specularBumpNormal ), \ 84 | PARAM_OUTPUT_ENABLE( VSTRUCTIN, VSTRUCTOUT, PREFIX, vector, AnisotropyDirection, specularAnisotropyDirection ) 85 | 86 | #define SECONDARYSPECULAR_OUTPUT_PARAMS(VSTRUCTIN,VSTRUCTOUT,PREFIX) \ 87 | PARAM_OUTPUT( VSTRUCTIN, VSTRUCTOUT, PREFIX, color, CG, roughSpecularEdgeColor ), \ 88 | PARAM_OUTPUT( VSTRUCTIN, VSTRUCTOUT, PREFIX, color, FaceCG, roughSpecularFaceColor ), \ 89 | PARAM_OUTPUT( VSTRUCTIN, VSTRUCTOUT, PREFIX, float, FresnelExponent, roughSpecularFresnelShape ), \ 90 | PARAM_OUTPUT( VSTRUCTIN, VSTRUCTOUT, PREFIX, color, RefractionCI, roughSpecularIor ), \ 91 | PARAM_OUTPUT( VSTRUCTIN, VSTRUCTOUT, PREFIX, color, ExtinctionCC, roughSpecularExtinctionCoeff ), \ 92 | PARAM_OUTPUT( VSTRUCTIN, VSTRUCTOUT, PREFIX, float, Roughness, roughSpecularRoughness ), \ 93 | PARAM_OUTPUT( VSTRUCTIN, VSTRUCTOUT, PREFIX, float, Anisotropy, roughSpecularAnisotropy ), \ 94 | PARAM_OUTPUT_ENABLE( VSTRUCTIN, VSTRUCTOUT, PREFIX, normal, ShadingNormal, roughSpecularBumpNormal ), \ 95 | PARAM_OUTPUT_ENABLE( VSTRUCTIN, VSTRUCTOUT, PREFIX, vector, AnisotropyDirection, roughSpecularAnisotropyDirection ) 96 | 97 | #define IRIDESCENCE_OUTPUT_PARAMS(VSTRUCTIN,VSTRUCTOUT,PREFIX) \ 98 | PARAM_OUTPUT( VSTRUCTIN, VSTRUCTOUT, PREFIX, float, FaceGain, iridescenceFaceGain ), \ 99 | PARAM_OUTPUT( VSTRUCTIN, VSTRUCTOUT, PREFIX, float, EdgeGain, iridescenceEdgeGain ), \ 100 | PARAM_OUTPUT( VSTRUCTIN, VSTRUCTOUT, PREFIX, color, FaceColor, iridescencePrimaryColor ), \ 101 | PARAM_OUTPUT( VSTRUCTIN, VSTRUCTOUT, PREFIX, color, EdgeColor, iridescenceSecondaryColor ), \ 102 | PARAM_OUTPUT( VSTRUCTIN, VSTRUCTOUT, PREFIX, float, Exponent, iridescenceCurve ), \ 103 | PARAM_OUTPUT( VSTRUCTIN, VSTRUCTOUT, PREFIX, float, Repetitions, iridescenceScale ), \ 104 | PARAM_OUTPUT( VSTRUCTIN, VSTRUCTOUT, PREFIX, float, Thickness, iridescenceThickness ), \ 105 | PARAM_OUTPUT( VSTRUCTIN, VSTRUCTOUT, PREFIX, float, Roughness, iridescenceRoughness ), \ 106 | PARAM_OUTPUT( VSTRUCTIN, VSTRUCTOUT, PREFIX, float, Anisotropy, iridescenceAnisotropy ), \ 107 | PARAM_OUTPUT_ENABLE( VSTRUCTIN, VSTRUCTOUT, PREFIX, normal, ShadingNormal, iridescenceBumpNormal ), \ 108 | PARAM_OUTPUT_ENABLE( VSTRUCTIN, VSTRUCTOUT, PREFIX, vector, AnisotropyDirection, iridescenceAnisotropyDirection ) 109 | 110 | #define FUZZ_OUTPUT_PARAMS(VSTRUCTIN,VSTRUCTOUT,PREFIX) \ 111 | PARAM_OUTPUT_SET_GAIN( VSTRUCTIN, VSTRUCTOUT, PREFIX, Gain, fuzzGain ), \ 112 | PARAM_OUTPUT( VSTRUCTIN, VSTRUCTOUT, PREFIX, color, CG, fuzzColor ), \ 113 | PARAM_OUTPUT( VSTRUCTIN, VSTRUCTOUT, PREFIX, float, ConeAngle, fuzzConeAngle ), \ 114 | PARAM_OUTPUT_ENABLE( VSTRUCTIN, VSTRUCTOUT, PREFIX, normal, ShadingNormal, fuzzBumpNormal ) 115 | 116 | #define DIFFUSE_OUTPUT_PARAMS(VSTRUCTIN,VSTRUCTOUT,PREFIX) \ 117 | PARAM_OUTPUT_SET_GAIN( VSTRUCTIN, VSTRUCTOUT, PREFIX, Gain, diffuseGain ), \ 118 | PARAM_OUTPUT_SET_GAIN( VSTRUCTIN, VSTRUCTOUT, PREFIX, TransmitGain, diffuseTransmitGain ), \ 119 | PARAM_OUTPUT_ENABLE( VSTRUCTIN, VSTRUCTOUT, PREFIX, normal, ShadingNormal, diffuseBumpNormal ), \ 120 | PARAM_OUTPUT( VSTRUCTIN, VSTRUCTOUT, PREFIX, color, CG, diffuseColor ), \ 121 | PARAM_OUTPUT( VSTRUCTIN, VSTRUCTOUT, PREFIX, float, Roughness, diffuseRoughness ), \ 122 | PARAM_OUTPUT( VSTRUCTIN, VSTRUCTOUT, PREFIX, float, Exponent, diffuseExponent ), \ 123 | PARAM_OUTPUT( VSTRUCTIN, VSTRUCTOUT, PREFIX, color, BackfaceCG, diffuseBackColor ), \ 124 | PARAM_OUTPUT( VSTRUCTIN, VSTRUCTOUT, PREFIX, color, TransmitCG, diffuseTransmitColor ) 125 | 126 | #define SCATTER_OUTPUT_PARAMS(VSTRUCTIN,VSTRUCTOUT,PREFIX) \ 127 | PARAM_OUTPUT_SET_GAIN( VSTRUCTIN, VSTRUCTOUT, PREFIX, Gain, singlescatterGain ), \ 128 | PARAM_OUTPUT_SET_GAIN( VSTRUCTIN, VSTRUCTOUT, PREFIX, DirectGain, singlescatterDirectGain ), \ 129 | PARAM_OUTPUT( VSTRUCTIN, VSTRUCTOUT, PREFIX, color, CG, singlescatterColor ), \ 130 | PARAM_OUTPUT( VSTRUCTIN, VSTRUCTOUT, PREFIX, float, PathLength, singlescatterMfp ), \ 131 | PARAM_OUTPUT( VSTRUCTIN, VSTRUCTOUT, PREFIX, color, PathColor, singlescatterMfpColor ), \ 132 | PARAM_OUTPUT( VSTRUCTIN, VSTRUCTOUT, PREFIX, float, Direction, singlescatterDirectionality ), \ 133 | PARAM_OUTPUT( VSTRUCTIN, VSTRUCTOUT, PREFIX, float, Roughness, singlescatterBlur ), \ 134 | PARAM_OUTPUT( VSTRUCTIN, VSTRUCTOUT, PREFIX, float, RefractionIndex, singlescatterIor ), \ 135 | PARAM_OUTPUT( VSTRUCTIN, VSTRUCTOUT, PREFIX, color, BacksideCG, singlescatterDirectGainTint ) 136 | 137 | #define SUBSURFACE_OUTPUT_PARAMS(VSTRUCTIN,VSTRUCTOUT,PREFIX) \ 138 | PARAM_OUTPUT( VSTRUCTIN, VSTRUCTOUT, PREFIX, float, Gain, subsurfaceGain ), \ 139 | PARAM_OUTPUT( VSTRUCTIN, VSTRUCTOUT, PREFIX, color, Color, subsurfaceColor ), \ 140 | PARAM_OUTPUT( VSTRUCTIN, VSTRUCTOUT, PREFIX, float, PathLength, subsurfaceDmfp ), \ 141 | PARAM_OUTPUT( VSTRUCTIN, VSTRUCTOUT, PREFIX, color, PathColor, subsurfaceDmfpColor ), \ 142 | PARAM_OUTPUT( VSTRUCTIN, VSTRUCTOUT, PREFIX, color, PostTint, subsurfacePostTint ), \ 143 | PARAM_OUTPUT( VSTRUCTIN, VSTRUCTOUT, PREFIX, float, TransmitGain, subsurfaceTransmitGain ), \ 144 | PARAM_OUTPUT( VSTRUCTIN, VSTRUCTOUT, PREFIX, float, ShortGain, shortSubsurfaceGain ), \ 145 | PARAM_OUTPUT( VSTRUCTIN, VSTRUCTOUT, PREFIX, color, ShortColor, shortSubsurfaceColor ), \ 146 | PARAM_OUTPUT( VSTRUCTIN, VSTRUCTOUT, PREFIX, float, ShortLength, shortSubsurfaceDmfp ), \ 147 | PARAM_OUTPUT( VSTRUCTIN, VSTRUCTOUT, PREFIX, float, LongGain, longSubsurfaceGain ), \ 148 | PARAM_OUTPUT( VSTRUCTIN, VSTRUCTOUT, PREFIX, color, LongColor, longSubsurfaceColor ), \ 149 | PARAM_OUTPUT( VSTRUCTIN, VSTRUCTOUT, PREFIX, float, LongLength, longSubsurfaceDmfp ), \ 150 | PARAM_OUTPUT( VSTRUCTIN, VSTRUCTOUT, PREFIX, float, Directionality, subsurfaceDirectionality ), \ 151 | /* XXX Not Really Connectable! PARAM_OUTPUT( VSTRUCTIN, VSTRUCTOUT, PREFIX, float, DiffuseBlend, subsurfaceDiffuseBlend ), */ \ 152 | PARAM_OUTPUT( VSTRUCTIN, VSTRUCTOUT, PREFIX, float, Bleed, subsurfaceBleed ) 153 | 154 | #define GLASS_OUTPUT_PARAMS(VSTRUCTIN,VSTRUCTOUT,PREFIX) \ 155 | PARAM_OUTPUT_SET_GAIN( VSTRUCTIN, VSTRUCTOUT, PREFIX, Gain, refractionGain ), \ 156 | PARAM_OUTPUT( VSTRUCTIN, VSTRUCTOUT, PREFIX, float, ReflectionGain, reflectionGain ), \ 157 | PARAM_OUTPUT( VSTRUCTIN, VSTRUCTOUT, PREFIX, float, Roughness, glassRoughness ), \ 158 | PARAM_OUTPUT( VSTRUCTIN, VSTRUCTOUT, PREFIX, float, Anisotropy, glassAnisotropy ), \ 159 | PARAM_OUTPUT( VSTRUCTIN, VSTRUCTOUT, PREFIX, color, RefractionCG, refractionColor ), \ 160 | PARAM_OUTPUT( VSTRUCTIN, VSTRUCTOUT, PREFIX, float, RefractionIndex, glassIor ), \ 161 | PARAM_OUTPUT( VSTRUCTIN, VSTRUCTOUT, PREFIX, float, ManifoldExplorationIOR, mwIor ), \ 162 | PARAM_OUTPUT_ENABLE( VSTRUCTIN, VSTRUCTOUT, PREFIX, normal, ShadingNormal, glassBumpNormal ), \ 163 | PARAM_OUTPUT_ENABLE( VSTRUCTIN, VSTRUCTOUT, PREFIX, vector, AnisotropyDirection, glassAnisotropyDirection ), \ 164 | \ 165 | /* No vstructmember for ssAlbedo parameter in PxrSurface.args */ \ 166 | output color PREFIX##_ssAlbedo = color(0.0) [[ string widget = "null" ]], \ 167 | \ 168 | /* No vstructmember for extinction parameter in PxrSurface.args */ \ 169 | output color PREFIX##_extinction = color(0.0) [[ string widget = "null" ]] 170 | 171 | #define GLOW_OUTPUT_PARAMS(VSTRUCTIN,VSTRUCTOUT,PREFIX) \ 172 | PARAM_OUTPUT_SET_GAIN( VSTRUCTIN, VSTRUCTOUT, PREFIX, Gain, glowGain ), \ 173 | PARAM_OUTPUT( VSTRUCTIN, VSTRUCTOUT, PREFIX, color, CG, glowColor ) 174 | 175 | #endif 176 | -------------------------------------------------------------------------------- /osl/material/v2_PxrSurfaceAdapter.osl: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018-2020 Laika, LLC. Authored by Mitch Prater. 3 | * 4 | * Licensed under the Apache License Version 2.0 http://apache.org/licenses/LICENSE-2.0, 5 | * or the MIT license http://opensource.org/licenses/MIT, at your option. 6 | * 7 | * This program may not be copied, modified, or distributed except according to those terms. 8 | */ 9 | /* 10 | * This adapts the Material Output of a material shader to a 11 | * displacement and its corresponding bxdf shader's parameters: 12 | * PxrSurface in this case. 13 | */ 14 | #include "ikaFunctions.h" 15 | 16 | #include "material/v2_PxrSurface.h" 17 | #include "material/v2_PxrSurfaceAdapter.h" 18 | 19 | shader v2_PxrSurfaceAdapter 20 | [[ 21 | int rfm_nodeid = 1234036, 22 | string rfm_classification = "rendernode/RenderMan/pattern/material", 23 | string label = "PxrSurface Adapter", 24 | string help = 25 | "This adapts the Material Output of a v2_PxrSurface material " 26 | "to a SetP displacement shader and a PxrSurface bxdf's " 27 | "Input Material connection. " 28 | ]] 29 | ( 30 | string Notes = "" 31 | [[ 32 | int connectable = 0, 33 | string help = 34 | "This adapts the Material Output of a v2_PxrSurface material " 35 | "to a SetP displacement shader and a PxrSurface bxdf's " 36 | "Input Material connection. " 37 | ]], 38 | 39 | /* 40 | * The input material. 41 | */ 42 | // The vstruct parameter. This is the single material connection point 43 | // for all the material parameters in the material struct. 44 | PXRSURFACE_MATERIAL_VSTRUCT( MaterialInput, Material Input, 45 | Connect a v2_PxrSurface Material shader's Material Output here. 46 | ), 47 | 48 | // The struct parameter. 49 | PXRSURFACE_MATERIAL_STRUCT( MaterialInput, MatIn ), 50 | 51 | // The Enable parameters. 52 | ALL_ENABLE_PARAMS( MaterialInput, ClearCoat ), 53 | ALL_ENABLE_PARAMS( MaterialInput, PrimarySpecular ), 54 | ALL_ENABLE_PARAMS( MaterialInput, SecondarySpecular ), 55 | RESPONSE_ENABLE_PARAM( MaterialInput, Iridescence ), 56 | SHADINGNORMAL_ENABLE_PARAM( MaterialInput, Iridescence ), 57 | ANISOTROPYDIRECTION_ENABLE_PARAM( MaterialInput, Iridescence ), 58 | RESPONSE_ENABLE_PARAM( MaterialInput, Fuzz ), 59 | SHADINGNORMAL_ENABLE_PARAM( MaterialInput, Fuzz ), 60 | RESPONSE_ENABLE_PARAM( MaterialInput, Diffuse ), 61 | SHADINGNORMAL_ENABLE_PARAM( MaterialInput, Diffuse ), 62 | RESPONSE_ENABLE_PARAM( MaterialInput, Scatter ), 63 | RESPONSE_ENABLE_PARAM( MaterialInput, Subsurface ), 64 | RESPONSE_ENABLE_PARAM( MaterialInput, Glass ), 65 | SHADINGNORMAL_ENABLE_PARAM( MaterialInput, Glass ), 66 | ANISOTROPYDIRECTION_ENABLE_PARAM( MaterialInput, Glass ), 67 | RESPONSE_ENABLE_PARAM( MaterialInput, Glow ), 68 | 69 | 70 | /* 71 | * This output Material vstruct is connected to a PxrSurface bxdf shader. 72 | */ 73 | output float MaterialOutput = 0.0 74 | [[ 75 | string label = "Material Output", 76 | string widget = "null", 77 | string tag = "vstruct", 78 | string help = 79 | "Connect this to a PxrSurface bxdf shader's Material Input. " 80 | ]], 81 | 82 | /* 83 | * Displaced P output. 84 | */ 85 | output point out_P = point(0.0) 86 | [[ 87 | string widget = "null", 88 | string tag = "point", 89 | string help = 90 | "This represents the displaced surface and is connected to a SetP displacement shader." 91 | ]], 92 | 93 | /* 94 | * Composited Mask outputs. 95 | */ 96 | output float maxMask = 1.0 [[ string widget = "null" ]], 97 | 98 | /* 99 | * Utility Plug output. 100 | */ 101 | output int Plug = 0 [[ string widget = "null" ]], 102 | 103 | /* 104 | * Output PxrSurface (vstruct) shader parameters start here. 105 | */ 106 | output normal Global_ShadingNormal = normal( 0.0 ) 107 | [[ 108 | string widget = "null", 109 | string vstructmember = "MaterialOutput.bumpNormal" 110 | ]], 111 | 112 | output color Global_ShadowColor = color( 0.0 ) 113 | [[ 114 | string widget = "null", 115 | string vstructmember = "MaterialOutput.shadowColor" 116 | ]], 117 | 118 | // Clear Coat 119 | CLEARCOAT_OUTPUT_PARAMS( MaterialInput, MaterialOutput, ClearCoat ), 120 | 121 | // Primay Specular 122 | PRIMARYSPECULAR_OUTPUT_PARAMS( MaterialInput, MaterialOutput, PrimarySpecular ), 123 | 124 | // Secondary Specular 125 | SECONDARYSPECULAR_OUTPUT_PARAMS( MaterialInput, MaterialOutput, SecondarySpecular ), 126 | 127 | // Iridescence 128 | IRIDESCENCE_OUTPUT_PARAMS( MaterialInput, MaterialOutput, Iridescence ), 129 | 130 | // Fuzz 131 | FUZZ_OUTPUT_PARAMS( MaterialInput, MaterialOutput, Fuzz ), 132 | 133 | // Diffuse 134 | DIFFUSE_OUTPUT_PARAMS( MaterialInput, MaterialOutput, Diffuse ), 135 | 136 | // Scatter 137 | SCATTER_OUTPUT_PARAMS( MaterialInput, MaterialOutput, Scatter ), 138 | 139 | // Subsurface 140 | SUBSURFACE_OUTPUT_PARAMS( MaterialInput, MaterialOutput, Subsurface ), 141 | 142 | // Scatter & Subsurface 143 | output color ScatterAndSubsurface_IlluminationTint = color( 1.0 ) 144 | [[ 145 | string widget = "null", 146 | string vstructmember = "MaterialOutput.irradianceTint", 147 | string vstructConditionalExpr = "connect if " 148 | "MaterialInput_Scatter_Enable == 1 or MaterialInput_Subsurface_Enable == 1" 149 | ]], 150 | 151 | output float ScatterAndSubsurface_Roughness = 0.0 152 | [[ 153 | string widget = "null", 154 | string vstructmember = "MaterialOutput.irradianceRoughness", 155 | string vstructConditionalExpr = "connect if " 156 | "MaterialInput_Scatter_Enable == 1 or MaterialInput_Subsurface_Enable == 1" 157 | ]], 158 | 159 | // Glass 160 | GLASS_OUTPUT_PARAMS( MaterialInput, MaterialOutput, Glass ), 161 | 162 | // Glow 163 | GLOW_OUTPUT_PARAMS( MaterialInput, MaterialOutput, Glow ) 164 | ) 165 | /* 166 | * Adapter functionality. 167 | * vstruct connections from the output parameters to the PxrSurface parameter vstructmembers 168 | * are specified in the output parameter declarations. 169 | */ 170 | { 171 | Plug = MatIn.socket; 172 | maxMask = MatIn.maxMask; 173 | 174 | // 175 | // Displacement. 176 | // 177 | point Po; 178 | getattribute( "builtin", "Po", Po ); 179 | 180 | out_P = Po + MatIn.deltaP; 181 | 182 | 183 | // 184 | // Bxdf responses. 185 | // 186 | // When enabled, simply copy the response's parameter values 187 | // to their corresponding vstruct output parameters. 188 | // 189 | 190 | // UVTangent default output. 191 | // When out_P has been connected to a displacement, Nn becomes the post-displacement normal. 192 | normal Nn = normalize( N ); 193 | vector Tn, Bn; 194 | ikaCreateOrthonormalBasis( Nn, Tn, Bn ); 195 | 196 | vector defaultAnisotropyDirection = Tn; 197 | 198 | // Always the un-displaced normal. 199 | normal Non; 200 | getattribute( "builtin", "Non", Non ); 201 | 202 | vector deltaN = MatIn.Displacement_BumpPercent * vector( Nn - Non ); 203 | normal bumpShadingNormal = normalize( Non + deltaN ); 204 | 205 | // global Shading Normal -> PxrSurface BumpNormal. 206 | Global_ShadingNormal = normalize( mix( 207 | bumpShadingNormal, 208 | MatIn.Global_ShadingNormal, 209 | MatIn.Global_UseShadingNormal 210 | )); 211 | Global_ShadingNormal = ikaBumpCompensation( Global_ShadingNormal ); 212 | 213 | // global ShadowColor -> PxrSurface ShadowColor. 214 | Global_ShadowColor = MatIn.Global_ShadowColor; 215 | 216 | // Clear Coat 217 | if( MaterialInput_ClearCoat_Enable ) 218 | { 219 | COPY_PARAM( MatIn, ClearCoat, CG ); 220 | COPY_PARAM( MatIn, ClearCoat, FaceCG ); 221 | COPY_PARAM( MatIn, ClearCoat, FresnelExponent ); 222 | COPY_PARAM( MatIn, ClearCoat, LayerThickness ); 223 | COPY_PARAM( MatIn, ClearCoat, LayerColor ); 224 | COPY_PARAM( MatIn, ClearCoat, Roughness ); 225 | COPY_PARAM( MatIn, ClearCoat, Anisotropy ); 226 | 227 | // Can't allow IOR to go below 1. 228 | ClearCoat_RefractionCI = ikaMax( 1.0, MatIn.ClearCoat_RefractionCI ); 229 | 230 | ClearCoat_ShadingNormal = normalize( mix( 231 | Global_ShadingNormal, 232 | ikaBumpCompensation( MatIn.ClearCoat_ShadingNormal ), 233 | MatIn.ClearCoat_UseShadingNormal 234 | )); 235 | 236 | ClearCoat_AnisotropyDirection = mix( 237 | defaultAnisotropyDirection, 238 | MatIn.ClearCoat_AnisotropyDirection, 239 | MatIn.ClearCoat_UseAnisotropyDirection 240 | ); 241 | } 242 | 243 | // Primary Specular 244 | if( MaterialInput_PrimarySpecular_Enable ) 245 | { 246 | COPY_PARAM( MatIn, PrimarySpecular, CG ); 247 | COPY_PARAM( MatIn, PrimarySpecular, FaceCG ); 248 | COPY_PARAM( MatIn, PrimarySpecular, FresnelExponent ); 249 | COPY_PARAM( MatIn, PrimarySpecular, ExtinctionCC ); 250 | COPY_PARAM( MatIn, PrimarySpecular, Roughness ); 251 | COPY_PARAM( MatIn, PrimarySpecular, Anisotropy ); 252 | 253 | // Can't allow IOR to go below 1. 254 | PrimarySpecular_RefractionCI = ikaMax( 1.0, MatIn.PrimarySpecular_RefractionCI ); 255 | 256 | PrimarySpecular_ShadingNormal = normalize( mix( 257 | Global_ShadingNormal, 258 | ikaBumpCompensation( MatIn.PrimarySpecular_ShadingNormal ), 259 | MatIn.PrimarySpecular_UseShadingNormal 260 | )); 261 | 262 | PrimarySpecular_AnisotropyDirection = mix( 263 | defaultAnisotropyDirection, 264 | MatIn.PrimarySpecular_AnisotropyDirection, 265 | MatIn.PrimarySpecular_UseAnisotropyDirection 266 | ); 267 | } 268 | 269 | // Secondary Specular 270 | if( MaterialInput_SecondarySpecular_Enable ) 271 | { 272 | COPY_PARAM( MatIn, SecondarySpecular, CG ); 273 | COPY_PARAM( MatIn, SecondarySpecular, FaceCG ); 274 | COPY_PARAM( MatIn, SecondarySpecular, FresnelExponent ); 275 | COPY_PARAM( MatIn, SecondarySpecular, ExtinctionCC ); 276 | COPY_PARAM( MatIn, SecondarySpecular, Roughness ); 277 | COPY_PARAM( MatIn, SecondarySpecular, Anisotropy ); 278 | 279 | // Can't allow IOR to go below 1. 280 | SecondarySpecular_RefractionCI = ikaMax( 1.0, MatIn.SecondarySpecular_RefractionCI ); 281 | 282 | SecondarySpecular_ShadingNormal = normalize( mix( 283 | Global_ShadingNormal, 284 | ikaBumpCompensation( MatIn.SecondarySpecular_ShadingNormal ), 285 | MatIn.SecondarySpecular_UseShadingNormal 286 | )); 287 | 288 | SecondarySpecular_AnisotropyDirection = mix( 289 | defaultAnisotropyDirection, 290 | MatIn.SecondarySpecular_AnisotropyDirection, 291 | MatIn.SecondarySpecular_UseAnisotropyDirection 292 | ); 293 | } 294 | 295 | // Iridescence 296 | if( MaterialInput_Iridescence_Enable ) 297 | { 298 | Iridescence_FaceGain = MatIn.Iridescence_Gain; 299 | Iridescence_EdgeGain = MatIn.Iridescence_Gain; 300 | 301 | COPY_PARAM( MatIn, Iridescence, FaceColor ); 302 | COPY_PARAM( MatIn, Iridescence, EdgeColor ); 303 | COPY_PARAM( MatIn, Iridescence, Exponent ); 304 | COPY_PARAM( MatIn, Iridescence, Repetitions ); 305 | COPY_PARAM( MatIn, Iridescence, Thickness ); 306 | COPY_PARAM( MatIn, Iridescence, Roughness ); 307 | COPY_PARAM( MatIn, Iridescence, Anisotropy ); 308 | 309 | Iridescence_ShadingNormal = normalize( mix( 310 | Global_ShadingNormal, 311 | MatIn.Iridescence_ShadingNormal, 312 | MatIn.Iridescence_UseShadingNormal 313 | )); 314 | 315 | Iridescence_AnisotropyDirection = mix( 316 | defaultAnisotropyDirection, 317 | MatIn.Iridescence_AnisotropyDirection, 318 | MatIn.Iridescence_UseAnisotropyDirection 319 | ); 320 | } 321 | 322 | // Fuzz 323 | if( MaterialInput_Fuzz_Enable ) 324 | { 325 | COPY_PARAM( MatIn, Fuzz, CG ); 326 | COPY_PARAM( MatIn, Fuzz, ConeAngle ); 327 | 328 | Fuzz_ShadingNormal = normalize( mix( 329 | Global_ShadingNormal, 330 | ikaBumpCompensation( MatIn.Fuzz_ShadingNormal ), 331 | MatIn.Fuzz_UseShadingNormal 332 | )); 333 | } 334 | 335 | // Diffuse 336 | if( MaterialInput_Diffuse_Enable ) 337 | { 338 | COPY_PARAM( MatIn, Diffuse, CG ); 339 | COPY_PARAM( MatIn, Diffuse, Roughness ); 340 | COPY_PARAM( MatIn, Diffuse, Exponent ); 341 | COPY_PARAM( MatIn, Diffuse, BackfaceCG ); 342 | COPY_PARAM( MatIn, Diffuse, TransmitCG ); 343 | 344 | Diffuse_ShadingNormal = normalize( mix( 345 | Global_ShadingNormal, 346 | ikaBumpCompensation( MatIn.Diffuse_ShadingNormal ), 347 | MatIn.Diffuse_UseShadingNormal 348 | )); 349 | } 350 | 351 | // Scatter 352 | if( MaterialInput_Scatter_Enable ) 353 | { 354 | COPY_PARAM( MatIn, Scatter, CG ); 355 | COPY_PARAM( MatIn, Scatter, PathLength ); 356 | COPY_PARAM( MatIn, Scatter, PathColor ); 357 | COPY_PARAM( MatIn, Scatter, Direction ); 358 | COPY_PARAM( MatIn, Scatter, Roughness ); 359 | COPY_PARAM( MatIn, Scatter, BacksideCG ); 360 | 361 | // Can't allow IOR to go below 1. 362 | Scatter_RefractionIndex = max( 1.0, MatIn.Scatter_RefractionIndex ); 363 | } 364 | 365 | // Subsurface 366 | if( MaterialInput_Subsurface_Enable ) 367 | { 368 | COPY_PARAM( MatIn, Subsurface, Gain ); 369 | COPY_PARAM( MatIn, Subsurface, Color ); 370 | COPY_PARAM( MatIn, Subsurface, PathLength ); 371 | COPY_PARAM( MatIn, Subsurface, PathColor ); 372 | COPY_PARAM( MatIn, Subsurface, PostTint ); 373 | COPY_PARAM( MatIn, Subsurface, TransmitGain ); 374 | COPY_PARAM( MatIn, Subsurface, ShortGain ); 375 | COPY_PARAM( MatIn, Subsurface, ShortColor ); 376 | COPY_PARAM( MatIn, Subsurface, ShortLength ); 377 | COPY_PARAM( MatIn, Subsurface, LongGain ); 378 | COPY_PARAM( MatIn, Subsurface, LongColor ); 379 | COPY_PARAM( MatIn, Subsurface, LongLength ); 380 | COPY_PARAM( MatIn, Subsurface, Directionality ); 381 | // XXX Not Really Connectable! COPY_PARAM( MatIn, Subsurface, DiffuseBlend ); 382 | COPY_PARAM( MatIn, Subsurface, Bleed ); 383 | } 384 | 385 | // Scatter & Subsurface 386 | if( MaterialInput_Scatter_Enable || MaterialInput_Subsurface_Enable ) 387 | { 388 | COPY_PARAM( MatIn, ScatterAndSubsurface, IlluminationTint ); 389 | COPY_PARAM( MatIn, ScatterAndSubsurface, Roughness ); 390 | } 391 | 392 | // Glass 393 | if( MaterialInput_Glass_Enable ) 394 | { 395 | COPY_PARAM( MatIn, Glass, ReflectionGain ); 396 | COPY_PARAM( MatIn, Glass, Roughness ); 397 | COPY_PARAM( MatIn, Glass, Anisotropy ); 398 | COPY_PARAM( MatIn, Glass, RefractionCG ); 399 | COPY_PARAM( MatIn, Glass, ManifoldExplorationIOR ); 400 | 401 | Glass_ShadingNormal = normalize( mix( 402 | Global_ShadingNormal, 403 | ikaBumpCompensation( MatIn.Glass_ShadingNormal ), 404 | MatIn.Glass_UseShadingNormal 405 | )); 406 | 407 | Glass_AnisotropyDirection = mix( 408 | defaultAnisotropyDirection, 409 | MatIn.Glass_AnisotropyDirection, 410 | MatIn.Glass_UseAnisotropyDirection 411 | ); 412 | 413 | // Can't allow GlassIor to go below 1.0. 414 | Glass_RefractionIndex = max( 1.0, MatIn.Glass_RefractionIndex ); 415 | 416 | /* No vstructmember for ssAlbedo parameter in PxrSurface.args */ 417 | Glass_ssAlbedo = MatIn.Glass_ScatterColor; 418 | /* No vstructmember for extinction parameter in PxrSurface.args */ 419 | Glass_extinction = MatIn.Glass_ExtinctionCC; 420 | } 421 | 422 | // Glow 423 | if( MaterialInput_Glow_Enable ) 424 | { 425 | COPY_PARAM( MatIn, Glow, CG ); 426 | } 427 | } 428 | -------------------------------------------------------------------------------- /osl/material/v2_PxrSurfaceModify.osl: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018-2020 Laika, LLC. Authored by Mitch Prater. 3 | * 4 | * Licensed under the Apache License Version 2.0 http://apache.org/licenses/LICENSE-2.0, 5 | * or the MIT license http://opensource.org/licenses/MIT, at your option. 6 | * 7 | * This program may not be copied, modified, or distributed except according to those terms. 8 | */ 9 | #include "material/v2_PxrSurface.h" 10 | 11 | shader v2_PxrSurfaceModify 12 | [[ 13 | int rfm_nodeid = 1234052, 14 | string rfm_classification = "rendernode/RenderMan/pattern/material" 15 | ]] 16 | ( 17 | string Notes = "" 18 | [[ 19 | int connectable = 0, 20 | string help = 21 | "Modifies the Diffuse and Specular responses of a " 22 | "material_v2_PxrSurface. " 23 | ]], 24 | 25 | /* 26 | * The Input Material data set. 27 | * 28 | * This consists of a vstruct parameter, a material struct parameter, and a set 29 | * of enable parameters for each response. The material struct and response enable 30 | * parameters are members of the vstruct parameter. 31 | */ 32 | // The vstruct parameter. This is the single material connection point 33 | // for all the material parameters in the material struct. 34 | PXRSURFACE_MATERIAL_VSTRUCT( MaterialInput, Material Input, 35 | The Material whose responses will be Modified. 36 | ), 37 | 38 | // The material struct parameter. 39 | PXRSURFACE_MATERIAL_STRUCT( MaterialInput, MatIn ), 40 | 41 | // The response Enable parameters. These are linked to a vstructmember of the vstruct parameter. 42 | ALL_ENABLE_PARAMS( MaterialInput, ClearCoat ), 43 | ALL_ENABLE_PARAMS( MaterialInput, PrimarySpecular ), 44 | ALL_ENABLE_PARAMS( MaterialInput, SecondarySpecular ), 45 | RESPONSE_ENABLE_PARAM( MaterialInput, Iridescence ), 46 | SHADINGNORMAL_ENABLE_PARAM( MaterialInput, Iridescence ), 47 | ANISOTROPYDIRECTION_ENABLE_PARAM( MaterialInput, Iridescence ), 48 | RESPONSE_ENABLE_PARAM( MaterialInput, Fuzz ), 49 | SHADINGNORMAL_ENABLE_PARAM( MaterialInput, Fuzz ), 50 | RESPONSE_ENABLE_PARAM( MaterialInput, Diffuse ), 51 | SHADINGNORMAL_ENABLE_PARAM( MaterialInput, Diffuse ), 52 | RESPONSE_ENABLE_PARAM( MaterialInput, Scatter ), 53 | RESPONSE_ENABLE_PARAM( MaterialInput, Subsurface ), 54 | RESPONSE_ENABLE_PARAM( MaterialInput, Glass ), 55 | SHADINGNORMAL_ENABLE_PARAM( MaterialInput, Glass ), 56 | ANISOTROPYDIRECTION_ENABLE_PARAM( MaterialInput, Glass ), 57 | RESPONSE_ENABLE_PARAM( MaterialInput, Glow ), 58 | 59 | /* 60 | * This material's user interface parameters. 61 | */ 62 | int Enable = 1 63 | [[ 64 | int connectable = 0, 65 | string label = "Enable", 66 | string widget = "checkBox", 67 | string help = 68 | "Turns the modifications On/Off. " 69 | ]], 70 | 71 | float Mask = 1.0 72 | [[ 73 | string label = "Mask", 74 | int slider = 1, float slidermin = 0.0, float slidermax = 1.0, 75 | string help = 76 | "Determines where the modifications will be applied. " 77 | ]], 78 | 79 | // 80 | // Specular Modifications. 81 | // 82 | float SpecularHue = 0.0 83 | [[ 84 | string page = "Specular", 85 | string label = "Hue", 86 | int slider = 1, float slidermin = -0.5, float slidermax = 0.5, 87 | string help = 88 | "Shift the Hue by this amount. Hue is cyclical, so shifting by an integer " 89 | "amount causes no change. To invert the Hue, shift it by +/- .5. " 90 | ]], 91 | 92 | float SpecularSaturation = 1.0 93 | [[ 94 | string page = "Specular", 95 | string label = "Saturation", 96 | int slider = 1, float slidermin = 0.0, float slidermax = 2.0, 97 | string help = 98 | "Scale the Saturation by this amount. " 99 | ]], 100 | 101 | float SpecularExposure = 0.0 102 | [[ 103 | string page = "Specular", 104 | string label = "Exposure", 105 | int slider = 1, float slidermin = -4.0, float slidermax = 4.0, 106 | string help = 107 | "Adjust the Exposure by this amount. " 108 | ]], 109 | 110 | float SpecularGain = 1.0 111 | [[ 112 | string page = "Specular", 113 | string label = "Gain", 114 | int slider = 1, float slidermin = 0.0, float slidermax = 2.0, 115 | string help = 116 | "Scale the Gain by this amount. " 117 | ]], 118 | 119 | color SpecularTint = color( 1.0 ) 120 | [[ 121 | string page = "Specular", 122 | string label = "Tint", 123 | string help = 124 | "Scale the color with this Tint. " 125 | ]], 126 | 127 | float SpecularRoughness = 0.0 128 | [[ 129 | string page = "Specular", 130 | string label = "Roughness", 131 | int slider = 1, float slidermin = -1.0, float slidermax = 1.0, 132 | string help = 133 | "Modifies the material's Roughness values: " 134 | "

" 135 | "+ values increase Roughness. " 136 | "
" 137 | "- values decrease Roughness. " 138 | ]], 139 | 140 | // 141 | // Diffuse Modifications. 142 | // 143 | float DiffuseHue = 0.0 144 | [[ 145 | string page = "Diffuse", 146 | string label = "Hue", 147 | int slider = 1, float slidermin = -0.5, float slidermax = 0.5, 148 | string help = 149 | "Shift the Hue by this amount. Hue is cyclical, so shifting by an integer " 150 | "amount causes no change. To invert the Hue, shift it by +/- .5. " 151 | ]], 152 | 153 | float DiffuseSaturation = 1.0 154 | [[ 155 | string page = "Diffuse", 156 | string label = "Saturation", 157 | int slider = 1, float slidermin = 0.0, float slidermax = 2.0, 158 | string help = 159 | "Scale the Saturation by this amount. " 160 | ]], 161 | 162 | float DiffuseExposure = 0.0 163 | [[ 164 | string page = "Diffuse", 165 | string label = "Exposure", 166 | int slider = 1, float slidermin = -4.0, float slidermax = 4.0, 167 | string help = 168 | "Adjust the Exposure by this amount. " 169 | ]], 170 | 171 | float DiffuseGain = 1.0 172 | [[ 173 | string page = "Diffuse", 174 | string label = "Gain", 175 | int slider = 1, float slidermin = 0.0, float slidermax = 2.0, 176 | string help = 177 | "Scale the Gain by this amount. " 178 | ]], 179 | 180 | color DiffuseTint = color( 1.0 ) 181 | [[ 182 | string page = "Diffuse", 183 | string label = "Tint", 184 | string help = 185 | "Scale the color with this Tint. " 186 | ]], 187 | 188 | // 189 | // Utility socket. 190 | // 191 | int Socket = 0 192 | [[ 193 | string help = 194 | "Connect a shading node's Plug output here in order to execute that node and " 195 | "any shading tree connected to it. " 196 | ]], 197 | 198 | /* 199 | * The Output Material data set. 200 | * 201 | * This consists of a vstruct parameter, a material struct parameter, and a set 202 | * of enable parameters for each response. The material struct and response enable 203 | * parameters are members of the vstruct parameter. 204 | */ 205 | output PXRSURFACE_MATERIAL_VSTRUCT( MaterialOutput, Material Output, 206 | The modified Material. 207 | ), 208 | 209 | // The struct parameter. 210 | output PXRSURFACE_MATERIAL_STRUCT( MaterialOutput, MatOut ), 211 | 212 | // Set the output vstruct Enable parameters based on the input Enable value and user parameter settings. 213 | SET_ALL_ENABLE_PARAMS( MaterialOutput, MaterialInput, ClearCoat ), 214 | SET_ALL_ENABLE_PARAMS( MaterialOutput, MaterialInput, PrimarySpecular ), 215 | SET_ALL_ENABLE_PARAMS( MaterialOutput, MaterialInput, SecondarySpecular ), 216 | SET_RESPONSE_ENABLE_PARAM( MaterialOutput, MaterialInput, Iridescence ), 217 | SET_SHADINGNORMAL_ENABLE_PARAM( MaterialOutput, MaterialInput, Iridescence ), 218 | SET_ANISOTROPYDIRECTION_ENABLE_PARAM( MaterialOutput, MaterialInput, Iridescence ), 219 | SET_RESPONSE_ENABLE_PARAM( MaterialOutput, MaterialInput, Fuzz ), 220 | SET_SHADINGNORMAL_ENABLE_PARAM( MaterialOutput, MaterialInput, Fuzz ), 221 | SET_RESPONSE_ENABLE_PARAM( MaterialOutput, MaterialInput, Diffuse ), 222 | SET_SHADINGNORMAL_ENABLE_PARAM( MaterialOutput, MaterialInput, Diffuse ), 223 | SET_RESPONSE_ENABLE_PARAM( MaterialOutput, MaterialInput, Scatter ), 224 | SET_RESPONSE_ENABLE_PARAM( MaterialOutput, MaterialInput, Subsurface ), 225 | SET_RESPONSE_ENABLE_PARAM( MaterialOutput, MaterialInput, Glass ), 226 | SET_SHADINGNORMAL_ENABLE_PARAM( MaterialOutput, MaterialInput, Glass ), 227 | SET_ANISOTROPYDIRECTION_ENABLE_PARAM( MaterialOutput, MaterialInput, Glass ), 228 | SET_RESPONSE_ENABLE_PARAM( MaterialOutput, MaterialInput, Glow ) 229 | ) 230 | { 231 | // Function Definitions. 232 | float GainCorrect( float in, float Mask, float Expo, float Gain ) 233 | { 234 | float out = in; 235 | 236 | out *= pow( 2.0, Expo ) * Gain; 237 | 238 | return mix( in, out, Mask ); 239 | } 240 | 241 | color ColorCorrect( color in, float Mask, float Hue, float Sat, float Expo, float Gain, color Tint ) 242 | { 243 | color RGB = in; 244 | 245 | color hsl = transformc( "rgb", "hsl", RGB ); 246 | hsl[0] += Hue; 247 | hsl[1] *= Sat; 248 | RGB = transformc( "hsl", "rgb", hsl ); 249 | 250 | RGB *= pow( 2.0, Expo ) * Gain * Tint; 251 | 252 | return mix( in, RGB, Mask ); 253 | } 254 | 255 | float RoughnessCorrect( float in, float Mask, float Rough ) 256 | { 257 | float r = mix( 258 | mix( 0.0, 1.0 + Rough, in ), 259 | mix( Rough, 1.0, in ), 260 | step( 0.0, Rough ) 261 | ); 262 | 263 | return clamp( r, 0.0, 1.0 ); 264 | } 265 | 266 | 267 | // Output = Input. 268 | MatOut = MatIn; 269 | 270 | // Pull on the Socket to make sure it's evaluated. 271 | MatOut.socket = Socket; 272 | 273 | // Modify the Output material. 274 | if( Enable == 1 && Mask != 0.0 ) 275 | { 276 | // ClearCoat. 277 | MatOut.ClearCoat_CG = ColorCorrect( MatOut.ClearCoat_CG, Mask, 278 | SpecularHue, 279 | SpecularSaturation, 280 | SpecularExposure, 281 | SpecularGain, 282 | SpecularTint 283 | ); 284 | 285 | MatOut.ClearCoat_FaceCG = ColorCorrect( MatOut.ClearCoat_FaceCG, Mask, 286 | SpecularHue, 287 | SpecularSaturation, 288 | SpecularExposure, 289 | SpecularGain, 290 | SpecularTint 291 | ); 292 | 293 | MatOut.ClearCoat_Roughness = RoughnessCorrect( MatOut.ClearCoat_Roughness, Mask, 294 | SpecularRoughness 295 | ); 296 | 297 | // PrimarySpecular. 298 | MatOut.PrimarySpecular_CG = ColorCorrect( MatOut.PrimarySpecular_CG, Mask, 299 | SpecularHue, 300 | SpecularSaturation, 301 | SpecularExposure, 302 | SpecularGain, 303 | SpecularTint 304 | ); 305 | 306 | MatOut.PrimarySpecular_FaceCG = ColorCorrect( MatOut.PrimarySpecular_FaceCG, Mask, 307 | SpecularHue, 308 | SpecularSaturation, 309 | SpecularExposure, 310 | SpecularGain, 311 | SpecularTint 312 | ); 313 | 314 | MatOut.PrimarySpecular_Roughness = RoughnessCorrect( MatOut.PrimarySpecular_Roughness, Mask, 315 | SpecularRoughness 316 | ); 317 | 318 | // SecondarySpecular. 319 | MatOut.SecondarySpecular_CG = ColorCorrect( MatOut.SecondarySpecular_CG, Mask, 320 | SpecularHue, 321 | SpecularSaturation, 322 | SpecularExposure, 323 | SpecularGain, 324 | SpecularTint 325 | ); 326 | 327 | MatOut.SecondarySpecular_FaceCG = ColorCorrect( MatOut.SecondarySpecular_FaceCG, Mask, 328 | SpecularHue, 329 | SpecularSaturation, 330 | SpecularExposure, 331 | SpecularGain, 332 | SpecularTint 333 | ); 334 | 335 | MatOut.SecondarySpecular_Roughness = RoughnessCorrect( MatOut.SecondarySpecular_Roughness, Mask, 336 | SpecularRoughness 337 | ); 338 | 339 | // Iridescence. 340 | MatOut.Iridescence_FaceColor = ColorCorrect( MatOut.Iridescence_FaceColor, Mask, 341 | SpecularHue, 342 | SpecularSaturation, 343 | SpecularExposure, 344 | SpecularGain, 345 | SpecularTint 346 | ); 347 | 348 | MatOut.Iridescence_EdgeColor = ColorCorrect( MatOut.Iridescence_EdgeColor, Mask, 349 | SpecularHue, 350 | SpecularSaturation, 351 | SpecularExposure, 352 | SpecularGain, 353 | SpecularTint 354 | ); 355 | 356 | MatOut.Iridescence_Roughness = RoughnessCorrect( MatOut.Iridescence_Roughness, Mask, 357 | SpecularRoughness 358 | ); 359 | 360 | // Glass. 361 | MatOut.Glass_ReflectionGain = GainCorrect( MatOut.Glass_ReflectionGain, Mask, 362 | SpecularExposure, 363 | SpecularGain 364 | ); 365 | 366 | MatOut.Glass_RefractionCG = ColorCorrect( MatOut.Glass_RefractionCG, Mask, 367 | SpecularHue, 368 | SpecularSaturation, 369 | SpecularExposure, 370 | SpecularGain, 371 | SpecularTint 372 | ); 373 | 374 | MatOut.Glass_Roughness = RoughnessCorrect( MatOut.Glass_Roughness, Mask, 375 | SpecularRoughness 376 | ); 377 | 378 | // Fuzz. 379 | MatOut.Fuzz_CG = ColorCorrect( MatOut.Fuzz_CG, Mask, 380 | DiffuseHue, 381 | DiffuseSaturation, 382 | DiffuseExposure, 383 | DiffuseGain, 384 | DiffuseTint 385 | ); 386 | 387 | // Diffuse. 388 | MatOut.Diffuse_CG = ColorCorrect( MatOut.Diffuse_CG, Mask, 389 | DiffuseHue, 390 | DiffuseSaturation, 391 | DiffuseExposure, 392 | DiffuseGain, 393 | DiffuseTint 394 | ); 395 | 396 | MatOut.Diffuse_BackfaceCG = ColorCorrect( MatOut.Diffuse_BackfaceCG, Mask, 397 | DiffuseHue, 398 | DiffuseSaturation, 399 | DiffuseExposure, 400 | DiffuseGain, 401 | DiffuseTint 402 | ); 403 | 404 | MatOut.Diffuse_TransmitCG = ColorCorrect( MatOut.Diffuse_TransmitCG, Mask, 405 | DiffuseHue, 406 | DiffuseSaturation, 407 | DiffuseExposure, 408 | DiffuseGain, 409 | DiffuseTint 410 | ); 411 | 412 | // Scatter. 413 | MatOut.Scatter_CG = ColorCorrect( MatOut.Scatter_CG, Mask, 414 | DiffuseHue, 415 | DiffuseSaturation, 416 | DiffuseExposure, 417 | DiffuseGain, 418 | DiffuseTint 419 | ); 420 | 421 | MatOut.Scatter_BacksideCG = ColorCorrect( MatOut.Scatter_BacksideCG, Mask, 422 | DiffuseHue, 423 | DiffuseSaturation, 424 | DiffuseExposure, 425 | DiffuseGain, 426 | DiffuseTint 427 | ); 428 | 429 | // Subsurface. 430 | MatOut.Subsurface_Gain = GainCorrect( MatOut.Subsurface_Gain, Mask, 431 | DiffuseExposure, 432 | DiffuseGain 433 | ); 434 | 435 | MatOut.Subsurface_ShortGain = GainCorrect( MatOut.Subsurface_ShortGain, Mask, 436 | DiffuseExposure, 437 | DiffuseGain 438 | ); 439 | 440 | MatOut.Subsurface_LongGain = GainCorrect( MatOut.Subsurface_LongGain, Mask, 441 | DiffuseExposure, 442 | DiffuseGain 443 | ); 444 | } 445 | } 446 | -------------------------------------------------------------------------------- /ris/Makefile: -------------------------------------------------------------------------------- 1 | # 2 | # RMANTREE points to the RenderManProServer directory. 3 | # Set it if it's not already set in the environment. 4 | # 5 | RMANTREE ?= /opt/pixar/RenderManProServer-23.2 6 | 7 | # 8 | # Compiler and linker settings. 9 | # 10 | CC = clang++ 11 | CFLAGS = -Wall -Wno-switch -Wno-reorder -Wno-sign-compare -Wno-narrowing -Wno-deprecated-declarations -fPIC -std=c++14 -O3 12 | INCLUDE = -I. -I./include -I${RMANTREE}/include -I/usr/include/freetype2 13 | 14 | LD = clang++ 15 | LFLAGS = -shared 16 | LIBS = -lfreetype 17 | 18 | # 19 | # Control variables. 20 | # These subdirectories will be searched for .cpp files, which will then be built into .so files. 21 | # 22 | SUBDIRS := displace displayfilter 23 | 24 | # These shaders won't be built. Use 'subdirectory/basename'. 25 | EXCLUDE := 26 | 27 | # 28 | # Make functionality. 29 | # src will be the list of .cpp files to build from. 30 | # 31 | src := $(foreach dir,$(SUBDIRS),$(wildcard $(dir)/*.cpp)) 32 | 33 | EXCLUDE := $(basename $(EXCLUDE)) 34 | EXCLUDE := $(addsuffix .cpp, $(EXCLUDE)) 35 | 36 | src := $(filter-out $(EXCLUDE), $(src)) 37 | 38 | # 39 | # Create target lists. 40 | # 41 | obj := $(src:%.cpp=%.o) 42 | dso := $(src:%.cpp=%.so) 43 | 44 | # 45 | # Targets and prerequisites. 46 | # 47 | all: $(dso) 48 | 49 | $(obj): ${RMANTREE}/include/*.h 50 | 51 | # 52 | # Rules. 53 | # 54 | clean: 55 | -$(shell rm -f $(shell find . -name "*.so" -print) $(shell find . -name "*.o" -print)) 56 | 57 | show_src: 58 | @echo $(src) 59 | 60 | show_obj: 61 | @echo $(obj) 62 | 63 | show_dso: 64 | @echo $(dso) 65 | 66 | # 67 | # Build rules. 68 | # 69 | %.o : %.cpp 70 | $(CC) $(CFLAGS) $(INCLUDE) -o $@ -c $< 71 | 72 | %.so : %.o 73 | $(LD) $(LFLAGS) $(LIBS) -o $@ $< 74 | -------------------------------------------------------------------------------- /ris/displace/Args/SetP.args: -------------------------------------------------------------------------------- 1 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | Directly sets the value of P. 16 | 17 | 18 | 22 | 23 | 24 | The new value of P. 25 | 26 | 27 | 28 | 32 | 33 | 34 | How much effect will this have on the displacement? 35 | 36 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /ris/displace/SetP.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-2019 Laika, LLC. Authored by Mitch Prater. 3 | * 4 | * Licensed under the Apache License Version 2.0 http://apache.org/licenses/LICENSE-2.0, 5 | * or the MIT license http://opensource.org/licenses/MIT, at your option. 6 | * 7 | * This program may not be copied, modified, or distributed except according to those terms. 8 | */ 9 | /* 10 | * P = mix( P, Q, Enable ). That's it. 11 | */ 12 | #include "RixDisplacement.h" 13 | #include "RixShadingUtils.h" 14 | 15 | /* 16 | * RixDisplacementFactory class declaration. 17 | */ 18 | class SetPFactory : public RixDisplacementFactory 19 | { 20 | private: 21 | 22 | enum ui_Id 23 | { 24 | ui_Enable, 25 | ui_Q 26 | }; 27 | 28 | // Default shader parameter values. 29 | RtFloat default_Enable; 30 | RtPoint3 default_Q; 31 | 32 | public: 33 | 34 | SetPFactory() 35 | { 36 | default_Enable = RtFloat( 1.0f ); 37 | default_Q = RtPoint3( 0.0f ); 38 | } 39 | ~SetPFactory() {} 40 | 41 | 42 | // GetParamTable() method. 43 | const RixSCParamInfo* GetParamTable() 44 | { 45 | static RixSCParamInfo s_ptable[] = 46 | { 47 | RixSCParamInfo( RtUString( "Enable" ), k_RixSCFloat ), 48 | RixSCParamInfo( RtUString( "Q" ), k_RixSCPoint ), 49 | 50 | RixSCParamInfo() 51 | }; 52 | 53 | return &s_ptable[0]; 54 | } 55 | 56 | // BeginDisplacement() declaration. 57 | RixDisplacement* BeginDisplacement( 58 | const RixShadingContext *, 59 | RixSCShadingMode, 60 | RtPointer 61 | ); 62 | void EndDisplacement( RixDisplacement* ) {} 63 | 64 | // Parent class virtual methods, so must define them even though they're no-ops. 65 | int Init( RixContext &, RtUString const ) { return 0; } 66 | void Finalize( RixContext & ) {} 67 | void Synchronize( RixContext&, RixSCSyncMsg, const RixParameterList* ) {} 68 | #if _PRMANAPI_VERSION_ > 22 69 | void CreateInstanceData( RixContext&, const RtUString, const RixParameterList*, InstanceData* ) {} 70 | #else 71 | int CreateInstanceData( RixContext&, const RtUString, const RixParameterList*, InstanceData* ) { return 0; } 72 | #endif 73 | }; 74 | 75 | 76 | /* 77 | * RixDisplacement class declaration. 78 | */ 79 | class SetPDisp : public RixDisplacement 80 | { 81 | private: 82 | // Shader-specific parameter(s). 83 | const RixSCDetail m_detail_Enable; 84 | const RtFloat* m_Enable; 85 | const RixSCConnectionInfo m_cinfo_Q; 86 | const RtPoint3* m_Q; 87 | 88 | public: 89 | // Class constructor. 90 | // An instance of this class is created in BeginDisplacement(). 91 | // The constructor's purpose is to set its class method variables 92 | // for use in its GetDisplacement() method. 93 | SetPDisp( 94 | const RixShadingContext* sCtx, 95 | RixDisplacementFactory* dFac, 96 | 97 | const RixSCDetail detail_Enable, 98 | const RtFloat* Enable, 99 | const RixSCConnectionInfo cinfo_Q, 100 | const RtPoint3* Q 101 | ) : 102 | // Sets the protected RixDisplacement class variables 103 | // 'shadingCtx' to sCtx, and 'displacementFactory' to dFac. 104 | RixDisplacement( sCtx, dFac ), 105 | 106 | // Sets user parameter variables. 107 | m_detail_Enable( detail_Enable ), 108 | m_Enable( Enable ), 109 | m_cinfo_Q( cinfo_Q ), 110 | m_Q( Q ) 111 | { } 112 | 113 | // The class destructor is a no-op. 114 | ~SetPDisp() {} 115 | 116 | 117 | // RixDisplacement::GetDisplacement() method. 118 | // Called by the renderer to affect P. 119 | // XXX What is the value of P: P or Po? 120 | bool GetDisplacement( RtPoint3* P ) 121 | { 122 | // Leave P alone if Q is not connected. 123 | if( m_cinfo_Q != k_RixSCNetworkValue ) return false; 124 | 125 | if( m_detail_Enable == k_RixSCUniform ) 126 | { 127 | if( m_Enable[0] == 0.0f ) return false; 128 | 129 | for( int i=0; i < shadingCtx->numPts; ++i ) P[i] = RixMix( P[i], m_Q[i], m_Enable[0] ); 130 | } 131 | else 132 | { 133 | for( int i=0; i < shadingCtx->numPts; ++i ) P[i] = RixMix( P[i], m_Q[i], m_Enable[i] ); 134 | } 135 | 136 | return true; 137 | } 138 | }; 139 | 140 | 141 | /* 142 | * RixDisplacementFactory::BeginDisplacement() 143 | * 144 | * The BeginDisplacement method returns an instance of this shader's RixDisplacement class. 145 | * It also computes any class variables needed by the RixDisplacement class and passes them 146 | * to its constructor. Such variables typically come from user parameters that are used to 147 | * control the shader's functionality. 148 | */ 149 | RixDisplacement* SetPFactory::BeginDisplacement( 150 | const RixShadingContext* sCtx, 151 | RixSCShadingMode shadingMode, 152 | RtPointer instanceData 153 | ) { 154 | // SetPDisp() parameters. 155 | RixSCDetail detail_Enable; 156 | const RtFloat* Enable; 157 | RixSCConnectionInfo cinfo_Q; 158 | const RtPoint3* Q = NULL; 159 | 160 | // Get the parameter data. 161 | detail_Enable = sCtx->EvalParam( ui_Enable, -1, &Enable, &default_Enable, false ); 162 | assert( detail_Enable == k_RixSCUniform || detail_Enable == k_RixSCVarying ); 163 | 164 | RixSCType type = k_RixSCPoint; 165 | sCtx->GetParamInfo( ui_Q, &type, &cinfo_Q ); 166 | 167 | if( detail_Enable != k_RixSCUniform || Enable[0] != 0.0f ) 168 | { 169 | sCtx->EvalParam( ui_Q, -1, &Q, &default_Q, true ); 170 | } 171 | // XXX else what? Leaves Q = NULL. 172 | 173 | // Allocate memory for this shader's RixDisplacement object in the 174 | // renderer's Displacement (shares Bxdf) shading context memory pool. 175 | RixShadingContext::Allocator pool( sCtx ); 176 | void* mem = pool.AllocForBxdf< SetPDisp >(1); 177 | 178 | // Create an instance of this shader's RixDisplacement object 179 | // and pass its parameter data to it. 180 | SetPDisp* disp = new (mem) SetPDisp( sCtx, this, 181 | detail_Enable, 182 | Enable, 183 | cinfo_Q, 184 | Q 185 | ); 186 | 187 | return disp; 188 | } 189 | 190 | 191 | /* 192 | * These are the entrypoints to the plugin from the renderer. 193 | */ 194 | extern "C" PRMANEXPORT RixDisplacementFactory* CreateRixDisplacementFactory( RtConstString hint ) 195 | { 196 | return new SetPFactory(); 197 | } 198 | 199 | extern "C" PRMANEXPORT void DestroyRixDisplacementFactory( RixDisplacementFactory* dFac ) 200 | { 201 | delete static_cast< SetPFactory* >( dFac ); 202 | } 203 | -------------------------------------------------------------------------------- /ris/displayfilter/Annotate.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 Laika, LLC. Authored by Mitch Prater. 3 | * 4 | * Licensed under the Apache License Version 2.0 http://apache.org/licenses/LICENSE-2.0, 5 | * or the MIT license http://opensource.org/licenses/MIT, at your option. 6 | * 7 | * This file may not be copied, modified, or distributed except according to those terms. 8 | */ 9 | /* 10 | * Annotates the rendered image with the supplied text. 11 | */ 12 | #include 13 | #include FT_FREETYPE_H 14 | #include FT_GLYPH_H 15 | 16 | #include "RixPredefinedStrings.hpp" 17 | #include "RixDisplayFilter.h" 18 | #include "RixIntegrator.h" 19 | 20 | class Annotate : public RixDisplayFilter 21 | { 22 | private: 23 | 24 | RixMessages* rixMsg; 25 | 26 | // InstanceData Definition. 27 | struct textImage 28 | { 29 | // text upper left corner display pixel location. 30 | int xpos; 31 | int ypos; 32 | 33 | // 8 bit rendered text image. 34 | int xsize; 35 | int ysize; 36 | unsigned char* alpha; 37 | }; 38 | 39 | struct localInstanceData 40 | { 41 | static void Delete( RtPointer ); 42 | RixChannelId InputId; 43 | RixChannelId OutputId; 44 | RixChannelId AlphaId; 45 | RtColorRGB Color; 46 | textImage Text; 47 | }; 48 | 49 | void setInstanceData( 50 | RixContext &, 51 | const RtUString, 52 | const RixParameterList *, 53 | InstanceData * 54 | ); 55 | 56 | // GenerateTextImage() declaration. 57 | void GenerateTextImage( 58 | const RixParameterList*, 59 | FT_Face, 60 | int, 61 | int, 62 | int, 63 | int, 64 | int, 65 | int, 66 | textImage* 67 | ); 68 | 69 | // WriteTextPixel() declaration. 70 | void WriteTextPixel( 71 | const textImage*, 72 | const RtColorRGB*, 73 | const int, 74 | const int, 75 | const bool, 76 | RtColorRGB*, 77 | RtFloat* 78 | ); 79 | 80 | enum ui_Id 81 | { 82 | ui_Text = 0, 83 | ui_Color, 84 | ui_Top, 85 | ui_Left, 86 | ui_Height, 87 | ui_Font, 88 | 89 | ui_Input, 90 | ui_Output, 91 | ui_Alpha 92 | }; 93 | 94 | public: 95 | 96 | Annotate() {} 97 | ~Annotate() {} 98 | 99 | const RixSCParamInfo* GetParamTable() 100 | { 101 | static RixSCParamInfo s_ptable[] = 102 | { 103 | // inputs. 104 | RixSCParamInfo( RtUString( "Text" ), k_RixSCString ), 105 | RixSCParamInfo( RtUString( "Color" ), k_RixSCColor ), 106 | RixSCParamInfo( RtUString( "Top" ), k_RixSCFloat ), 107 | RixSCParamInfo( RtUString( "Left" ), k_RixSCFloat ), 108 | RixSCParamInfo( RtUString( "Height" ), k_RixSCFloat ), 109 | RixSCParamInfo( RtUString( "Font" ), k_RixSCString ), 110 | 111 | RixSCParamInfo( RtUString( "Input" ), k_RixSCString ), 112 | RixSCParamInfo( RtUString( "Output" ), k_RixSCString ), 113 | RixSCParamInfo( RtUString( "Alpha" ), k_RixSCInteger ), 114 | 115 | RixSCParamInfo() 116 | }; 117 | 118 | return &s_ptable[0]; 119 | } 120 | 121 | // Create and Synchronize InstanceData definitions. 122 | void CreateInstanceData( 123 | RixContext& Ctx, 124 | const RtUString plugNodeName, 125 | const RixParameterList* pList, 126 | InstanceData* instanceData 127 | ) { 128 | instanceData->synchronizeHints = RixShadingPlugin::SynchronizeHints::k_All; 129 | } 130 | 131 | void SynchronizeInstanceData( 132 | RixContext& Ctx, 133 | const RtUString plugNodeName, 134 | const RixParameterList* pList, 135 | uint32_t editHints, 136 | InstanceData* instanceData 137 | ) { 138 | setInstanceData( Ctx, plugNodeName, pList, instanceData ); 139 | return; 140 | } 141 | 142 | // Get pointers to Rix interfaces. 143 | int Init( RixContext& Ctx, RtUString const plugPathName ) 144 | { 145 | rixMsg = static_cast< RixMessages* >( Ctx.GetRixInterface( k_RixMessages )); 146 | return ( !rixMsg ) ? -1 : 0; 147 | } 148 | 149 | // Filter() declaration. 150 | void Filter( 151 | RixDisplayFilterContext &, 152 | RtPointer 153 | ); 154 | 155 | // Parent class virtual methods, so must define them even though they're no-ops. 156 | void Finalize( RixContext& ) {} 157 | void Synchronize( RixContext&, RixSCSyncMsg, const RixParameterList* ) { } 158 | }; 159 | 160 | /* 161 | * GenerateTextImage definition. 162 | */ 163 | void Annotate::GenerateTextImage( 164 | const RixParameterList* pList, 165 | const FT_Face face, 166 | const int size, 167 | const int xres, 168 | const int yres, 169 | const int ui_Text, 170 | const int ui_Top, 171 | const int ui_Left, 172 | textImage* TextImage 173 | ) { 174 | RtUString Text( Rix::k_empty ); 175 | pList->EvalParam( ui_Text, 0, &Text ); 176 | 177 | // Short-circuit for an empty Text string. 178 | if( Text == Rix::k_empty ) 179 | { 180 | TextImage->alpha = NULL; 181 | return; 182 | } 183 | 184 | // Get the x,y display position for the Text. 185 | RtFloat Top( 0.0f ); 186 | pList->EvalParam( ui_Top, 0, &Top ); 187 | 188 | RtFloat Left( 0.0f ); 189 | pList->EvalParam( ui_Left, 0, &Left ); 190 | 191 | TextImage->ypos = std::round( Top * yres ); 192 | TextImage->xpos = std::round( Left * xres ); 193 | 194 | // Convert Text to C string. 195 | const char* text = Text.CStr(); 196 | const int textLen = Text.Length(); 197 | 198 | // 199 | // Determine the text's alpha image dimensions based on the Text's characters. 200 | // 201 | // Set the glyph image transformation to zero. 202 | FT_Vector pen; 203 | pen.x = 0; 204 | pen.y = 0; 205 | FT_Set_Transform( face, NULL, &pen ); 206 | 207 | // Render the first character's glyph bitmap into the face->glyph "slot". 208 | FT_Load_Char( face, text[0], FT_LOAD_RENDER ); 209 | const FT_GlyphSlot slot = face->glyph; 210 | 211 | // Save its alpha image starting x offset. 212 | const int xstart = -( slot->bitmap_left ); 213 | 214 | // Save its character width (in 1/64 pixel units). 215 | FT_Pos textWidth = slot->advance.x; 216 | 217 | // Highest pixel above the baseline (baseline=0, + is up). 218 | int textTop = int( slot->bitmap_top ); 219 | 220 | // Lowest pixel below the baseline, minus 1 (baseline=0. Would need to add 1 to get the actual pixel location). 221 | int textBottom = int( slot->bitmap_top - slot->bitmap.rows ); 222 | 223 | // Process the remaining characters. 224 | for( int c=1; c < textLen; ++c ) 225 | { 226 | // Render the character's glyph bitmap into the face->glyph "slot". 227 | FT_Load_Char( face, text[c], FT_LOAD_RENDER ); 228 | const FT_GlyphSlot slot = face->glyph; 229 | 230 | // Accumulate the character width (in 1/64 pixel units). 231 | textWidth += slot->advance.x; 232 | 233 | // Highest pixel above the baseline (baseline=0, + is up). 234 | textTop = std::max( textTop, int( slot->bitmap_top )); 235 | 236 | // Lowest pixel below the baseline, minus 1 (baseline=0. Would need to add 1 to get the actual pixel location). 237 | textBottom = std::min( textBottom, int( slot->bitmap_top - slot->bitmap.rows )); 238 | } 239 | 240 | // 241 | // Generate the Text string's bitmap alpha image. 242 | // 243 | const int xsize = int( textWidth >> 6 ) + 1; // Convert to pixels. 244 | const int ysize = textTop - textBottom; // Since we didn't add 1 when computing textBottom, 245 | // we don't need to add 1 to ysize. 246 | // Save the text image dimensions. 247 | TextImage->xsize = xsize; 248 | TextImage->ysize = ysize; 249 | 250 | // Allocate the text image memory. 251 | const int alphaSize = xsize * ysize; 252 | TextImage->alpha = new unsigned char[ alphaSize ]; 253 | 254 | // Convenience pointer. 255 | unsigned char* alphaImage = TextImage->alpha; 256 | for( int i=0; i < alphaSize; ++i ) alphaImage[i] = 0; // Zero data. 257 | 258 | // Reset the pen position. 259 | // Start at the xstart offset of the first character. pen is in 1/64 pixel units. 260 | // We could also set this to 0, and add xstart to the alphaIndex (x), but this is more optimized. 261 | pen.x = xstart << 6; 262 | pen.y = 0; 263 | 264 | // For each character. 265 | for( int c=0; c < textLen; ++c ) 266 | { 267 | // Set the glyph image transformation to the current pen location. 268 | FT_Set_Transform( face, NULL, &pen ); 269 | 270 | // Render the character's glyph bitmap into the face->glyph "slot". 271 | FT_Load_Char( face, text[c], FT_LOAD_RENDER ); 272 | const FT_GlyphSlot slot = face->glyph; 273 | 274 | // Left edge of this character. 275 | int x = slot->bitmap_left; 276 | // Offset from the image top (y=0) to put this character's baseline at the image's baseline row. 277 | int y = textTop - slot->bitmap_top; 278 | 279 | // Loop over this glpyh's bitmap and merge it into the text image. 280 | const FT_Bitmap bitmap = slot->bitmap; 281 | for( int j=0; j < bitmap.rows; ++j ) for( int i=0; i < bitmap.width; ++i ) 282 | { 283 | const int alphaIndex = x+i + (y+j)*xsize; 284 | if( 0 <= alphaIndex && alphaIndex < alphaSize ) 285 | { 286 | alphaImage[ alphaIndex ] = std::max( alphaImage[ alphaIndex ], bitmap.buffer[ i + j*bitmap.width ] ); 287 | } 288 | } 289 | 290 | // Advance the pen position. 291 | pen.x += slot->advance.x; 292 | } 293 | } 294 | 295 | /* 296 | * WriteTextPixel definition. 297 | */ 298 | void Annotate::WriteTextPixel( 299 | const textImage* TextImage, 300 | const RtColorRGB* Color, 301 | const RtInt x, 302 | const RtInt y, 303 | const bool useAlpha, 304 | RtColorRGB* Input, 305 | RtFloat* Alpha 306 | ) { 307 | if( TextImage->alpha ) 308 | { 309 | const int xsize = TextImage->xsize; 310 | const int ysize = TextImage->ysize; 311 | const int xpos = TextImage->xpos; 312 | const int ypos = TextImage->ypos; 313 | 314 | // Is the x,y display pixel within the text image? 315 | if( xpos <= x && x < xpos+xsize && ypos <= y && y < ypos+ysize ) 316 | { 317 | // Get the text image pixel's alpha value. 318 | const unsigned char* alpha = TextImage->alpha; 319 | const float a = float( alpha[ x-xpos + (y-ypos)*xsize ] )/255.0f; 320 | 321 | // Modify the display pixel. 322 | *Input = RixMix( *Input, *Color, a ); 323 | if( useAlpha ) *Alpha = a + *Alpha*( 1.0f-a ); 324 | } 325 | } 326 | } 327 | 328 | /* 329 | * Delete and Set Instance Data. 330 | */ 331 | void Annotate::localInstanceData::Delete( RtPointer data ) 332 | { 333 | localInstanceData* iData = static_cast< localInstanceData* >( data ); 334 | 335 | if( iData->Text.alpha ){ delete[] iData->Text.alpha; } 336 | 337 | delete iData; 338 | } 339 | 340 | void Annotate::setInstanceData( 341 | RixContext& Ctx, 342 | const RtUString plugNodeName, 343 | const RixParameterList* pList, 344 | InstanceData* instanceData 345 | ) { 346 | // If we've already created instanceData, free it first so we can synchronize with the latest settings. 347 | if( instanceData->data && instanceData->freefunc ) instanceData->freefunc( instanceData->data ); 348 | 349 | // Init instanceData. 350 | instanceData->datalen = 0; 351 | instanceData->data = NULL; 352 | instanceData->freefunc = NULL; 353 | instanceData->paramtable = NULL; 354 | 355 | // Create new local instance data. 356 | localInstanceData* iData = new localInstanceData; 357 | if( !iData ) return; 358 | 359 | // Get render state and integrator environment. 360 | RixRenderState* rixRS = static_cast< RixRenderState* >( Ctx.GetRixInterface( k_RixRenderState )); 361 | 362 | const RixIntegratorEnvironment* rixIE; 363 | { 364 | RixRenderState::FrameInfo rixFI; 365 | rixRS->GetFrameInfo( &rixFI ); 366 | 367 | rixIE = static_cast< const RixIntegratorEnvironment* >( rixFI.integratorEnv ); 368 | } 369 | 370 | // Get image dimensions in pixels. 371 | RixRenderState::FrameInfo frameInfo; 372 | rixRS->GetFrameInfo( &frameInfo ); 373 | 374 | const int xres = frameInfo.displayState.resolution[0]; 375 | const int yres = frameInfo.displayState.resolution[1]; 376 | 377 | // 378 | // Get the display channel Id's. 379 | // 380 | RtUString Input( Rix::k_Ci ); 381 | pList->EvalParam( ui_Input, 0, &Input ); 382 | 383 | RtUString Output( Rix::k_Ci ); 384 | pList->EvalParam( ui_Output, 0, &Output ); 385 | 386 | RtInt Alpha = 1; 387 | pList->EvalParam( ui_Alpha, 0, &Alpha ); 388 | 389 | // Init Id's. 390 | RixChannelId InputChannelId = k_InvalidChannelId; 391 | RixChannelId OutputChannelId = k_InvalidChannelId; 392 | RixChannelId AlphaChannelId = k_InvalidChannelId; 393 | 394 | // Find matching channels. 395 | for( int i=0; i < rixIE->numDisplays; ++i ) 396 | { 397 | if( rixIE->displays[i].channel == Input ) InputChannelId = rixIE->displays[i].id; 398 | if( rixIE->displays[i].channel == Output ) OutputChannelId = rixIE->displays[i].id; 399 | if( Alpha == 1 && rixIE->displays[i].channel == Rix::k_a ) AlphaChannelId = rixIE->displays[i].id; 400 | } 401 | 402 | // Error check. 403 | if( InputChannelId == k_InvalidChannelId ) 404 | { 405 | rixMsg->Warning( "The Input channel \"%s\" is invalid.", Input); 406 | delete iData; 407 | return; 408 | } 409 | 410 | if( OutputChannelId == k_InvalidChannelId ) 411 | { 412 | rixMsg->Warning( "The Output channel \"%s\" is invalid.", Output); 413 | delete iData; 414 | return; 415 | } 416 | 417 | if( Alpha == 1 && AlphaChannelId == k_InvalidChannelId ) 418 | { 419 | rixMsg->Warning( "The Alpha channel was not found." ); 420 | delete iData; 421 | return; 422 | } 423 | 424 | // Set instanceData. 425 | iData->InputId = InputChannelId; 426 | iData->OutputId = OutputChannelId; 427 | iData->AlphaId = AlphaChannelId; // k_InvalidChannelId if not using alpha. 428 | 429 | // 430 | // Get Font data and initialize the type face. 431 | // 432 | iData->Color = RtColorRGB( 1.0f, 0.7f, 0.0f ); 433 | pList->EvalParam( ui_Color, 0, &iData->Color ); 434 | 435 | // Determine text size in pixels. 436 | RtFloat Height = 0.03f; 437 | pList->EvalParam( ui_Height, 0, &Height ); 438 | 439 | const int size = std::max( 8.0f, std::round( Height * yres )); 440 | 441 | // Get the desired font file. 442 | RtUString Font( Rix::k_empty ); 443 | pList->EvalParam( ui_Font, 0, &Font ); 444 | 445 | // Init FreeType library. 446 | FT_Library library; 447 | FT_Init_FreeType( &library ); 448 | 449 | // Get the type face (i.e. font) from the specified file. 450 | FT_Face face; 451 | FT_Error err = FT_New_Face( library, Font.CStr(), 0, &face ); 452 | 453 | if( err ) 454 | { 455 | rixMsg->Warning( "Error accessing Font file \"%s\" err = %d", Font, err ); 456 | delete iData; 457 | } 458 | else 459 | { 460 | // Set the font's rendered glyph's em-square pixel height (and width). 461 | FT_Set_Pixel_Sizes( face, 0, size ); 462 | 463 | // Generate the Text Image iData. 464 | Annotate::GenerateTextImage( pList, face, size, xres, yres, ui_Text, ui_Top, ui_Left, &( iData->Text )); 465 | 466 | // Done with FreeType face. 467 | FT_Done_Face( face ); 468 | 469 | // Set instanceData to iData. 470 | instanceData->datalen = sizeof( *iData ); 471 | instanceData->data = static_cast< void* >( iData ); 472 | instanceData->freefunc = localInstanceData::Delete; 473 | } 474 | 475 | // Done with FreeType library. 476 | FT_Done_FreeType( library ); 477 | } 478 | 479 | 480 | /* 481 | * Filter definition. 482 | */ 483 | void Annotate::Filter( 484 | RixDisplayFilterContext& fCtx, 485 | RtPointer instanceData 486 | ) { 487 | // Retrieve the non-connectable parameter values. 488 | const localInstanceData* iData = static_cast< const localInstanceData* >( instanceData ); 489 | 490 | // Nothing to do. 491 | if( !iData ) return; 492 | 493 | const bool useAlpha = iData->AlphaId != k_InvalidChannelId; 494 | 495 | // Loop over the current bucket of display pixels. 496 | for( int y = fCtx.ymin; y < fCtx.ymax; ++y ) 497 | for( int x = fCtx.xmin; x < fCtx.xmax; ++x ) 498 | { 499 | RtColorRGB Input; 500 | fCtx.Read( iData->InputId, x, y, Input ); 501 | 502 | RtFloat Alpha; 503 | if( useAlpha ) fCtx.Read( iData->AlphaId, x, y, Alpha ); 504 | 505 | Annotate::WriteTextPixel( &( iData->Text ), &( iData->Color ), x, y, useAlpha, &Input, &Alpha ); 506 | 507 | fCtx.Write( iData->OutputId, x, y, Input ); 508 | if( useAlpha ) fCtx.Write( iData->AlphaId, x, y, Alpha ); 509 | } 510 | } 511 | 512 | 513 | /* 514 | * These are the entrypoints to the plugin from the renderer. 515 | */ 516 | RIX_DISPLAYFILTERCREATE 517 | { 518 | return new Annotate(); 519 | } 520 | 521 | RIX_DISPLAYFILTERDESTROY 522 | { 523 | delete static_cast< Annotate* >( filter ); 524 | } 525 | -------------------------------------------------------------------------------- /ris/displayfilter/Args/Annotate.args: -------------------------------------------------------------------------------- 1 | 9 | 10 | 11 | 12 | 13 | 14 | 18 | 19 | Annotate the rendered image with the supplied Text. 20 | 21 | 22 | 23 | 27 | 28 | Text to composite into the image. 29 | 30 | 31 | 32 | 36 | 37 | The Color of the Text. 38 | 39 | 40 | 41 | 46 | 47 | Determines where the Top of the Text will be located. 48 |

49 | In NDC coordinates: upper left (0,0) to lower right (1,1). 50 |
51 | 52 | 53 | 58 | 59 | Determines where the Left edge of the Text will be located. 60 |

61 | In NDC coordinates: upper left (0,0) to lower right (1,1). 62 |
63 | 64 | 65 | 70 | 71 | Character Height as a percentage of the image height (NDC space). 72 | 73 | 74 | 75 | 80 | 81 | The file containing the desired Font. 82 |

83 | On linux systems, these are typically in /usr/share/fonts. 84 |
85 | 86 | 87 | 91 | 92 | The name of the display channel to be annotated. 93 | 94 | 95 | 96 | 100 | 101 | The name of the display channel to write the annotated image to. 102 | This may be the same as the Input. 103 | 104 | 105 | 106 | 111 | 112 | Include the Text's alpha in the alpha (a) channel. 113 | 114 | 115 | 116 |
117 | -------------------------------------------------------------------------------- /scene/Teapot.katana: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LaikaStudios/shading-library/b9032f49cf034746645fe3e4a97a6b5ea2f0268c/scene/Teapot.katana -------------------------------------------------------------------------------- /scene/Teapot_Annotated.katana: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LaikaStudios/shading-library/b9032f49cf034746645fe3e4a97a6b5ea2f0268c/scene/Teapot_Annotated.katana -------------------------------------------------------------------------------- /wiki_images/Annotate.params.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LaikaStudios/shading-library/b9032f49cf034746645fe3e4a97a6b5ea2f0268c/wiki_images/Annotate.params.png -------------------------------------------------------------------------------- /wiki_images/Annotate.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LaikaStudios/shading-library/b9032f49cf034746645fe3e4a97a6b5ea2f0268c/wiki_images/Annotate.png -------------------------------------------------------------------------------- /wiki_images/Material_v2_NMC.macro.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LaikaStudios/shading-library/b9032f49cf034746645fe3e4a97a6b5ea2f0268c/wiki_images/Material_v2_NMC.macro.png -------------------------------------------------------------------------------- /wiki_images/Material_v2_NMC.params.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LaikaStudios/shading-library/b9032f49cf034746645fe3e4a97a6b5ea2f0268c/wiki_images/Material_v2_NMC.params.png -------------------------------------------------------------------------------- /wiki_images/Material_v2_Shaders.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LaikaStudios/shading-library/b9032f49cf034746645fe3e4a97a6b5ea2f0268c/wiki_images/Material_v2_Shaders.png -------------------------------------------------------------------------------- /wiki_images/Teapot.katana.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LaikaStudios/shading-library/b9032f49cf034746645fe3e4a97a6b5ea2f0268c/wiki_images/Teapot.katana.jpg -------------------------------------------------------------------------------- /wiki_images/material_v2_PxrSurface.params.expanded.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LaikaStudios/shading-library/b9032f49cf034746645fe3e4a97a6b5ea2f0268c/wiki_images/material_v2_PxrSurface.params.expanded.png -------------------------------------------------------------------------------- /wiki_images/material_v2_PxrSurface.params.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LaikaStudios/shading-library/b9032f49cf034746645fe3e4a97a6b5ea2f0268c/wiki_images/material_v2_PxrSurface.params.png -------------------------------------------------------------------------------- /wiki_images/material_v2_PxrSurface.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LaikaStudios/shading-library/b9032f49cf034746645fe3e4a97a6b5ea2f0268c/wiki_images/material_v2_PxrSurface.png --------------------------------------------------------------------------------