Spatio Chromathic Texture Synthesizer
This implementation of variation of AM-halftoning started as an experiment, trying to create a filter that did engraving style lines depending on the source hue/saturation for angle and frequency, the core structure of the filter thus developed was suited also for the core of a glsl shader.
When used with the GEGL tool in GIMP-2.9, it can often be advantagous to first apply a gaussian blur to the input image, this produces nicer smoother isoline/countour line like patterns.
The following code is the core of spachromtyzer, both for the GEGL operation for use with GIMP-2.9 and beyond, and the glsl webgl shader. The code is written for compatibility both with C and webgl's variation of glsl. It takes the coordinates and input colors of one pixel and returns the grayscale level of a corresponding halftoning mask for that pixel, multiple masks are combined to create the composite RGB/CMYK results.
/*
 * Copyright (c) 2017 Øyvind Kolås <pippin@gimp.org>
 *
 * Permission to use, copy, modify, and/or distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */
float spachrotyze (
    float x,
    float y,
    float part_white,
    float offset,
    float hue,
    int   pattern,
    float period,
    float turbulence,
    float blocksize,
    float angleboost,
    float twist)
{
  const float aa  = 2.0;  /* this gives 2x2 MSAA -
                             increase value for better antialiasing*/
  float acc   = 0.0;
  float angle = (1.0-(hue * angleboost) + twist);
  float width = (period * (1.0 - turbulence) +
                (period * offset) * turbulence);
  float vec0 = cosf (-angle * 3.14151 / 2.0);
  float vec1 = sinf (-angle * 3.14151 / 2.0);
  float aa_sq = aa * aa;
  for (float xi = 0.0; xi < aa; xi += 1.0)
  {
    float u = fmodf (x + xi/aa + 0.5 * width, blocksize * width);
    for (float yi = 0.0; yi < aa; yi += 1.0)
    {
      float v = fmodf (y + yi/aa + 0.5 * width, blocksize * width);
      float w = vec0 * u + vec1 * v;
      float q = vec1 * u - vec0 * v;
      float wperiod = fmodf (w, width);
      float wphase  = (wperiod / width) * 2.0 - 1.0;
      float qperiod = fmodf (q, width);
      float qphase  = (qperiod / width) * 2.0 - 1.0;
      if (pattern == 0) {      /* line */
        if (fabsf (wphase) < part_white)
          acc += 1.0 / aa_sq;
      }
      else if (pattern == 1) { /* dot */
        if (qphase * qphase + wphase * wphase <
          part_white * part_white * 2.0)
          acc += 1.0 / aa_sq;
      }
      else if (pattern == 2) { /* diamond */
        if (fabsf(wphase) + fabsf(qphase) < (part_white*2.0) )
          acc += 1.0 / aa_sq;
      }
      else if (pattern == 3) { /* dot-to-diamond-to-dot */
          float ax = fabsf (wphase ) ;
          float ay = fabsf (qphase ) ;
          float v = 0.0;
          if  (ax + ay > 1.0)
          {
            v = 2.0 - sqrtf((1.0-ay) * (1.0-ay) + (1.0-ax) * (1.0-ax));
          }
          else
          {
            v = sqrtf (ay * ay + ax * ax);
          }
          v/=2.0;
          if (v < part_white)
            acc = acc + 1.0 / aa_sq;
      }
    }
  }
  return acc;
}