Flicker with P3D but No flicker with Default Renderer

edited October 2013 in Using Processing

The following is a simple example I found on learning processing. In the setup function changing: size(320,240);

to: size(320,240, P2D); or size(320,240, P3D);

causes the image to flicker. I'm not sure why this happens. Any help would be appreciated.

// Learning Processing
// Daniel Shiffman
// http://www.learningprocessing.com

// Example 16-13: Simple motion detection

import processing.video.*;
// Variable for capture device
Capture video;
// Previous Frame
PImage prevFrame;
// How different must a pixel be to be a "motion" pixel
float threshold = 50;

void setup() {
  size(320,240, P2D);
  video = new Capture(this, width, height, 30);
  // Create an empty image the same size as the video
  prevFrame = createImage(video.width,video.height,RGB);
  video.start();
}

void draw() {

  // Capture video
  if (video.available()) {
    // Save previous frame for motion detection!!
    prevFrame.copy(video,0,0,video.width,video.height,0,0,video.width,video.height); // Before we read the new frame, we always save the previous frame for comparison!
    prevFrame.updatePixels();
    video.read();
  }

  loadPixels();
  video.loadPixels();
  prevFrame.loadPixels();

  // Begin loop to walk through every pixel
  for (int x = 0; x < video.width; x ++ ) {
    for (int y = 0; y < video.height; y ++ ) {

      int loc = x + y*video.width;            // Step 1, what is the 1D pixel location
      color current = video.pixels[loc];      // Step 2, what is the current color
      color previous = prevFrame.pixels[loc]; // Step 3, what is the previous color

      // Step 4, compare colors (previous vs. current)
      float r1 = red(current); float g1 = green(current); float b1 = blue(current);
      float r2 = red(previous); float g2 = green(previous); float b2 = blue(previous);
      float diff = dist(r1,g1,b1,r2,g2,b2);

      // Step 5, How different are the colors?
      // If the color at that pixel has changed, then there is motion at that pixel.
      if (diff > threshold) { 
        // If motion, display black
        pixels[loc] = color(0);
      } else {
        // If not, display white
        pixels[loc] = color(255);
      }
    }
  }
  updatePixels();
}

Answers

  • I can reproduce your problem, as well. But in my case the reason is that my laptop has Intel Graphics Adapter, which doesn't seem to implement full fledge OPENGL functions.

    Processing P2D and P3D seems to be working well only on latest drivers and best graphics adapters.

    See the error messages in red in console? That is a sign that graphics adapter may not be not supported or that you may need to update drivers to latest version.

    example error messages

  • edited October 2013

    On my laptop which has a 6750m Radeon processor, I only have a white screen display when I try to use a p2d or p3d context. It works smooth with the default.

    On desktop which has a Radeon 5770 I see flicker with p2d and p3d.

    Both my desktop and my laptop have fairly capable video cards as far as what I'm trying to do. Also I don't see the errors that you see which is odd.

  • And did you have issues when running other P3D/P2D sketches??

    For example Trefoil? ( which doens't work for me)? Or other sketches from the examples folder? image alt text

  • Trefoil and the others work fine. I thought it was the webcam but if I add image(video, 0, 0) the video plays on the screen just fine even with the p3d/p2d.

    I get no errors when using p2d/p3d. The flicker is the only issue I see.

  • Answer ✓

    That sounds like a problem with loadPixels() updatePixels() in P2D renderer. Which is not really meant for pixel operations.

    The best solution for you would be to introduce new PImage, let's say

    PImage differenceBetweenFrames;
    
    // add to setup()
    differenceBetweenFrames = createImage(width, height, RGB);
    
    
    //now in your draw instead of :
    loadPixels();
      video.loadPixels();
      prevFrame.loadPixels();
    
    // you do
     differenceBetweenFrames.loadPixels();
      video.loadPixels();
      prevFrame.loadPixels();
    
    
    // then in your for() loops, you write difference result not into pixels[] array but into differenceBetweenFrames.pixels[] array.
    
    // then in the very end of the draw() loop you do
    image(differenceBetweenFrames, 0,0);
    

    I guess you got the point: we introduce intermediary "framebuffer" into which we write the difference.

    As P2D is just P3D with exception that Z-coordinate is not used. It's implementation is based on OPENGL and is meant to draw 3D objects. Or at worst: geometrical primitves (Like triangles, quads, rects) and later putting textures on those objects or primitives.

    Operating directly with pixels under this OpenGL based renderer is against the paradigm of the open gl. This leads me to believe that operating directly on P2D pixels[] array will not always produce good results, as it doesn't seem something OpenGL was meant to do.

    So when we introduce intermediary image, we avoid breaking OpenGL paradigm: the direct pixel operations happen on the PImages (which are raster images) and operate with 2D and pixel rasterparaidgm. Later the raster will be send to the screen as "texture stretched to screen size". Thus way it kinda doesn't break OPENGL paradigm and should work :)

  • I ended up implementing exactly what you described to get around the issue. Good to see it was the correct path. Thank you.

Sign In or Register to comment.