@Override
    public void reshape(ViewPort vp, int w, int h) {
        Camera cam = vp.getCamera();
        //this has no effect at first init but is useful when resizing the canvas with multi views
        cam.setViewPort(left, right, bottom, top);
        //resizing the camera to fit the new viewport and saving original dimensions
        cam.resize(w, h, true);
        left = cam.getViewPortLeft();
        right = cam.getViewPortRight();
        top = cam.getViewPortTop();
        bottom = cam.getViewPortBottom();
        originalWidth = w;
        originalHeight = h;

        //computing real dimension of the viewport and resizing the 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);

        //Testing original versus actual viewport dimension.
        //If they are different we are in a multiview situation and
        //camera must be handled differently
        if(originalWidth!=width || originalHeight!=height){
            multiView = true;
        }

        cameraInit = true;
        computeDepth = false;

        if (renderFrameBuffer == null && renderFrameBufferMS == 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.OpenGL32)) {
                Texture2D msColor = new Texture2D(width, height, numSamples, fbFormat);
                Texture2D msDepth = new Texture2D(width, height, numSamples, depthFormat);
                renderFrameBufferMS.setDepthTarget(FrameBufferTarget.newTarget(msDepth));
                renderFrameBufferMS.addColorTarget(FrameBufferTarget.newTarget(msColor));
                filterTexture = msColor;
                depthTexture = msDepth;
            } else {
                renderFrameBufferMS.setDepthTarget(FrameBufferTarget.newTarget(depthFormat));
                renderFrameBufferMS.addColorTarget(FrameBufferTarget.newTarget(fbFormat));
            }
        }

        if (numSamples <= 1 || !caps.contains(Caps.OpenGL32)) {
            renderFrameBuffer = new FrameBuffer(width, height, 1);
            renderFrameBuffer.setDepthTarget(FrameBufferTarget.newTarget(depthFormat));
            filterTexture = new Texture2D(width, height, fbFormat);
            renderFrameBuffer.addColorTarget(FrameBufferTarget.newTarget(filterTexture));
        }

        if (renderFrameBufferMS != null) {
            renderFrameBufferMS.setName("FilterPostProcessor MS");
        }

        if (renderFrameBuffer != null) {
            renderFrameBuffer.setName("FilterPostProcessor");
        }

        for (Filter filter : filters.getArray()) {
            initFilter(filter, vp);
        }
        setupViewPortFrameBuffer();
    }
compute the index of the last filter to render
jme3-core/src/main/java/com/jme3/post/FilterPostProcessor.java