FilterPostProcessor weird behavior

I wasn’t sure if it was me or not, maybe it is, but I don’t think so… Anyway. I’ve done a small test case and it behaves the same way as in my game. I’m not sure at all what is going on internally, but it’s wrong. Maybe someone can shed some light on that.



Here’s a little description what the code does.



This will do a simple scene. The test uses the default viewport and a secondary, independent, one. In both cases I add a cube, one yellow in the main view and the other one white in the secondary view.



Bound on SPACE is a toggler on the secondary viewport that will either remove or add the BloomFilter depending if it’s already present or not.

Bound on TAB is a similar toggler but this time for the main viewport.



Now what happens when you toggle the bloom filter is odd. First, in the secondary viewport, after adding then removing the filter, it will resize the object inside (!?) (maybe the view frustum changes for some reason?) but the viewport’s original size will remain the same.



If you then hit TAB to switch the main view, the effect is different. The cube inside that view remains correctly rendered but the secondary viewport will act weird. Sometimes it disappear, other times not. It seems to depend on the order it is done.



If you TAB before you hit SPACE (changing the main view before the secondary view) nothing happens. All is good as long as you don’t add/remove the bloom filter to the secondary viewport. If you do, it gets weirder. I’ve seen the secondary viewport almost disappear, becoming like a semi-transparent white square with nothing else in it.



Unsure exactly what is happening but I’d tend to guess it’s a bug that acts erratically.



You can play with it by hitting SPACE/TAB in different sequence, multiple times, etc and see what happens.



Hopefully this will help shed some lights on the problem. Again, it is possible it’s me. If it is please tell me what’s wrong. :slight_smile:



Thanks.



[java]

package mygame;



import com.jme3.app.SimpleApplication;

import com.jme3.input.KeyInput;

import com.jme3.input.controls.ActionListener;

import com.jme3.input.controls.KeyTrigger;

import com.jme3.material.Material;

import com.jme3.math.ColorRGBA;

import com.jme3.math.Vector3f;

import com.jme3.post.FilterPostProcessor;

import com.jme3.post.filters.BloomFilter;

import com.jme3.renderer.Camera;

import com.jme3.renderer.ViewPort;

import com.jme3.scene.Geometry;

import com.jme3.scene.Node;

import com.jme3.scene.shape.Box;



/**

  • test
  • @author MadJack

    */

    public class Main extends SimpleApplication {



    ViewPort vp;

    FilterPostProcessor fpp;

    Node secViewNode = new Node("Secondary Viewport Node");



    public static void main(String[] args) {

    Main app = new Main();

    app.start();

    }



    @Override

    public void simpleInitApp() {

    mainViewBox();

    secViewBox();

    setSecViewPort();

    bindKeys();

    }



    @Override

    public void simpleUpdate(float tpf) {

    }



    private void mainViewBox() {

    Box b = new Box(Vector3f.ZERO, 1, 1, 1);

    Geometry geom = new Geometry("MainBox", b);



    Material mat = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");

    mat.setColor("Color", ColorRGBA.Yellow);

    geom.setMaterial(mat);



    rootNode.attachChild(geom);

    }



    private void secViewBox() {

    Box b = new Box(Vector3f.ZERO, 1, 1, 1);

    Geometry geom = new Geometry("SecondaryBox", b);



    Material mat = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");

    mat.setColor("Color", ColorRGBA.White);

    geom.setMaterial(mat);

    geom.rotate(0, 5f, 0);



    secViewNode.attachChild(geom);

    }



    private void setSecViewPort() {



    int w = settings.getWidth(), h = settings.getHeight();

    float sizeXL = 220;

    float sizeXR = 420;

    float sizeYB = 220;

    float sizeYT = 420;



    Camera secCam = new Camera(w, h);

    secCam.setFrustumPerspective(90.0f, 1f, 1f, 75f);

    secCam.setName("Test ViewPort Camera");

    secCam.setLocation(new Vector3f(5, 0, 0));

    secCam.lookAt(Vector3f.ZERO, Vector3f.UNIT_Y);

    secCam.setViewPort(sizeXL / w, sizeXR / w, sizeYB / h, sizeYT / h);



    vp = renderManager.createMainView("Test Viewport", secCam);

    vp.setClearFlags(true, true, true);

    vp.attachScene(secViewNode);

    vp.setBackgroundColor(ColorRGBA.DarkGray);



    setPostProcess();



    vp.setEnabled(true);

    secViewNode.updateGeometricState();

    }



    private void setPostProcess() {

    fpp = new FilterPostProcessor(assetManager);



    BloomFilter bf = new BloomFilter(BloomFilter.GlowMode.SceneAndObjects);

    bf.setExposurePower(1.5f);

    bf.setBloomIntensity(3f);

    bf.setBlurScale(.75f);

    bf.setExposureCutOff(.5f);



    fpp.addFilter(bf);

    }



    private void toggleSecondaryViewPortPostProcess() {

    if (vp.getProcessors().contains(fpp)) {

    vp.removeProcessor(fpp);

    } else {

    vp.addProcessor(fpp);

    }

    }



    private void toggleMainViewPortPostProcess() {

    if (viewPort.getProcessors().contains(fpp)) {

    viewPort.removeProcessor(fpp);

    } else {

    viewPort.addProcessor(fpp);

    }

    }



    private void bindKeys() {

    inputManager.addMapping("TogglePostProcessSecondaryViewPort", new KeyTrigger(KeyInput.KEY_SPACE));

    inputManager.addMapping("TogglePostProcessMainViewPort", new KeyTrigger(KeyInput.KEY_TAB));



    inputManager.addListener(actionListener, "TogglePostProcessSecondaryViewPort", "TogglePostProcessMainViewPort");

    }



    private ActionListener actionListener = new ActionListener() {



    public void onAction(String name, boolean isPressed, float tpf) {

    if (name.equals("TogglePostProcessSecondaryViewPort") && !isPressed) {

    toggleSecondaryViewPortPostProcess();

    } else if (name.equals("TogglePostProcessMainViewPort") && !isPressed) {

    toggleMainViewPortPostProcess();

    }

    }

    };

    }

    [/java]

Yeah, well…the thing is, FilterPostProcessor doesn’t like much multiple viewports.



And the bug here is the resized viewport when you disable the filter.



But…you are using 1 processor and one filter for 2 viewports, so when they are both enabled, it’s a mess

So, as a rule of thumb, always use separate processors and Filters set for separate viewports.



also, don’t remove the filter post processor to disable it, disable the filters instead



here is your code modified with the changes I talked about

[java]

package mygame;



import com.jme3.app.SimpleApplication;

import com.jme3.input.KeyInput;

import com.jme3.input.controls.ActionListener;

import com.jme3.input.controls.KeyTrigger;

import com.jme3.material.Material;

import com.jme3.math.ColorRGBA;

import com.jme3.math.Vector3f;

import com.jme3.post.FilterPostProcessor;

import com.jme3.post.filters.BloomFilter;

import com.jme3.renderer.Camera;

import com.jme3.renderer.ViewPort;

import com.jme3.scene.Geometry;

import com.jme3.scene.Node;

import com.jme3.scene.shape.Box;



/**

  • test
  • @author MadJack

    */

    public class Main extends SimpleApplication {



    ViewPort vp;

    FilterPostProcessor fpp1, fpp2;

    BloomFilter bf1, bf2;

    Node secViewNode = new Node(“Secondary Viewport Node”);



    public static void main(String[] args) {

    Main app = new Main();

    app.start();

    }



    @Override

    public void simpleInitApp() {

    mainViewBox();

    secViewBox();

    setSecViewPort();

    bindKeys();

    }



    @Override

    public void simpleUpdate(float tpf) {

    }



    private void mainViewBox() {

    Box b = new Box(Vector3f.ZERO, 1, 1, 1);

    Geometry geom = new Geometry(“MainBox”, b);

    Material mat = new Material(assetManager, “Common/MatDefs/Misc/Unshaded.j3md”);

    mat.setColor(“Color”, ColorRGBA.Yellow);

    geom.setMaterial(mat);

    rootNode.attachChild(geom);

    }



    private void secViewBox() {

    Box b = new Box(Vector3f.ZERO, 1, 1, 1);

    Geometry geom = new Geometry(“SecondaryBox”, b);

    Material mat = new Material(assetManager, “Common/MatDefs/Misc/Unshaded.j3md”);

    mat.setColor(“Color”, ColorRGBA.White);

    geom.setMaterial(mat);

    geom.rotate(0, 5f, 0);

    secViewNode.attachChild(geom);

    }



    private void setSecViewPort() {

    int w = settings.getWidth(), h = settings.getHeight();

    float sizeXL = 220;

    float sizeXR = 420;

    float sizeYB = 220;

    float sizeYT = 420;

    Camera secCam = new Camera(w, h);

    secCam.setFrustumPerspective(90.0f, 1f, 1f, 75f);

    secCam.setName(“Test ViewPort Camera”);

    secCam.setLocation(new Vector3f(5, 0, 0));

    secCam.lookAt(Vector3f.ZERO, Vector3f.UNIT_Y);

    secCam.setViewPort(sizeXL / w, sizeXR / w, sizeYB / h, sizeYT / h);

    vp = renderManager.createMainView(“Test Viewport”, secCam);

    vp.setClearFlags(true, true, true);

    vp.attachScene(secViewNode);

    vp.setBackgroundColor(ColorRGBA.DarkGray);

    setPostProcess();

    vp.setEnabled(true);

    secViewNode.updateGeometricState();

    }



    private void setPostProcess() {

    fpp1 = new FilterPostProcessor(assetManager);

    fpp2 = new FilterPostProcessor(assetManager);

    bf1 = new BloomFilter(BloomFilter.GlowMode.SceneAndObjects);

    bf1.setExposurePower(1.5f);

    bf1.setBloomIntensity(3f);

    bf1.setBlurScale(.75f);

    bf1.setExposureCutOff(.5f);

    fpp1.addFilter(bf1);



    bf2 = new BloomFilter(BloomFilter.GlowMode.SceneAndObjects);

    bf2.setExposurePower(1.5f);

    bf2.setBloomIntensity(3f);

    bf2.setBlurScale(.75f);

    bf2.setExposureCutOff(.5f);

    fpp2.addFilter(bf2);





    viewPort.addProcessor(fpp1);

    vp.addProcessor(fpp2);

    }



    private void toggleSecondaryViewPortPostProcess() {

    bf2.setEnabled(!bf2.isEnabled());

    }



    private void toggleMainViewPortPostProcess() {

    bf1.setEnabled(!bf1.isEnabled());



    }



    private void bindKeys() {

    inputManager.addMapping(“TogglePostProcessSecondaryViewPort”, new KeyTrigger(KeyInput.KEY_SPACE));

    inputManager.addMapping(“TogglePostProcessMainViewPort”, new KeyTrigger(KeyInput.KEY_TAB));

    inputManager.addListener(actionListener, “TogglePostProcessSecondaryViewPort”, “TogglePostProcessMainViewPort”);

    }

    private ActionListener actionListener = new ActionListener() {



    public void onAction(String name, boolean isPressed, float tpf) {

    if (name.equals(“TogglePostProcessSecondaryViewPort”) && !isPressed) {

    toggleSecondaryViewPortPostProcess();

    } else if (name.equals(“TogglePostProcessMainViewPort”) && !isPressed) {

    toggleMainViewPortPostProcess();

    }

    }

    };

    }

    [/java]



    I’m gonna look into the resizing issue

Just a note on this older topic: when both viewports have post processors with bloom filter attached, setClearColor is useless. It works tho without the bloom filter on the “top” viewport. Try set Color to false in setClearFlags to see what I mean.