Halloween Costume ideas 2015

OSL / Using Google Plotting For Visualizing Functions in OSL

One only really knows how deep the water when he jumps, otherwise he will only be touching the surface.

After reading that book titled "Open Shading Language for Blender" by Michel Anders which I reviewed in previous post, I decided to revisit some of previous OSL topics and hopefully can make some parts clearer and will explore further some basic concepts.

From this post onward, I am going to write OSL shaders following the structure that Michel uses. And I will probably use some snippet of codes from Michel book, such us when we like to Rotate or Scale or to Mirror procedural textures. When I do so, I will give credit to Michel.

My focus is still on the Procedural Texture and Patterns Generation only, but overtime, I want to also start discovering some useful OSL features we can use.

CONTROLLING SIGNAL USING THE FORCE

I use word "The Force" in the previous posts to help some beginners to grasp the basic concept of pattern generation. Whenever using "The Force", we are really using Math FUNCTIONS (2D or 3D functions) that generates pattern or further modify and reshape pattern. It is okey, you can still think of function as the force.

As you may already see in previous posts, the easiest way we can apply a FUNCTIONS and to actually generate a procedural texture is: to insert the function as a FACTOR of mix() function that will then modulate between 2 colors. The mix() function does this kind of job of MIXING 2 colors really well as we can see later.

Ok, if above paragraph might sound very alien to you, do not worry, I am really going to go back to the basic and slowly building up the complexity.

MATH, FUNCTIONS, AND OSL

Function is a "magical force" that takes input and gives you an output. The "magical force" is Math operations. The Math can be very simple like addition, but can also be really complex.

We do not need to worry about the complexity of functions, all we need to care is to know which function does what to the input and just apply it to get the output.

In computer graphics, we really use functions all the time. Maybe some of you have some computer animation background and you know that you can graph a motion.

With OSL, we will be dealing with function, but especially to see how function can modify and generate pattern of colors.

For example:
Let say we have a function (x + x), which takes input x.
If x = 2, function f(x + x) will give you result of 4.
If x = 4, function f(x + x) will give you result of 8.

We will be dealing with functions all the time when writing OSL.  Time to time, I refer to Renderman documentation on its built-in functions.
http://renderman.pixar.com/resources/current/rps/rslFunctions.html
http://web.engr.oregonstate.edu/~mjb/prman/shaderfunctions.html

INCLUDE
If you see #include notation at the beginning of OSL shader, it means that the shader loads some additional functions in C language that we can use later. <-- Let me know if I am wrong, I am only guessing.

For example:
#include "stdosl.h"

This is stdosl.h file if you open it and look inside. It has some additional variable we can use such as M_PI, etc.

Of course not all functions in Renderman available in OSL, but there are plenty of similar functions, and we can always create/write own function that mimics certain function.
  • sin(), cos() -> wave pattern
  • mod() aka MODULUS
  • abs()
  • sign()
  • step()
  • max()
  • min()
  • smoohstep()
  • ...

More interesting function:
  • distance()
  • noise() -> this function comes in many multiple forms




I want to slowly showing and visualizing each functions that are available in OSL by default and adding reference related to it. Read also OSL specification PDF documentation about functions.
http://www.openshading.com/osl/getting-started/

OSL AND MIX FUNCTION

I am afraid that I started to become very wordy, so now time to get inside Blender and start making things.

My favourite layout is like below:


STEP 001
shader basic_function(
    color ColA = color(1, 0, 0),
    color ColB = color(0, 1, 0),
    output color ColOut = color(0, 0, 1)
)
{
}

That OSL shader above is already working, but it really does nothing much other than:

  • Create color variable ColA and assign RED color.
  • Create color variable ColB and assign GREEN color.
  • With OSL shader to work, we need to have output, so we create a color output and assign it the default color of BLUE. Hence the shader resulting of plain BLUE color.
  • We have not done anything yet inside the shader. 
STEP 002
shader basic_function(
    color ColA = color(1, 0, 0),
    color ColB = color(0, 1, 0),
    output color ColOut = color(0, 0, 1)
)
{
    ColOut = mix(ColA, ColB, 0.5); 
}

We can do something like above which simply mixes 2 colors ColA and ColB and give a result of color that is yellowish. That is our first use of mix() function inside the shader.


Although that is not particularly interesting.

STEP 003
shader basic_function(
    point Pos = P,
    color ColA = color(1, 0, 0),
    color ColB = color(0, 1, 0),
    output color ColOut = color(0, 0, 1)
)
{
    float x = Pos[0];
    float y = Pos[1];
    float z = Pos[2];
    
    ColOut = mix(ColA, ColB, x); 
}

We modify the code and here we bring in P. P is a built-in Global Variable, it is basically storing the pixel position of a surface geometry.

P is really a set of array of 3 values that can be broken up into 3 x Float values, and for ease of use, we just tell Blender to think of it as the X, Y, Z.

Here, things started to get interesting. As you can see, we can mix the 2 colors using X, Y, or Z and it will give a result.


This is fine and dandy. Eventhough we are getting a result, it is still hard to figure out what is really happening in the background. Why is is when we insert the X into mix(), it gives us the result above? What does the function really do to the input values of P?


STEP 004: Experiment time!

COOL: Visualizing Function Using Google Search Plotter

A function can be more easily visualized using graph. The graph itself can be 2D or 3D. Thanks to Google, we can use Google Search to quickly plot graph of function.

For the above function, we are really just using the X values (that goes from minus infinity to zero all the way to positive infinity). And so we get that almost sharp blend between RED and GREEN.

Let's try below:

Google Search: x + y



Let's apply that function inside Blender:

Now, we can really see what is happening! That function is kind of mixing color by slicing into two big area inside square, so that whatever underneath the slice gets the RED and the other half gets the GREEN.

It is very exciting, let's continue with other functions!

Google Search: x * x



You see how it is just a bit touching and it gives that nice blurry red line along Y axis? Apparently we can get more blurry when we divide the X.


Let's try something different:

Google Search: abs(x)



Absolute function abs() will return the absolute value, when we insert X position, we are getting value that is always positive.

In term of writing the function, let's write it like below:

shader basic_function(
    point Pos = P,
    color ColA = color(1, 0, 0),
    color ColB = color(0, 1, 0),
    output color ColOut = color(0, 0, 1)
)
{
    float x = Pos[0];
    float y = Pos[1];
    float z = Pos[2];
    
    float f = abs(x);
    
    ColOut = mix(ColA, ColB, f); 
}

With the absolute function, we can further do something like maybe OFFSET the graph slightly above or below the axis, by modifying the function slightly:



You can see now how we can OFFSET or TRANSLATE that RED "line" quite easily.


Google Search: sin(x)




SNIPPET: sign() function


Google Search: sin(x) + sin(y)

Occasionally, Google gave back a 3D graph, like when we use function above. How would that affect our procedural texture inside OSL?


That is pretty interesting, right?


Of course, not everything can be graphed by Google Plotter, sometimes we need to further test it inside Blender, however, it is a good start. You can also use Wolfram Alpha sometimes for graphing, although the feature is limited unless you have pro account.

RIPPLE FUNCTION

If you do a bit more research on function, you might find "basic functions" that gives a pattern you need.

A quick search using Google leads me to this:

Very useful website and we can certainly borrow the example functions. Of course, things are not always clear cut and of the way we write the function may need to be converted to OSL way of writing function, for example:

x^2 => pow(x,2);

Things like this you learn by looking at examples, by trial and error, you gain experience.

Google Search: sin(10 * ((x/10)^2+(y/10)^2))/10

BLENDER OSL
shader basic_function(
    point Pos = P,
    color ColA = color(1, 0, 0),
    color ColB = color(0, 1, 0),
    output color ColOut = color(0, 0, 1)
)
{
    float x = Pos[0];
    float y = Pos[1];
    float z = Pos[2];
       
    float f = sin(10 * (pow(x/10,2)+pow(y/10,2)))/10;
    
    ColOut = mix(ColA, ColB, sign(f)); 
}




OTHER USEFUL FUNCTIONS

Based on this website:

POWER FUNCTION pow()
To increase the contrast. See below how we can implement it:


SAWTOOH WAVE FUNCTION

x - floor(x)

We can use Wolframalpha for graphing, but I do not like how Wolframalpha keeps asking to sign up for pro feature. So, usually I rely more on blogs and Wiki for informations.


The SAWTOOTH function is interestingly similar to MODULUS function graph, that we have used in previous post when we are generating repeating stripes pattern.


NOISE FUNCTION

noise(x) -> there are many ways we can use the noise function.

Noise gives output that range from 0-1, some other noise may give different range.


Noise function is one of the most interesting and useful functions to generate procedural pattern that is more natural and less repetitive.






cellnoise()


Those are all just the basic of functions, hopefully you can understand this part alright.

SINGLE DOT

I think I wrote about how we can create a single dot using OSL, after reading Michel's book, I am thinking to revisit the idea. It is basically related to distance() function.


distance() and sin()


distance() & modulus mod()



Disturbing the HSV Color Space using Noise.




FURTHER TWEAKING.... or FURTHER TWERKING WITH SHADER? (Updated: 2013.11.28)


sign() function results in texture that is crisp, I think we can assume it creates -1 or 1, no in between. This might be good, but in some cases, we actually want a bit of blur/fuzz, so that we do not get moire pattern. This relates to Anti-Aliasing.

Above started to look like WOOD or WATERMELON shader. However, we need to remember the LAYERING method that I mentioned in the previous post.

It's fun to play around with Math function. Sometimes you get interesting complex pattern by accident. For me, the harder parts will be:
  • To understand what is happening and use it to advantage
  • To make distinction of 2D and 3D procedural texture
  • To organize the shader code so it can be expanded
Maybe with more experience, thing gets a lot easier.

FURTHER SHADER TWEAKING: Combining Star Shader and Other Snippet
THE CODE:
#include "stdosl.h"

shader DPStar(
    int npoints = 5,
    float sctr = 0.5,
    float tctr = 0.5,
    color Color_A = color(1,0,0),
    color Color_B = color(0,1,0),
    float rmin = 0.07,
    float rmax = 0.2,
    float freq = 1.0,
    point Pos = P, // added this so that Vector can be plugged
    output color Col_Out = color(0.8)
)

{
    float PI = M_PI; 
    float ss;
    float tt;
    float angle;
    float r;
    float a;
    float in_out;
    float starangle = 2*PI/npoints;
    
    point p0 = rmax * point(cos(0),sin(0),0);
    point p1 = rmin * point(cos(starangle/2),sin(starangle/2),0);
    
    point d0 = p1 - p0;
    point d1;
    
    float x = Pos[0];
    float y = Pos[1];
    
    ss = x - sctr;
    tt = y - tctr; // s t become u v or X and Y
    angle = atan2(ss, tt) + PI;
    r = sqrt(ss*ss + tt*tt);
    a = mod(angle, starangle)/starangle;
    
    if (a >= 0.5)
        a = 1 - a;

    d1 = r * point(cos(a), sin(a),0) - p0;

    in_out = step(0, d1[0]);
    

    // snippet of my little code
    point myPoint = point(0,0,0);
    float f = distance(d1, a);
    
    Col_Out = mix(Color_A,Color_B, sin(f * freq));
   
}

Psychedelic Christmas..?


ADD NOISE FUNCTION....

THE CODE:
#include "stdosl.h"

shader DPStar(
    int npoints = 5,
    float sctr = 0.5,
    float tctr = 0.5,
    color Color_A = color(1,0,0),
    color Color_B = color(0,1,0),
    float rmin = 0.07,
    float rmax = 0.2,
    float freq = 1.0,
    point Pos = P, // added this so that Vector can be plugged
    output color Col_Out = color(0.8)
)

{
    float PI = M_PI; 
    float ss;
    float tt;
    float angle;
    float r;
    float a;
    float in_out;
    float starangle = 2*PI/npoints;
    
    point p0 = rmax * point(cos(0),sin(0),0);
    point p1 = rmin * point(cos(starangle/2),sin(starangle/2),0);
    
    point d0 = p1 - p0;
    point d1;
    
    float x = Pos[0];
    float y = Pos[1];
    
    ss = x - sctr;
    tt = y - tctr; // s t become u v or X and Y
    angle = atan2(ss, tt) + PI;
    r = sqrt(ss*ss + tt*tt);
    a = mod(angle, starangle)/starangle;
    
    if (a >= 0.5)
        a = 1 - a;

    d1 = r * point(cos(a), sin(a),0) - p0;

    in_out = step(0, d1[0]);
    

    // snippet of my little code
    point myPoint = point(0,0,0);
    float f = distance(d1, a);
    
    Col_Out = mix(Color_A,Color_B, sin(f * freq * noise(f, freq)));
   
}

It feels like Christmas alraedy!
How to turn this shader into something that looks more like "explosion", does anyone know? If you do, please let me know. Thanks!


OTHER LINKS

Post a Comment

MKRdezign

Contact Form

Name

Email *

Message *

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