Hello OSL

.start

About

I finally got my hands on writing Open Shading Language (OSL) shaders after reading the OSL language specification.I am really blown away by the seamless integration of OSL with Blender Cycles Rendering Engine. I wrote two shaders today.

OSL Script #1

Before writing my first script, I implemented a simple idea using existing nodes. You can see the node network in the image below


And the OSL code that was attached to the Script node is below. This shaders basically outputs a color.
#include "stdosl.h"

shader this_or_that(
    color This = color(1,0,0),
    color That = color(0,1,0),
    int axis = 0,
    output color ThisOrThat = color(1,1,1)
)
{
point Position = P;
    if (Position[axis] < 0) {
        ThisOrThat = This;
    } else {
        ThisOrThat = That;
    }
}
In the preceding code, P is the position of the point being shaded and is a Global variable (a.k.a. Graphics state variable).

Following is an excerpt from the OSL language specification.
Global variables (sometimes called graphics state variables) contain the basic information that the renderer knows about the point being shaded, such as position, surface orientation, and default surface color. You need not declare these variables; they are simply available by default in your shader. Global variables available in shaders are: P, I, N, Ng, u, v, dPdu, dPdv, Ps, time, dtime, dPdtime and Ci.

What the script is doing is give us the ability to choose one axis and paint all vertices on the negative axis to red and green otherwise.

OSL Script #2

Also, thanks to a nice and simple script by an user on BlenderArtists, I modified that script as follows.
  1. Ability to receive Shading (N) or Geometric (Ng) Normal as input, so that that shading can be changed accordingly.
  2. And some minor refactoring to suit my programming style.
#include "stdosl.h"

shader toon_shader(
    normal Normal = N,
    color Highlight = 1,
    float HighAngle = 10.0,
    float HighBoost = 1,
    float Mid = 0.5,
    float MidAngle = 65.0,
    float Shadow = 0.25,
    output color Color = Highlight * Shadow
)
{
    float highValue = cos(radians(clamp(HighAngle, 0, 90)));
    float midValue  = cos(radians(clamp(MidAngle, 0, 90)));
   
    if(abs(dot(-I, Normal)) > midValue) {
        Color = Highlight * Mid;
    }
   
    if(abs(dot(-I, Normal)) > highValue) {
        Color = Highlight * HighBoost;
    }
}

OSL Script #2 - Refactor

In the osl code from previous section, on interchanging the order of evaluation of lines that calculate the Highlight and Midtone, the highlight in my render vanished. I asked around on the BlenderArtists forums and realized the mistake I made. Following is the modified shader
#include "stdosl.h"
shader toon_shader(
    normal Normal = N,
    color Highlight = 1,
    float HighAngle = 10.0,
    float HighBoost = 1,
    float Mid = 0.5,
    float MidAngle = 65.0,
    float Shadow = 0.25,
    output color Color = color(1, 0, 0)
)
{
    float highValue = cos(radians(clamp(HighAngle, 0, 90)));
    float midValue  = cos(radians(clamp(MidAngle, 0, 90)));
 
    float scalar = abs(dot(-I, Normal));
 
    if( scalar > highValue ) {
        Color = Highlight * HighBoost;
    } else  if( scalar > midValue ) {
        Color = Highlight * Mid;
    } else {
        Color = Highlight * Shadow;
    }
}

Also, now I am calculating the dot product of the Viewing and Normal vectors only once. But, I did not find that much of difference in render time. Should test it on larger scenes.

That's it for now. If you want to get started with OSL concepts, I recommend you to read OSL Introduction document and also SIGGRAPH 2012 Course: Practical Physically Based Shading in Film and Game Production

Once I gain more understanding of OSL, I will write detailed tutorials covering various aspects of shader authoring using OSL.

Behind The Scenes

This section contains some technical details that I noticed while recompiling the shaders and/or when there were script errors.

On recompiling the shader from the script node, the following message was printed in the konsole.
Info: OSL shader compilation succeeded
On choosing an axis value of 3 from the script node, the following  error was printed in the konsole.
ERROR: Index [3] out of range [0..2]: /usr/scratch/tmp5j47fg.osl:12
So I went searching for the file /usr/scratch/tmp5j47fg.osl but to no avail. Instead I found /usr/scratch/tmp9wzu0u.oso
OpenShadingLanguage 1.00
# Compiled by oslc 1.3.0
shader this_or_that
param   color   This    1 0 0            %read{4,4} %write{2147483647,-1}
param   color   That    0 1 0            %read{5,5} %write{2147483647,-1}
param   int     axis    0                %read{1,1} %write{2147483647,-1}
oparam  color   ThisOrThat      1 1 1            %read{2147483647,-1} %write{4,5}
global  point   P        %read{0,0} %write{2147483647,-1}
local   point   Position         %read{1,1} %write{0,0}
temp    float   $tmp1    %read{2,2} %write{1,1}
const   int     $const1 0                %read{2,2} %write{2147483647,-1}
temp    int     $tmp2    %read{3,3} %write{2,2}
code ___main___
# /usr/scratch/tmp5j47fg.osl:10
#     point Position = P;
        assign          Position P      %filename{"/usr/scratch/tmp5j47fg.osl"} %line{10} %argrw{"wr"}
# /usr/scratch/tmp5j47fg.osl:12
#     if (Position[axis] < 0) {
        compref         $tmp1 Position axis     %line{12} %argrw{"wrr"}
        lt              $tmp2 $tmp1 $const1     %argrw{"wrr"}
        if              $tmp2 5 6       %argrw{"r"}
# /usr/scratch/tmp5j47fg.osl:13
#         ThisOrThat = This;
        assign          ThisOrThat This         %line{13} %argrw{"wr"}
# /usr/scratch/tmp5j47fg.osl:15
#         ThisOrThat = That;
        assign          ThisOrThat That         %line{15} %argrw{"wr"}
        end
On my windows machine at home, I got the following results on errors in my shader
c:\\users\\lenovo\\appdata\\local\\temp\\tmpsu9usf.osl:12: error: shader parameter 'Color' MUST have a default initializer
Error: OSL script compilation failed, see console for errors
Another error
error: No shader function defined
Error: OSL script compilation failed, see console for errors 

References

Related Posts


.end
satishgoda at gmail dot com

Popular posts from this blog

Blender 2.64 - Tutorial - Intro to Masking (Rotoscoping)

Render Wedges using the Blender Video Sequence Editor