Problems when drawing multiple PGraphics objects

edited April 2018 in Python Mode

Hi everyone,

(Please forgive me for asking a lot of questions recently, I'm just trying to be as efficient as possible while learning Processing.)

I'm drawing multiple ellipses that I would like to convert to PGraphics objects. The goal here is to later apply a blur effect to each object without having the frame rate dropping too much.

Ellipses look like this:

When converting them to PG objects I encounter different problems:

  • First, they are not drawn at the first iteration. I have to wait maybe 10 seconds before seeing them displayed on the screen.
  • Second, images of PGraphic objects are not aligned with the ellipses. I've been trying to play with ellipseMode(CENTER) and imageMode(CENTER)... unsuccessfuly.
  • Last, all PG objects display the same misaligned picture.

There must be something I'm doing wrong but can't figure out what exactely.

Snippet (from line 28 to 35):

pg.beginDraw()
pg.noStroke()
for b in balls:
    pg.ellipse(b.x, b.y, b.r, b.r)
    pg.fill(b.color[0],b.color[1],b.color[2])
    image(pg, b.x, b.y)
    b.update()
pg.endDraw()

Full code:

colors = [[255,20, 20], [20,255,255], [250,255,20]]

count = 0
rdm_count = 1
balls = []

def setup():
    global origin, pg
    size(800, 600, P2D)

    pg = createGraphics(10, 10)
    noStroke()

def draw():
    global origin, count, rdm_count
    background(30, 60, 100)

    if count == rdm_count:
        balls.append(Ball())
        count = 0
        rdm_count = 3 + floor(random(1) * 5)

    # for b in balls:
    #     ellipse(b.x, b.y, b.r, b.r)
    #     fill(b.color[0],b.color[1],b.color[2])
    #     b.update()

    pg.beginDraw()
    pg.noStroke()
    for b in balls:
        pg.ellipse(b.x, b.y, b.r, b.r)
        pg.fill(b.color[0],b.color[1],b.color[2])
        image(pg, b.x, b.y)
        b.update()
    pg.endDraw()

    removeBall()
    count += 1

def removeBall():
    for i, b in enumerate(balls):
        if b.x + b.r < 0 or b.x - b.r > width or b.y + b.r < 0 or b.y - b.r > height or b.r <= 0:
            del balls[i]

class Ball(object):
    def __init__(self):
        self.x = random(width)
        self.y = random(height)
        self.angle = PI * 2 * random(1)
        self.vx = (1.3 + random(1) * .3) * cos(self.angle)
        self.vy = (1.3 + random(1) * .3) * sin(self.angle)
        self.r = 6 + 3 * random(1)
        self.color = colors[int(random(len(colors)))]

    def update(self):
        self.x += self.vx
        self.y += self.vy
        self.r -= .01
Tagged:

Answers

  • edited April 2018 Answer ✓

    Problem solved, I needed:

    • to create a PGraphic object at each iteration for every objects in balls
    • to give constant x, y coordinates to pg.ellipse

       for b in balls:
              pg = createGraphics(10, 10)
              pg.beginDraw()
              pg.noStroke()
              pg.ellipseMode(CENTER)
              pg.fill(b.color[0],b.color[1],b.color[2])
              pg.ellipse(4, 4, b.r, b.r)
              image(pg, b.x, b.y)
              b.update()
              pg.endDraw()
      

    Overall it's a bad approach for what I was trying to do. Applying a blur filter to each object is worse than what I imagined.

  • edited April 2018

    Well, you could just clear the PGraphics or call background on it. You don't need to create a new one each time. A PGraphics works just like the main canvas -- it accumulates pixels unless you tell it not to explicitly.

    I'm not clear from your description and sketch what you are trying to do. It seems like there is a specific visual effect that you want to achieve (something involving blurring) that you can't achieve by simply drawing to the main sketch canvas -- but I'm not sure what that effect is.

  • @jeremydouglass Yes indeed, there's a specific effect I would like to achieve and I should have mentionned it in the first place, sorry.

    Do you remember when I was trying to draw 2d metaballs but the sketch was too slow in Python mode ? Well, while I was trying to figure out a solution I stumbled onto this very interesting article entitled "Creative Gooey Effects".

    Basically, it explains how to mimic a blob-like motion by:

    • applying a gaussian filter on moving ellipses
    • increasing the contrast of the alpha channel

    This is in a nutshell what I'm trying to do here.

  • edited April 2018

    So, how would working on a 10x10 PGraphics help you achieve that effect?

    It looks like it needs to be much higher resolution than that...?

    Also: why do this in a small area -- why not do this to the whole canvas, treating all balls at once?

  • edited April 2018

    I thought that applying a blur effect on multiple 10x10 PGs would be less computer intensive than applying it on a large 800x600 canvas. Sorry, what do you mean by "clearing" the PGraphics ?

  • https://processing.org/reference/clear_.html

    I might suggest doing a single blur pass on a single buffer first -- then trying to optimize once you have got a simple implementation of the basic effect working.

  • edited April 2018

    Oh I see, thanks. You're probably right, I'll do as you say.

  • edited April 2018

    Do you know how to tweak the contrast of the alpha channel in Processing ? Or preferably, is there a way to access the color matrix directly ?

    In HTML, the effect described above is implemented like this:

    <filter id="goo">
          <feGaussianBlur in="SourceGraphic" stdDeviation="10" result="blur" />
          <feColorMatrix in="blur" mode="matrix" values="1 0 0 0 0  0 1 0 0 0  0 0 1 0 0  0 0 0 19 -9" result="goo" />
    

    I guess filter(BLUR, 10) would do the trick for feGaussianBlur but how can I translate this kind of RGBAM color matrix ?

     r g b a m
    "1 0 0 0 0  
     0 1 0 0 0  
     0 0 1 0 0  
     0 0 0 19 -9"
    
  • is there a way to access the color matrix directly

    What is M in RGBAM?

    Do you mean accessing the pixels[] array to modify per-pixel values? Or perhaps tint()?

  • Sweet baby jesus, I just realized you're the Jeremy Douglass from the "10 Print" book... I love that book !

  • edited April 2018

    What is M in RGBAM?

    I don't know either, can't seem to find any info on that.

    EDIT: The fifth column seems to be the offset.

    Do you mean accessing the pixels[] array to modify per-pixel values?

    No, I have already tried to increase the color contrast by accessing the pixels array but the effect didn't work well.

    snippet from the test code:

    contrast = 10 * (mouseX/ float(width))
    bright = 255 * (mouseY / float(width) - .5)
    
    loadPixels()
    for i in range(width*height):
       index = pixels[i]
       r = (index >> 16) & 0xFF
       g = (index >> 8) & 0xFF
       b = index & 0xFF
    
       r = (r * contrast + bright)
       g = (g * contrast + bright)
       b = (b * contrast + bright)
    
       if r < 0: r == 0, 
       if r > 255: r == 255
       if g < 0: g == 0 
       if g > 255: g == 255
       if b < 0: b == 0 
       if b > 255: b == 255 
    
       pixels[i] = color(r,g,b, 255)
    
     updatePixels()
    

    Here you can see the alpha value set to max (255) no matter the amount of RGB contrast (depending on mouseX). From what I understand, it's quite the opposite that I should do:

    • keeping the color constrast as it is
    • increasing the alpha channel contrast (hence my question on color matrix filters)

    You can have a look here to see the effect live. In the HTML code (top left corner) if you replace line 7 by

    <feColorMatrix in="blur" mode="matrix" values="1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 0 0"/>

    ... you'll see the same sketch but all blured because of the alpha channel contrast being set to 0 (instead of 60 originally). Increasing that alpha contrast to 60 seems to sharpen the ellipses previously blured by the Gaussian filter.

    In short, I believe there's a difference between changing the alpha value (transparency) and changing the alpha channel contrast (sharpening ?).

Sign In or Register to comment.