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.

1 comment:

  1. Some great work again. It would be helpful if you clarify the licensing that applies to your code.

    ReplyDelete