In today’s post, we are going to use Open Shading Language (OSL) to make a slimy, translucent alien skin. The inspiration for this shader can be found on Youtube (cycles nodes). The full code is below. In addition, check out our Github repository, which has this shader plus several others. If you need a refresher on OSL, check out our intro to OSL post.
The Shader Model
The shader model is fairly simple.
BSDF = specular + diffuse + translucent
We add a clear coat on time to give it the overall shininess.
Specular
Specular is the easiest. We have two input factors that we use for specularity: specular and roughness. We feed these into the microfacet_ggx function. Specular is the amount of specularity. Roughness determines how rough the surface is. This affects whether the light bounces directly back to the view or not.
// Specular
closure color finalSpecular = microfacet_ggx(N, roughness) * specular;
Remember that N is a globally defined variable in OSL that describes the normal of the surface at the point being shaded.
Diffuse
The diffuse is also fairly simple:
// Diffuse
closure color finalDiffuse = diffuse(N) * (1-specular)*(1-transparency)*baseColor;
We simply multiply diffuse(N) by the base color and then give it a weighting that depends on the amount of specularity and transparency.
Translucent
The translucent component is the most complicated. We use the noise function to mix between translucent and transparent.
// Transparent/Translucent
closure color finalTransparent;
float mixNoise = 0.15*noise("usimplex",P*2);
if(mixNoise < 0.75)
{
finalTransparent = fleckColor*translucent(N) * (mixNoise * 2) * (1-specular)*transparency;
}
else
{
finalTransparent = transparent()*(1-specular)*transparency;
}
We use the usimplex option, which is unsigned (values between 0 and 1). We multiply the point by 2, which scales the noise larger.
If the noise is less than 0.75, we use translucent(). If it is greater than or equal we use transparent. Note that usimplex has an average value of 0.5, so in most cases, the value will be less than 0.75. We weight the output, depending on the specularity and the input transparency factor.
Clear Coat
The final step is to add a clear coat. We use the input ior (index of refraction) factor and the normal in a function called simple_fresnel. The OSL standard includes a fresnel function; however, it is more complicated than we need. Therefore, I added my own simple_fresnel function that is based on the same function in the Surface Car Paint OSL script from CG Lion.
We use another microfacet_ggx with a roughness of 0 multiplied by the output of the simple_fresnel equation (we call this the clear coat weight).
Full Code
Here is the full code:
// Simple Fresnel: Based on Surface Car Paint at https://cg-lion.com/2020/07/25/freebie-advanced-car-paint-osl-shader/
float simple_fresnel(normal nrm, float ior)
{
float r = pow( ( 1.0 - ior ) / ( 1.0 + ior ), 2.0 );
return r + ( 1.0 - r ) * pow( 1.0 - fabs( dot( -I, nrm ) ), 5.0 );
}
shader alien(
color baseColor=color(0,1.0,0),
color fleckColor=color(0.336,0,1.0),
float roughness=0.2,
float transparency=0.75,
float specular=0.25,
float ior=1.6,
float clearCoat=1.0,
output closure color bsdf=diffuse(N))
{
// Diffuse
closure color finalDiffuse = diffuse(N) * (1-specular)*(1-transparency)*baseColor;
// Transparent/Translucent
closure color finalTransparent;
float mixNoise = 0.15*noise("usimplex",P*2);
if(mixNoise < 0.75)
{
finalTransparent = fleckColor*translucent(N) * (mixNoise * 2) * (1-specular)*transparency;
}
else
{
finalTransparent = transparent()*(1-specular)*transparency;
}
// Specular
closure color finalSpecular = microfacet_ggx(N, roughness) * specular;
// Clear Coat
float clearCoatWeight = simple_fresnel(N,ior) * clearCoat;
bsdf = finalSpecular + finalDiffuse + finalTransparent;
bsdf = bsdf * (1-clearCoatWeight) + microfacet_ggx(N,0) * clearCoatWeight;
}
Conclusion
This is a fun shader that is not too complicated to understand. I would love to see renders that you create using this shader. Drop a link in the comments.
2 Comments
Comments are closed.