Get RadialGradientPaint to work in processing 3

edited April 2018 in Questions about Code

I found this code on github that works fine on processing 2, but doens't on processing 3. It is supossed to draw radial gradients influenced by the mouse position using a java library. But in processing 3 it just shows a grey screen. I tried altering some things and a lot of google searches but I can't find the cause.

I had to add this line for it to find PGraphicsJava2D too:

import processing.awt.PGraphicsJava2D;
import java.awt.Graphics2D;
import java.awt.RadialGradientPaint;
import java.awt.Color;
import java.awt.geom.*;

Graphics2D g2;
Rectangle2D.Double rectangle;

Point2D center;
Point2D focus;
float radius;
float[] dist = { 0.0f, 0.4f, 1.0f };

Color[] gradColors = new Color[dist.length];

Color[] endColors = {
    new Color(254, 189, 75), // yellow
    new Color(255, 98, 43), // red
    new Color(87, 25, 198) // violet
};

Color[] startColors = {
    new Color(232, 185, 71),
    new Color(180, 98, 56),
    new Color(87, 36, 68)
};

void setup() {
  size(300, 600); // make sure NOT to use P2D
  g2 = ((PGraphicsJava2D)g).g2;

  rectangle = new Rectangle2D.Double(0, 0, width, height);
  radius = height;
  center = new Point2D.Float(width/2.0f, height);
  focus = new Point2D.Float(width/2.0f, height);
  updateColors(0);
}

void draw() {
  RadialGradientPaint gradient =
         new RadialGradientPaint(center,
                                 radius, 
                                 focus,
                                 dist, 
                                 gradColors,
                                 RadialGradientPaint.CycleMethod.NO_CYCLE);
  g2.setPaint(gradient);
  g2.fill(rectangle);
}

void mouseMoved() {
  updateColors((float) mouseY / height);
}

void updateColors(double blend) {
  for(int i = 0; i < gradColors.length; i++) {
    gradColors[i] = lerpColor(startColors[i], endColors[i], blend);
  }
}

Color lerpColor(Color color1, Color color2, double blend) {
  double inverseBlend = 1.0 - blend;
  int redPart = (int) (color1.getRed() * blend + color2.getRed() * inverseBlend);
  int greenPart = (int) (color1.getGreen() * blend + color2.getGreen() * inverseBlend);
  int bluePart = (int) (color1.getBlue() * blend + color2.getBlue() * inverseBlend);
  return new Color(redPart, greenPart, bluePart);
}
Tagged:

Answers

  • edited April 2018 Answer ✓

    While this doesn't answer your question about the AWT library, if I understand the effect you're looking to create, you could try as an alternative

    color[] endColors = {
      color(254, 189, 75), 
      color(255, 98, 43), 
      color(87, 25, 198)
    };
    
    color[] startColors = {
      color(232, 185, 71), 
      color(180, 98, 56), 
      color(87, 36, 68)
    };
    
    int lerpMode0 = HSB;
    int lerpMode1 = RGB;
    float cx, cy, maxdist, radscalar = 0.25;
    
    void setup() {
      size(300, 600, P2D);
      //size(300, 600);
      maxdist = radscalar * (width * width + height * height);
    }
    
    void draw() {
      loadPixels();
      cx = mouseX;
      cy = mouseY;
      float u = 0.5 + 0.5 * cos(frameCount * 0.01);
      color start = lerpColor(startColors, u, lerpMode0);
      color stop = lerpColor(endColors, u, lerpMode0);
      for (int i = 0, y = 0; y < height; ++y) {
        float rise = y - cy;
        rise *= rise;
        for (int x = 0; x < width; ++x, ++i) {
          float run = x - cx;
          run *= run;
          float dist = rise + run;
          float t = dist / maxdist;
          pixels[i] = lerpColor(start, stop, t, lerpMode1);
        }
      }
      updatePixels();
    }
    
    color lerpColor(color[] arr, float t, int colorMode) {
      int sz = arr.length;
      if (sz == 1 || t <= 0.0) { 
        return arr[0];
      } else if (t >= 1.0) { 
        return arr[sz - 1];
      }
      float fsz = float(sz - 1);
      float sclt = t * fsz;
      int i = int(sclt);
      return lerpColor(arr[i], arr[i + 1], sclt - i, colorMode);
    }
    

    The options you have for creating color gradients vary depending on

    which renderer you use; whether you want to fill a background with a gradient or a specific shape; and how sophisticated your gradient is (equidistant color stops are simpler than color stops at arbitrary percentages).

    This is why the comment in the original code advises against supplying 'P2D' or 'P3D' to the size function. Those renderers are based on OpenGL, and will let you supply fills on a vertex by vertex basis between begin- and endShape or write your own shader in GLSL, then supply it to PShader.

    If you want to create a specific shape like the donut in the original Stack Overflow question, you can use

    int detail = 32;
    float x = 0.0;
    float y = 0.0;
    float majorrad = 52.0;
    float minorrad = 32.0;
    PVector[] vs = new PVector[detail];
    
    void setup() {
      size(512, 256, P3D);
      x = width * 0.5;
      y = height * 0.5;
      majorrad = min(width, height) * 0.5;
      minorrad = majorrad * 0.5;
      float itopi = TWO_PI / float(detail - 1);
      for (int i = 0; i < detail; ++i) {
        float theta = i * itopi;
        vs[i] = new PVector(cos(theta), sin(theta));
      }
    }
    
    void draw() {
      stroke(0xffffffff);
      background(255);
      beginShape(QUADS);
      for (int i = 0, j; i < detail; ++i) {
        j = (i + 1) % detail;
        fill(0xffff0000);
        vertex(x + vs[i].x * minorrad, y + vs[i].y * minorrad);
        fill(0xffffff00);
        vertex(x + vs[i].x * majorrad, y + vs[i].y * majorrad);
        fill(0xffffff00);
        vertex(x + vs[j].x * majorrad, y + vs[j].y * majorrad);
        fill(0xffff0000);
        vertex(x + vs[j].x * minorrad, y + vs[j].y * minorrad);
      }
      endShape(CLOSE);
    }
    

    The disadvantage of this is that, since color is tied to a vertex, if you want more control over the colors, you have to add more vertices. For example, if you want a middle color between the red inner edge and yellow outer edge of the donut, you have to add an extra ring in the middle.

  • Thank you very much for the response! It really helped me out a lot, works great for what I wanted to achieve.

Sign In or Register to comment.