Shader writing with OSL - 2
I've been experimenting with shader writing using OSL for Redshift in Cinema 4D. I did some work with OSL a few years ago during the development of Cycles for C4D by Insydium. My ultimate aim is to write some new shaders for Redshift using OSL, but clearly, the way to start is by looking at some shaders that already exist for Redshift and seeing how they work. There is an OSL shader repository on Github, but you can only get so much from existing, known working shaders. The next step is to try converting some existing OSL scripts for other renderers to Redshift, and you can learn a lot from that.
Given that I already had a number of working shaders from various sources which I knew worked in Cycles (the C4D implementation), this seemed a good place to start. But it turned out that it wasn't as simple as it first looked. Generally speaking, the shaders fell into three categories when attempting to convert them.
1. OSL shaders which load and run in Redshift without problems, or needing only a small alteration
These are pretty few in number in the collection I had. Take a very simple shader which produces a camo pattern in Cycles:
In Redshift, it does this:
It seems apparent that the only problem is one of scale, and altering the scale parameter gave this result:
This is identical to the Cycles version, allowing for the expected differences in colour management and lighting between the two engines. That's a very simple fix.
2. OSL shaders which don't work in Redshift without a significant modification to the code or scene
There's a shader which produces a result like this in Cycles:
It's very simple - just takes two colours and returns a colour part way betwen the two, but in Redshift it renders black and in the OSL node messages box you see this output:
D:\Documents\C4D Plugins\OSL_files\OSL-Shaders-Pack1\ChHueRamp\ChHueRamp.osl:4: error: error: could not find include file: oslutil.h
Could not compile shader
Looking at the OSL file, these two lines are the problem:
#include "oslutil.h"
#include "node_color.h"
The reason it won't compile the shader is that Redshift can't find the two include files oslutil.h
(and node_color.h
will also flag an error if you manage to fix the first file). A quick search through the Redshift installation folder shows they aren't present, but in Cycles, there is a library folder which contains them. So in this case, if we can find these files we should be able to copy them to, well, somewhere and the shader will work, right?
The file oslutil.h
is actually part of the OSL source code (you can find the complete source on Github) and if you go to the folder src/shaders you can download and use it. The second, node_color.h
, is more tricky. Cycles is a render engine from Blender, and indeed, looking in the Blender source code we can find it. But where to put the files? After some trying, it turns out that as you might expect they should be placed in the same folder as the OSL script file, but - and here's the annoying issue - it seems that you have to restart C4D before Redshift will see them. This is really odd ( I could understand it if they had to be placed in the Redshift installation folder) but there doesn't seem to be any way around it. Even clearing the Redshift caches doesn't help. Anyway, doing that and once again altering the scale fixes the problem.
A more complex problem is with a script from Mitch Prater's book which returns a colour derived from the surface tangent vector. This script fails in both Cycles and Redshift. The problem is this part of the code:
vector tangent;
// get the inbuilt variable 'Tn' and store it in 'tangent'
getattribute("builtin", "Tn", tangent)
// etc...
However, there is no warning or error message - the shader just returns black. This is because the getattribute()
function is part of OSL, so the script compiles correctly. The problem is that which attributes the function can return is dependent on the render engine. In this case, the tangent vector is returned by Renderman - it's a built-in variable for that engine - but not by Cycles or Redshift. In this particular case though, there is a workaround for Redshift. The State node returns a variety of attributes for the point being shaded, including the tangent we want. Altering the script to add a vector input and linking that to the tangent output of the State node will then give this rather nice effect:
3. OSL shaders which cannot work in Redshift
Look at this line from a script which in Cycles produces a dark red velvet surface:
{
BSDF = (Color * diffuse(Normal)) +
(Specular * ashikhmin_velvet(Normal, Roughness));
}
In Redshift it fails with this error warning:
BaVelvet.osl:21: error: function 'ashikhmin_velvet' was not declared in this scope
Could not compile shader
In Cycles, this function is compiled into the Cycles render engine itself, but in Redshift it isn't. There doesn't seem to be any way around this, so to produce a working velvet shader in Redshift would need a complete rewrite.
The conclusion from all this is that converting OSL shaders to work in Redshift can be problematic. This is not Redshift's fault: in the main, it is the additions to the various render engines that can kill cross-engine compatibility of OSL scripts.
Until next time, I am continuing to work on these scripts and I will try to make some additional scripts available for download.
Page last updated November 11th 2024