Halloween Costume ideas 2015

OSL / Wooly Mummy OSL

Up until today, I believe I have spent over 100+ hours to study about OSL (Open Shading Language). I believe that's a good first steps for someone who never wrote Shaders before.

Maybe this shader can also be called Mummy OSL Shader.

I know I am still very much a beginner in Shader Writing. There are still plenty of things about OSL that I honestly do not understand. For most of part, I understand it in certain way, but maybe someone in the future will correct me or help me to understand it better.

I am still confused about Closure in OSL, for example. So far, I am only dealing with Procedural Texture creation in OSL.

With better understanding of the code, I think we can create our own Closure. However, we can actually mix and match the pre-built closures like Diffuse, Glass, Glossy, etc. within a single node. Lots of power. But I think before we get there, I like to focus with procedural Texture creation and design.

This post is a little intermezzo to note  down what I have learned so far on OSL, how I got this far. Hopefully if you are also starting to write OSL from zero, you can pickup a thing or two.

TEXTURE CREATIONS: NODE OR CODE?

Things are surely a lot easier when we connect nodes to create Shader, right? Cycles Node Network is brilliant as it is, so easy to use to create beautiful render using the built in nodes. It is quite a robust system already.

The additional Script Node that allows us to write our own node using OSL is even making Cycles in Blender more amazing. It is not yet GPU accelerated as of today, OSL is still CPU only render, but I still find it pretty fast and great to try ideas.

Interestingly enough, I found that whenever I rewrite a snippet of code that actually recreates the same thing of what the built-in node can already do (Noise, Voronoi, Cellnoise, etc), I gain a little more layers of knowledge.

I figure that a lot of interesting procedural textures are all based on Noise function. By layering Noise function, we create turbulance. And turbulance texture itself is really good powerful for adding details.

With a bit of knowledge of shader writing, it is as if now I am starting to be able to see better, to break down and to think about Texture (procedurally or non procedurally) in more details and also simplified at the same time.

Shader writing (RSL, OSL, GLSL, etc) is really quite challenging area but also rewarding experience. Perhaps shader writing is not for everyone, but you should try first.

As a prequisite, it helps to know a little bit about programming (Python is my basis, but I knew a bit of MEL scripting which is a little bit like C) in order to learn to write and code shader. Good grasp of programming concept should be ok to get you started in shader writing.

I remember the first time writing OSL, by following and rewriting code that is shown by other great Blender Artists and Developers out there.

  • Thomas Dingto
  • Geofrey..

RSL to OSL

"I have to learn and understand RSL (RenderMan Shading Language) in order to understand OSL!". That is the sentence that kept telling myself whenever I am stuck.

There are materials out there that talk about Shader Writing. I tried to read and digest all the available RenderMan books at the library that I (am lucky enough) to have access to. Some of the RenderMan books are already pretty dusty and many years old.

Here are list of the books I could find at the UTS (University of Technology of Sydney) Library:

  • The RenderMan Shading Language Guide
  • Advanced RenderMan: Creating CGI for Motion Pictures
    http://www.larrygritz.com/arman/materials.html
  • Essential RenderMan
  • Rendering for beginners : image synthesis using RenderMan
  • The RenderMan companion : a programmer's guide to realistic computer graphics

I probably can grasp about 25-30% of those materials, I have to re-read them again in the near future if I need to get deeper.

There are so many amazing RSL Shaders I discover along the way.

Some shaders are SIMPLE but very CLEVER and actually a good exercise for beginner:
  • Bowling Pin
  • Pencil
  • Ruled Paper
  • Watermelon
  • Banana
  • Woods

The issue with learning RenderMan is ACCESS to it. Like everything in life, often it is all about ACCESS to the tool and the materials.

I am currently using Pixar Photorealistic RenderMan (PRMan) to dig RenderMan. I happened to have access to it, thanks to one nice guy from Pixar. Since I have this privilege, I definitely MUST take this opportunity to study and use the tool while I can.

However, if one does not have access to PRMan, 3Delight is a good alternative.

It is only recently that I look into RenderMan properly and its latest development with their Physically Plausible GPShaders (General Purpose Shaders), I can see how things have changed over the years. PRMan implementation inside Maya is fantastic. It is really a lot easier to get a highly realistic render.

ONLINE SOURCES FOR RSL AND OSL

Ok, so apart from those great legacy books on RenderMan to read, there are plenty of online materials that are really helpful.

Pixar's documentation of RenderMan:
http://renderman.pixar.com/resources/current/rps/rslFunctions.html

Although RSL is not OSL, they have similarities.

This online note by Steve May (Pixar) actually the one that finally clicks with my brain.
http://accad.osu.edu/~smay/RManNotes/index.html

Malcolm Kesson's priceless RSL materials at FUNDZA
http://www.fundza.com/

Inigo Quilez notes and YouTube
http://www.iquilezles.org/www/articles/distfunctions/distfunctions.htm
http://www.iquilezles.org/www/articles/functions/functions.htm

Check ShaderToy:
https://www.shadertoy.com/

MY FIRST SHADER: OSL Wooly

I hope that this shader is pretty original.

This took nearly 3 hours to render... but looks quite nice.

It is very simple actually, started with just 2 stripes, originated from this RLS shader:
http://accad.osu.edu/~smay/RManNotes/RegularPatterns/transitions.html#cross_tile

I also found some hints from:
http://www.fundza.com/rman_shaders/surface/index.html
http://www.fundza.com/rman_shaders/displacement/index.html

I figure that I could introduce 2 kind of "randomization". We don't really use random function in shader writing I think.

Let me quote Larry Gritz from OSL Developer Thread:

"I can't really think of a good use for random(), since you can't guarantee the order of shading, it wouldn't be stable from run to run.  The only thing I can think of is for use in sampling, but (a) the whole point of OSL is that you don't need to be doing sampling in the shader anymore, and (b) even if you did, it would be better for us to think of a way to provide specialized functions that were reproducible and better-stratified than just having a uniform RNG. 

As for hash(), the idea there was something like the cellnoise trick.  What I had in mind was just using a strong has on the floating point bits of whatever you passed in (like the hash we use on the integer lattice values to generate infinite, non-repeating cellnoise values). 

Since nobody seems to care enough to notice that these are unimplemented, I'm fine with removing them from the spec.  We can always add them back if we decide that there is a legit use case. "


The "random" and "details" can apparently come from:
1. Random color per object.
http://blenderartists.org/forum/archive/index.php/t-277986.html
2. Random by multi-layering the same texture using simple loops.

This one post from BlendBits actually has snippet of "random function" using Cellnoise function.
http://blendbits.blogspot.com.au/2013/05/lens-flare-shader-for-blender-cycles.html

Champagne Gold with lots of Colors stripes. Sounds familiar?

Wooly OSL Shader is very simple. Just repetition of lines that is rotated slightly. It is a 2D texture.

Maybe with the same idea, we can create Pokemon Ball OSL Shader.



Here, at BlenderThings blog, again it introduces one shader that uses "randomization".
http://blenderthings.blogspot.com.au/2012/12/a-hagelslag-sprinkles-osl-shader-for.html

Out of curiosity, I often plug one OSL Shader into another Shader. In this case below I plug the Sprinkles OSL into my Wooly OSL Shader:

Interesting cartoony style NPR shader, not perfect, but has potential.

Shaders that are using multi-layers randomization is indeed slow to render, but looks nice and detailed. With Blender, "slow render" is not an easy, we can always have unlimited render farm.

Over one hour and still rendering a single frame...
I tried combining this shader with pre-built nodes in Cycles:


TAKING WOOLY OSL SHADER TO THE NEXT STAGE

At current stage, I think Wooly OSL Shader is still a work in progress. I would like so that each line is more 3D like thread, with a bit of shadowing whenever it overlaps layer below it.

I think some OSL experts out there can probably take it to high level production ready shader.

These concepts below are crucial to understand and able to write OSL:

  • PROGRAMMING CONCEPT >> Variable declaration, Loop, .... 
  • STRUCTURE & CONSTRUCT >> we can write OSL in whatever way we like, however without proper planning, we could easily get lost with the code. following a good construct and having a plan will help us to have manageable and flexible reusable code.
  • MATH & BASIC FUNCTIONS: sin(), cos(), atan2(), smoothstep(), 
  • INCLUDE >> When you see word INCLUDE, usually that is when we source some snippet or macro or helper functions that is bundled as external file.
  • LAYERS & BLENDING >> I only found this concept quite recently and I would like to implement my previous OSL writing so that every "shape" or "texture" created procedurally can be easily layered on top of one another.

REWRITING THE WOOLY SHADER FROM SCRATCH...

The whole code is like this:

THE CODE: WOOLY OSL SHADER

(TO BE CLEANED UP)

/* ALL HELPER FUNCTIONS COME BEFORE THE ACTUAL SHADER */

void rotate2d (

    float x,
    float y,
    float rad,
    float ox,
    float oy,
    float rx,
    float ry
)
{
    rx = ((x) - (ox)) * cos(rad) - ((y) - (oy)) * sin(rad) + (ox);
    ry = ((x) - (ox)) * sin(rad) + ((y) - (oy)) * cos(rad) + (oy);
}


color blend(

    color a,
    color b,
    color x
)

{

    return ((a) * (1-(x)) + (b) * (x));
}

float pulse (

    float a, 
    float b, 
    float fuzz, 
    float x
)
{
    return (smoothstep((a)-(fuzz), (a), (x)) - smoothstep((b)-(fuzz), (b), (x)));
}





/* THE ACTUAL SHADER CODE BELOW */


shader crosstile(

    float rot = 45,
    color Cs = color(1.0),
    color Os = color(1.0),
    float fuzz = 0.05,
    int seed = 231,
    int iteration = 10,
    vector Pos = P,
    output color Oi = color(0.2),
    // output color Ci = color(0.2),
    output color Col_Out = color(0.5)
)
{
    // we have to do this in OSL
    // becayse we do not have Global Variable s and t
    float s = Pos[0];
    float t = Pos[1];

    // background layer

    color surface_color = Cs;
    color surface_opac = Os;
    
    // initialize layer
    color layer_color = color(0.1);
    color layer_opac = color(0.2);
    
    /*
    // vertical bar layer
    layer_color = color(0.1,0.5,0.22);
    layer_opac = pulse(0.35, 0.65, fuzz, s);
    surface_color = blend(surface_color, layer_color, layer_opac);
    */
    
    // THANKS FOR CODE SNIPPET
    // http://blendbits.blogspot.com.au/2013/05/lens-flare-shader-for-blender-cycles.html
    
    // Generate repeatable sequences of 'random' numbers - based on nrand and seed settings.
     float nrand = 0;
          
     // Random helper function
     float urand () {
       nrand += 1; 
       return cellnoise(nrand, seed);
     } 


    // multiple rotating bars with random values

    float ss;
    float tt;
    float power;
    for (float i=0.0; i<iteration; i++){
    
        // want random
        float Random=0;
        float R=0;
        float G=0;
        float B=0;
        getattribute("object:random", Random);
        R=trunc(Random*100.0)/100.0;
        G=trunc((Random*100.0-trunc(Random*100.0))*100.0)/100.0;
        B=trunc((Random*10000.0-trunc(Random*10000.0))*100.0)/100.0;
        
        rotate2d(s,t,radians(rot * i * urand()), 0.5*urand(), 0.5*urand(), ss, tt);   
        //layer_color = color(0,(i+1)/iteration,0);
        layer_color = color((i+1)/iteration * urand(), G*0.5 , B*0.4);
        layer_opac = pulse(0.50, 0.55, fuzz, tt);
        surface_color = blend(surface_color, layer_color, layer_opac);
    }

  for (float i=0.0; i<iteration; i++){
    
        // want random
        float Random=0;
        float R=0;
        float G=0;
        float B=0;
        getattribute("object:random", Random);
        R=trunc(Random*100.0)/100.0;
        G=trunc((Random*100.0-trunc(Random*100.0))*100.0)/100.0;
        B=trunc((Random*10000.0-trunc(Random*10000.0))*100.0)/100.0;
        
        rotate2d(s,t,radians(rot * i * urand()), 0.5*urand(), 0.5*urand(), ss, tt);   
        //layer_color = color(0,(i+1)/iteration,0);
        layer_color = color((i+1)/iteration * urand(), G*0.5 , B*0.4);
        layer_opac = pulse(0.50, 0.55, fuzz, ss);
        surface_color = blend(surface_color, layer_color, layer_opac);
    }

    
    /*
    // horizontal bar layer
    layer_color = color(0.1,0.1,0.3);
    layer_opac = pulse(0.35, 0.65, fuzz, t);
    surface_color = blend(surface_color, layer_color, layer_opac);
    */
    
    // output if we need to specify CLOSURE
    
    Oi = surface_opac;
    // Ci = surface_opac * surface_color;
    Col_Out = surface_opac * surface_color;
    
}


I want to show step by step process how I get to the current look of Wooly OSL Shader.

(TO BE ADDED)

BONUS: SPLINE FUNCTION

Spline function is like Color Ramp node in Cycles. Allowing us to have multiple color array to blend. Useful for things like FIRE.

color colorarray[X] = { .... }

spline("linear", colorarray ....


BONUS: PULSE FUNCTION

Pulse is like the combination of smoothstep...

OTHER LINKS

Post a Comment

MKRdezign

Contact Form

Name

Email *

Message *

Powered by Blogger.
Javascript DisablePlease Enable Javascript To See All Widget