public void preFrame(float tpf) {
    if (filters.isEmpty() || lastFilterIndex == -1) {
      // If the camera is initialized and there are no filter to render, the camera viewport is
      // restored as it was
      if (cameraInit) {
        viewPort.getCamera().resize(originalWidth, originalHeight, true);
        viewPort.getCamera().setViewPort(left, right, bottom, top);
        viewPort.setOutputFrameBuffer(outputBuffer);
        cameraInit = false;
      }

    } else {
      if (renderFrameBufferMS != null) {
        viewPort.setOutputFrameBuffer(renderFrameBufferMS);
      } else {
        viewPort.setOutputFrameBuffer(renderFrameBuffer);
      }
      // init of the camera if it wasn't already
      if (!cameraInit) {
        viewPort.getCamera().resize(width, height, true);
        viewPort.getCamera().setViewPort(0, 1, 0, 1);
      }
    }

    for (Iterator<Filter> it = filters.iterator(); it.hasNext(); ) {
      Filter filter = it.next();
      if (filter.isEnabled()) {
        filter.preFrame(tpf);
      }
    }
  }
  /**
   * iterate through the filter list and renders filters
   *
   * @param r
   * @param sceneFb
   */
  private void renderFilterChain(Renderer r, FrameBuffer sceneFb) {
    Texture2D tex = filterTexture;
    FrameBuffer buff = sceneFb;
    boolean msDepth = depthTexture != null && depthTexture.getImage().getMultiSamples() > 1;
    for (int i = 0; i < filters.size(); i++) {
      Filter filter = filters.get(i);
      if (filter.isEnabled()) {
        if (filter.getPostRenderPasses() != null) {
          for (Iterator<Filter.Pass> it1 = filter.getPostRenderPasses().iterator();
              it1.hasNext(); ) {
            Filter.Pass pass = it1.next();
            pass.beforeRender();
            if (pass.requiresSceneAsTexture()) {
              pass.getPassMaterial().setTexture("Texture", tex);
              if (tex.getImage().getMultiSamples() > 1) {
                pass.getPassMaterial().setInt("NumSamples", tex.getImage().getMultiSamples());
              } else {
                pass.getPassMaterial().clearParam("NumSamples");
              }
            }
            if (pass.requiresDepthAsTexture()) {
              pass.getPassMaterial().setTexture("DepthTexture", depthTexture);
              if (msDepth) {
                pass.getPassMaterial()
                    .setInt("NumSamplesDepth", depthTexture.getImage().getMultiSamples());
              } else {
                pass.getPassMaterial().clearParam("NumSamplesDepth");
              }
            }
            renderProcessing(r, pass.getRenderFrameBuffer(), pass.getPassMaterial());
          }
        }

        filter.postFrame(renderManager, viewPort, buff, sceneFb);

        Material mat = filter.getMaterial();
        if (msDepth && filter.isRequiresDepthTexture()) {
          mat.setInt("NumSamplesDepth", depthTexture.getImage().getMultiSamples());
        }

        if (filter.isRequiresSceneTexture()) {
          mat.setTexture("Texture", tex);
          if (tex.getImage().getMultiSamples() > 1) {
            mat.setInt("NumSamples", tex.getImage().getMultiSamples());
          } else {
            mat.clearParam("NumSamples");
          }
        }

        buff = outputBuffer;
        if (i != lastFilterIndex) {
          buff = filter.getRenderFrameBuffer();
          tex = filter.getRenderedTexture();
        }
        renderProcessing(r, buff, mat);
      }
    }
  }
  public void postQueue(RenderQueue rq) {

    for (Iterator<Filter> it = filters.iterator(); it.hasNext(); ) {
      Filter filter = it.next();
      if (filter.isEnabled()) {
        filter.postQueue(renderManager, viewPort);
      }
    }
  }
  /**
   * Adds a filter to the filters list<br>
   *
   * @param filter the filter to add
   */
  public void addFilter(Filter filter) {
    filters.add(filter);

    if (isInitialized()) {
      initFilter(filter, viewPort);
    }

    setFilterState(filter, filter.isEnabled());
  }
 public void read(JmeImporter im) throws IOException {
   InputCapsule ic = im.getCapsule(this);
   numSamples = ic.readInt("numSamples", 0);
   filters = ic.readSavableArrayList("filters", null);
   for (Filter filter : filters) {
     filter.setProcessor(this);
     setFilterState(filter, filter.isEnabled());
   }
   assetManager = im.getAssetManager();
 }