How Do I Make "Smarter" Linear Gradients (Ex. From Orange To Violet)?

Greetings everyone!

I’m struggling with an issue where I want to create a linear gradient that goes from two colors that are relatively close together on the color wheel (ex. orange and violet). What I want is a simple gradient that takes the shortest path around the color wheel between orange and violet (orange > red > violet).

However, by using the established tools like the Linear Gradient function found on the Processing.org Examples page or the lerpColor() function, I end up getting a gradient that includes all of the colors in between orange and violet when taking the LONG way around the color wheel (orange > yellow > green > blue > indigo > violet).

Does anyone have any pointers on how to produce the desired gradient without turning the function’s code into a very long and convoluted collection of conditional operators? I can’t help but feel that I’m going about thins the wrong way, so I wanted to see if any of you could point me in the right direction.

Thanks in advance for any help that you all may be able to provide me! Thanks for your time, and have a wonderful day!

Below is a sample code that shows when I try to transition from orange to violet:

int dw = 20;
int dh = 20;
color ORA, VIO;
int Y_AXIS = 1; // Top to bottom gradient.
int X_AXIS = 2; // Left to right gradient.

float gradBoxWidth, gradBoxHeight;

void setup() {
  size(640,480);
  colorMode(HSB, 360, 100, 100, 100);
  ORA = color(30, 100, 100, 100);
  VIO = color(270, 100, 100, 100);
  gradBoxWidth = 250;
  gradBoxHeight = 50;
}

void draw() {
  noStroke();
  // The following for() loops will generate a series of circles that scroll down the Display Area that will iterate from color ORA to VIO.
  for (int x = 0; x < width; x += dw) {
    for (int y = 0; y < height; y += dh) {
      int loc = x + y * width;
      float ratio = float(loc) / (width * height);
      color c = lerpColor(ORA, VIO, ratio);
      fill(c);
      ellipse(x, y, dw, dh);    
    }
  }
  
  // The following code block will generate a box that will contain a linear gradient.
  stroke(0, 0, 0, 100);
  strokeWeight(2);
  fill(0, 0, 100, 100);
  rect(int((width / 2) - (gradBoxWidth / 2)), int((height / 2) - (gradBoxHeight / 2)), gradBoxWidth, gradBoxHeight);
  
  // The following code block will generate a linear gradient using the standard setGradient() function.
  noStroke();
  strokeWeight(1);
  noFill();
  setGradient(int((width / 2) - (gradBoxWidth / 2)), int((height / 2) - (gradBoxHeight / 2)), gradBoxWidth, gradBoxHeight, ORA, VIO, X_AXIS);
}

// This function will render either a vertical or horizontal gradient.
void setGradient(int x, int y, float w, float h, color c1, color c2, int axis ) {
  // This function will create a gradient.
  noFill();
  strokeWeight(1);

  if (axis == Y_AXIS) {  // Top to bottom gradient
    for (int i = y; i <= y+h; i++) {
      float inter = map(i, y, y+h, 0, 1);
      color c = lerpColor(c1, c2, inter);
      stroke(c);
      line(x, i, x+w, i);
    }
  }  
  else if (axis == X_AXIS) {  // Left to right gradient
    for (int i = x; i <= x+w; i++) {
      float inter = map(i, x, x+w, 0, 1);
      color c = lerpColor(c1, c2, inter);
      stroke(c);
      line(i, y, i, y+h);
    }
  }
}

Hello,

Welcome to the forum.

An example for you:

// Gradient
// v1.0.0
// GLV 2021-07-24

void setup() 
  {
  size(360, 100);
  colorMode(HSB, 360, 100, 100);
  
  for(int i = 0; i<360; i++)
    {
    stroke(i, 100, 100);  
    line(i, 0, i, height/2);      
    }
  
  for(int i = 0; i<360; i++)
    {  
    float hue = map(i, 0, 360, 30, -90);

    println(i, int(hue), int(360+hue));   // See what is going on!

    if (hue < 0)
      hue = 360+hue;  
 
    stroke(hue, 100, 100);  
    line(i, height/2, i, height);      
    }    
  }

image

It is simple, uncommented and a quick first pass at this.

There are resources (tutorials, references, examples, etc.) here:
https://processing.org/

And examples that come with Processing:

image

:)

1 Like

I played with your code a bit, and found a simple change of the colorMode after you set the colors in setup worked. But ofc then the colormode is changed and you might not want that (In which case glv has another solution above).

void setup() {
  size(640,480);
  colorMode(HSB, 360, 100, 100, 100);
  ORA = color(30, 100, 100, 100);
  VIO = color(270, 100, 100, 100);
  colorMode(RGB);  // <--- 
  gradBoxWidth = 250;
  gradBoxHeight = 50;
}

1 Like

Hey raron,

Thank you kindly for your input! I should’ve specified in my original post that I wanted to keep everything functioning in the HSB color mode as opposed to using RGB. But your first post gives me the insight that I need to get myself moving along in this project! Thank you so very much!