Creating the hSurface shader
The surface shader should be able to be used in a production. So I will implement all necessary features step by step. Fortuateley I will not have to define and create any microsurface sampling functions or something similiar. Almost all shader API's offer built-in functions which enables the user to build custom shaders from these function.
e.g. in OSL you have a closure called diffuse(N), which calculates the diffuse reflection. You do not have to care about the details of the calculation, just use it.
The plan is to have a Maya shader and write translations for the different renderers. The idea is that I can write an osl shader for Arnold, 3delight and Appleseed and reuse it. To be able to see how it works with different engines, I implement the features step by step and not all features in one go. So the very first feature is a simple diffuse shading with color and roughness.
So the first step is to write an Maya shader what is quite easy because I can use Python for a shading plugin. The shader is available here. In the first implementation I do not care about the correct display in Maya's Viewport 2.0 since this procedure can drive me crazy. This first step works fine if the plugin path for Maya is set correctly. The shader appears as Hypershade node, I can assign it and use it. Since all rendering should be done in an plugin renderer, we do not care about speed. The python plugin is just a placeholder for all the shader settings. The different renderers should be able to read these attribute and use the appropriate shader implemenation.
Since Arnold is the default renderer in Maya these days, I first implemented the shader in OSL for Arnold. The shader is available in the repository and starts simply. Only one Oren-Nayar closure is calculated, nothing special. It should work out of the box for Arnold and all other OSL material supporting renderers.
So I set the ARNOLD_PLUGIN_PATH to the correct directory where the osl sourcefile is located and started Maya. Arnold compiled the shader automatically and created the oso file which is used for rendering. And the result looks like this:
Not too exciting, but it works. That's the basis to continue with...
Compared to Arnold, 3Delight needs a bit more work. Here it is important that the OSL output closure of the surface shader is called outColor unless Maya will crash if a node of this type is created. 3Delight works fine, and we have a full funcional free version for 12 cores what is really great for testing. The Maya renderview is not very well supported so the first advice is not to use it, but the 3delight viewer. A simple osl testshader without any Maya plugin counterpart loads fine and is translated as expected. But this procedure does not work with an exisiting Maya plugin node. If there is already a node called hSurface, 3delight skips the shader load process (Skipping duplicate 'hSurface'). I try to solve this problem.
Appleseed needs some metadata to recognize the shader as Appleseed shader. The metadata have to include the string as_maya_classification = "drawdb/shader/surface:shader/surface" info. It automatically seems to extract the needed informations for the AETemplate from the shader source what can result in a conflict if you already have an existing AETemplate. It only works if the shader template is loaded before loading the renderer plugin. But then it works as expected. This is the first result:
Not too bad I for the first try!
Before trying Cycles I have to learn the basics of Blender, will take a while. Then I'll try to render my scene with Cycles in Blender. Even if I still have to go a long way with Blender, I managed to import the geometry and OSL shader into Blender, assign the shaders and render with area lights. Here's the first result:
The lighting looks a bit different because I still have no clue how it really works and we seem not to have an option called "normalize" for arealights what is a bit tricky. It seems that fbx import is better than alembic import at the moment even if the rotations are screwed up. And the area lights behave a bit different as you can see in the shadows.
Renderman is a completly other thing. Since it only supports texture shaders but no surface shaders. I have to write it in C++. After some search I finally found a quite detailed description here. Let's see how it works. After some really helpful forum conversation, I downloaded the developers examples file with a bunch of bxdf source codes. Unfortunately, creating a own bxdf is not such a trivial task any more. You have to take care about creating samples and a lot of others tasks. I'm not yet sure if I will go this way or simply write a converter script.
Last update: 01.2021