GLGraphics & Processing 3.0

edited October 2015 in GLSL / Shaders

Hi all, so I'm getting more into OpenGL and shaders. Started looking at the GLGraphics library which as far as I remember is compatible with processing 1.5. I've been trying to run the examples on processing 3.0 but I'm getting errors like this: POINT_SPRITES does not exist. Does anyone know how to adapt the code for processing 3.0?

Answers

  • // A simple particle system example with GLGraphics
    // By Andres Colubri
    
    import processing.opengl.*;
    import codeanticode.glgraphics.*;
    import java.nio.FloatBuffer;
    
    GLModel sys;
    GLTexture tex;
    
    int npartTotal = 1000;
    int npartPerFrame = 10;
    float speed = 1.0;
    float gravity = 0.05;
    
    int partLifetime;
    
    PVector velocities[];
    int lifetimes[];
    
    void setup() {
      size(640, 480, GLConstants.GLGRAPHICS);  
    
      partLifetime = npartTotal / npartPerFrame;
    
      sys = new GLModel(this, npartTotal, GLModel.POINT_SPRITES, GLModel.DYNAMIC);
      initColors();
      initPositions();
      initSprites();
    
      initVelocities();
      initLifetimes();  
    }
    
    void draw() {    
      GLGraphics renderer = (GLGraphics)g;
      renderer.beginPGL();  
    
      background(0);
    
      updatePositions();
      updateColors();
      updateLifetimes();
    
      //translate(mouseX, mouseY, 0);   
    
      // Disabling depth masking to properly render semitransparent
      // particles without need of depth-sorting them.    
      renderer.setDepthMask(false);
      sys.render();
      renderer.setDepthMask(true);
    
      renderer.endPGL();
    }
    
    void initSprites() {
       tex = new GLTexture(this, "particle.png");    
       float pmax = sys.getMaxPointSize();
       println("Maximum sprite size supported by the video card: " + pmax + " pixels.");   
       sys.initTextures(1);
       sys.setTexture(0, tex);  
       // Setting the maximum sprite to the 90% of the maximum point size.
       sys.setMaxSpriteSize(0.9 * pmax);
       // Setting the distance attenuation function so that the sprite size
       // is 20 when the distance to the camera is 400.
       sys.setSpriteSize(20, 400);
       sys.setBlendMode(BLEND);  
    }
    
    void initColors() {
      sys.initColors();
      sys.setColors(0, 0);
    }
    
    void initPositions() {
      sys.beginUpdateVertices();
      FloatBuffer vbuf = sys.vertices;
      float pos[] = { 0, 0, 0, 0 };
      for (int n = 0; n < sys.getSize(); n++) {
        vbuf.position(4 * n);
        vbuf.get(pos, 0, 3);  
    
        pos[0] = 0;
        pos[1] = 0;
        pos[2] = 0;
        pos[3] = 1; // The W coordinate must be 1.
    
        vbuf.position(4 * n);
        vbuf.put(pos, 0, 4);
      }  
      sys.endUpdateVertices();  
    }
    
    void initVelocities() {
      velocities = new PVector[npartTotal];
      for (int n = 0; n < velocities.length; n++) {
        velocities[n] = new PVector();
      }  
    }
    
    void initLifetimes() {
      // Initialzing particles with negative lifetimes so they are added
      // progresively into the scene during the first frames of the program  
      lifetimes = new int[npartTotal];
      int t = -1;
      for (int n = 0; n < lifetimes.length; n++) {    
        if (n % npartPerFrame == 0) {
          t++;
        }
        lifetimes[n] = -t; 
      }  
    }
    
    void updatePositions() {
      sys.beginUpdateVertices();
      FloatBuffer vbuf = sys.vertices;
      float pos[] = { 0, 0, 0 };
      for (int n = 0; n < sys.getSize(); n++) {
        vbuf.position(4 * n);
        vbuf.get(pos, 0, 3);  
    
        if (lifetimes[n] == 0) {
          // Respawn dead particle:
          pos[0] = mouseX; 
          pos[1] = mouseY;
          pos[2] = 0;
          float a = random(0, TWO_PI);
          float s = random(0.5 * speed, speed);
          velocities[n].x = s * cos(a);
          velocities[n].y = s * sin(a);
          velocities[n].z = 0;  
        } else {
          // Update moving particle.
          pos[0] += velocities[n].x; 
          pos[1] += velocities[n].y;
          pos[2] += velocities[n].z;
          // Updating velocity.
          velocities[n].y += gravity;      
        }
    
        vbuf.position(4 * n);
        vbuf.put(pos, 0, 3);
      }
      vbuf.rewind();
      sys.endUpdateVertices();  
    }
    
    void updateColors() {
      sys.beginUpdateColors();
      FloatBuffer cbuf = sys.colors;
      float col[] = { 0, 0, 0, 0 };
      for (int n = 0; n < sys.getSize(); n++) {
        if (0 <= lifetimes[n]) {
          // Interpolating between alpha 1 to 0:
          float a = 1.0 - float(lifetimes[n]) / partLifetime;
    
          col[0] = 1.0;
          col[1] = 1.0;
          col[2] = 1.0;
          col[3] = a;
    
          cbuf.position(4 * n);
          cbuf.put(col, 0, 4);
        }
      }
      cbuf.rewind();
      sys.endUpdateColors();
    }
    
    void updateLifetimes() {
      for (int n = 0; n < sys.getSize(); n++) {
        lifetimes[n]++;
        if (lifetimes[n] == partLifetime) {
          lifetimes[n] = 0;
        }    
      }
    }  
    
  • edited October 2015 Answer ✓

    Well, as the title in the comments implies, this is just a simple particle system utilizing the features of GLGraphics. In other words: It's basically just a demo of fancy point sprites.

    I cleaned up the code and ported the example to Processing 3.0. All that's left to do is to implement a custom point sprite shader. Just read 10. Point and line shaders on Processing's shader page for more information.

    class Particle {
    
        float posX, posY;
        float velX, velY;
        int lifetime;
    
        void spawn() {
            posX = mouseX;
            posY = mouseY;
            float angle = random(TWO_PI);
            float speed = random(0.5 * SPEED, SPEED);
            velX = speed * cos(angle);
            velY = speed * sin(angle);
            lifetime = MAX_LIFETIME;
        }
    
        void update() {
            posX += velX;
            posY += velY;
            velY += GRAVITY;
            --lifetime;
        }
    
        void render() {
            stroke(0xffffffff, 255.0 * (float)lifetime / MAX_LIFETIME);
            point(posX, posY);
        }
    
    }
    
    static final int MAX_PARTICLES = 1000;
    static final int MAX_SPAWN = 10;
    static final int MAX_LIFETIME = MAX_PARTICLES / MAX_SPAWN;
    static final float SPEED = 1.0;
    static final float GRAVITY = 0.05;
    
    Particle[] particles;
    int aliveParticles;
    
    void setup() {
        size(640, 480, P2D);
        hint(DISABLE_DEPTH_MASK);
        initParticles();
    }
    
    void draw() {
        background(0);
        spawnParticles(MAX_SPAWN);
        updateParticles();
        renderParticles();
    }
    
    void initParticles() {
        particles = new Particle[MAX_PARTICLES];
        for(int n = MAX_PARTICLES; n-- > 0;)
            particles[n] = new Particle();
        strokeWeight(40);
    }
    
    void spawnParticles(int amount) {
        while(amount-- > 0 && aliveParticles < MAX_PARTICLES)
            particles[aliveParticles++].spawn();
    }
    
    void updateParticles() {
        for(int n = aliveParticles; n-- > 0;) {
            particles[n].update();
            if(particles[n].lifetime <= 0) {
                Particle dead = particles[n];
                particles[n] = particles[--aliveParticles];
                particles[aliveParticles] = dead;
            }
        }
    }
    
    void renderParticles() {
        for(int n = aliveParticles; n-- > 0;)
            particles[n].render();
    }
    
  • Thanks a lot for your help!

Sign In or Register to comment.