4

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

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.

Rich Sedman
  • 44,721
  • 2
  • 105
  • 222
Artem
  • 373
  • 2
  • 9

1 Answers1

9

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".

script node including distortion inputs

This can produce the following result :

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).

Rich Sedman
  • 44,721
  • 2
  • 105
  • 222
  • 2
    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 02 '17 at 17:49
  • That’s a very good point @LarryGritz - thanks. I’ll update my answer to include this. – Rich Sedman Nov 02 '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 07 '17 at 07:47
  • 1
    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 07 '17 at 16:22
  • 1
    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 07 '17 at 16:26