# OSL distortion effect

I have a simple math function that produce a saw-like pattern. The question is - How to apply a distortion effect to it?

Here's an example of the code:

shader basic_function(
point Pos = P,
output float f = 0)

{float x = Pos[0];
float y = Pos[1];
float z = Pos[2];

f = (z + 0.5 - floor(z));}


PS Honestly, Im a new one in osl shader writing so it possible that I dont understand what im doing.

You can use the same methods as you would use to apply distortion to a node-based material - ie, distort the input coordinates.

For example, change the script to include a DistortFactor and DistortScale as follows :

shader basic_function(
point Pos = P,
float DistortFactor = 0.0,
float DistortScale = 1.0,
output float f = 0)

{

vector distortion = noise("perlin", P*DistortScale)*DistortFactor;

float x = Pos[0]+distortion[0];
float y = Pos[1]+distortion[1];
float z = Pos[2]+distortion[2];

f = (z + 0.5 - floor(z));
}


This will give you two additional inputs on the script node to allow you to adjust the amount of distortion and its scale. The 'noise' function is used to generate distortion based on the point vector (P), scaled by the input DistortScale and multiplied by the input DistortFactor - and added in to the coordinates used to generate the "stripes".

This can produce the following result :

EDIT : As @LarryGritz pointed out, the above solution is generally only of use for static objects - any object using this shader which is moving through the scene (whether location, rotation, or scale) will move through the distortion and the pattern will change as it moves. To address this we need to transform the World coordinates of 'P' into Object coordinates so the OSL code becomes the following :

shader basic_function2(
point Pos = P,
float DistortFactor = 0.0,
float DistortScale = 1.0,
output float f = 0)

{

point Pobj = transform("world","object",Pos);

vector distortion = noise("perlin", Pobj*DistortScale)*DistortFactor;

float x = Pobj[0]+distortion[0];
float y = Pobj[1]+distortion[1];
float z = Pobj[2]+distortion[2];

f = (z + 0.5 - floor(z));
}


Note the use of the 'transform' function to convert from 'world' to 'object' coordinates (similar to the Vector Transform node in node-based materials).

• Note that it's almost never wise to compute noise(P), because P is a world space quantity so if he object moves, it will move through the noise, rather than having the pattern stick to the object. Much better to: point Pobj = transform("current","object",P); blah = noise(Pobj); – Larry Gritz Nov 2 '17 at 17:49
• That’s a very good point @LarryGritz - thanks. I’ll update my answer to include this. – Rich Sedman Nov 2 '17 at 21:10
• @LarryGritz this almost worked - I needed to change "current" to "world" and now the above example is working as it should. Thanks. – Rich Sedman Nov 7 '17 at 7:47
• Typo on my part. It should have been "common", not "current". This is the common shading space. It's equivalent to "world" in most renderers, but doesn't have to be, so the most portable way to express this is to use "common". – Larry Gritz Nov 7 '17 at 16:22
• Additional note for those who appreciate the gory details: the use of object space coordinates for the noise lookup will solve the problem for rigid objects. But if the mesh deforms, it still isn't enough to make the pattern stick to the surface -- for that case, you need to use an "undeformed reference mesh" or "Pref" (I don't know what the proper Blender terminology is for that). – Larry Gritz Nov 7 '17 at 16:26