/**
   * renders a filter on a fullscreen quad
   *
   * @param r
   * @param buff
   * @param mat
   */
  private void renderProcessing(Renderer r, FrameBuffer buff, Material mat) {
    if (buff == outputBuffer) {
      fsQuad.setWidth(width);
      fsQuad.setHeight(height);
      filterCam.resize(originalWidth, originalHeight, true);
      fsQuad.setPosition(left * originalWidth, bottom * originalHeight);
    } else {
      fsQuad.setWidth(buff.getWidth());
      fsQuad.setHeight(buff.getHeight());
      filterCam.resize(buff.getWidth(), buff.getHeight(), true);
      fsQuad.setPosition(0, 0);
    }

    if (mat.getAdditionalRenderState().isDepthWrite()) {
      mat.getAdditionalRenderState().setDepthTest(false);
      mat.getAdditionalRenderState().setDepthWrite(false);
    }

    fsQuad.setMaterial(mat);
    fsQuad.updateGeometricState();

    renderManager.setCamera(filterCam, true);
    r.setFrameBuffer(buff);
    r.clearBuffers(false, true, true);
    renderManager.renderGeometry(fsQuad);
  }
  public void initialize(RenderManager rm, ViewPort vp) {
    renderManager = rm;
    renderer = rm.getRenderer();
    viewPort = vp;
    fsQuad = new Picture("filter full screen quad");

    Camera cam = vp.getCamera();

    // save view port diensions
    left = cam.getViewPortLeft();
    right = cam.getViewPortRight();
    top = cam.getViewPortTop();
    bottom = cam.getViewPortBottom();
    originalWidth = cam.getWidth();
    originalHeight = cam.getHeight();
    // first call to reshape
    reshape(vp, cam.getWidth(), cam.getHeight());
  }
  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);
    }
  }