public void postFrame(FrameBuffer out) {

    FrameBuffer sceneBuffer = renderFrameBuffer;
    if (renderFrameBufferMS != null && !renderer.getCaps().contains(Caps.OpenGL31)) {
      renderer.copyFrameBuffer(renderFrameBufferMS, renderFrameBuffer);
    } else if (renderFrameBufferMS != null) {
      sceneBuffer = renderFrameBufferMS;
    }
    renderFilterChain(renderer, sceneBuffer);
    renderer.setFrameBuffer(outputBuffer);

    // viewport can be null if no filters are enabled
    if (viewPort != null) {
      renderManager.setCamera(viewPort.getCamera(), false);
    }
  }
  public void reshape(ViewPort vp, int w, int h) {
    // this has no effect at first init but is useful when resizing the canvas with multi views
    Camera cam = vp.getCamera();
    cam.setViewPort(left, right, bottom, top);
    // resizing the camera to fit the new viewport and saving original dimensions
    cam.resize(w, h, false);
    left = cam.getViewPortLeft();
    right = cam.getViewPortRight();
    top = cam.getViewPortTop();
    bottom = cam.getViewPortBottom();
    originalWidth = w;
    originalHeight = h;
    cam.setViewPort(0, 1, 0, 1);

    // computing real dimension of the viewport and resizing he camera
    width = (int) (w * (Math.abs(right - left)));
    height = (int) (h * (Math.abs(bottom - top)));
    width = Math.max(1, width);
    height = Math.max(1, height);
    cam.resize(width, height, false);
    cameraInit = true;
    computeDepth = false;

    if (renderFrameBuffer == null) {
      outputBuffer = viewPort.getOutputFrameBuffer();
    }

    Collection<Caps> caps = renderer.getCaps();

    // antialiasing on filters only supported in opengl 3 due to depth read problem
    if (numSamples > 1 && caps.contains(Caps.FrameBufferMultisample)) {
      renderFrameBufferMS = new FrameBuffer(width, height, numSamples);
      if (caps.contains(Caps.OpenGL31)) {
        Texture2D msColor = new Texture2D(width, height, numSamples, Format.RGBA8);
        Texture2D msDepth = new Texture2D(width, height, numSamples, Format.Depth);
        renderFrameBufferMS.setDepthTexture(msDepth);
        renderFrameBufferMS.setColorTexture(msColor);
        filterTexture = msColor;
        depthTexture = msDepth;
      } else {
        renderFrameBufferMS.setDepthBuffer(Format.Depth);
        renderFrameBufferMS.setColorBuffer(Format.RGBA8);
      }
    }

    if (numSamples <= 1 || !caps.contains(Caps.OpenGL31)) {
      renderFrameBuffer = new FrameBuffer(width, height, 1);
      renderFrameBuffer.setDepthBuffer(Format.Depth);
      filterTexture = new Texture2D(width, height, Format.RGBA8);
      renderFrameBuffer.setColorTexture(filterTexture);
    }

    for (Iterator<Filter> it = filters.iterator(); it.hasNext(); ) {
      Filter filter = it.next();
      initFilter(filter, vp);
    }

    if (renderFrameBufferMS != null) {
      viewPort.setOutputFrameBuffer(renderFrameBufferMS);
    } else {
      viewPort.setOutputFrameBuffer(renderFrameBuffer);
    }
  }