Procedural texture generator (example and wishes)

So, from deevad’s list it seems some kind of implementation of fractal flames would be cool.

I am also looking forward to seeing if we can get some of the non-orthographic-tiling entries from the tesselation wikipedia page generated with seexpr.

1 Like

Thanks for starting this thread @Deevad! I couldn’t get round to doing it because of too much homework here. Also, afternight Eurographics sessions don’t help either :wink:

To summarise: I’ll be really, really grateful if you post references or code here!
During my CG research, I’ve noticed there’s a definite lack of “secret sauce” in the literature; we know the mathematical bits, and we see in the post above the end results from the artists. What we lack, and I’d like to add as examples to my project, is how each example is made.

1 Like

Awesomely made request! I think this would be a great way to expand Krita’s creative capabilities!

Definitely would need some work but I’m looking forward to the progress of this topic!

1 Like

I just have one question, can it be possible to create a fill layer that utilize g’mic-qt via g’mic-qt being used a library? I know that’s a difficult task that would in theory take year or two to program, but I think something like this would fill the needs of the OP in the long run as g’mic-qt already have plenty of useful filters and tools that can be used to generate procedural work.

This thread is regarding @amyspark’s GSOC task to implement Disney/Pixars SeExpr texture generators to Krita. It is not about gmic or implementing Gmic filters and file layers. You can read about the GSOC proposal and posts on the dev’s blog.

1 Like

Hey, I’m not skirting this one :slight_smile:

@Reptorian, yes, it should be possible. This would, incidentally, fix the current unavailability of GMic-Qt on macOS. tl;dr: due to system restrictions on shared memory between apps (Krita and GMic run as separate processes), GMic cannot access opened documents in Krita.

1 Like

Ok, managed to get a really nice one down:

$ratiov = $h/$w;
$uv = [$u, $v*$ratiov, 0];
$size = 15; # 0,30;
$outlines = 10; #1, 20;
$color1 = [0,0,0];
$color2 = [1,1,1];

$point = pvoronoi($size*$uv,4,0,.2);

#circle determining part

$dist = ($uv*$size)-$point;
$dotproduct = dot(dist, dist) * 4;

#filling the circles

$fac = fmod(sin($dotproduct*$outlines) , 1);
$color = ccurve($fac,0,$color1,4,1,$color2,4);

$color

This one is very similar to an old hand-drawn graphical pattern where you place a circle, and then another circle and you then draw circles around those. The problem with getting a computer to do this is that it’s a little hard to explain what exactly what you want, which makes things like having variation between circles while keeping the outline consistent a little hard.

EDIT: I updated it so the circles would be round…

4 Likes

Wow, good one @wolthera :+1: I also really like the setting you expose on the top GUI; “size, repeat, color1 and color 2”. This is exactly the type of preset I would love to get in a list.

So, these are all variations on a theme. What we’re doing here is just repeating the same function on the base uv coordinate over and over and getting funky marbely patterns through that.

Malachite:

$ratiov = $h/$w;
$uv = [$u, $v*$ratiov, 0];

$uv = $uv+vfbm($uv);
$uv = $uv+vfbm($uv);
$uv = $uv+vfbm($uv);
$uv = $uv+vfbm($uv);

$c = fbm($uv);

$color = ccurve($c,0,[0,0,0],4,0.567308,[0,0.666667,0.498039],4,1,[0.235294,1,0.45098],4);
$color

This one’s kinda bizarely metalic:

$ratiov = $h/$w;
$uv = [$u, $v*$ratiov, 0];

$uv = $uv+vnoise($uv*5);
$uv = $uv+vnoise($uv*5);
$c = noise($uv*5);

$color = ccurve($c,0,[0,0,0],4,1,[1,1,1],4);
$color

One based on turbulence.

$ratiov = $h/$w;
$uv = [$u, $v*$ratiov, 0];

$uv = vturbulence($uv*2);
$c = vturbulence($uv*3);

$color = ccurve($c,0,[0,0,0],4,1,[1,1,1],4);
$color

Don’t remember why I saved this one…

$ratiov = $h/$w;
$uv = [$u, $v*$ratiov, 0];

$uv = vfbm($uv);
$uv = $uv+vfbm($uv);
$c = voronoi($uv, 2);

$color = ccurve($c,0,[0,0,0],4,1,[1,1,1],4);
$color

One with very bright lines:

$ratiov = $h/$w;
$uv = [$u, $v*$ratiov, 0];
$size = 3;

$uv = vturbulence($uv*$size);
$c = voronoi($uv*$size, 2);

$color = ccurve($c,0,[0,0,0],4,1,[1,1,1],4);
$color
7 Likes

Very good presets @wolthera, I tried them all, and the Malachite is really impressive.

I toyed with the two last you posted; (thanks!) I found they were a good base for electric arcs, and it was exactly what I was needing while detailing episode 33 :smiley:

$ratiov = $h/$w;
$uv = [$u, $v*$ratiov, 0];
$size = 1;

$uv = vturbulence($uv*$size);
$c = voronoi($uv*$size*8, 2);

$color = ccurve($c,0.915058,[1,1,1],4,0.409266,[0,0,0],4,0.594595,[0.173112,0.173112,0.173112],4);
$color

Result, rendered at 4K: ( :heart_eyes_cat: oh the details!)

Then overlay on my panel that felt a bit flat. It adds a cool magnetic field (after being tinted in magenta and put in addition blending mode):

6 Likes

Decided to comment this one rather aggressively.

# SeExpr script to draw tiled dots not unlike screentones.
# We'd ideally work this one out further so it'll have the lines be less canvas-
# size based and more 'per so many pixels' or something.

# [$u, $v, 0] is a vector constructed from the proportional horizontal and
# vertical positions ($u and $v) of the output pixel and 0 as the Z-value.
# We multiply the proportional vertical by the ratio we can get from the height
# and width of the image, so that our computed shapes are in a square aspect
# ratio, they'd get streched otherwise.

$ratiov = $h / $w;
$uv = [$u, $v * $ratiov, 0];

# These are all the configurable variables. There's no reason why they're all
# assembled here besides making it easier to read the script. Values inside the
# comments are used by SeExpr widgets to determine the upper and lower limits.

$radius = 1; #0.0, 5.0
$lines = 60; #1, 300
$size = $lines;
$angle = 35; #0, 359
$softness = 0.2; #0.001, 1.0
$color1 = [0,0,0];
$color2 = [1,1,1];


# Tiling part.
# ------------
# we'll construct the position of the current pixel
# in a pattern from the $uv

$tiles = $uv * size;
$repeat = boxstep(1 , fmod( $tiles[1], 1.0) );

# reassemble the tiled vector;

$tiles = [ $tiles[0] + $repeat, $tiles[1], 0];

# Now we rotate the tiled vector, 2d rotation uses the z-axis, that's [0, 0, 1].

$tiles = rotate($tiles, [0, 0, 1], rad($angle));

# Here we remove the offset from the tiled vector.

$tiles -= floor($tiles);

# circle determining part
# -----------------------
# we're computing a 'distance field' here.

$dist = $tiles - [0.5, 0.5, 0];
$dotproduct = dot(dist, dist) * 4;
$leftSide  = (1.0 - (0.5 * $softness)) * $radius;
$rightSize = (1.0 + (0.5 * $softness)) * $radius;
$fac = smoothstep($leftSide, $rightSize, $dotproduct);

# filling the shape
# -----------------
# we only want to use color interpolation if we're sure our distance
# factor is above 0, otherwise it'll need to be color 2.

if ($fac>0) {
  $color = ccurve($fac, 0, $color1, 4, 1, $color2, 4);
} else {
  $color = $color2;
}

# and we return the color

$color
5 Likes

Still having all these super graphical ones in my system… Less comments this time around.

Square dots/Lines

# SeExpr script to draw tiled squares not unlike screentones.
# We'd ideally work this one out further so it'll have the lines be less canvas-
# size based and more 'per so many pixels' or something.

# [$u, $v, 0] is a vector constructed from the proportional horizontal and
# vertical positions ($u and $v) of the output pixel and 0 as the Z-value.
# We multiply the proportional vertical by the ratio we can get from the height
# and width of the image, so that our computed shapes are in a square aspect
# ratio, they'd get streched otherwise.

$ratiov = $h / $w;
$uv = [$u, $v * $ratiov, 0];

# These are all the configurable variables. There's no reason why they're all
# assembled here besides making it easier to read the script. Values inside the
# comments are used by SeExpr widgets to determine the upper and lower limits.

$radius = 0.33; #0.0, 1.0
$lines = 27; #1, 300
$size = $lines;
$angle = 122; #0, 359
$softness = 0.4006; #0.001, 1.0
$color1 = [0,0,0];
$color2 = [1,1,1];


# Tiling part.
# ------------
# we'll construct the position of the current pixel
# in a pattern from the $uv

$tiles = $uv * size;
$repeat = boxstep(1 , fmod( $tiles[1], 1.0) );

# reassemble the tiled vector;

$tiles = [ $tiles[0] + $repeat, $tiles[1], 0];

# Now we rotate the tiled vector, 2d rotation uses the z-axis, that's [0, 0, 1].

$tiles = rotate($tiles, [0, 0, 1], rad($angle));

# Here we remove the offset from the tiled vector.

$tiles -= floor($tiles);

# square determining part
# -----------------------
# we're computing a 'distance field' here.

$fac = remap($tiles[0], .5, 0.5*$radius, 1*$softness, 2);
# comment out the following to make this a lines-script.
$fac *= remap($tiles[1], .5, 0.5*$radius, 1*$softness, 2);


# filling the shape
# -----------------

$color = ccurve($fac, 0, $color2, 4, 1, $color1, 4);

# and we return the color

$color

Truchet

Classic

$ratiov = $h/$w;
$uv = [$u, $v*$ratiov, 0];
$scale2 = 10; #0,50
$color1 = [0,0,0];
$color2 = [1,1,1];

$celval = cellnoise($uv*$scale2);

#circle determining part

$distance = ($uv*$scale2);

$angle = floor($celval*4)*90;
$distance = rotate($distance, [0,0,1], rad($angle));
$distance -= floor($distance);

$dotproduct = (distance[0]+distance[1]);

$fac = smoothstep(.999, 1.001, $dotproduct);

$color = $color2;
if ($fac>0) {
 $color = ccurve($fac,0,$color1,4,1,$color2,4);
}

$color

Maze

$ratiov = $h/$w;
$uv = [$u, $v*$ratiov, 0];
$scale2 = 10; #0,50
$color1 = [0,0,0];
$color2 = [1,1,1];

$celval = cellnoise($uv*$scale2);

$distance = ($uv*$scale2);

$angle = floor($celval*4)*90;
$distance = rotate($distance, [0,0,1], rad($angle));
$distance -= floor($distance);

$dotproduct = (distance[0]+distance[1]);

$border = 0.01;
$fac = smoothstep(1-$border, 1.0, $dotproduct);
$fac += smoothstep(1+$border, 1.0, $dotproduct);

$color = ccurve($fac,0,$color1,4,1,$color2,4);

$color

Halfround:

$ratiov = $h/$w;
$uv = [$u, $v*$ratiov, 0];
$scale2 = 10; #0,50
$color1 = [0,0,0];
$color2 = [1,1,1];

$celval = cellnoise($uv*$scale2);

$distance = ($uv*$scale2);

$angle = floor($celval*4)*90;
$distance2 = rotate($distance, [0,0,1], rad($angle+180));
$distance = rotate($distance, [0,0,1], rad($angle));
$distance -= floor($distance);
$distance2 -= floor($distance2);

$dotproduct = dot($distance,$distance)*4;
$dotproduct2 = dot($distance2,$distance2)*4;

$border = 0.05;#0, .21
$lowerBorder = 1-$border;
$upperBorder = 1+$border;
$fac = gaussstep($lowerBorder, 1.0, $dotproduct);
$fac += gaussstep($upperBorder, 1.0, $dotproduct);
$fac += gaussstep($lowerBorder, 1.0, $dotproduct2);
$fac += gaussstep($upperBorder, 1.0, $dotproduct2);

$color = ccurve(1-$fac,0.0,$color1,4,1,$color2,4);

$color
4 Likes

Ok, here we go…

I made small scripts that basically just expose the different inbuilt functions and add some basic scale and rotation controls:

Voronoi cells

# Basic usage of the inbuilt seexpr voronoi function.
# This just exposes each of the variables in the voronoi function for editing. Also adds rotation and scaling.

# UV vector manipulation
# ----------------------

# Construction of the UV vector. $u and $v are the normalized x and y coordinates for the image. This gives non-square results by default, so we calculate the ratio and then multiply the relevant dimension with said ratio to get a square result from the algorithms.
# The zCoordinate can be set manually in many of the inbuilt noise functions, as these produce 3d noise, but we have a 2d plane. So allowing people to manipulate the last dimension manually allows them to access other slices of the 3d noise.

$ratio = $h/$w;
$zCoord = 0; #0.0, 1.0
$uv = [$u, $v*$ratio, zCoord];

# We multiply the subdivisions with the uv vector to give a sense of zooming out.

$subdivisions = 10; # 1, 100;
$uv *= $subdivisions;

# We also rotate the uv coordinate around the z-axis, [0,0,1]. 

$rotation = 0; #0, 359;
$uv = rotate($uv, [0,0,1], rad(rotation));


# Voronoi Function
# ----------------

# The type of voronoi algorithm as explain in the manual.
$type = 2; #1, 5

# The jitter, low jitter gives almost grid like appearance, high jitter a
$jitter = 1; #0.0, 1.0

# Some variables for introducing some fractal brownian motion into the voronoi cells.

# The strength of the FBM effect.
$fbmScale = 0;

# Controls the frequencies.
$fbmOctaves = 4; #0, 10

# Spacing between the frequencies - a value of 2 means each octave is twice the previous frequency.
$fbmLacunarity = 2; #0, 10;

# controls how much each frequency is scaled relative to the previous frequency.
$fbmGain = 0.5; #0, 10.0

# Finally we input all the variables into the function to get a factor.
$fac = voronoi($uv, $type, $jitter, $fbmScale, $fbmOctaves, $fbmLacunarity, $fbmGain);


# Color
# -----
# We put the factor into a gradient to get the color.

$color = ccurve($fac,0,[0.141,0.059,0.051],4,0.709957,[1,1,0],4,1,[0.976,0.976,0.976],4,0.212121,[0.333333,0,0],4,0.519481,[1,0.333333,0],4);

# return the color.
$color

Perlin Noise 1983

# Basic usage of the inbuilt seexpr noise function.
# This is based on the original 1983 perlin noise.

# UV vector manipulation
# ----------------------

# Construction of the UV vector. $u and $v are the normalized x and y coordinates for the image. This gives non-square results by default, so we calculate the ratio and then multiply the relevant dimension with said ratio to get a square result from the algorithms.
# The zCoordinate can be set manually in many of the inbuilt noise functions, as these produce 3d noise, but we have a 2d plane. So allowing people to manipulate the last dimension manually allows them to access other slices of the 3d noise.

$ratio = $h/$w;
$zCoord = 0; #0.0, 1.0
$uv = [$u, $v*$ratio, zCoord];

# We multiply the subdivisions with the uv vector to give a sense of zooming out.

$subdivisions = 67; # 1, 100;
$uv *= $subdivisions;

# We also rotate the uv coordinate around the z-axis, [0,0,1]. 

$rotation = 0; #0, 359;
$uv = rotate($uv, [0,0,1], rad(rotation));


# Noise Function
# ----------------


# Finally we input all the UV into the function to get a factor.
$fac = noise($uv);


# Color
# -----
# We put the factor into a gradient to get the color.

$color = ccurve($fac,0,[0.141,0.059,0.051],4,0.709957,[0.576471,0.87451,1],4,1,[0.976,0.976,0.976],4,0.320346,[0.266667,0.117647,0.713725],4);

# return the color.
$color

Cellnoise

# Basic usage of the inbuilt seexpr cellnoise function.
# This is based on the prman cellnoise function

# UV vector manipulation
# ----------------------

# Construction of the UV vector. $u and $v are the normalized x and y coordinates for the image. This gives non-square results by default, so we calculate the ratio and then multiply the relevant dimension with said ratio to get a square result from the algorithms.
# The zCoordinate can be set manually in many of the inbuilt noise functions, as these produce 3d noise, but we have a 2d plane. So allowing people to manipulate the last dimension manually allows them to access other slices of the 3d noise.

$ratio = $h/$w;
$zCoord = 0; #0.0, 1.0
$uv = [$u, $v*$ratio, zCoord];

# We multiply the subdivisions with the uv vector to give a sense of zooming out.

$subdivisions = 67; # 1, 100;
$uv *= $subdivisions;

# We also rotate the uv coordinate around the z-axis, [0,0,1]. 

$rotation = 0; #0, 359;
$uv = rotate($uv, [0,0,1], rad(rotation));


# Cellnoise Function
# ------------------


# Finally we input all the UV into the function to get a factor.
$fac = cellnoise($uv);


# Color
# -----
# We put the factor into a gradient to get the color.

$color = ccurve($fac,0,[0.141,0.059,0.051],4,0.709957,[0.996078,1,0.572549],4,1,[0.976,0.976,0.976],4,0.320346,[0.713725,0.427451,0.647059],4);

# return the color.
$color

Fractal Brownian Motion

# Basic usage of the inbuilt seexpr FBM function.
# This just exposes each of the variables in the FBM function for editing. Also adds rotation and scaling.

# UV vector manipulation
# ----------------------

# Construction of the UV vector. $u and $v are the normalized x and y coordinates for the image. This gives non-square results by default, so we calculate the ratio and then multiply the relevant dimension with said ratio to get a square result from the algorithms.
# The zCoordinate can be set manually in many of the inbuilt noise functions, as these produce 3d noise, but we have a 2d plane. So allowing people to manipulate the last dimension manually allows them to access other slices of the 3d noise.

$ratio = $h/$w;
$zCoord = 0; #0.0, 1.0
$uv = [$u, $v*$ratio, zCoord];

# We multiply the subdivisions with the uv vector to give a sense of zooming out.

$subdivisions = 23; # 1, 100;
$uv *= $subdivisions;

# We also rotate the uv coordinate around the z-axis, [0,0,1]. 

$rotation = 0; #0, 359;
$uv = rotate($uv, [0,0,1], rad(rotation));


# FBM Function
# ----------------

# Controls the frequencies.
$fbmOctaves = 2; #0, 10

# Spacing between the frequencies - a value of 2 means each octave is twice the previous frequency.
$fbmLacunarity = 1; #0, 10;

# controls how much each frequency is scaled relative to the previous frequency.
$fbmGain = 0.5; #0, 10.0

# Finally we input all the variables into the function to get a factor.
$fac = fbm($uv, $fbmOctaves, $fbmLacunarity, $fbmGain);


# Color
# -----
# We put the factor into a gradient to get the color.

$color = ccurve($fac,0,[0.141,0.059,0.051],4,0.709957,[0.556863,1,0.913725],4,1,[0.976,0.976,0.976],4,0.212121,[0.105882,0.164706,0.266667],4);

# return the color.
$color

Turbulence

# Basic usage of the inbuilt seexpr turbulence function.
# This just exposes each of the variables in the turbulence function for editing. Also adds rotation and scaling.

# UV vector manipulation
# ----------------------

# Construction of the UV vector. $u and $v are the normalized x and y coordinates for the image. This gives non-square results by default, so we calculate the ratio and then multiply the relevant dimension with said ratio to get a square result from the algorithms.
# The zCoordinate can be set manually in many of the inbuilt noise functions, as these produce 3d noise, but we have a 2d plane. So allowing people to manipulate the last dimension manually allows them to access other slices of the 3d noise.

$ratio = $h/$w;
$zCoord = 0; #0.0, 1.0
$uv = [$u, $v*$ratio, zCoord];

# We multiply the subdivisions with the uv vector to give a sense of zooming out.

$subdivisions = 23; # 1, 100;
$uv *= $subdivisions;

# We also rotate the uv coordinate around the z-axis, [0,0,1]. 

$rotation = 0; #0, 359;
$uv = rotate($uv, [0,0,1], rad(rotation));


# Tubulence Function
# ------------------

# Controls the frequencies.
$fbmOctaves = 2; #0, 10

# Spacing between the frequencies - a value of 2 means each octave is twice the previous frequency.
$fbmLacunarity = 1; #0, 10;

# controls how much each frequency is scaled relative to the previous frequency.
$fbmGain = 0.5; #0, 10.0

# Finally we input all the variables into the function to get a factor.
$fac = turbulence($uv, $fbmOctaves, $fbmLacunarity, $fbmGain);


# Color
# -----
# We put the factor into a gradient to get the color.

$color = ccurve($fac,0,[0.141,0.059,0.051],4,0.709957,[0.980392,0.662745,1],4,1,[0.976,0.976,0.976],4,0.212121,[0.105882,0.164706,0.266667],4);

# return the color.
$color

And the same song, but now it’s the colornoise functions.

Color Voronoi

# Basic usage of the inbuilt seexpr color voronoi function.
# This just exposes each of the variables in the voronoi function for editing. Also adds rotation and scaling.

# UV vector manipulation
# ----------------------

# Construction of the UV vector. $u and $v are the normalized x and y coordinates for the image. This gives non-square results by default, so we calculate the ratio and then multiply the relevant dimension with said ratio to get a square result from the algorithms.
# The zCoordinate can be set manually in many of the inbuilt noise functions, as these produce 3d noise, but we have a 2d plane. So allowing people to manipulate the last dimension manually allows them to access other slices of the 3d noise.

$ratio = $h/$w;
$zCoord = 0; #0.0, 1.0
$uv = [$u, $v*$ratio, zCoord];

# We multiply the subdivisions with the uv vector to give a sense of zooming out.

$subdivisions = 10; # 1, 100;
$uv *= $subdivisions;

# We also rotate the uv coordinate around the z-axis, [0,0,1]. 

$rotation = 0; #0, 359;
$uv = rotate($uv, [0,0,1], rad(rotation));


# Voronoi Function
# ----------------

# The type of voronoi algorithm as explain in the manual.
$type = 1; #1, 5

# The jitter, low jitter gives almost grid like appearance, high jitter a
$jitter = 1; #0.0, 1.0

# Some variables for introducing some fractal brownian motion into the voronoi cells.

# The strength of the FBM effect.
$fbmScale = 0.21533;

# Controls the frequencies.
$fbmOctaves = 4; #0, 10

# Spacing between the frequencies - a value of 2 means each octave is twice the previous frequency.
$fbmLacunarity = 2; #0, 10;

# controls how much each frequency is scaled relative to the previous frequency.
$fbmGain = 0.5; #0, 10.0

# Color
# -----
# We put all the variables into the color voronoi function to get the color.

$color = cvoronoi($uv, $type, $jitter, $fbmScale, $fbmOctaves, $fbmLacunarity, $fbmGain);

# return the color.
$color

Color Perlin Noise 1983

# Basic usage of the inbuilt seexpr color noise function.
# This is based on the original 1983 perlin noise.

# UV vector manipulation
# ----------------------

# Construction of the UV vector. $u and $v are the normalized x and y coordinates for the image. This gives non-square results by default, so we calculate the ratio and then multiply the relevant dimension with said ratio to get a square result from the algorithms.
# The zCoordinate can be set manually in many of the inbuilt noise functions, as these produce 3d noise, but we have a 2d plane. So allowing people to manipulate the last dimension manually allows them to access other slices of the 3d noise.

$ratio = $h/$w;
$zCoord = 0; #0.0, 1.0
$uv = [$u, $v*$ratio, zCoord];

# We multiply the subdivisions with the uv vector to give a sense of zooming out.

$subdivisions = 67; # 1, 100;
$uv *= $subdivisions;

# We also rotate the uv coordinate around the z-axis, [0,0,1]. 

$rotation = 0; #0, 359;
$uv = rotate($uv, [0,0,1], rad(rotation));



# Function
# --------
# Finally we input the UV into the color function to get a color.

$color = cnoise($uv);

# return the color.
$color

Color Cellnoise

# Basic usage of the inbuilt seexpr color cellnoise function.
# This is based on the prman cellnoise function

# UV vector manipulation
# ----------------------

# Construction of the UV vector. $u and $v are the normalized x and y coordinates for the image. This gives non-square results by default, so we calculate the ratio and then multiply the relevant dimension with said ratio to get a square result from the algorithms.
# The zCoordinate can be set manually in many of the inbuilt noise functions, as these produce 3d noise, but we have a 2d plane. So allowing people to manipulate the last dimension manually allows them to access other slices of the 3d noise.

$ratio = $h/$w;
$zCoord = 0; #0.0, 1.0
$uv = [$u, $v*$ratio, zCoord];

# We multiply the subdivisions with the uv vector to give a sense of zooming out.

$subdivisions = 67; # 1, 100;
$uv *= $subdivisions;

# We also rotate the uv coordinate around the z-axis, [0,0,1]. 

$rotation = 0; #0, 359;
$uv = rotate($uv, [0,0,1], rad(rotation));


# Cellnoise Function
# ------------------

# We input all the uv into the function to get a color.

$color = ccellnoise($uv);

# return the color.
$color

Color Fractal Brownian Motion

# Basic usage of the inbuilt seexpr color FBM function.
# This just exposes each of the variables in the FBM function for editing. Also adds rotation and scaling.

# UV vector manipulation
# ----------------------

# Construction of the UV vector. $u and $v are the normalized x and y coordinates for the image. This gives non-square results by default, so we calculate the ratio and then multiply the relevant dimension with said ratio to get a square result from the algorithms.
# The zCoordinate can be set manually in many of the inbuilt noise functions, as these produce 3d noise, but we have a 2d plane. So allowing people to manipulate the last dimension manually allows them to access other slices of the 3d noise.

$ratio = $h/$w;
$zCoord = 0; #0.0, 1.0
$uv = [$u, $v*$ratio, zCoord];

# We multiply the subdivisions with the uv vector to give a sense of zooming out.

$subdivisions = 23; # 1, 100;
$uv *= $subdivisions;

# We also rotate the uv coordinate around the z-axis, [0,0,1]. 

$rotation = 0; #0, 359;
$uv = rotate($uv, [0,0,1], rad(rotation));


# FBM Function
# ----------------

# Controls the frequencies.
$fbmOctaves = 2; #0, 10

# Spacing between the frequencies - a value of 2 means each octave is twice the previous frequency.
$fbmLacunarity = 1; #0, 10;

# controls how much each frequency is scaled relative to the previous frequency.
$fbmGain = 0.5; #0, 10.0


# Color
# -----
# Finally we input all the variables into the function to get a color.

$color = cfbm($uv, $fbmOctaves, $fbmLacunarity, $fbmGain);

# return the color.
$color

Color Turbulence

# Basic usage of the inbuilt seexpr color turbulence function.
# This just exposes each of the variables in the turbulence function for editing. Also adds rotation and scaling.

# UV vector manipulation
# ----------------------

# Construction of the UV vector. $u and $v are the normalized x and y coordinates for the image. This gives non-square results by default, so we calculate the ratio and then multiply the relevant dimension with said ratio to get a square result from the algorithms.
# The zCoordinate can be set manually in many of the inbuilt noise functions, as these produce 3d noise, but we have a 2d plane. So allowing people to manipulate the last dimension manually allows them to access other slices of the 3d noise.

$ratio = $h/$w;
$zCoord = 0; #0.0, 1.0
$uv = [$u, $v*$ratio, zCoord];

# We multiply the subdivisions with the uv vector to give a sense of zooming out.

$subdivisions = 23; # 1, 100;
$uv *= $subdivisions;

# We also rotate the uv coordinate around the z-axis, [0,0,1]. 

$rotation = 0; #0, 359;
$uv = rotate($uv, [0,0,1], rad(rotation));


# Tubulence Function
# ------------------

# Controls the frequencies.
$fbmOctaves = 2; #0, 10

# Spacing between the frequencies - a value of 2 means each octave is twice the previous frequency.
$fbmLacunarity = 1; #0, 10;

# controls how much each frequency is scaled relative to the previous frequency.
$fbmGain = 0.5; #0, 10.0


# Color
# -----
# We put the factor into the color turbulence to get the color.

$color = cturbulence($uv, $fbmOctaves, $fbmLacunarity, $fbmGain);

# return the color.
$color
5 Likes

Some gradients this time, and some stuff I had lying around that I hadn’t published yet.

The gradients in particular were something I really wanted to get done, as the ‘dirty screentone’ gradient is in effect a combination of several scripts, which in turn shows how you can combine and layer scripts for cool effects, and I really wanted to get that across.

Linear Gradient

# Basic angled linear gradient.
# -----------------------------
# By itself not a terribly interesting generator, but a useful building block in more complex scripts.

# UV vector manipulation
# ----------------------

# Construction of the UV vector. $u and $v are the normalized x and y coordinates for the image. This gives non-square results by default, so we calculate the ratio and then multiply the relevant dimension with said ratio to get a square result from the algorithms.

$ratio = $h / $w;
$uv = [$u, $v * $ratio, 0];

# Linear Gradient
# ---------------
# We're going to draw a linear angled gradient. Let's get the angle.

$rotation = 45; #0, 359

# The gradient is going to need a central point through which it's direction is crossing.

$centerX = 0.5;
$centerY = 0.5;

$center = [$centerX, $centerY*$ratio, 0];

# Subtract center from uv to get coordinate relative to center.
$uv -= $center;

# Use trig to get the value of this relative point on the gradient.

$fac = cos(rad($rotation))* $uv[0];
$fac += sin(rad($rotation))* $uv[1];

# Normalize the value into 0-1 space so we use the whole gradient.

$fac = clamp(0.5 - $fac, 0, 1);

# Color
# -----
# We put the factor into a gradient to get the color.

$color = ccurve($fac,0,[0.141,0.059,0.051],4,0.709957,[0.576471,0.87451,1],4,1,[0.976,0.976,0.976],4,0.320346,[0.196078,0.262745,0.4],4);

# return the color.
$color

Dirty Screentone

Here’s a combo between that gradient and the screentone dots and cell noise to create a unique dirty effect.

    # Angled, 'dirty' screentone.
# ---------------------------
# This combines a linear gradient, a cellnoise function, and the tiled dots scripts. We use both the cellnoise function and the gradient to additionally manipulate the radius of the dots. Combining different parts of scripts together is where little shader languages like SeExpr really shine.


# UV vector manipulation
# ----------------------

# Construction of the UV vector. $u and $v are the normalized x and y coordinates for the image. This gives non-square results by default, so we calculate the ratio and then multiply the relevant dimension with said ratio to get a square result from the algorithms.

$ratio = $h/$w;
$uv = [$u, $v*$ratio, 0];

# Everything for the dots.

# These are all the configurable variables. There's no reason why they're all
# assembled here besides making it easier to read the script. Values inside the
# comments are used by SeExpr widgets to determine the upper and lower limits.

$radius = 2; #0.0, 5.0
$lines = 60; #1, 300
$size = $lines;
$angle = 35; #0, 359
$softness = 0.2; #0.001, 1.0
$color1 = [0,0,0];
$color2 = [1,1,1];


# Linear Gradient
# ---------------

# We're going to draw a linear angled gradient.

$gradientRotation = 45; #0, 359

# The gradient is going to need a central point through which it's direction is crossing.

$centerX = 0.5;
$centerY = 0.5;

$center = [$centerX, $centerY*$ratio, 0];

$gradientUV = $uv - $center;

$gradientFac = cos(rad($gradientRotation))*$gradientUV[0];
$gradientFac += sin(rad($gradientRotation))*$gradientUV[1];

$gradientFac = clamp(0.5-$gradientFac, 0, 1);

# Applying the gradient to the radius...
$gradientFactor = 1;
$radius *= compress($gradientFac, 1-$gradientFactor, 1+$gradientFactor);

# Tiling part.
# ------------
# we'll construct the position of the current pixel
# in a pattern from the $uv

$tiles = $uv * size;
$repeat = boxstep(1 , fmod( $tiles[1], 1.0) );

# reassemble the tiled vector;

$tiles = [ $tiles[0] + $repeat, $tiles[1], 0];

# Now we rotate the tiled vector, 2d rotation uses the z-axis, that's [0, 0, 1].

$tiles = rotate($tiles, [0, 0, 1], rad($angle));

# 'Dirty' factor
# --------------
# If we input a multiplied and rotated uv into the cellnoise
# function, we can use that to make the radius, and thus the
# circles a little 'dirty'.
$dirtyFactor = 0.3;
$radius *= compress(cellnoise($tiles), 1-$dirtyFactor, 1+$dirtyFactor);

# Here we remove the offset from the tiled vector.
$tiles -= floor($tiles);

# circle determining part
# -----------------------
# we're computing a 'distance field' here.

$dist = $tiles - [0.5, 0.5, 0];
$dotproduct = dot(dist, dist) * 4;
$leftSide  = (1.0 - (0.5 * $softness)) * $radius;
$rightSize = (1.0 + (0.5 * $softness)) * $radius;
$fac = smoothstep($leftSide, $rightSize, $dotproduct);

# filling the shape
# -----------------
# we only want to use color interpolation if we're sure our distance
# factor is above 0, otherwise it'll need to be color 2.

if ($fac>0) {
$color = ccurve($fac, 0, $color1, 4, 1, $color2, 4);
} else {
$color = $color2;
}

# return the color.
$color

Conical Gradient

Not too happy with this one, as I can’t seem to figure out how to make the center possible to modify thanks to that hack…

# Conical Gradient.
# -----------------
# Creates a conical gradient by using the angle of the current pixel to the center.

# Construction of the UV vector. $u and $v are the normalized x and y coordinates for the image. This gives non-square results by default, so we calculate the ratio and then multiply the relevant dimension with said ratio to get non-stretched results from the algorithms.
$ratio = $h/$w;
$uv = [$u, $v*$ratio, 0];

# Center of the image.
$center = [.5, .5*$ratio, 0];

# Figure out how many repeats the gradient should have.
$repeats = 12;#0, 24;
$slice = 360/$repeats;

# Find the angle between the current pixel and the image center.
$relPixel = $uv-$center;
$curAngle = angle($center, $relPixel);

# convoluted thing to flip the angle right.
if (((1-$u)+$v)>1) {
$curAngle = (2*PI)-$curAngle;
}

# figure out in which section of the slice the pixel is.
$fac = fmod(deg($curAngle), $slice)/$slice;

# Colors
# ------

$color = ccurve($fac,0,[1,0,0],4,1,[1,0,0],4,0.5,[0,1,1],4,0.66,[0,0,1],4,0.33,[0,1,0],4,0.16,[1,1,0],4,0.83,[1,0,1],4);

# and we return the color

$color

Weird rectangle pattern

# This generates a pattern of concentric rectangles where the center is the same for each.

$outlines = 14; #1, 20;
$color1 = [0,0,0];
$color2 = [1,1,1];

# UV vector manipulation
# ----------------------

# Construction of the UV vector. $u and $v are the normalized x and y coordinates for the image. This gives non-square results by default, so we calculate the ratio and then multiply the relevant dimension with said ratio to get a square result from the algorithms.
# The zCoordinate can be set manually in many of the inbuilt noise functions, as these produce 3d noise, but we have a 2d plane. So allowing people to manipulate the last dimension manually allows them to access other slices of the 3d noise.

$ratio = $h/$w;
$zCoord = 0; #0.0, 1.0
$uv = [$u, $v*$ratio, zCoord];

# We multiply the subdivisions with the uv vector to give a sense of zooming out.

$subdivisions = 12; # 1, 100;
$uv *= $subdivisions;

# We also rotate the uv coordinate around the z-axis, [0,0,1]. 

$rotation = 0; #0, 359;
$uv = rotate($uv, [0,0,1], rad(rotation));

$point = pvoronoi($uv, 4, 0);

#square determining part

$distance = ($uv)-$point;

$fac = remap($distance[0], 0, .0, 2, 0);
$fac *= remap($distance[1], 0, .0, 2, 0);
$fac *=5;

#filling the squares

$fac = fmod(sin((1-$fac)*$outlines) , 1);
$color = ccurve($fac,0,$color1,4,1,$color2,4);

$color

Circles with voronoi

This one is slightly different from the other circle pattern.

# This generates a pattern of concentric circles where the center is the same for each.

$outlines = 8; #1, 20;
$color1 = [0,0,0];
$color2 = [1,1,1];

# UV vector manipulation
# ----------------------

# Construction of the UV vector. $u and $v are the normalized x and y coordinates for the image. This gives non-square results by default, so we calculate the ratio and then multiply the relevant dimension with said ratio to get a square result from the algorithms.
# The zCoordinate can be set manually in many of the inbuilt noise functions, as these produce 3d noise, but we have a 2d plane. So allowing people to manipulate the last dimension manually allows them to access other slices of the 3d noise.

$ratio = $h/$w;
$zCoord = 0; #0.0, 1.0
$uv = [$u, $v*$ratio, zCoord];

# We multiply the subdivisions with the uv vector to give a sense of zooming out.

$subdivisions = 10; # 1, 100;
$uv *= $subdivisions;

# We also rotate the uv coordinate around the z-axis, [0,0,1]. 

$rotation = 0; #0, 359;
$uv = rotate($uv, [0,0,1], rad(rotation));

# We get the center point of the voronoi cells, to use as a circle center.

$point = pvoronoi($uv, 4, 0);

#circle determining part

$distance = ($uv)-$point;

$fac = remap($distance[0], 0, .0, 1.1, 1);
$fac *= remap($distance[1], 0, .0, 1.1, 1);
$fac *=5;

#filling the circles

$fac = fmod(sin((1-$fac)*$outlines) , 1.)*($fac*.5);
$color = ccurve($fac,0,$color1,4,1,$color2,4);

$color

Random rotated hatches.

# tiled hatches.
# --------------
# Uses cellnoise to randomly rotate some straight lines 90°.

$ratiov = $h/$w;
$uv = [$u, $v*$ratiov, 0];
$scale2 = 10; #0,50
$color1 = [0,0,0];
$color2 = [1,1,1];

#use cellnoise to get a random value.

$celval = cellnoise($uv*$scale2);

# Draw the lines
#---------------

$distance = ($uv*$scale2)-[.5,.5,0];

# angle the lines using the cellnoise.

$angle = floor($celval*4)*90;
$distance = rotate($distance, [0,0,1], rad($angle));

$fac = fmod(sin($distance*(50-$scale2)), 1);

# Color
#------
$color = ccurve($fac,0,$color1,4,1,$color2,4);

$color

EDIT: fixed the dirty screentone as the cellnoise was using the wrong input…

4 Likes

Two more cellnoise adjusted textures and a moiré pattern:

Dirty Squares/Lines

# SeExpr script to draw tiled squares not unlike screentones, incoporates a radial graidient and uses cellnoise to introduce some dirtyness.

# [$u, $v, 0] is a vector constructed from the proportional horizontal and
# vertical positions ($u and $v) of the output pixel and 0 as the Z-value.
# We multiply the proportional vertical by the ratio we can get from the height
# and width of the image, so that our computed shapes are in a square aspect
# ratio, they'd get streched otherwise.

$ratiov = $h / $w;
$uv = [$u, $v * $ratiov, 0];

# These are all the configurable variables. There's no reason why they're all
# assembled here besides making it easier to read the script. Values inside the
# comments are used by SeExpr widgets to determine the upper and lower limits.

$radius = 0.5; #0.0, 1.0
$lines = 74; #1, 300
$size = $lines;
$angle = 217; #0, 359
$softness = 0.3; #0.001, 1.0
$color1 = [0,0,0];
$color2 = [1,1,1];

# Radial Gradient
#-----------------

$centerX = 0.5;
$centerY = 0.5;
$gradientUV = $uv-[$centerX, $centerY*$ratiov, 0];
$gradientFac = dot(gradientUV, gradientUV);
$gradientFactor = 1;
$radius *= compress($gradientFac, 1-$gradientFactor, 1+$gradientFactor);


# Tiling part.
# ------------
# we'll construct the position of the current pixel
# in a pattern from the $uv

$tiles = $uv * size;
$repeat = boxstep(1 , fmod( $tiles[1], 1.0) );

# reassemble the tiled vector;

$tiles = [ $tiles[0] + $repeat, $tiles[1], 0];

# Now we rotate the tiled vector, 2d rotation uses the z-axis, that's [0, 0, 1].

$tiles = rotate($tiles, [0, 0, 1], rad($angle));

# Here we remove the offset from the tiled vector.

$tileUV = $tiles;
$tiles -= floor($tiles);

# 'Dirty' factor
# --------------
# If we input a multiplied and rotated uv into the cellnoise
# function, we can use that to make the radius, and thus the
# circles a little 'dirty'.
$dirtyFactor = 1;
$radius *= compress(cellnoise([$tileUV[0], 0, 0]), 1-$dirtyFactor, 1+$dirtyFactor);


# square determining part
# -----------------------
# we're computing a 'distance field' here.

$fac = remap($tiles[0], 0.5, 0.5*$radius, 1*$softness, 2);
$fac *= remap($tiles[1], .5, 0.5*$radius, 1*$softness, 2);


# filling the shape
# -----------------

$color = ccurve($fac, 0, $color2, 4, 1, $color1, 4);

# and we return the color

$color

Radial Lines

# Radial Lines
# Using a variety of techniques, this combines a concentric gradient with a radial gradient and some cell noise to create radial lines.

$ratio = $h/$w;
$uv = [$u, $v*$ratio, 0];
$center = [.5, .5*$ratio, 0];
$subdivs = 120;#0, 360;
$slice = 360/$subdivs;
$color1 = [0,0,0];
$color2 = [1,1,1];

# Radial Gradient
#-----------------

$gradientUV = $uv-$center;
$gradientFac = dot(gradientUV, gradientUV);
$gradientFac = curve($gradientFac,0,0,4,1,1,1);
$gradientFactor = 1;

$radius = compress($gradientFac, 1-$gradientFactor, 1+$gradientFactor);

# Find the angle between the current pixel and the image center.
$curAngle = angle($center, $uv-$center);

# convoluted thing to flip the angle right.
if (((1-$u)+$v)>1) {
$curAngle = (2*PI)-$curAngle;
}

$fac = fmod(deg($curAngle), $slice)/$slice;

$fac = invert(abs(0.5-($fac))*2);

# Dirty factor using cellnoise.
$dirtyFactor = 0.5;
$dirtyAdjust = 3;#0, 10;
$random = cellnoise([deg($curAngle)/slice, $dirtyAdjust, 0]);
$random = compress($random, 1-$dirtyFactor, 1+$dirtyFactor);


$fac = fac*random*radius;
$fac = gaussstep(.9, 1.1, $fac);


# filling the shape
# -----------------

$color = ccurve($fac,0,$color2,2, 1,$color1,2);
if (fac <= 0) { color = color1;}

# and we return the color

$color

Moiré Pattern

# SeExpr script to create a moire pattern of two grids of dots.
# Moiré patterns are often brought up as mistakes, but can be invoked deliberately for cool effects.

# [$u, $v, 0] is a vector constructed from the proportional horizontal and
# vertical positions ($u and $v) of the output pixel and 0 as the Z-value.
# We multiply the proportional vertical by the ratio we can get from the height
# and width of the image, so that our computed shapes are in a square aspect
# ratio, they'd get streched otherwise.

$ratiov = $h / $w;
$uv = [$u, $v * $ratiov, 0];

# These are all the configurable variables. There's no reason why they're all
# assembled here besides making it easier to read the script. Values inside the
# comments are used by SeExpr widgets to determine the upper and lower limits.

$radius = 0.3; #0.0, 5.0
$lines = 60; #1, 300
$size = $lines;
$angle = 30; #0, 359
$moireOffset = 30; #0, 90
$softness = 0.2; #0.001, 1.0
$color1 = [0,0,0];
$color2 = [1,1,1];


# Tiling part.
# ------------
# we'll construct the position of the current pixel
# in a pattern from the $uv

$tiles = ($uv-[0.5, 0.5*$ratiov, 0]) * size;
$repeat = boxstep(1 , fmod( $tiles[1], 1.0) );

# reassemble the tiled vector;

$tiles = [ $tiles[0] + $repeat, $tiles[1], 0];

# Now we rotate the tiled vector, 2d rotation uses the z-axis, that's [0, 0, 1].

$tiles2= rotate($tiles, [0, 0, 1], rad($angle+$moireOffset));
$tiles = rotate($tiles, [0, 0, 1], rad($angle));

# Here we remove the offset from the tiled vector.

$tiles -= floor($tiles);
$tiles2 -= floor($tiles2);

# circle determining part
# -----------------------
# we're computing a 'distance field' here.

$dist = $tiles - [0.5, 0.5, 0];
$dotproduct = dot(dist, dist) * 4;
$leftSide  = (1.0 - (0.5 * $softness)) * $radius;
$rightSize = (1.0 + (0.5 * $softness)) * $radius;
$fac = smoothstep($leftSide, $rightSize, $dotproduct);

$dist = $tiles2 - [0.5, 0.5, 0];
$dotproduct = dot(dist, dist) * 4;
$fac2 = smoothstep($leftSide, $rightSize, $dotproduct);

# filling the shape
# -----------------
# we only want to use color interpolation if we're sure our distance
# factor is above 0, otherwise it'll need to be color 2.

if ($fac>0) {
$color = ccurve($fac, 0, $color1, 4, 1, $color2, 4);
} else {
$color = $color2;
}

if ($fac2>0) {
$colorb = ccurve($fac2, 0, $color1, 4, 1, $color2, 4);
} else {
$colorb = $color2;
}

color = min (color, colorb);

# and we return the color

$color

Of the examples deevad selected, one of them is a fractal flame, which cannot be done via seexpr, but maybe we could integrate flame3 somehow?

Put tiled into perspective is… within reach, but… making it’s UX make sense is it’s own mountain :slight_smile:

I also tried to search for this weird circular dot pattern I saw. Seems that this actually require poisson distribution, or as a hack, we reuse the penrose tiles, so I added some options to generate dots in the multigrid…

I think I’ve hit most of what I wanted to do…

5 Likes

Uploaded all of Wolthera and David’s examples here!

https://dump.amyspark.me/Krita_Artists’_SeExpr_examples.bundle

1 Like

These are some great examples. Thanks @wolthera for doing all this work coming up with these.

Spiral - logarithmic

Exposes a bunch of parameters and different rendering styles to choose from.

$moveHorizontal = 0; # -1.0, 1.0
$moveVertical = 0; # -1.0, 1.0
$zoom = 1; # 1.0, 10.0
$arms = 1; # 1,32
$mirror = 1; # 0,1
# default growth value 0.61803 (=1/φ =1-φ) is conjugate of golden ratio φ=1.61803...
$growth = 0.61803; # 0.0, 3.0
$drawStyle = 2; # 1, 3
$useGradient = 1; # 0, 1
$color = 0*1; # calculation to hide it from UI

# UV centering, offset, scaling, aspect correction
$ratiov = $h/$w;
$u = ($u-.5 - $moveHorizontal)/$zoom;
$v = ($v-.5 - $moveVertical)*$ratiov/$zoom;

$pxSize = 1/$w; # relative pixel size

$dist = hypot($u,$v); # distance from UV center
$ang = atan2($u,$v); # angle towards UV center
if ($mirror) {$ang = -atan2($u,$v);} # choice to flip growth direction

$fBase = $arms*(log($dist)/$growth + $ang); # function for 1 spiral period
$fOverlay = log(1+$arms*$pxSize/($dist*$zoom*log(1+$growth))); # used for correcting sharp edges

# allow switching between different styles
if ($drawStyle == 1) {
  $color = -sin($fBase)*0.5+0.5;
}
if ($drawStyle == 2) {
  $f1 = $fBase/(2*PI) % 1;
  # remove the edge aliasing caused by the modulo
  $f2 = $f1 - 0.1*$fOverlay;
  $color = $f1 - smoothstep($f1,$f2,1);
}
if ($drawStyle == 3) {
  $f1 = abs(sin($fBase));
  # keep constant line thickness with anti-aliasing
  $f2 = $f1 - 0.5*$fOverlay;
  $color = smoothstep($f2,$f1,0);
}

$color = max($color,0.0); # clamp to positive values

if ($useGradient) {
  $gradient = ccurve($color,0,[0,0,0.25],4,1,[1,1,1],4,0.5,[1,0.666667,0],4,0.25,[0.35,0,0.25],4);
  $color = $gradient;
}

$color

Spiral - simple

$moveHorizontal = 0; # -1.0, 1.0
$moveVertical = 0; # -1.0, 1.0
$zoom = 1; # 1.0, 10.0
$arms = 1; # 1,32
$mirror = 0; # 0,1
$drawStyle = 2; # 1, 3
$color = 0*1; # calculation to hide it from UI
$color1 =[0,0,0];
$color2 = [1,1,1];

# UV centering, offset, scaling, aspect correction
$ratiov = $h/$w;
$u = ($u-.5 - $moveHorizontal)/$zoom;
$v = ($v-.5 - $moveVertical)*$ratiov/$zoom;

$dist = hypot($u,$v); # distance from UV center
$ang = atan2($u,$v); # angle towards UV center

if ($mirror) {$ang = -atan2($u,$v);} # choice to flip growth direction

$color = sin($arms*$ang+$dist*100); # spiral sine function

# automatically converts to RGB vec3
if ($drawStyle == 1) {$color = $color1 + max($color,0)*$color2;}
# if drawStyle isn't 1, use ccurve to remap the sine function
$border=0.1/$zoom;
if ($drawStyle == 2) {$color = ccurve($color,-$border,$color1,4,$border,$color2,4);}
if ($drawStyle == 3) {$color = ccurve($color,-$border,$color1,4,0,$color2,4,$border,$color1,4);}

$color

Jewelry

Messing around with combining some periodic functions and a gradient map, also exposes a bunch of parameters to play with.
If anyone happens to know a nice and simple enough method to anti-alias or bandlimit those kind of functions in SeExpr, let me know.

$moveHorizontal = 0; # -1.0, 1.0
$moveVertical = 0.2; # -1.0, 1.0
$zoom = 3; # 1.0, 8.0
$mix = -0.8; # -1.0, 2.0
$mixOverlay = -0.2; # -2.0, 1.0
$f1Symmetry = 1.2; # 0.0, 2.0
$f2Frequency = 0.4; # 0.0, 2.0
$f2Crease = 0.5; # 0.0, 2.0
$f2Beam = 1.25; # 0.0, 2.0
$f2Mirror = 0; # 0, 1
$falloff = 1.25; # 0.0, 3.0

# UV centering, offset, scaling, aspect correction
$ratiov = $h/$w;
$u = ($u-.5 - $moveHorizontal)/$zoom;
$v = ($v-.5 - $moveVertical)*$ratiov/$zoom;

$pxSize = 1/$w; # relative pixel size

$ang = atan2($u,$v)/PI; # angle towards UV center between -1 to 1
$dist = hypot($u,$v)*100; # distance from UV center

$f1 = ($ang+$dist-1.5) % abs($ang) +$v+1/$dist;
if ($f1Symmetry) {
  $angMirror = atan2($u,-$v)/PI;
  $f1 += $f1Symmetry*(($angMirror+$dist-1.5) % abs($angMirror) -$v+1/$dist);
}

if ($f2Mirror) {
  $ang = atan2($u,-$v)/PI;
}
$f2 = 1/sin($f2Frequency*$dist*PI^($f2Crease*abs($ang)+1));
if ($f2Beam) {
  $f2 += $f2Beam*abs(1/($ang*3));
}

$color = mix($f1,$f2,$mix) + abs(($f1+$f2)/2)^$mixOverlay;

$dist ^= $falloff;

$gradient = ccurve(1/$dist * $color,0,[0.121569,0.027451,0.0431373],4,0.55,[0.764706,0.521569,0.239216],4,0.9,[1,0.909804,0.2],4,0.15,[0.894118,1,0.905882],4,0.35,[1,0.968627,0.490196],4,0.06,[0,0.0705882,0.32549],4,0.98,[1,1,0.796078],4,0.65,[0.454902,0.345098,0.270588],4,1,[1,1,0.498039],4);

$color = $gradient;
$color

Edit: Slight update to the spiral - simple one.

6 Likes

so pretty =0

1 Like

Spiral logarithmic can be coded in as part of the gradient preset instead. I should do that later as I did Spiral gradient. Thanks for the code.

1 Like