How to do this kind of gradient on shapes

here are bunch of shapes floating here and there. so i need to apply this kind of a gradient on them. can anyone tell me how to do these kind of thing will be appreciated.

Here is the SS:

Many Thanks! :blush:
-scoopz

Hi Scoopz!

You can probably create that gradient effect by mapping the position of each shape to a certain hue value. I could explain that a bit further if you would like, but it’s my suggestion. Let me know!

Thanks,
-Justin

Just interrupting to add a little tidbit onto JustinJohnson’s post: you can also play with the saturation value (the S in HSB) to get that “in the distance fade” effect!
Have fun and good luck!

  • Trilobyte

Gradient should extract for each shape from this kind of color gradient.

@helloscoopz – do you want the gradient to be within the shapes as well, or should each shape be a flat color?

If you want each shape to have a part of the gradient on it as well, use masking with PImage.mask().

If you want flat color, a simple test sketch to get you started is to load your gradient in an image, then use PImage.get() with mouseX / mouseY and see how you can load the gradient color of a coordinate and print it to the console. From there, use the coordinates for each shape, and retrieve the color to set its fill value.

2 Likes

Scoopz,

For a smooth gradient that is expressed within each shape, you could use a shader to create the gradient and PShapes to store the polygons. From the screenshot it looks like you’ve got an angled linear gradient from the upper-left corner to the lower-right corner with about three color stops–green, teal and red. The fragment shader for this might go like

#ifdef GL_ES
precision mediump int;
precision mediump float;
#endif

const vec2 origin = vec2(0.0, 256.0);
const vec2 destination = vec2(512.0, 0.0);

const vec4[] palette = vec4[3] (
  vec4(0.0, 1.0, 0.0, 1.0), /* Green */
  vec4(0.0, 0.5, 1.0, 1.0), /* Teal */
  vec4(1.0, 0.0, 0.0, 1.0) /* Red */
  );

vec4 mix_rgb(vec4[3] arr, float t) {
  if(t <= 0.0) {
    return arr[0];
  }

  int j = arr.length() - 1;
  if(t >= 1.0) {
    return arr[j];
  }

  float scaled = t * j;
  int i = int(scaled);
  return mix(arr[i], arr[i + 1], scaled - i);
}

float linear_gradient(vec2 origin, vec2 dest, vec2 point) {
  vec2 od = dest - origin;
  vec2 op = point - origin;
  return clamp(dot(op, od) / dot(od, od), 0.0, 1.0);
}

void main() {
  gl_FragColor = mix_rgb(palette,
    linear_gradient(origin, destination, gl_FragCoord.xy));
}

The linear gradient function works by scalar projection of one vector onto another. You can see various explanations of it at https://stackoverflow.com/questions/1459368/snap-point-to-a-line and https://natureofcode.com/book/chapter-6-autonomous-agents/ . This gives you the ability to change the kind of gradient (radial, conic), and the colors later on.

Th shader file goes in the sketch’s data folder. To apply it to the polygons:

int count = 75;
int[] sides = {3, 4, 64};
ArrayList<PShape> polygons = new ArrayList<PShape>(count);
PShader gradient;

void setup() {
  size(512, 256, P3D);
  smooth(8);
  gradient = loadShader("gradient.frag");
  shader(gradient);

  for (int i = 0; i < count; ++i) {
    int rndindex = int(random(0, sides.length));
    int rndside = sides[rndindex];
    PShape polygon = convexPolygon(rndside);
    polygon.scale(16.0);
    polygon.rotate(random(TWO_PI));
    polygon.translate(random(width), random(height));
    polygons.add(polygon);
  }
}

void draw() {
  background(0xffffffff);
  for (PShape polygon : polygons) {
    polygon.translate(random(-1.0, 1.0), random(-1.0, 1.0));
    shape(polygon);
  }
}

PShape convexPolygon(int sides) {
  PShape result = createShape();
  result.beginShape(POLYGON);
  result.strokeWeight(0.0);
  float iToTheta = TWO_PI / float(sides);
  for (int i = 0; i < sides; ++i) {
    float theta = i * iToTheta;
    result.vertex(cos(theta), sin(theta));
  }
  result.endShape(CLOSE);
  return result;
}

This produced the following screenshot:
screencap

2 Likes

wow. This is great. Thanks!

1 Like