Framebuffer error loading images in OPENGL renderer

Hi,

I have set up a class that manipulates images, and have a reset() function to then undo all of that manipulation. When reset() is called, it throws an OPENGL error: "OpenGL error 1282 at top endDraw(): invalid operation OpenGL error 1281 at bot endDraw(): invalid value"

The program doesn't crash completely, sometimes only 1 image out of the sequence of 4 shows, sometimes none.

Here is the code that causes this to occur, pretty sure it is the imgs[i] = colorImage(imgs[i],-blueLog[i]); line:

  void resetBlue(){
    for(int i = 0;i < 4;i++){
      imgs[i].loadPixels();
      imgs[i] = colorImage(imgs[i],-blueLog[i]);
      imgs[i].updatePixels();
    }
  }

  PImage colorImage(PImage img,float b){
    img.loadPixels();
    for(int i = 0;i < img.pixels.length;i++){
      img.pixels[i] += color(0,0,b);
    }
    img.updatePixels();
    return img;
  }

Some further console error info:

Caused by: java.lang.RuntimeException: unknown framebuffer error (0)
    at processing.opengl.PGL.validateFramebuffer(PGL.java:2526)
    at processing.opengl.FrameBuffer.setColorBuffers(FrameBuffer.java:287)
    at processing.opengl.FrameBuffer.setColorBuffer(FrameBuffer.java:251)
    at processing.opengl.Texture.get(Texture.java:478)
    at processing.opengl.Texture.loadPixels(Texture.java:506)
    ... 19 more

Is the buffer simply being overloaded by 4 sequential calls to loadPixels()? Any help will be greatly appreciated, thanks

Answers

  • edited April 2014
    • Why blueLog is a float[]? Wouldn't an int[] or a short[] be more appropriate?
    • Are you sure blueLog's length is at least 4?
    • Why pass the negative of blueLog's values?
    • At line #12, what's the aim of the += operation?
    • Also @ color(0,0,b), defaulted expected range for each parameter is 0-255!

    http://processing.org/reference/color_.html

  • edited April 2014

    1 - easing is involved, so float is better to handle the smoother decimal point movement

    2 - blueLog's length is exactly 4. "float[] blueLog = new float[4];"

    3 - I am adding (+=) blue level to the image sequence as my manipulation, meanwhile totalling that all up so that when I resetBlue(), it removes the total blue added.

    4 - see above.

    5 - Yeah I understand that, I quite like the numbers overflowing though. As this is for a live show for an electronic musician, lots of flashes are good

  • I don't think img.pixels[i] += color(0,0,b); is the correct way to manipulate the Blue channel!
    We gotta use bit-shift operators and apply masks to isolate 1 of the 4 channels from the color value!

  • Agreed, that may be the better way, but that function is working - blue is applied during the render() function of my class, and the image responds correctly. Or are you saying that my manipulation may be causing the OpenGL error? This would be strange considering I've used this function multiple times before with no trouble

  • edited April 2014

    I still can't figure out the blue adding (or subtraction?) logic behind it. :-/
    Nevertheless, I've made some tweaks for it. And who knows it might fare better? [-O<

    // forum.processing.org/two/discussion/4273/
    // framebuffer-error-loading-images-in-opengl-renderer
    
    static final int NUM = 4;
    
    final PImage[] imgs = new PImage[NUM];
    final float[] blueLogs = new float[NUM];
    
    void resetBlue() {
      for ( int i = 0; i != NUM; colorImage(imgs[i], -blueLogs[i++]) );
    }
    
    static final void colorImage(PImage img, float b) {
      img.loadPixels();
    
      final color[] c = img.pixels;
      for ( int i = c.length; i-- != 0; c[i] += b );
    
      img.updatePixels();
    }
    
  • Sorry it's a bit of a rough one for sure. Basically I have a sequence of 4 images that cycle through while the program runs. Every time the draw loop is called, the blue from a variable is added to the current image. This variable is by default set to 0 so that nothing is added. A keypress sets this variable to 20, which then adds that level of blue to the current image. The variable has easing applied to it, with the target constantly set to 0. This means that for the first image in the sequence, 20 will be applied, but by the time the last image is displayed, only 6, for example, will be applied. I wanted a button to reset the images back to their original colour makeup, hence the negative blueLog

    Thanks for putting the effort in to coding that. I'm still not entirely familiar with static and certainly not the final keyword, so am slightly wary of adding this to my program. Also, you can call methods inside the for loop incrementer?? Nice.

  • Just tried adding it and it didn't like the static keyword in the function declaration. Removed that, and it came up with the same error as before

  • I don't see anything that could be triggering the framebuffer error in the code snippets that have been posted so far, so I'd guess that something else in the main draw() or another place in the sketch is causing the trouble. Could you post some of the higher-level logic of your sketch? Where resetBlue() is called from?

  • edited April 2014

    resetBlue() is called inside reset(), which resets the whole visualisation:

    void reset(){
        whatYouIdea = false;  whatYouB = 0;  prevMillis = 0;  count = 0;
        resetBlue();
    }
    

    This is then called inside a MIDI noteOn function once:

        void noteOn(int channel,int pitch,int velocity){
          //println(pitch);
    
          if(pitch < 24 && pitch != 8 && pitch != 16){
            //Visual Rack
            currentVisual = pitch%8;
            switch(currentVisual){
              case 0:  easy.setEasyfade(17); easy.setBackgroundColor(color(0));  break;
              case 1:  break;
              case 2:  break;
              case 3:  breathe.reset(); easy.setEasyfade(0); easy.setBackgroundColor(color(0));  break;
              case 4:  whatYou.reset(); easy.setEasyfade(34); easy.setBackgroundColor(color(0));  break;
              case 5:  break;
              case 6:  lost.reset(); easy.setEasyfade(0); easy.setBackgroundColor(color(0));  break;
              case 7:  break;
            }
          }
    }
    

    So resetBlue() is called once when the visual starts, and is then assigned to another MIDI button which I can trigger at any time. When I comment out the resetBlue() call inside reset(), the visual starts fine, but throws the same error when I press the assigned button.

  • edited April 2014

    You haven't tipped anything about having concurrent Thread access! :-w
    Beware of Thread shared variables & objects! (~~)

    Perhaps you should read this recent post below:

    http://forum.processing.org/two/discussion/4167/concurrentmodificationexception

  • edited April 2014

    That post gets very complicated very quickly. I haven't learned about concurrent threads, 'vectors', or synchronicity (synchronism?). As I understand, concurrent modification issues only become important when using something with variable length such as an ArrayList, of which I am using none. Is this false? What in my code has this problem?

    I'm way behind you in terms of programming ability, bear in mind.

    Edit: OK, I've got my head around the whole synchronising problem referred to in the thread, but as I said I am using no ArrayLists and am not getting a concurrent modification exception...

  • OH hang on is it because I'm trying to loadPixels() from 2 places at once?

  • edited April 2014 Answer ✓

    We dunno your whole program yet. And the situation you're in is that you've got your code running in 2 threads at the same time:

    1. "Animation" thread: the main Processing's executing Thread.
    2. "MIDI" thread: the other 1 run by the MIDI library when invoking noteOn().

    My knowledge w/ threads is still intermediary. So I'll just try to guess what might be going on!

    Your field variable imgs[] is being accessed by both threads:

    • I believe in draw(), which is run by the "Animation" thread, the imgs[] are rendered w/ image().
    • While at the same time in colorImage(), run by "MIDI" thread, the pixels[] from imgs[] are merciless manipulated!
    • Also, updatePixels() is something to consider too!

    Maybe you should synchronize those critical parts in order to disallow concurrent access by 2 threads at the same time! >-)

  • edited April 2014

    Just tried adding it and it didn't like the static keyword in the function declaration.

    The only way I see for not allowing it would be if colorImage() resided in an inner class rather than the sketch's top-class!
    I assumed that colorImage() was a general utility function. I don't see why it should belong to a specific class!

  • edited April 2014

    AH my mistake, it's a method. I included it there because if I copy that class file and it references a general colorImage() function, the class wouldn't run. I'm sure that's not the proper way of doing it though. If only I could make my own library of image processing functions, but I digress.

    So I should set up a flagging boolean to say "this visualisation has been switched on, now call it's reset function" inside draw().

    Nice one GoToLoop, thanks for the help!

    Edit: yep, error's all gone. sweet.

  • edited April 2014

    if I copy that class file and it references a general colorImage() function, the class wouldn't run.

    • Definition of a class is: fields + methods which act upon those fields.
    • If a method doesn't use any of those fields, it should go somewhere else!
    • For example, a class which only contains utility methods, like Java's static class Math!
    • In Processing's case, such methods stay w/ the sketch's top-class, along w/ setup(), draw() and company!

    P.S.: a static method can be invoked directly w/o instantiating the class it belongs to! :D

Sign In or Register to comment.