Giter VIP home page Giter VIP logo

processing-postfx's Introduction

PostFX for Processing Build Status Build status codebeat badge

A simple post effects library for processing.

Introduction

PostFX is a simple post effects library for processing. Post effects are applied to the whole scene after it was rendered, to enhance the scene with some special effects. For example the bloom effect helps to simulate the light diffusion to be more realistic.

PFX Example

Example of the post effects sobel, bloom and toon.

Why did I implement it?

There are a lot of tutorials which help you to implement a bloom filter in OpenGL (e.g. Learn OpenGL - Bloom). But for processing I could not find one that is as performant as I needed in my P3D renderings.

So I started to implement a simple but fast library to run post effects on P2D and P3D graphics objects.

What is included?

Here you find two examples which are based on the Lenna and Lichtenstein test images:

Lenna Effect

Lenna Effect

The PostFX library currently contains following built in effects:

  • bright pass
  • blur horizontal
  • blur vertical
  • sobel edge detection
  • toon filter

Version 1.1 adds a lot of new shaders:

Color

  • Brightness and Contrast Shader
  • Saturation and Vibrance Shader
  • Invert Shader
  • Grayscale Shader

Reconstruction

  • Denoise Shader

Effects

  • Bloom Shader
  • Pixelate Shader
  • Chromatic aberration shader
  • Noise Shader
  • Vignette Shader
  • RGB Split Shader

And there is also a method to run your own custom shaders.

Some of the shaders are from the spite/Wagner respoitory and only adapted to work in processing.

Example

There are two API's to use the PostFX library. The basic one is very easy and removes responsibility of the pass management. The advanced way is, where you have to create pass instances yourself, but have the freedom to manage them by your own.

Custom shaders are supported, in the basic and the advanced version.

Setup

To use the library you have to install it over the processing contribution manager.

Contribution Manager

Import following packages to use all classes of the PostFX library.

import ch.bildspur.postfx.builder.*;
import ch.bildspur.postfx.pass.*;
import ch.bildspur.postfx.*;

Use the library on every PGraphics3D or PGraphics2D object or even on the screen object (g).

Basic Example

To add a post effect to your processing sketch, you just have to create a new PostFX object.

PostFX fx;

void setup()
{
  size(500, 500, P3D);
  
  fx = new PostFX(this);  
}

Now you have to call the render() method of the PostFX library. This returns an object, on which you can call all implemented effects.

void draw()
{
  // draw something onto the screen
  background(22);
  box(100);

  // add bloom filter
  fx.render()
    .bloom(0.5, 20, 40)
    .compose();
}

Finally you can use compose() to draw it onto the main screen (g object). It is also possible to compose to onto another Graphics2D object.

Based on SimpleEffect example

Off-Screen Buffer

To add a post effect onto a off-screen graphics object, you have to create a new graphics object (canvas). To use the basic version of the API, instantiate a new PostFX object.

PostFX fx;
PGraphics canvas;

void setup()
{
  size(500, 500, P2D);
  
  fx = new PostFX(this);  
  canvas = createGraphics(width, height, P3D);
}

Now you have to draw onto your canvas and after rendering, you just pass the canvas into the render() method of the PostFX library. This returns an object, on which you can call all implemented effects.

void draw()
{
  canvas.beginDraw();
  // draw something onto the canvas
  canvas.endDraw();
  
  blendMode(BLEND);
  image(canvas, 0, 0);

  // add bloom filter
  blendMode(SCREEN);
  fx.render(canvas)
    .brightPass(0.5)
    .blur(20, 50)
    .compose();
}

Finally you can use compose() to draw it onto the main screen (g object). It is also possible to compose to onto another Graphics2D object.

Based on OffScreenEffect example

Pass Preloading

For performance reasons it is sometimes necessary to preload the pass and compile the shaders before you use it. For this problem, there is the method preloadPass.

To preload a pass you have to call the method and pass the class type as argument.

void setup()
{
  size(500, 500, P3D);

  fx = new PostFX(this);

  // compile shaders in setup
  fx.preload(BloomPass.class);
  fx.preload(RGBSplitPass.class);
}

Everything else works like usual, but you have now compiled your shaders in the setup() method and not in the time critical draw() method.

Based on PassPreloading example

Advanced

The advanced version is used as the underlaying layer of the basic API. It does not create the pass objects itself, but gives the freedom to manage them by your own.

Instead of an PostFX class you have to create a new PostFXSupervisor which handles all the pass buffers. For each pass, you have to create a pass object, which contains the implementation and the parameters.

It is possible to use the same pass object twice, with different parameter settings.

PostFXSupervisor supervisor;
BrightPass brightPass;
SobelPass sobelPass;

PGraphics canvas;

void setup()
{
  size(500, 500, P2D);

  // create supervisor and load shaders
  supervisor = new PostFXSupervisor(this);
  brightPass = new BrightPass(this, 0.3f);
  sobelPass = new SobelPass(this); 

  canvas = createGraphics(width, height, P3D);
}

To render the effects onto the canvas, you have to call the render() method on the supervisor and pass all the passes.

void draw()
{
  // draw a simple rotating cube around a sphere
  canvas.beginDraw();
  // draw something onto the canvas
  canvas.endDraw();

  blendMode(BLEND);
  image(canvas, 0, 0);

  // add white ring around sphere
  blendMode(SCREEN);
  supervisor.render(canvas);
  supervisor.pass(brightPass);
  supervisor.pass(sobelPass);
  supervisor.compose();
}

Finally, the compose() method draws the scene onto the main screen. It is possible to draw the result onto another another Graphics2D object.

Based on AdvancedEffect example

Custom Shader

This tutorial shows how to create a negate pass.

To add a custom shader as pass, you have to create a new class which implements the Pass interface.

class NegatePass implements Pass
{
  PShader shader;

  public NegatePass()
  {
    shader = loadShader("negateFrag.glsl");
  }

  @Override
    public void prepare(Supervisor supervisor) {
    // set parameters of the shader if needed
  }

  @Override
    public void apply(Supervisor supervisor) {
    PGraphics pass = supervisor.getNextPass();
    supervisor.clearPass(pass);

    pass.beginDraw();
    pass.shader(shader);
    pass.image(supervisor.getCurrentPass(), 0, 0);
    pass.endDraw();
  }
}

The shader for this example is very simple and just calculates one minus the color value.

#ifdef GL_ES
precision mediump float;
precision mediump int;
#endif

uniform sampler2D texture;

varying vec4 vertColor;
varying vec4 vertTexCoord;

void main() {
    vec4 c = texture2D(texture, vertTexCoord.st) * vertColor;
    c.xyz = 1.0 - c.xyz;
    gl_FragColor = c;
}

To use the shader, you have to create a new instance of it and then add it as pass:

// in setup
NegatePass negatePass = new NegatePass();

// in draw
supervisor.render(canvas);
supervisor.pass(negatePass);
supervisor.compose();

Based on CustomShaderEffect example

Custom Shader Builder Pattern

With version 1.1 it is now also possible to add a custom shader directly to the builder pattern, which simplifies the whole process:

// in setup
NegatePass negatePass = new NegatePass();

// in draw
fx.render()
  .custom(negatePass)
  .compose();

About

Developed by Florian Bruggisser (bildspur.ch) 2017

processing-postfx's People

Contributors

cansik avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

processing-postfx's Issues

Shader path method not working on Windows

As mentioned by first in the processing forum (Thread: PostFX library not working), there is a problem with the shader path parsing on Windows.

Here is the full error message:

Could not parse -1 for --display
java.lang.reflect.InvocationTargetException
  at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
  at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
  at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
  at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
  at ch.bildspur.postfx.builder.PostFXBuilder.getPass(PostFXBuilder.java:38)
  at ch.bildspur.postfx.builder.PostFXBuilder.brightPass(PostFXBuilder.java:122)
  at OffScreenEffect.draw(OffScreenEffect.java:65)
  at processing.core.PApplet.handleDraw(PApplet.java:2439)
  at processing.opengl.PSurfaceJOGL$DrawListener.display(PSurfaceJOGL.java:849)
  at jogamp.opengl.GLDrawableHelper.displayImpl(GLDrawableHelper.java:692)
  at jogamp.opengl.GLDrawableHelper.display(GLDrawableHelper.java:674)
  at jogamp.opengl.GLAutoDrawableBase$2.run(GLAutoDrawableBase.java:443)
  at jogamp.opengl.GLDrawableHelper.invokeGLImpl(GLDrawableHelper.java:1293)
  at jogamp.opengl.GLDrawableHelper.invokeGL(GLDrawableHelper.java:1147)
  at com.jogamp.newt.opengl.GLWindow.display(GLWindow.java:759)
  at com.jogamp.opengl.util.AWTAnimatorImpl.display(AWTAnimatorImpl.java:81)
  at com.jogamp.opengl.util.AnimatorBase.display(AnimatorBase.java:452)
  at com.jogamp.opengl.util.FPSAnimator$MainTask.run(FPSAnimator.java:178)
  at java.util.TimerThread.mainLoop(Timer.java:555)
  at java.util.TimerThread.run(Timer.java:505)
Caused by: java.nio.file.InvalidPathException: Illegal char <:> at index 2: /C:/Users/Sandro%20Castronari/Documents/Processing/libraries/PostFX/library/PostFX.jar
  at sun.nio.fs.WindowsPathParser.normalize(WindowsPathParser.java:182)
  at sun.nio.fs.WindowsPathParser.parse(WindowsPathParser.java:153)
  at sun.nio.fs.WindowsPathParser.parse(WindowsPathParser.java:77)
  at sun.nio.fs.WindowsPath.parse(WindowsPath.java:94)
  at sun.nio.fs.WindowsFileSystem.getPath(WindowsFileSystem.java:255)
  at java.nio.file.Paths.get(Paths.java:84)
  at ch.bildspur.postfx.pass.BasePass.getLibPath(BasePass.java:54)
  at ch.bildspur.postfx.pass.BasePass.<init>(BasePass.java:21)
  at ch.bildspur.postfx.pass.BrightPass.<init>(BrightPass.java:19)
  at ch.bildspur.postfx.pass.BrightPass.<init>(BrightPass.java:15)
  ... 20 more

Add travis build support

Travis build support which tests the library on MacOS, Windows and Linux.
Unit tests for shaders.

Imcompability with peasycam

Hi, as I tried to use postfx with peasycam : http://mrfeinberg.com/peasycam/ , I got this bug :
image
As you can see, the original is displayed in the background, and the post fx render appears in the front, scaled down.

I tried to move the focus point of my peasycam object, but it doesn't fix the issue :/

a sketch which reproduce this bug :

import ch.bildspur.postfx.builder.*;
import ch.bildspur.postfx.pass.*;
import ch.bildspur.postfx.*;

import peasy.*;
import peasy.org.apache.commons.math.*;
import peasy.org.apache.commons.math.geometry.*;

PeasyCam cam;

PostFX fx;
void setup(){
  size(400,400,P3D);
  cam=new PeasyCam(this, 800);
  fx = new PostFX(this);  
}
void draw(){
  background(100);
  pushMatrix();
translate(width/2,height/2);
rotateY(frameCount/17.0);
box(200);
    popMatrix();
 fx.render()
    .bloom(0.5, 20, 40)
    .compose();

}

regards

Is it possible to only affect a PGraphics Layer?

I have this code here where ellipses are drawn on a PGraphics layer. The PGraphics layer is not displayed through draw, but is redrawn by a grid of ellipses - later in draw. Now I want to blur the PGraphics layer so that the "blurred PGraphics" layer is redrawn by the grid. Until now I only managed to blur the whole sketch... Is it possible to blur a PGraphics and then store it this way in the memory?

This is my code for a better understanding:

import ch.bildspur.postfx.builder.*;
import ch.bildspur.postfx.pass.*;
import ch.bildspur.postfx.*;

PostFX fx;



PGraphics pg;

float size;
float pixel;

ArrayList<Circle> circles;
void setup () {

  size(600, 600, P2D);
  pixel = 50;
  size = width/pixel;
  circles = new ArrayList<Circle>();
  circles.add(new Circle());
  frameRate(30);

  rectMode(CENTER);
  fx = new PostFX(this);
  pg = createGraphics(width, height);
}

void draw() {
  background(0);

  pg.beginDraw();
  pg.background(255);

  for (int i = circles.size()-1; i >= 1; i--) {

    Circle circle = circles.get(i);
    circle.display(pg);
  }
  pg.endDraw();

  //DRAW THE GRID
  for (int y = 0; y < pixel; y++) {
    for (int x = 0; x < pixel; x++) {

      color c = pg.get(int(size*x), int(size*y));
      float motionsize = map(brightness(c), 0, 255, size, 0);
      pushMatrix();
      translate(size/2, size/2);
      translate(x*size, y*size);
      fill(255);
      noStroke();
      ellipse(0, 0, motionsize, motionsize);
      popMatrix();
    }
  }
  // fx.render()
  //    .blur(10, 10)
  //    .compose();
}
void mousePressed() {
  circles.add(new Circle());
}

class Circle {

  int x = int(random(width));
  int y = int(random(height));

  Circle() {
  }
  void display(PGraphics pg) {
    pg.fill(0);
    pg.noStroke();
    pg.ellipse(x, y, 100, 100);
  }
}

applying fx after 3d tint produces error

When trying to apply the pixelate filter at the end of the drawing loop like this fx.render().pixelate(i).compose(); on a scene with some 3d mesh with some tint() applied to it breaks the renderer and it throws this error #1

btw great library for simpler quick hassle free post procesing!

License type for effects?

Hello, thanks for making this effects, they are really awesome. I am wondering since I can't find it, what license type is attached to these effects? Are they OK to use for commercial closed source projects?

Thanks!

Black screen using postFX

Hi guys, i'm trying to use postFx but it's not working with my video, what am i missing?

Perhaps my computer is not powerful enough?

I'm new with processing.

import processing.video.*;
import processing.sound.*;
import ch.bildspur.postfx.builder.*;
import ch.bildspur.postfx.pass.*;
import ch.bildspur.postfx.*;

PostFX fx;

SoundFile file;
Movie myMovie;
Amplitude amp;

int numPixels;
int blockSize = 1;
color myMovieColors[];

void setup(){
 fullScreen(P3D);
  
  fx = new PostFX(this); 
  //file = new SoundFile(this, "FKAtwigs.mp3");
  //file.play();
  
  //amp = new Amplitude(this);
  //amp.input(file);
  
  myMovie = new Movie(this, "teo2.mp4");
  numPixels = width/blockSize;
  myMovieColors = new color[numPixels * numPixels];
  myMovie.loop();
}

void movieEvent(Movie m) {
  m.read();
  m.loadPixels();
  m.play();

  for(int j = 0; j < numPixels; j = j + 8){
    for(int i = 0; i < numPixels; i = i + 8){
      myMovieColors[j * numPixels + i] = m.get(i, j);
    }
  }
}
void draw(){
  background(0);
  //float vol = amp.analyze()*600;  
  
  for(int j = 0; j < numPixels; j = j + 8){
    for(int i = 0; i < numPixels; i = i + 8){
      int loc = myMovieColors[j * numPixels + i];
      float r = red(loc);
      float g = green(loc);
      float b = blue(loc);
      float br = brightness(loc);
      strokeWeight(5);  
      stroke(r, g, b);   
      point(i * blockSize, j * blockSize, (br * 1.2));
    }
  }
  //saveFrame("frames/##########.jpg");
  //image(myMovie, 100, 100);
  fx.render().bloom(0.5, 20, 40).compose();
}

Render Stuck at origin

Hello, thank you for providing this awesome library!

I was building an audio visualiser and used postfx to apply a glow to a fractal tree. I cant seem to get the render out of the top left corner though, i have tried matrixReset() and have looked at pretty much every other issue. There was a problem with matrices of PeasyCam, but i am not using this library.

Libraries used: PostFX, Sound

bugmaybe

I dont think this is a common issue, so i wanted to report :)

Run custom shader inside builder pattern

The simple builder pattern should also allow running custom pass / shaders:

CustomPass myPass = new CustomPass();

fx.render(canvas)
        .brightnessContrast(0.1f, 1.0f)
        .custom(myPass)
        .compose(passResult);

Add more shaders to the library

Add more default shaders to the library:

Color

  • Brightness and Contrast Shader
  • Invert Shader
  • Grayscale Shader
  • LUT Shader (nice to have)

Reconstruction

  • Denoise Shader

Effects

  • Bloom Shader
  • Pixelate Shader by prince_polka
  • Chromatic aberration shader
  • Noise Shader
  • Vignette Shader
  • RGB Split Shader

Provide .jar on Github

Provide the necessary jars as a release on Github for users who do not use the Processing IDE, but use the processing library elsewhere.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.