Tea Tree
Tea Tree

Reputation: 984

How to create a line with a gradient color?

I'd like to draw a line between a sphere and another sphere. The line should change its color from the color of the first sphere to the next. How do I do that?

Upvotes: 0

Views: 562

Answers (2)

George Profenza
George Profenza

Reputation: 51857

xImperiak's solution is correct (+1). If speed/efficiently becomes an issue the pixels[] can be accessed directly.

e.g.

loadPixels();
// for...
pixels[(int)newRelPoint.x + (int)newRelPoint.y * height] = colorAtPoint;

Since you mention spheres, you could potentially take advantage of the P3D renderer to change vertex colours to achieve a gradient effect:

color firstColor  = 0xffb957ce;
color secondColor = 0xff5994ce;

void setup(){
  size(600, 600, P3D);
  sphereDetail(9);
}

void draw(){
  background(#3a4e93);
  translate(width * 0.5, height * 0.5, 0);
  noFill();
  float sphere1Y = sin(frameCount * 0.01) * 30;
  float sphere2Y = sin((frameCount * 0.01) + PI) * 30;
  // draw 1st sphere
  drawSphere(-150, sphere1Y, 0, 90, firstColor);
  // draw 2nd sphere
  drawSphere( 150, sphere2Y, 0, 90, secondColor);
  //draw gradient line
  drawGradientLine(-150, sphere1Y, 0,
                    150, sphere2Y, 0,
                    firstColor, secondColor);
}

void drawGradientLine(float x1, float y1, float z1,
                      float x2, float y2, float z2,
                      color colorFrom, color colorTo){
  noStroke();
  // draw gradient line
  beginShape();
    // change vertex colours between vertices to achieve gradient look
    fill(colorFrom);
    vertex(x1, y1, z1);
    // slight offset to fake thickness
    vertex(x1, y1-3, z1);    
    fill(colorTo);
    vertex(x2, y2, z2);
    // slight offset to fake thickness
    vertex(x2, y2+3, z2);    
  endShape(CLOSE);                        
}

void drawSphere(float x, float y, float z, float radius, color strokeColor){
  stroke(strokeColor);
  pushMatrix();
    translate(x, y, z);
    sphere(radius);
  popMatrix();
}

gradient line

Notice a thin rectangle is drawn using 4 points: the two points between spheres and slight vertical offsets for each.

This is more of a workaround. Normally you would need to compute the angle between lines to correctly rotate coordinates, but since this is a stroke this could work well enough.

Additionally it might be possible to use @micycle's PeasyGradients libraries and mask() the lines you need.

Upvotes: 5

xImperiak
xImperiak

Reputation: 384

You will have to calculate the mathematical function of the line you want to draw. This is easly done just by substracting the vector of one of the points to the other point vector. This will be the direction vector, which will go multiplied by the variable, and then add one of the points. Afterwards you will have to use the set() (to change the color of the pixels) and the lerpColor() function (to do the gradient) provided by processing.

The final code would be something like this given:

PVector point1;
PVector point2;
color color1;
color color2;
void drawGradientLine(PVector point1, PVector point2, color color1, color color2){

  PVector direcVector = PVector.sub(point2, point1);

  for(float f = 0; f < 1; f += 0.0001){                 //0.0001 or the value that you prefer 0<k<1.

    PVector newRelPoint = PVector.mult(direcVector, f); //Rel from relative to, in this case, point1

    color colorAtPoint = lerpColor(color1, color2, f);

    set((int)newRelPoint.x, (int)newRelPoint.y, colorAtPoint);
  }
}

Upvotes: 3

Related Questions