Is it possible to change the transparency of a PShape object in draw()?

Hi,

The title says it all, I’d like to change in draw() the alpha value of a PShape object originally created in setup().

A quick example:

def setup():
    size(800, 800, P3D)
    global shp
    
    shp = createShape()
    shp.beginShape(POINTS)
    shp.strokeWeight(15)
    for e in range(300):
        shp.stroke(random(255), random(255), random(255))
        shp.vertex(random(width), random(height), random(width))
    shp.endShape()
                   
def draw():
    background(0)
    
    shape(shp, 0, 0)

I know I can change the visibility of the shape after it’s created with the setStroke() method but can’t find an equivalent for the alpha value.

I could certainly combine setStroke() with color()

def draw():

alpha_value = 110
shp.setStroke(color(255, alpha_value))

shape(shp, 0, 0)

… but then I’m losing all the colors previously set in setup().

How can I change the transparency while preserving all the colors ? Is that even possible ?

Would love your help,

Thank you

Here’s my attempt, for both Java & Python modes: :cowboy_hat_face:

/**
 * PShape Change Alpha Color (v1.0)
 * GoToLoop (2018/Jul/02)
 *
 * https://Discourse.Processing.org/t/
 * is-it-possible-to-change-the-transparency-of-a-pshape-object-in-draw/1429/2
 */

static final int DOTS = 300, DIAM = 020, RAD = DIAM >> 1;
PShape shp;

void setup() {
  size(800, 600, P2D);
  smooth(8);
  noLoop();

  strokeWeight(DIAM);

  shp = createShape();
  shp.beginShape(POINTS);

  for (int w = width - RAD, h = height - RAD, i = 0; i < DOTS; ++i) {
    shp.stroke((color) random(PImage.ALPHA_MASK));
    shp.vertex(random(RAD, w), random(RAD, h));
  }

  shp.endShape();
}

void draw() {
  clear();
  shape(shp, 0, 0);
}

void mousePressed() {
  if (mouseButton == LEFT)  for (int i = 0; i < DOTS; ++i) {
    final color stroke = shp.getStroke(i);
    final color rawStroke = stroke << 010 >>> 010;
    final color alpha = (color) random(0x100) << 030;
    final color alphaStroke = alpha | rawStroke;
    shp.setStroke(i, alphaStroke);
  } else if (mouseButton == RIGHT)  for (int i = 0; i < DOTS; 
    shp.setStroke(i++, (color) random(PImage.ALPHA_MASK)));
  else for (int w = width - RAD, h = height - RAD, i = 0; i < DOTS; 
    shp.setVertex(i++, random(RAD, w), random(RAD, h)));

  redraw();
}
"""
 PShape Change Alpha Color (v1.0.3)
 GoToLoop (2018/Jul/02)

 https://Discourse.Processing.org/t/
 is-it-possible-to-change-the-transparency-of-a-pshape-object-in-draw/1429/2
"""

ALL_COLORS = PImage.ALPHA_MASK
NO_ALPHA = ~PImage.ALPHA_MASK

DOTS = 300
RANGE = tuple(range(DOTS))

DIAM = 020
RAD = DIAM >> 1

def setup():
    size(800, 600, P2D)
    smooth(8)
    noLoop()

    strokeWeight(DIAM)

    global shp
    shp = createShape()
    w, h = width - RAD, height - RAD

    shp.beginShape(POINTS)

    for i in RANGE:
        shp.stroke(int(random(ALL_COLORS)))
        shp.vertex(random(RAD, w), random(RAD, h))

    shp.endShape()


def draw():
    clear()
    shape(shp, 0, 0)


def mousePressed():
    if mouseButton == LEFT:
        for i in RANGE:
            stroke = shp.getStroke(i)
            rawStroke = stroke & NO_ALPHA

            alpha = int(random(0x100)) << 030
            alphaStroke = alpha | rawStroke

            shp.setStroke(i, alphaStroke)

    elif mouseButton == RIGHT:
        for i in RANGE: shp.setStroke(i, int(random(ALL_COLORS)))

    else:
        w, h = width - RAD, height - RAD
        for i in RANGE: shp.setVertex(i, random(RAD, w), random(RAD, h))

    redraw()

Hi Solub! :slight_smile:
You can instantiate colors and points once in setup, and then call them later in draw

a = 0
def setup():
    size(800, 800, P3D)
    global shp, colors, points
    
    #Initiate colors and points once
    colors = [color(random(255),random(255),random(255)) for i in range(300)]
    points = [PVector(random(width), random(height), random(width)) for i in range(300)]
    
    shp = createShape()
    shp.beginShape(POINTS)
    shp.strokeWeight(15)
    for i,j in zip(colors,points):
        shp.stroke(i)
        shp.vertex(j.x,j.y,j.z)
    shp.endShape()

                   
def draw():
    background(0)
    global a
    for i,j in enumerate(colors):
        shp.setStroke(i,color(j,int(255*sin(a))))

    shape(shp, 0, 0)
    
    a += 0.01;

Edited: Since they’re both stored in a list, you can keep recreating the shape but changing the alpha of the stroke everytime (i mapped a simple sin for a quick test).

Is this the most efficient way? I’m not sure, I was hoping that there is a setVertexColor method in the documentation, but couldn’t find any. I would prefer doing that than simply recreating the shape. Hope this helps. Just by using setStroke(int index, color) method would be fine.

@WakeMeAtThree @GoToLoop Thank you both of you for your replies !

Upon reading your solutions I realized my problem was a bit more complex than I first thought and my question should have been more precise.

I’m trying to highlight a specific cluster within a point cloud by decreasing the alpha value of every points except the ones from the selected cluster.

However, not only the point cloud is a single PShape object (impossible to select a specific area) but also it is generated from a point shader (impossible to play with the alpha value without messing with the fragment shader directly)

Fortunately, thanks to your suggestions, I somewhat managed to find a workaround. The process goes like this:

pointShader

  • creating an alpha variable

setup()

  • loading the pointShader and setting alpha to 0.5
  • create a single PShape from the different point clusters
  • storing the colors in a 2D array list

draw()

  • applying the point shader
  • displaying the PShape (original point cloud with alpha set to 0.5)
  • reseting the point shader (resetShader(POINTS))
  • redrawing the selected points over the points already displayed
  • setting their colors from the 2D array list
  • setting their alpha value to max (not mendatory, 255 by default)

The only issue I have is that when I reset the shader I’m losing the perspective effect for the new points.

So I end up with a whole point cloud with a perspective effect and a cluster where the point sizes don’t vary in space, no matter how far their are from the camera.

point cloud with alpha = 1.0

point cloud with alpha = .4

You can see the new points. From a distance they look bigger than the original ones from the PShape.

close up with alpha = 1.0

close up with alpha = .4

But up close, it’s the contrary, they’re smaller than the original points. Hence, the difficulty to distinguish them from the other points.

2 Likes