Showing posts with label pattern. Show all posts
Showing posts with label pattern. Show all posts

Irregular stone patterns in OSL, a first attempt

On the BlenderArtists forum a member was analyzing irregular stone walls and posed the interesting question: does this resemble a tree pattern and can it be done in OSL? Quite a lot of thinking and tinkering is needed for a full solution put in this post we explore some of the basic requirements.

Irregular stone patterns


A sample pattern with primary colors, Mondrian eat your heart out :-)
The sample image shows that we have generated a pattern consisting of rows with different heights, each consiting of stones of varying width. Additionally, some stones within a row are further split horizontally. The code to generate the pattern is shown below:
shader stones(
  point p = P,
  vector Scale = 1,
  float w = 0.02,
  float s = 2,
    
  output float Fac = 0
){
  point Pos = p * Scale;
  
  float bot = floor(Pos[1]-1)+cellnoise(Pos[1]-1);
  float lev = floor(Pos[1])+cellnoise(Pos[1]);
  float top = floor(Pos[1]+1)+cellnoise(Pos[1]+1);

  if( Pos[1] < lev ){
    Pos[0] += s*cellnoise(Pos[1]);
  }else{
    Pos[0] += s*cellnoise(Pos[1]+1);
  }
  float left = floor(Pos[0]-1)+cellnoise(Pos[0]-1);
  float mid = floor(Pos[0])+cellnoise(Pos[0]);
  float right = floor(Pos[0]+1)+cellnoise(Pos[0]+1);
  if( 
    ((Pos[0] > left+w) && ( Pos[0] < mid - w )) 
    || 
    ((Pos[0] > mid+w ) && ( Pos[0] < right - w))
  ){
    if( 
      ((Pos[1] > bot+w) && ( Pos[1] < lev - w )) 
      || 
      ((Pos[1] > lev+w ) && ( Pos[1] < top - w))
    ){
      int stoneindex=0;
      float seeda = left;
      float seedb = bot;
      float bounda = mid;
      float boundb = lev;
      
      if( Pos[0] > mid ){ stoneindex += 2; seeda = mid; bounda = right; }
      if( Pos[1] > lev ){ stoneindex += 1; seedb = lev; boundb = top; }
      int pattern = (int)floor(cellnoise(seeda,seedb)*4);
      if( pattern == 0 ){
            // horizontally halved
            float nlev = (seedb + boundb)/2;
            if( (Pos[1] > nlev - w) &&  (Pos[1] < nlev + w) ){
              Fac = 0;
            } else {
              Fac = cellnoise(vector(seeda,seedb,Pos[1]>nlev));
            }
      } else {
        Fac = cellnoise(vector(seeda,seedb,-1));
      }
    }
  }
}
(The code is also available on GitHub.)

Sample node setup

The example image at the top of this article was made with the following node setup (click to enlarge)
:

Further work

Obviously we need more sub patterns for the individual stones and add some distortion to the underlying coordinates to make really random stones. It would probably also be a good idea to vary the spacing between the stones and use the output value to drive displacement and bump maps and the code could certainly do with a bit of cleanup but I thinks this approach is at least shows promiss.

An OSL wood knot shader

Back in january I presented a wood shader that produces decent results but one of things that was missing was a way to add realistic knots to planks. In this article a present a shader that is meant as a first step in producing knots. It is not a finished shader yet, but it is fully functional as a texture warping tool and in a future article I might detail how to combine it with a wood shader and a shader to texture the inside of the knot properly. Because that will take some time so I thought it better to present it as a WIP as I am currently unable to spend more than a few minutes behind my desk (and there's no Blender for Android alas).

Warping space

The idea is quite simple and might be adaptable to more than just producing knots: we distribute points randomly and warp the position coordinates around these points. These warped coordinates are then used as the basis for a texture. In the example image we use the warped coordinates as the input to a bands texture:

As you can see the bands of the texture seem to flow around the knots as if they were repelled by them and in fact that is pretty much how the algorithm works.

Implementation


int bend(vector p, vector k, float r, float a, float m, output vector B){
vector D = k - p;
float L = length(D);
if( L < r ){
float c = L/r;
float d = m * pow( 1 - c , a);
if( d < L ){
B = d * normalize(D);
return 1;
}else{
B = D;
return 2;
}
}
return 0;
}

shader knot(
vector Pos = P,
float Scale = 5,

float R = 0.8,
float Falloff = 1,
float Strength = 0.9,
float Knots=0.5,

output vector Vec = P,
output float Fac = 0
){
vector p = Scale * Pos;
vector sdp = 0;

float TR = ceil(R);
for(float dx=-TR; dx <= TR; dx++){
for(float dy=-TR; dy <= TR; dy++){
for(float dz=-TR; dz <= TR; dz++){
vector ip = floor(p)+vector(dx,dy,dz);
for(int ik=0; ik < (int)Knots; ik++){
vector k = noise("cell",ip,ik);
vector dp= 0;
int ret = bend(p,ip+k,R,Falloff,Strength,dp);
if(ret != 0){
Fac=max(Fac,ret==2);
sdp+=dp;
}
}
if( noise("cell",ip,-1) < mod(Knots,1.0) ){
vector k = noise("cell",ip,-2);
vector dp= 0;
int ret = bend(p,ip+k,R,Falloff,Strength,dp);
if(ret != 0){
Fac=max(Fac,ret==2);
sdp+=dp;
}
}
}
}
}
if( Fac < 1 ){
Vec = p + sdp;
}else{
Vec = sdp;
}
}
The magic is in the bend() function. It calculates the difference vector from the point being shaded to the center of the repulsion. If the distance is short enough, a translation vector is returned that is a distance dependent fraction of the difference vector. It takes some thinking to see that in order to create the illusion of repulsion we actually have to replace the point being shaded towards the center of repulsion: remember that at the point we are shading we want to see the lines closer to the center.

When we calculate the translation towards the center and we are close enough to it, we might overshoot the center point. In which case we return a value of 2, signalling we are inside the knot and return not the translated shading point but the vector pointing to the center (which might be useful to render some concentric pattern in the knot).

The shader itself is nothing more than checking if we might be in range of one of the randomly distributed points and calling the bend() function to do the actual work. We do allow for a fractional number of knots per unit cell, in which case the fraction acts as the probability that a knot might occur.

Room for improvement

Obviously knots are not spherical marbles embedded randomly in some wood but as the remnants of branches they are more reminiscent of stubby cylinders which might be better modeled by determining the distance to a randomly oriented line segment instead, something I intend to implement in the near future.

Another area that needs attention is to way the inside of the knot appears. In the example setup we produced some concentric circles but a real knot is a bit more complex than that.

An overview of Gabor noise parameters

In this post we tabulate some of the parameters of Gabor noise as provided in Cycles'Open Shading Language.

In a previous post I presented a small OSL node that gives access to the fairly new Gabor noise that is available in OSL. I already showed some examples of how to use it and made an attempt to implement a fabric shader based on this noise. To help visualize the parameters of this noise I made the overview shown below (click to enlarge):

Gabor noise has tree modes:

  • Isotropic
  • Anisotropic
  • Mixed
These modes are triggered by the values 0, 1 and 2 of the anisotropic parameter. In isotropic mode the direction parameter is ignored but in the other modes the length and direction of this vector determine the frequency and the direction of the anistropy.

The impulses parameter determines the number of features (bumps) present per unit area, whereas the bandwidth parameter determines how much detail of these bumps is visible.

In the image above the colored squares show a systematic variation of these parameters. Gabor noise has a value between [-1, 1] centered around zero (the green in the colored examples). The black and white examples show some specific patterning that is possible if you choose suitable cutoffs for the noise values. They we created using the following node setup:

Note that the add/divide nodes on the left to nothing more than map the [-1, 1] range to [0, 1]. The less than/ more than nodes in combination with the multiply node pass on a value if its between the two limits or zero otherwise.

OSL leaf veins shader for Cycles

When we look at images the addition of veins greatly adds to the preceived realism of rendered leaves and in this article I present a simple veins shader that complements the leaf shader discussed previously.

Leaf veins

I forgot to update the page that describes equations.h (thanks samblerdevel for pointing that out). I just corrected that so if you had any errors complaining abot a function splinedist() that was missing, download & install equations.h and try again

The node setup used to create the leaf shape and veination in the close-up image above is relatievely complicated and presented at the end of this article. Luckily, the basic stuff of generating vein patterns is not that complicated so lets have a look at that first.

As illustrated in the images above the veins in the leaf are all represented by cubic splines, starting at the red dots on the central vein and curving to the green end points on the edge of the leaf. Their curvature is controled by the blue control points. A node setup for the image above looks like this:
The Angle and L parameters mimic the ones in the leaf shape shader and are kept the same in this case to let the endpoints of the veins coincide with the actual leaf edge. The number of veins, their distribution, width and the way they curve are controlled by the Veins, Width, Squish and Up parameters as we will see later on. Their is some randomness in the placement as well which can bee influenced by the Seed and Var parameters. The outputs consist chiefly of a Vein socket which will be one for a vein, and a Fac socket which is the square root of the distance to the center of the vein and can be used to drive displacement.

The code for this node is shown below makes use of the equations.h include discussed in the article on leaf shapes.


#include "equations.h"

shader arcuateveins(
point Pos = P,
int Veins = 7,
int Seed = 42,
float Var = 0,
float Width = 0.05,
float NWidth = 0.25, // size of the reticulated area

float Squish = 0.5, // distribution of endpoints on edge
float Squish2 = 0.5, // distribution of controlpoints
float Squish3 = 0.5, // distribution of starting points
float Up = 0.5,

float Angle1 = 70,
float L1 = 1,
float Angle2 = 70,
float L2 = 1,

output float Vein = 0,
output float Net = 0,
output float Fac = 0
){

float delta = 1.0/((float)Veins+1);
float delta2= delta/2;
float delta4= delta/4;

// calculate the four control points of the cubic spline that defines the leaf edge
float x1,y1,x2,y2;
sincos(radians(Angle1),y1,x1);
sincos(radians(Angle2),y2,x2);
point P0 = point(0 , 0 ,0);
point P1 = point(x1 , y1,0)*L1;
point P2 = point(1-x2*L2, y2*L2,0);
point P3 = point(1 , 0 ,0);

point P0q = point(P0[0],P0[1]*Up,P0[2]);
point P1q = point(P1[0],P1[1]*Up,P1[2]);
point P2q = point(P2[0],P2[1]*Up,P2[2]);
point P3q = point(P3[0],P3[1]*Up,P3[2]);

int i;
for(i=0;i < Veins;i++){

// determine the starting points of the veins
float x = (i*delta+delta2*Var*cellnoise(i+10+Seed))*Squish3;
float dx = (delta4*Var*cellnoise(i+17+Seed))*Squish3;
point P0up = point(delta2+x+dx,0,0);
point P0down = point(delta2+x,0,0);
// determine the endpoints on the leaf edge
float t=(i*delta+delta2)*Squish+1-Squish;
point P2up = cubicspline(t,P0,P1,P2,P3);
point P2down = point(P2up[0],-P2up[1],P2up[2]);
// the veins are quadratic splines, so need one additional control point
t=(i*delta+delta2)*Squish2+1-Squish2;
point P1up = cubicspline(t,P0q,P1q,P2q,P3q);
point P1down = point(P1up[0],-P1up[1],P1up[2]);

float r;
int f = splinedist(P0up, P1up, P2up, Pos, r, t);
if ( f && (r < NWidth ) ) Net = 1 ;
if ( f && (r < Width * ( 1- t) * (1-Pos[0]) ) ) { Vein = 1; Fac = sqrt(1-r/Width); break; }
f = splinedist(P0down, P1down, P2down, Pos, r , t);
if ( f && (r < NWidth ) ) Net = 1 ;
if ( f && (r < Width * ( 1- t) * (1-Pos[0]) ) ) { Vein = 1; Fac = sqrt(1-r/Width); break; }
}

// the central vein
float d = distance(point(0,0,0),point(1,0,0),Pos);
if ( d < NWidth ) Net = 1 ;
if (d < (Width * (1-Pos[0])) ) { Vein = 1; Fac = sqrt(1-d/Width);}
}

Relation to real venation patterns in leaves

The shader in its current form is able to model pinnate and arcuate venation patters and intermediate forms of these. (For an explanation of terminolgy refer to Wikipedia, especially this overview sheet). Its spline-based modelling of the veins is not based on any underlying theory of the formation of veins as it happens in nature, as these reaction-diffusion equations cannot so easily be implemented in an OSL shader (at least not at present: we wouldn't want to redo such a costly simulation again and again for each point being shaded so we would need peform the simulation before we start shading each pixel. Currently there is no facility for adding something to a shader that will be executed once beforehand, although there might be in the future. An alternative approach might be to perform the simulation, maybe in a Python add-on, and store the result in a texture. Here we opted for art before science: if it looks all right we don't care what it is based on).

Controlling the curve shape of the veins

In the following images I have illustrated how you can control the shape of the veins. How much the starting points on the central vein and the control points in the middle and the end points on the leaf edge are bunched up, is controlled by the Squish parameters. The blue control points all lie on a spline that is a copy of the spline that defines the leaf edge by scaled by the Up parameter. Some experimenting shows that is is possible to create both pinnate venation patterns as well as arcuate patterns:

Example node setup

The leaves in the image at the top of this article were created with the following node setup:

The values in the blue box simultaneously control the shape of the leaf edge both in the leaf shader and in the vein shader. The leaf coloring is controled by the nodes in the green box (leaves are both glossy and translucent) while the vein coloring is is defined by the nodes in the red box, the choice being determined by the Vein output socket of the vein shader. The yellow box provides some noisy patterns to drive both the colloration of the leaf as well as mix with the bump patern from the vein shader to drive the displacement. The exact contribution of these displacements is controlled by the purple nodes.

Room for improvement

Although the shader is already quite versatile there is ample room for imrpovement. For example, I would like it to be able to produce palmate vein patters and to control the narrowing towards the tips of the veins. On the other hand the shader is not limited to producing vein pattersn: I imagine it can be used to produce fish bones and bird feather patterns (barbs) as well. I might expand on that in the future.

A OSL leaf shape shader for Cycles

In this first part of a series I present a simple shader that can be used to generate different leaf shapes. In later articles we will add shaders that produce the veins of the leaf.

Simple leaf shape with cubic splines

In the example image we have used the IvyGen addon to generate a single limb of some climbing plant species and used the shader from this article to produce the leaf shapes The node setup for this specific material is dicussed later on. (the stone texture is from cgtextures.com and was converted to a normal map and a displacement map with Shadermap CL. The backplate and environment lighting are from the Topanga Forest B collection by Blochi as found on Sibl archive)

The leaf shape shader is essentially creates one side of a leaf from a cubic spline and mirrors that to the other side to create a symmetrical shape. The spline that is used has four controls.

It starts on the left in the direction of P1 and ends on the right coming from the direction of P2. The lenght and angles of the vectors going to P1 and P2 are inputs to the shader. Some of the shapes you can create are shown below.
Note that it is also possible to define a shape that crosses itself in which case the behavior of the shader is undefined.

The annotated code for the shader is shown below. It includes a small library of functions that will be reused by shaders that will appear on this blog in the near future and this include has its separate page where you can download it and find installation instructions.


#include "equations.h"

shader leaf(
point Pos = P,
float Angle1 = 70,
float L1 = 1,
float Angle2 = 70,
float L2 = 1,
output float Leaf = 0
){

// calculate the four control point of the cubic spline
float x1,y1,x2,y2;
sincos(radians(Angle1),y1,x1);
sincos(radians(Angle2),y2,x2);
point P0 = point(0 , 0 ,0);
point P1 = point(x1 , y1,0)*L1;
point P2 = point(1-x2*L2, y2*L2,0);
point P3 = point(1 , 0 ,0);

// to determin the y value(s) of the spline at the x position we
// are located, we want to solve spline(t) - x = 0
// we therefore gather all factors and solve the cubic equation
float tfactor[4] = { P0[0]-Pos[0],
3*P0[0]+3*P1[0],
3*P0[0]-6*P1[0]+3*P2[0],
P0[0]+3*P1[0]-3*P2[0]+P3[0] };
float t[3];
int nrealroots;
cubic(tfactor, t, nrealroots);

// at this point, the array t holds up to 3 real roots
// remove any real root that is not in range [0,1]
int i=0;
while(i < nrealroots){
if ((t[i] < 0) || (t[i] > 1)) {
int j=i;
while(j < (nrealroots-1)){
t[j]=t[j+1];
j++;
}
nrealroots--;
}
i++;
}

// note that a cubic funtion can have 3 real roots,
// but in this case we ignore such very warped curves
// TODO: w. 3 real roots w could set leaf = 1, if y < y0 OR y between y1,y2
// TODO: seration, possible by determining the closest
// distance (if inside leaf) to the spline and
// determining if w are within some periodic funtion f(t)

// we generate the shape mirrored about the x-axis
float y = Pos[1];
if(y<0) y = -y;

if(nrealroots > 0){
point Sy0 = cubicspline(t[0],P0,P1,P2,P3);
if(nrealroots > 1){
// if we have 2 roots we calculate and order the y values
// and check whether the current y values is between them
point Sy1 = cubicspline(t[1],P0,P1,P2,P3);
if ( Sy1[1] < Sy0[1] ){
if( (y > Sy1[1]) && (y < Sy0[1]) ) Leaf = 1;
}else{
if( (y > Sy0[1]) && (y < Sy1[1]) ) Leaf = 1;
}
}else{
// with a single value we check if we are below the y value
if( y < Sy0[1] ) Leaf = 1;
}
}
}

Example node setup

The node setup used to create the sample shapes look like this:

As you can see there is nothing fancy going on here. The leaves are simple squares with a reset uv-map and a mapping node is used to position the leave onto this square (in this case rotated 90 degrees). The output of the shader is then used to drive a mix shader which shows some green material where there is a leaf and a fully transparent material where there isn't.

Combining things with the Ivy Generator

The sample image at the beginning was create with the IvyGen addon. The leaves it produces are simple square faces that are not connected but nevertheless consist of a single mesh object. Because we want to orient each individual leaf a bit different we need a random number for each leaf. We therefore have to separate each face into its own object.

The workflow to achieve that then becomes:

  1. Create your ivy
  2. Assign the material shown in the noodle below to the leaf object
  3. Goto edit mode
  4. Select all
  5. Select Mesh->Vertices->Separate->By loose parts
  6. Go back to object mode.
Each leaf now is its own object we our leaf material attacthed.

Example node setup II

The noodle consists of three distinct parts:
  • The green part adds a small random rotation around the z axis to each uv map. This will be different for each individual leaf. The actual rotation is done by another OSL shader (given below) because the vector mapping node cannot be driven by inputs.
  • The red part maps the rotated uv to the correct position before handing it to our leaf shader. This mapping is necessary because the squares created by IvyGen are sort of centered on the vines and we want our leaves to protrude from the vined instead of being pierced by them.
  • The blue part is just a simple mottled green shader with some gloss.

The rotation of the uv-map arond the z-axis is performed by an OSL shader because the vector mapping node has no inputs to control the rotation and it would take a lot of vector math nodes to achieve what we want whereas thanks to OSL this rotation is a no-brainer:


shader rotate_z(
point Pos = P,
float Angle = 0,
output point Pout = P
){
Pout = rotate(Pos,radians(Angle),point(0,0,0),point(0,0,1));
}

Next steps

In a next article I will show how to add veins to the leaf shapes.

A chainmail OSL shader in Blender Cycles

A golden oldie reimplemented in OSL: a simple 4-in-1 chainmail pattern.
If you want to know more about chainmail patterns, both historical and contemporary ones, you might like to visit artofchainmail.com or cgmaille.com.

In the picture ob the left I used the chainmail shader to generate the pattern on the neck flap. The picture was created with a wood texture from cgtextures.com for the table top but all other textures are procedural. The scene was lit using the Prov-Wash HDRI maps by Alex Hart as found on hdrlabs.com. I think it is a kind of museum and that fits the helmet setting nicely.
Like the barbwire and chainlink shaders the shader presented in this article is again essentially nothing more than a simple black and white pattern with the distance to the center of the line added as a feature to aid in generating bumps. The difficulty here is to get all those overlaps correct as can be seen in the enlarged cut out selection shown on the right.


#include "stdosl.h"

int between(float v, float a, float b){ return v >= a && v <= b; }
float arc(float r, float a, float b) { return sqrt(0.5-abs(0.5-((r-a)/(b-a)))); }
float rmap(float a, float b, float ra[3] ){
 if ( between(ra[0], a, b) ) { return ra[0]; }
 if ( between(ra[1], a, b) ) { return ra[1]; }
 if ( between(ra[2], a, b) ) { return ra[2]; }
 return -1;
}

float basepattern(float r1, float r2, float r3, int fx, int fy, float Rm, float Rp){
 float x0y0[3] = {r3, r1, r2};
 float x0y1[3] = {r2, r3, r1};
 float x1y0[3] = {r1, r3, r2};
 float x1y1[3] = {r2, r1, r3};
 
 float r = -1;
 if ( fx ){
  if ( fy ) {
   r = rmap(Rm, Rp, x1y1);
  } else {
   r = rmap(Rm, Rp, x1y0);
  }

 } else {
  if ( fy ) {
   r = rmap(Rm, Rp, x0y1);
  } else {
   r = rmap(Rm, Rp, x0y0); 
  }
 }
 return r;
}

shader chainmail4in1 (
 point Pos = P,
 float Scale = 1,
 float Radius = 0.47,
 float Width = 0.08,
 output float Fac = 0,
 output float Disp = 0
){
 point p = Pos * Scale ;
 float x = mod(p[0],1);
 float y = mod(p[1],1);
 
 float Rm = Radius - Width;
 float Rp = Radius + Width;
 
 float r=-1,r1,r2,r3,cr1,cr2,cr3;
 
 int fx = 0, fy = 0 , flip = y > x, flipt = y > ( 1 - x );
 if ( x > 0.5 ){ x = 1 - x ; fx = 1; }
 if ( y > 0.5 ){ y = 1 - y ; fy = 1; }
 
 r1 = hypot(x-0.5,y-0.5);
 r2 = hypot(x-0.5,y+0.5);
 r3 = hypot(x+0.5,y-0.5);
 
 float xc = mod(p[0]+0.5,1);
 float yc = mod(p[1]+0.5,1);
 
 int fxc = 0, fyc = 0, flipc = y > x;
 
 if ( xc > 0.5 ){ xc = 1 - xc ; fxc = 1; }
 if ( yc > 0.5 ){ yc = 1 - yc ; fyc = 1; }
 
 cr1 = hypot(xc-0.5,yc-0.5);
 cr2 = hypot(xc-0.5,yc+0.5);
 cr3 = hypot(xc+0.5,yc-0.5);

 if ( flip ^ flipt ){
  // base pattern
  r = basepattern(r1,r2,r3,fx,fy,Rm,Rp);
  if ( r> -1){
   Fac = 1;
   Disp = arc(r,Rm,Rp);
  } else {
   // connecting rings
   r = basepattern(cr1,cr2,cr3,fxc,fyc,Rm,Rp);
   if ( r> -1){
    Fac = 1;
    Disp = arc(r,Rm,Rp);
   }
  }
 } else {
  // connecting rings
  r = basepattern(cr1,cr2,cr3,fxc,fyc,Rm,Rp);
  if ( r> -1){
   Fac = 1;
   Disp = arc(r,Rm,Rp);
  } else {
   // base patterm
   r = basepattern(r1,r2,r3,fx,fy,Rm,Rp);
   if ( r> -1){
    Fac = 1;
    Disp = arc(r,Rm,Rp);
   }
  }
 }
}
The trick is to see that the pattern is very symmetrical. Each quadrant is basically the aame and consists of two quarter ring segments, one centered on the center of the square we are filling, the other one on the corner. The whole business of which to test for in what order is done to make sure that we know which ring segment is on top so that we can calculate a displacement correctly. It is all a bit too complicated to explain and in fact the code was created on a trial and error basis :-) It is however quite simple to use and that's why I share it of course :-)

Example node setup

Like most of the shaders I present on this blog the pattern probably is easiest to work with on an uv-mapped object. In the picture of the helmet the neckflap is just that, a curved, subdivided square that is uv-mapped with simple unwrapping. The node setup is shown below.
The green part is where we switch between a fully transparent shader or a metal shader based on the ouput of our script node. The diffuse part of the metal shader is given some color variation by the noise generated in the red box. The blue box s where we perturb our uv-coordinates a little bit adding a small amount of color noise in order to make our chainmail pattern a little less regular.

A Hagelslag (sprinkles) OSL shader for Blender Cycles

Most of the noise patterns available in Blender are either continuous (like noise or musgrave) or serve a specific function (like voronoi or bands). None of these are easily adapted to generate the not quite microscopic dust particles that leave their marks in for example fingerprints. While developing such a shader I came across a great video by CGPGrey on Holland/The Netherlands, in which he mentions the national breakfast confectionery hagelslag (chocolate sprinkles). Because the shader we present here is easily adapted to generate sprinkle patters, I dubbed it the hagelslag shader, although originally I intended to present a picture of rod-like bacteria such as Bacillus subtilis, my guess is that people find this a tastier example.

The environment lighting and background plate in the picture is provided by HDRSource the Gold Room from HDRLabs.com. And yes I know the bread crust doesn't look tasty at all, that is why I always removed it as a child.
The code I presented earlier doesn't work on all version of the OSL compiler. The culprit was the return statement inside the actual shader definition. I think this is a bug in OSL , a return from a shader function should be possible, but I updated the code nevertheless. I tested it on Blender r53600 and r54202 on 64 bits Windows 7
The code below is self contained, which means I have included a replacement for the missing distance() function but I do not discuss that one here as I published a small blog article on it elsewhere.
The basic pattern is based on determining the distance to randomly scattered line segments. In its most pure form it might look like this:
The shader code is presented below and the inputs of the shader are (beside the position and scale) the number of sprinkles to produce per area (Np), a random Seed to vary the pattern, the Radius which controls the width of the sprinkle, and the Size which governs the length of the sprinkles. The output Fac is between 1 and 0, gradually reducing from centerline to edge.
#include "stdosl.h"

// replacement for the missing distance(p, p1, p2) function
float minimum_distance(point v, point w, point p) {
  vector s = w - v;
  float l2 = dot(s,s);
  if (l2 == 0.0) return distance(p, v);
  float t = dot(p - v, s) / l2;
  if (t < 0.0) return distance(p, v);
  else if (t > 1.0) return distance(p, w);
  vector projection = v + t * (s);
  return distance(p, projection);
}

shader sprinkles(
 point Pos = P,
 float Scale = 1,
 int Np = 1,
 int Seed = 42,
 float Radius = 0.05,
 float Size = 1,
 output float Fac = 0
){
 point p = Pos * Scale;
 point f = floor(p);
 
 int xx,yy,np;
 vector one = 1;
 
 for( xx=-1; xx<=1; xx++){
  for( yy=-1; yy<=1; yy++){
   point ff = f + vector(xx,yy,0);
   
   vector dp = vector(5,7,11);
   vector da = vector(5,3,1);
   vector dm = vector(7,5,2);
   
   for( np=0; np < Np; np++){
    vector pd1 = 2*cellnoise(ff+dp)-one;
    vector pd2 = 2*cellnoise(ff+dp+Seed)-one;
    
    dp += da;
 dp *= dm;
 dp = mod(dp,10000);
    
    point p1 = ff + pd1;
    point p2 = ff + pd2;
    
    p2 = (p2 - p1)*Size+p1;
    
    // reduce to 2D 
    p1[2]=0;
    p2[2]=0;
    p [2]=0;
    
    float r = minimum_distance(p1,p2,p);
    if ( r < Radius ) {
  //printf("%2.f %.2f\n",p,r);
     Fac = 1 - r/Radius;
    }
   }
  }
 }
}

Example node setup

The node setup for the plain pattern looks like this:
It uses a mix node that switches between two material based on whether Fac is larger than zero.
The shader node used for the image of the sandwich with the chocolate sprinkles is a variation on that:
Because the radius of a chocolate sprinkles varies a little bit along its length, we perturb the Radius with some noise (red box). The yellow box lets us switch between a completely transparent material and a chocolate material. (We use a transparent material here because we stacked two layers of sprinkles on top of each other, with different values for Seed to get a the effect of a thick layer of sprinkles. The green box converts the linear values of Fac to a rounded bump by calculating the sqaure root (power 0.5) and plugging it into a bump node. The brown box is our chocolate material, simply a dark brown but rather glossy material.

A fingerprint OSL shader for Blender Cycles

Scanning your own fingerprints for use in your renderings might not be such a good idea with new methods of identity theft being invented everyday so here I present a shader that generates random fingerprint patterns. Finally you can identify the suspect that emptied your whiskey glass!

In the example image we duplicated and separated a small square from the glass mesh and scaled it a minuscule bit outward, effectively turning it into a decal or sticker. This object was uv-mapped and the fingerprint material applied to it. (The decal is still a bit darker than the glass because I didn't use enough transparent bounces. I might update this image in the future.)

An elliptic mask shader

Besides the regular nodes this Cycles shader consist of two separate OSL shaders. The first is a generic one to generate elliptic masks, not unlike the one available in the compositor:
#include "stdosl.h"

shader ellipse(
 point Pos = P,
 point Center = 0.5,
 float Radius = 0.5,
 float E = 1,
 float Rotation = 0,
 float Blur = 0,
 output float Fac = 0
){
 point p = rotate(Pos,radians(Rotation),Center,Center+vector(0,0,1));
 vector d = p - Center;
 d[0] *= E;
 float r2 = d[0]*d[0]+d[1]*d[1];
 if (r2 <= Radius*Radius) {
  Fac = 1-Blur*sqrt(r2/(Radius*Radius));
 }
} 

Generating a flow field

The second one is a flow shader. It works by generating a number of points that are considered the centers of vortices (rotating vector fields) with different strengths. At the point being shaded all the vectors are summed and the magnitude of the resulting vector is calculated. This output is used in the example noodle at the end of this article as input to a sinus node to create the banding pattern. Of course this pattern only superficially resembles human fingerprints (for example, it will not produce whorls, just concentric circles) but it does resemble it and is in fact related to the way fingerprint patterns are produced in the developing embryo. Anyway, as always, shaders are not about science but about art. For more information check Wikipedia, this pdf or this research. The animation on that last site actually inspired me although I have no idea my simplistic implementation in any way resembles their approach apart from using a vector field to act as a base for generating the ridge patterns.
Apart from fingerprints I think it should be possible to generate all sorts of patterns that in real life might be produced by processes that resemble cellular automata or reaction-diffusion systems that are far too expensive to simulate insode a shader. Zebra stripes might be a prime example.
I think my approach is at generating these patterns for graphical purposes is quite new, but if you have pointers to similar solutions you saw elsewhere, please mention this is a comment.
#include "stdosl.h"
#include "node_texture.h"

shader flow(
 point Pos = P,
 float Scale = 1,
 int Np = 5,
 int Seed = 42,
 output float Fac = 0
){
 float da;
 point pa;
 float d;
 
 vector up   = vector(0,0,1);
 vector tdir = 0;
 
 int pi;
 
 for(pi=0; pi< Np; pi++){
  pa = Scale * point(
   cellnoise(point(pi,pi,pi)),
   cellnoise(point(pi,pi+Seed,pi)),
   cellnoise(point(pi,pi,pi+Seed)));
  da = pa[2];
  vector v = pa - Pos;
  float d = length(v);
  v[2]=0;
  v = normalize(v);
  tdir += cross(v,up)*da*d;
 }
 Fac = sqrt(dot(tdir,tdir));
}

If we use some lighting that shows of the details you can see that it resembles a fingerprint but is actually nowhere near a real one.

Example node setup

The are quite a few nodes in the example shown below, so it is good the understand the general flow. The flow shader is used drive a sinus node via a multiplication node that lets us control the spacing of the bands. The output of this sinus is only propagated if it is positive (that is what the greater than and multiply nodes do, akin to an electrical 'rectifier' circuit) [The red box]]. This is mutiplied (i.e. masked) by the output of the ellipse shader and again by some noise [both in the green box] before being fed into mixture of closures (shaders) that will turn complete transparent when black and whitish-with-a-slight-gloss if not black [the yellow highlight]. The sinusoidal ridges also drive the displacement, adding a little extra realism [the blue highlight].

A Barbwire OSL shader for Blender Cycles

The simple concept used to create a chain link fence is easily extended to a somewhat more elaborate shader that creates barbwire. Finally we can keep the farm animals out of our rendered gardens (but as a goat owner myself I do not really think you should use barbwire to keep animals out except for humans :-)

I won't claim that the composite is very good, but the barbwire material itself holds up quite well even fairly close up.
In the example image I used the sIBL HDRI set 'Topanga Forest B' from Blochi as found on the sIBL archive and for the wooden posts some textures from CGTextures.
The code for the shader is pretty tangled, mainly because the spikey bit of the barbwire is pretty hard to code. The Xscale input is provided in order to make it possible to reduce the number of spikes per length of wire. By default we generate one spike per two turns. If you want to reduce this, you increase the number of turns, scale your input position in the x-direction and divide the Xscale input by the same amount (otherwise the turns on the spike would scale along and look way to thick).
#include "stdosl.h"

float arc(float r){ return sqrt(0.25-(r-0.5)*(r-0.5)); }

shader barbwire(
 float Width = 0.05,
 int Turns = 2,
 int Spiketurns = 2,
 float Xscale = 1,
 point Pos = P,
 output float Fac = 0,
 output float Displ = 0
){
 float x = mod(Pos[0],1);
 float y = mod(Pos[1],1);
 
 if ( x > 0.5 ) {
  x = 1 - x;
  y = 1 - y;
 }
 
 float w = Width/2;
 float t = M_2PI*x*Turns;
 
 float c = cos(t);
 float h = c*w+w;
 float l = c*w-w;
 
 y -= 0.5;
 // the barb part
 float BWidth = Width*Xscale;
 float Lw = BWidth*(Spiketurns-1);
 float Hw = BWidth*Spiketurns;
 if ( x > Lw && x < Hw && y > 1.5*Width && y<4 br="" idth="" part="" spikey="" the="">  if( y<3 br="" idth="" x-width="" y-3="">   Fac = 1;
   Displ = arc(mod(x,BWidth)/BWidth);
  }
 } else if ( x < Hw && abs(y) < 2*Width ){
  if ( abs(y) > 1.5*Width) { // the rounded top and bottom parts
   if ( abs(y) - 1.5*Width < w*arc(mod(x,BWidth)/BWidth) ){
    Fac = 1;
    Displ = arc(mod(x,BWidth)/BWidth);
   }
  } else { // the main part
   Fac = 1;
   Displ = arc(mod(x,BWidth)/BWidth);
  }
 }
 // the wire part 
 else {
  // alternating top/bottom checks to get correct crossings
  if ( (int)(t/M_PI) % 2 == 1 ){
  
   if ( y > l && y < h ) {
    Fac = 1;
    Displ = arc((y-l)/Width);
   } else if ( -y > l && -y < h ) {
    Fac = 1;
    Displ = arc((-y-l)/Width);
   }
   
  } else {
  
   if ( -y > l && -y < h ) {
    Fac = 1;
    Displ = arc((-y-l)/Width);
   } else if ( y > l && y < h ) {
    Fac = 1;
    Displ = arc((y-l)/Width);
   }
  }
 }
}

Example node setup

In the example image at the start of this article the lengths of barbwire were modelled by creating a single square, uv-unwrapping it and then adding an array modifier and a curve modifier to this square. This way we could edit the curve anyway we liked while the square repeats itself as many times as necessary (I set the length of the array modifier to the the length of the same curve that was used in the curve modifier). The noodle that applies the barbwire segment to the square looks like this (it is basically the same as the one for the chain link fence shader):

A 4D voronoi OSL shader for Blender Cycles

I took a post on Blender Artists as a challenge and created a 4D voronoi shader.

Blogspot won't show animated gifs but I put up a short sequence on PasteAll and if that doesn't work it is also on my site. In this animated gif, the fourth dimension (time) is animated from 0 to 1 in 50 frames.
The shader presented below is simple enough but convoluted because we cannot manipulate arrays like points or vectors in OSL but otherwise it is a straight forward extension of Blenders bundled voronoi implementation, especially because OSLs cellnoise function supports 4D noise out of the box (you can pass it a point and a float).
#include "stdosl.h"

void cellnoise_color4d(float p[4], float c[4])
{
 c[0] = cellnoise(point(p[0],p[1],p[2]),p[3]);
 c[1] = cellnoise(point(p[1],p[0],p[2]),p[3]);
 c[2] = cellnoise(point(p[1],p[2],p[0]),p[3]);
 c[3] = cellnoise(point(p[3],p[1],p[2]),p[0]);
}

/* Voronoi 4D . we always use distance squared as the distance metric */

void voronoi4d(point p, float t, float da[4], point pa[4], float ta[4])
{
 /* returns distances in da, point coords in pa and time coords in ta*/
 int xx, yy, zz, tt, xi, yi, zi, ti;

 float op[4] = {p[0],p[1],p[2],t};
 
 xi = (int)floor(p[0]);
 yi = (int)floor(p[1]);
 zi = (int)floor(p[2]);
 ti = (int)floor(t);

 da[0] = 1e10;
 da[1] = 1e10;
 da[2] = 1e10;
 da[3] = 1e10;

 for (xx = xi - 1; xx <= xi + 1; xx++) {
  for (yy = yi - 1; yy <= yi + 1; yy++) {
   for (zz = zi - 1; zz <= zi + 1; zz++) {
    for (tt = ti - 1; tt <= ti + 1; tt++) {
     float ip[4] = {xx, yy, zz, tt};
     float vp[4];
     cellnoise_color4d(ip,vp);
     float pd[4] = { op[0] - (vp[0] + ip[0]), 
         op[1] - (vp[1] + ip[1]),
         op[2] - (vp[2] + ip[2]),
         op[3] - (vp[3] + ip[3])};
     // always distance squared
     float d = pd[0]*pd[0]+pd[1]*pd[1]+pd[2]*pd[2]+pd[3]*pd[3];

     vp[0] += xx;
     vp[1] += yy;
     vp[2] += zz;
     vp[3] += tt;

     if (d < da[0]) {
      da[3] = da[2];
      da[2] = da[1];
      da[1] = da[0];
      da[0] = d;

      pa[3] = pa[2]; ta[3] = ta[2];
      pa[2] = pa[1]; ta[2] = ta[1];
      pa[1] = pa[0]; ta[1] = ta[0];
      pa[0] = point(vp[0],vp[1],vp[2]); ta[0] = vp[3];
     }
     else if (d < da[1]) {
      da[3] = da[2];
      da[2] = da[1];
      da[1] = d;

      pa[3] = pa[2]; ta[3] = ta[2];
      pa[2] = pa[1]; ta[2] = ta[1];
      pa[1] = point(vp[0],vp[1],vp[2]); ta[1] = vp[3];
     }
     else if (d < da[2]) {
      da[3] = da[2];
      da[2] = d;

      pa[3] = pa[2]; ta[3] = ta[2];
      pa[2] = point(vp[0],vp[1],vp[2]); ta[2] = vp[3];
     }
     else if (d < da[3]) {
      da[3] = d;
      pa[3] = point(vp[0],vp[1],vp[2]); ta[3] = vp[3];
     }
    }
   }
  }
 }
}

shader node_voronoi_texture(
 float Scale = 5.0,
 point Vector = P,
 float Time = 0,
 output float Fac = 0.0,
 output color Color = color(0.0, 0.0, 0.0))
{
 point p = Vector;

 /* compute distance and point coordinate of 4 nearest neighbours */
 float da[4];
 point pa[4];
 float ta[4];
 
 voronoi4d(p * Scale, Time * Scale, da, pa, ta);

 Fac = fabs(da[0]);
 Color = color(Fac);
}

Example node setup

Straight forward enough but note the keyframed Time value.

A Chainlink Fence OSL Shader for Blender Cycles

A simple shader to generate a chain link fence pattern that shows that a little displacement can go a long way.

The example image was again generated using one of Bob Groothuis excellent HDRI maps from his Dutch Skies collection. The concrete texture in the front is from www.cgtextures.com

The whole trick in generating a chain link fence pattern is realizing there is a lot of symmetry involved so we only need to think about the calculations for one part.


#include "stdosl.h"

float arc(float x){ return sqrt(1-(x-0.5)*(x-0.5)/0.25); }

shader chainlink(
point Pos = P,
float Width = 0.05,
output float Fac = 0,
output float Displ = 0
){
float x = mod(Pos[0],1);
float y = mod(Pos[1],1);
float ox = x ;
float oy = y ;
x += Width * (0.5 - oy );
y -= Width * (ox - 0.5 );
if ( y > 0.5 ){
y = 1 - y;
x = 1 - x;
}
if ( x > 0.5 ){
if ( y > 0.5 - Width ){
Fac = 1;
Displ = arc((y-(0.5-Width))/Width);
}else if (x < 0.5 + Width) {
Fac = 1;
Displ = arc((x-0.5)/Width);
}
}else{
float r = hypot(x-0.5,y-0.5);
if (r < Width) {
Fac = 1;
Displ = arc(r/Width);
}
}
}
The symmetry trick is in lines 17 - 20 where we invert the right half of a square around the center. The way we generate our pattern would cause the ends of the wires at the edges of the square not to line up so in line 15 an 16 we skew the grid a bit to correct this. this extra work before hand makes generating the wires of the chain link fence now very straight forward,

Example node setup

The way to use this shader is by using a default (aka reset) uv map from a simple plane and scale/rotate it as you see fit. The node setup shown here is about the simplest you can get: we simply map the Fac socket to a mix shader to map between a fully transparent shader and a material, in this cas a node group that implements some simple rather dull metal (not shown here). The caclculated displacement is directly plugged into the material output node and thereby converted to a surface normal but we could have used a bump node as well.

Note that although hardly visible in the ambient lighting of the example image, our material does cast nice shadows.

A Fabric OSL shader for Blender Cycles

In this post I present a simple shader that creates fabric or weave patterns.
The shader that is shown in the code below is not only capable of creating simple over-under patterns but also so called twill patterns. Its application is of course not limited to just fabrics, you could use it for baskets made of spliced bamboo for example or a divider made of hazel twigs.

The code for the shader is as often quite simple:
// greatest common divisor
int gcd(int A, int B){
    int a=A, b=B;
    if (a == 0) { return b; }
    while (b != 0) {
        if (a > b) {
            a = a - b;
        } else {
            b = b - a;
        }
    }
 return a;
}

// smallest common multiple (assumes a, b > 0 )
int scm(int a, int b){ return a*b/gcd(a,b); }

shader weave(
 color WarpColor = color(0.8,0,0),
 color WeftColor = color(0,0.8,0),
 int skip = 1,
 int underrun = 1,
 int overrun = 1,
        float WarpWidth = 0.8,
        float WeftWidth = 0.8,
 vector Coordinates = 0,
 output color Color = 0,
 output int Index = 0,
        output float Dist = 0
)
{
 int ny = underrun + overrun;
 int nx = scm(skip,ny);
 
 float x = mod(Coordinates[0],1.0);
 float y = mod(Coordinates[1],1.0);
 
 int ix = int(floor(x*nx));
 int iy = int(floor(y*ny));

        float cx = mod(x*nx,1.0);
        float cy = mod(y*ny,1.0);
     
 int top;
 top = ((iy+skip*ix)%ny) < overrun;

        float lx = (1-WarpWidth)/2;
        float hx = 1-lx;
    float ly = (1-WeftWidth)/2;
    float hy = 1-lx;

    if (top) {
        if ( cx > lx && cx < hx ){
            Index = 1;
            Color = WarpColor;
            Dist = abs(0.5-cx);
        } else if (cy > ly && cy < hy ){
            Index = 2;
            Color = WeftColor;
            Dist = abs(0.5-cy);
        }
    } else {
        if (cy > ly && cy < hy ){
            Index = 2;
            Color = WeftColor;
            Dist = abs(0.5-cy);
        } else if ( cx > lx && cx < hx ){
            Index = 1;
            Color = WarpColor;
            Dist = abs(0.5-cx);
        }
    }    
}
You may experiment with the skip, overrun and underrun values to get different patterns. The only real trick is to determine if we should display the vertical thread on top or the horizontal one. This is done in line 45. The rest of the code then simply checks whether we are withing the width of a thread.

Example node setup

The shader may be straightforward, the node setup used to create a canvas (or burlap) like appearance is less so because we need to introduce a certain amount of color variation inside the individual fibres and make sure that we have transparency in between the fibres (click to enlarge):

Future steps

As I am convinced Blender could benefit from an extensive set of very basic patterns that can be reused, I think I'll focus on a polkadot pattern for a next article.

A soap bubble OSL shader for Blender

The next step in our yourney to develop useful OSL shaders is a soap bubble shader.

The color patterns in soap bubbles and oil films are caused by a phenomenon called thin film interference. Our goal is to recreate those color patterns in a more or less physically accurate way.
Unlike the scales and hexagon shaders we developed earlier, this shader does not simply generate a color pattern but produces colors that are dependent on the angle of incidence. Because the incidence vector I is already provided in OSL as are many vector operations, this irridescence shader is surprisingly simple to implement.

surface irridescence (
 float nmedium = 1, // approximate refractive index of air
 float nfilm   = 1.3, // approximate refractive index of water
 float d       = 1000, // 1000 nm = 1 micron
        output color Color = 0
)
{
 // condition for constructive interference:
 // 2 * nfilm * d * cos(t2) == (m-0.5)*lambda
 // d and lambda in nm
 float eta = nmedium/nfilm;
        // note that N should be the perturbed normal
 vector T = normalize(refract(I,N,eta));
        // no need to divide by (len(-I) * len(T)) as these are normalized
 float cost2 = dot(-I , T);
 float opd = 2*nfilm*d*cost2;

 int mmin = int(ceil(opd/750+0.5));
 int mmax = int(floor(opd/350+0.5));
        // if mmax < mmin the film is too thin to show an effect
 int m = (mmin + mmax)/2;

 if (m > 0){
     float lambda = opd / (m - 0.5);
            color c = wavelength_color(lambda);
            Color =  c;
 }
}

In the code shown above the trick is that we calculate the length of the optical path opd first and then (in line 18) calculate the minimum and maximum number of wavelengths (plus a half to correct for a phase shift, check the Wikipedia article to see why) that fit in this path. The minimum number of wavelengths is calculated by dividing by the wavelength of the longest waelength we can see (red, 750 nm), the maximum by dividing by the shortest wavelength (blue, 350 nm). If the film is too thin, mmin will be smaller tban zero.
The next step is to pick any integer that lies between those extremes (line 21) and calculate the wavelength lambda that corresponds with this integer (line 24). The final trick is converting this wavelength to a RGB-color with OSLs built-in wavelength_color() function.

Example node setup

The shader produces 'just' colors so it is best to combine plug it into a glossy shader and combine it with a general glossy shader too make things resemble a soap bubble. In the node setup shown below we've thrown in some noise to perturb the normal so we get the characteristic color swirls we see in real life soap bubbles.

Future steps

The next article in this series will probably cover weave patterns.

A Scales OSL shader for Blender

The second OSL shader I have implemented for Blender is a scales pattern. It provides an overlapping pattern of semicircles that can be used for things like fish scales or roof shingles.


Like the hexagon shader this is a generic shader, i.e. a shader that provides a color pattern irrespective of lighting conditions so it is possible to use it in different contexts. In the code shown below the shader is defined with two input colors, coordinates (typicallt uv-coordinates of the object) and a parameter called n which can be used to alter the shape of the scales.
Beside a color and an index we provide an output for the distance to the center of a scale (which can be used for nice displacement effects) and a vector Vindex which is unique for each scale but the same within the scale. This can be plugged into a texture to provide each individual scale with its own distinct color. In the example noodle for the image shown at the beginning you can see how this is done.
shader scales(
    color Diffuse_Color1 = color(0.2, 0.8, 0.2),
    color Diffuse_Color2 = color(0.8, 0.2, 0.2),
    vector Coordinates = 0,
    float n = 0,
    output color Color = 0,
    output int Index = 1,
    output float Distance = 0,
    output vector Vindex = 0)
{
    float sx = mod(Coordinates[0],1);
    float sy = mod(Coordinates[1],1);
    
    vector p  = vector(sx,sy,0);
    vector p0 = vector(0.5,0,0);
    vector p1 = vector(0.5,1,0);
    vector p2 = vector(0,0.5,0);
    vector p3 = vector(1,0.5,0);
    
    vector cell = vector(floor(Coordinates[0]),floor(Coordinates[1]),0);    
    int oddx = int(cell[0])%2;
    int oddy = int(cell[1])%2;
    
    float dist(vector a, vector b, float n){
        float x = b[0]-a[0];
     float y = b[1]-a[1];
     float r2 = x*x+y*y;
     if ( n != 0.0 ) {
            float theta = atan2(y,x);
         float cost, sint;
            sincos(theta, sint, cost);
         float cost2= cos(theta*2);
         float Y = pow(abs(sint),1+n*(1-cost2*cost2));
         r2 /= cost*cost+Y*Y;
        }
        return sqrt(r2);
    }
    
    float d1 = dist(p,p0,n);
    if ( d1<=0.5 ){
        Color = Diffuse_Color1;
        Index = 0 ;
        Distance = d1;
        Vindex = cell + p0;
    } else {
        float d2 = dist(p,p2,n);
        float d3 = dist(p,p3,n);
        if ( d2 <= 0.5 ) {
            Color = Diffuse_Color2;
            Index = 1;
            Distance = d2;
            Vindex = cell + p2;
        } else if ( d3 <= 0.5 ) {
            Color = Diffuse_Color2;
            Index = 1;
            Distance = d3;
            Vindex = cell + p3;
        } else {
            Color = Diffuse_Color1;
            Index = 0;
            Distance = dist(p,p1,n);
            Vindex = cell + p1;
       }
    }
}

Example node setup

The image of the abstract Koi carp provided at the beginning was created with a node setup that is shown below (click on the image for a larger view):

Future steps

The next shader I will implement I think, will be an irridescence shader so we can all enjoy some soap bubbles.

Example image

Just to illustrate that with scales you do a lot of interesting stuff, here is a picture of the exact same model but with different colors and displacement mapping added to the scales. Looks like a pine cone, right? (Maybe a bit chocolaty one :-)

A Hexagon OSL shader

Now that the Blender Cycles render engine can work with Open Shading Language (OSL) shaders the first task I've set out for myself is to recreate some of the textures I implemented before and the first one we tackle is the hexagon shader.


using an OSL shader in Blender

The hexagon shader in the code below was used to create both the colorfull cube and the chickenwire-like plane in the picture. Provided that you have a Blender build that supports OSL, using the code below requires just two simple steps:
  1. Enable the OSL features in the Cycles render settings (the 'Shading syst')
  2. Load to code below in the text editor
Now you can insert an OSL node anywhere in your node setup by clicking Add -> Script and selecting the name of your text editor buffer in the drop down.

#define A 0.86602540378443864676372317075294 // sqrt(3)/2
#define A2 (2*A)
#define A4 (4*A)
#define SY (1/A)

shader hexagons(
    color Diffuse_Color1 = color(0.2, 0.8, 0.2),
    color Diffuse_Color2 = color(0.8, 0.2, 0.2),
    color Diffuse_Color3 = color(0.2, 0.2, 0.8),
    vector Coordinates = 0,
    output color Color = 0,
    output int Index = 1,
    output float Distance = 0)
{
    // calculate the color
    
    color colors[3] = {Diffuse_Color1,
                       Diffuse_Color2,
                       Diffuse_Color3};   
 
    // we warp the grid so that two adjacent equilateral triangles
    // are mapped to two triangles that fit in a square
    float syc = Coordinates[1] * SY;
    float sxc = Coordinates[0] + 0.5 * syc;
 
    int ind[18] = {1,1,3,3,3,1, 2,2,2,3,3,3, 1,2,2,2,1,1};
 
    int iy = int(mod(syc,3.0));
    int ix = int(mod(sxc,3.0));
    ix = iy * 6 + ix * 2 + ( mod(sxc,1.0) > mod(syc,1.0) );    
 Index = ind[ix];
    Color = colors[Index-1];    
 
    // calculate the distance to the center of the hexagon
       
    float sx = mod(Coordinates[0],3);
    float sy = mod(Coordinates[1]+0.75,A4); 

    // map everthing to a single quadrant
    if ( sx > 1.5 ) sx = 3 - sx;
    if ( sy > A2 ) sy = A4 - sy;
    
    // the distance were interested in is the distance to 
    // the *closest* center point 
    float d1 = distance(vector(sx,sy,0),vector(1.5,A2,0));
    float d2 = distance(vector(sx,sy,0),vector(0,A,0));
    float d6 = distance(vector(sx,sy,0),vector(1.5,0,0));
        
    Distance = min(min(d1,d2), d6);
 
}
The code is a generic shader, i.e. its output color does not take any lighting calculations into account and a more familiar way to refer to such a shader would be a custom texture or pattern. Obviously you can plug its calculated color into a diffuse shader for example but you could also combine it with other textures.
The shader has 3 different colors as input parameters and a coordinate. Its outputs are not only a color, but also an integer color index and the distance to the center of the hexagonal cell. The latter can be used for all sorts of displacement tricks while an index is usefull if you want to change not just the color of a cell but use a completely different texture or shader for each cell.
The noodle for the colorful cube looks like this (click to get a better view):
The noodle for the chickenwire like material looks like this:

Future steps

In the next article I will probably focus on implementing a scales pattern that can either be used for fish scales or roof tiles (shingles).