Why is the background not redrawn when using GLOW filter?

I guess if you provide a copy past like test we can run, the feedback may be better. At least that worked for me the past few times I had grafic issues. @nehon normally helps with those graphic glitches or missbehaviour.
So it’s entierly up to you…

It is simple - i forgot something, someone pspeed pointed it out, i added it - problem solved - the rest was pretty unnecessary. Enough of this. Thanks to those trying to help :wink:

Hi there, sorry to bother you again. I had the chance now to try it on Android/Google Tango. As I feared,
the camera preview is occluded by a black area when switching off clearFlags in the second viewport. This time you’ll get a complete minimal code sample from me :wink: Hope someone can help. Here is again what I do:

NOTE: This doesn’t happen without glow activated!

adding a CameraPreview and rendering the Scene, GUI and Nifty GUI in front of it. I think having a look into Main, GUI and MainActivity should be sufficient, but I added the other classed as well, all reduced to a minimum.

Thanks for having a look

Main:

public class Main extends SimpleApplication  {

    private IJmeToAndroid       androidHarness;

    public static   Main                app;
    public          GUI                 gui;
    public          Node                camNode;


    public static void main(String[] args)
    {
        Main.app = new Main();
        app.showSettings = false;               // Don't use settings window
        
        // Set settings
        AppSettings appSettings = new AppSettings(true);
        appSettings.put("Width", 800);appSettings.put("Height", 480);
        appSettings.setSamples(4);              // Antialiasing
        appSettings.put("Title", "ARNetRayX");  // Title
        app.setSettings(appSettings);
        app.start();
    }

    @Override
    public void simpleInitApp()
    {
        this.app = this;
            
        // GLOW
        FilterPostProcessor fpp=new FilterPostProcessor(assetManager);
        BloomFilter bloom = new BloomFilter(BloomFilter.GlowMode.Objects);
        fpp.addFilter(bloom);
        viewPort.addProcessor(fpp);
        
        setUpCamera();
        setPlatformDependentStuff();    // Platform specific
        gui = setUpGUI();
        
        Box b = new Box(1,1,1);
        Geometry g = new Geometry("box", b);
        Material mat = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
        mat.setColor("Color", ColorRGBA.Blue);
        g.setMaterial(mat);
        rootNode.attachChild(g);
    }
    
    @Override
    public void simpleUpdate(float tpf)
    {
        // TODO
    }
    
    private void setPlatformDependentStuff() {
        androidHarness = getAndroidHarness();    // get android harness

        // harness == null --> DESKTOP
        // harness != null --> ANDROID/TANGO
        if (androidHarness != null) {
            // TODO
        } else {
            // --------------------------------------------------------- DESKTOP
            cam.setLocation(new Vector3f(-6, 3, 6));
            cam.lookAt(Vector3f.ZERO, Vector3f.UNIT_Y);
        }
    }
    
    private GUI setUpGUI() {
        GUI gui = new GUI(assetManager, inputManager, audioRenderer, 
                          guiViewPort, cam, this, guiNode, guiFont);
        
        // Move GUI node behind Nifty
        guiViewPort.attachScene(guiNode);
        guiNode.setQueueBucket(Bucket.Gui);
        Camera guiCam = new Camera(settings.getWidth(), settings.getHeight());
        ViewPort guiViewPort2 = renderManager
            .createPostView("Gui 2 Default", guiCam);
        guiViewPort2.addProcessor(gui.getNiftyDisplay());
        guiViewPort2.setClearFlags(false, false, false);
        
        return gui;
    }
    
    private void setUpCamera() {
        cam.setFrustumPerspective(
            45f, (float) cam.getWidth() / cam.getHeight(), 0.01f, 100f);
        flyCam.setDragToRotate(true);
    }
    
    public IJmeToAndroid getAndroidHarness()
    {
        return this.androidHarness;
    }

    
    public void setAndroidHarnessListener(IJmeToAndroid harness)
    {
        this.androidHarness = harness;
    }
}

GUI:

public final class GUI {
    // .............................................................. ATTRIBUTES
    private final Nifty nifty;
    private final Node guiNode;
    private final Picture hud2;
    public static final int LAYER_LABEL_BG = 0;
    public static final int LAYER_LABEL = 1;
    private final NiftyJmeDisplay niftyDisplay;

    // ............................................................. CONSTRUCTOR
    public GUI (AssetManager assets, InputManager inputs, AudioRenderer audio,
        ViewPort guiViewPort, Camera cam, Main app,
        Node guiNode, BitmapFont guiFont)
    {
        this.guiNode = guiNode;
        
        niftyDisplay
            = new NiftyJmeDisplay(assets, inputs, audio, guiViewPort);
        nifty = this.niftyDisplay.getNifty();
        nifty.fromXml("Interface/MainMenu.xml",
            "start", new MainMenu(nifty));
        guiViewPort.addProcessor(niftyDisplay);
        
        hud2 = new Picture("hud2_bg");
        hud2.setImage(assets, "Textures/hud2.png", true);
        
        setPlatformDependentStuff();
    }
    
    private void setPlatformDependentStuff() {
        if(GlobalSettings.ON_TANGO) {
            hud2.setWidth(400f/800f*1920f);
            hud2.setHeight(171f/480f*1080f);
            hud2.setPosition(0,0);
        } else {
            hud2.setWidth(400f);
            hud2.setHeight(171f);
            hud2.setPosition(0,0);
        }   
        guiNode.attachChild(hud2);
    }
    
    public SceneProcessor getNiftyDisplay() {
        return niftyDisplay;
    }
}

MainActivity:

public class MainActivity extends AndroidHarness implements IJmeToAndroid {
    
    private static final String TAG = "ARNetRayXMainActivity";
    private TangoTrackingProvider   tracking;           // Tracking
    private Config              _config;            // Android Specific
    private SettingsFragment    _settings;
    private TangoCameraPreview  tangoCameraPreview;
    
    // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ CONSTRUCTOR
    public MainActivity() {
        appClass = "de.imld.basic3d.Main";

        eglBitsPerPixel = 24;
        eglAlphaBits = 8;
        eglDepthBits = 16;
        eglSamples = 2;
        eglStencilBits = 0;

        frameRate = -1;

        joystickEventsEnabled = false;
        keyEventsEnabled = true;
        mouseEventsEnabled = true;

        finishOnAppStop = true;
        handleExitHook = true;
        exitDialogTitle = "Do you want to exit?";
        exitDialogMessage = "Use your home key to bring this app into the"
            + "background or exit to terminate it.";
        screenFullScreen = true;
        splashPicID = 0;
    }
    
    // ################################################################# METHODS
    @Override
    public void onCreate(Bundle savedInstanceState) {
        
        GlobalSettings.RES_X = 1920;    // Tango Resolution
        GlobalSettings.RES_Y = 1080;
        GlobalSettings.ON_TANGO=true;
        
        super.onCreate(savedInstanceState);
        this._settings = new SettingsFragment();
        _config = new ConfigNativeAndroid();

        // Check wether app object exists, app contains main JME class instance
        if(app != null) {
            // Main is JME's main class and has a harness listener
            // Main extends Application
            Log.i(TAG, "Main Class Instance is available");
            ((Main) app).setAndroidHarnessListener(this);
        }
        
        // --------------------------------------------------------------- tango
        try {
            tracking = new TangoTrackingProvider();
            ((TangoTrackingProvider)tracking).layoutDisplay(tangoCameraPreview);
        } catch (Exception e) {
            // TODO
        }
        
        startActivityForResult(Tango.getRequestPermissionIntent(
            Tango.PERMISSIONTYPE_MOTION_TRACKING),
            Tango.TANGO_INTENT_ACTIVITYCODE);
    }

    @Override
    protected void onResume() {
        super.onResume();
        tracking.resume();
    }

    @Override
    protected void onPause() {
        super.onPause();
        tracking.pause();
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
    }
    
    // ######################################### IJmeToAndroid INTERFACE METHODS
    
    public TangoTrackingProvider getTrackingProvider() {
        return this.tracking;
    }

    public Config getConfig() {
        return this._config;
    }

    // ######################################################## Activity METHODS
    @Override
    public boolean onOptionsItemSelected(MenuItem item)
    {
        // Display the fragment as the main content.
        getFragmentManager().beginTransaction()
                .replace(android.R.id.content, new SettingsFragment())
                .addToBackStack(null)
                .commit();

        return true;
    }
    
    @Override
    public boolean onCreateOptionsMenu(Menu menu)
    {
        getMenuInflater().inflate(R.menu.settings, menu);
        return true;
    }
    
    /**
     * Setting up the app layout. This method runs before onCreate()!
     */
    @Override
    public void layoutDisplay()
    {
        setContentView(R.layout.main);  // Read from res/layout/main.xml

        FrameLayout preview = (FrameLayout) findViewById(R.id.cameraPreview);
        tangoCameraPreview = new TangoCameraPreview(this);
        preview.addView(tangoCameraPreview);
        preview.addView(view); //Add JME view which is called in Main.java
        setContentView(preview);
    }

    
    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        // Check which request we're responding to 
        if (requestCode == Tango.TANGO_INTENT_ACTIVITYCODE) {
            // Make sure the request was successful 
            if (resultCode == RESULT_CANCELED) {
                Toast.makeText(this, "Motion Tracking Permissions Required!",
                    Toast.LENGTH_SHORT).show();
                finish();
            } else {
                ((TangoTrackingProvider) tracking).startCameraPreview();
                ((TangoTrackingProvider) tracking).mIsPermissionGranted = true;
            }
        }
    }
}

TangoTrackingProvider:

public class TangoTrackingProvider implements ITrackingProvider {
    
    // ############################################################## ATTRIBUTES
    Handler mainHandler;
    public  static final float  SCALE = 1;

    // Tango
    private         TangoConfig         config;
    private         TangoCameraPreview  tangoCameraPreview; 
    private         Tango               tango; 
    private boolean                     mIsConnected; 
    public  boolean                     mIsPermissionGranted;
    
    // ############################################################# CONSTRUCTOR
    public TangoTrackingProvider()
    {
        this.mainHandler = new Handler(App.getContext().getMainLooper());
        
        // Instantiate Tango client
        this.tango = new Tango(App.getContext());
        this.config = tango.getConfig(TangoConfig.CONFIG_TYPE_CURRENT);
    }

    // .......................................................... PAUSE & RESUME
    public void pause() {
        try {
            if (mIsConnected) {
                tango.disconnect();
                tangoCameraPreview.disconnectFromTangoCamera();
                mIsConnected = false;
            }
        } catch (TangoErrorException e) {
            Toast.makeText(App.getContext(), "Tango Error!",
                    Toast.LENGTH_SHORT).show();
        }
    }

    public void resume() {
        if (!mIsConnected && mIsPermissionGranted) {
            try {
                setTangoListeners();
            } catch (TangoErrorException e) {
                Toast.makeText(App.getContext(), "Tango Error! Restart the app!",
                        Toast.LENGTH_SHORT).show();
            }
            try {
                tango.connect(config);
                startCameraPreview();
            } catch (TangoOutOfDateException e) {
                Toast.makeText(App.getContext(),
                        "Tango Service out of date!", Toast.LENGTH_SHORT)
                        .show();
            } catch (TangoErrorException e) {
                Toast.makeText(App.getContext(),
                        "Tango Error! Restart the app!", Toast.LENGTH_SHORT)
                        .show();
            }
        }
    }
    
    // ################################################################# METHODS
    
    // Camera Preview 
    public void startCameraPreview() {
        // Connect to color camera 
        tangoCameraPreview.connectToTangoCamera(tango,
            TangoCameraIntrinsics.TANGO_CAMERA_COLOR);
        // Use default configuration for Tango Service. 
        tango.connect(config);
        mIsConnected = true;
        setTangoListeners();
    }

    private void setTangoListeners() {
        // Select coordinate frame pairs
        ArrayList<TangoCoordinateFramePair> framePairs 
            = new ArrayList<TangoCoordinateFramePair>();
        framePairs.add(new TangoCoordinateFramePair(
                TangoPoseData.COORDINATE_FRAME_AREA_DESCRIPTION,
                TangoPoseData.COORDINATE_FRAME_DEVICE));

        // Add a listener for Tango pose data
        tango.connectListener(framePairs, new TangoUpdateListener(tangoCameraPreview));
    }
    
    public Tango getTango() {
        return tango;
    }
    
    /**
     * Must be called in {@link MainActivity} in onCreate()
     * @param preview 
     */
    public void layoutDisplay(TangoCameraPreview preview) {
        this.tangoCameraPreview = preview;
    }

    public void addListener(TrackingListener tl) {
        // TODO
    }

    public TrackingUpdate getCurrent() {
        return null;
    }
}

TangoUpdateListener:

public class TangoUpdateListener implements OnTangoUpdateListener {
    
    private final TangoCameraPreview        tangoCameraPreview;
    
    public TangoUpdateListener(TangoCameraPreview tangoCameraPreview) {
        this.tangoCameraPreview = tangoCameraPreview;
    }

    @SuppressLint("DefaultLocale")
    @Override
    public void onPoseAvailable(TangoPoseData pose) {
        // TODO
    }

    @Override
    public void onXyzIjAvailable(TangoXyzIjData xyzIj) {
        // TODO
    }

    @Override
    public void onTangoEvent(TangoEvent arg0) {
        // TODO
    }

    @Override
    public void onFrameAvailable(int cameraId) {
        if (cameraId == TangoCameraIntrinsics.TANGO_CAMERA_COLOR) {
            tangoCameraPreview.onFrameAvailable();  // update camera preview
        }
    }
}
1 Like

Do you need any additional information? I’m pretty desperate :frowning:

Hope someone has an idea.

Cheers,
Gem

Not a good enlightened answer, but do you really need the glow filter and can’t bake the effect instead?

hi loopies,

i would really like to use it. have no idea how to “bake” it on my own.

Kind of depends what you want to see glow. If it’s only elements of the gui then you could simply use a texture that displays like a glow. Now, if we talking making “random” geometries in the scene glow, then that would be harder to bake, I guess. Sorry not really competent here, just making sure you didn’t miss a possible solution.

NB: I avoid all such effects like the pest on android because they are costly and may not be supported by some phones… at the same time I have no knowledge of the inner workings and haven’t tested the performances.

I need very complex 3d objects to glow. I guess it’s best to use the standard way. I recognized, that behind transparent gui images its not occluded, so i tried to fill the screen with a completely transparent image. and it worked.

a dirty solution, but working.

EDIT: not working - only when its not completely transparent, then it’s kinda working - but not perfect
EDIT2: works up to 50%, not further

@pspeed - sorry for bothering - any ideas?

And that work on a PC? Isn’t it possible to reproduce it in single simple app? If the answer is no then find out what is different, if the answer is yes the masters among us (sorry not me) can then maybe help better or some one with android under his belt.
Just some how you have to track down the problem to a point. Maybe a intermediate solution is: use a high alpha for your gui img?!

Already tried that image thing. It works up to 50% transparency and then it’s getting worse again.

On the PC there is no problem. It’s only on android, because there I have to place the video as an Android Surface behind the rendered scene. And somehow the glow filter draws the background black, so I can’t see the video image anymore.

Then I would write some thing very simple which fits in one class, like the beginners section, so we just can copy paste run and see. And maybe it is then not reproducable and from this point you just need to find the 10 differeces. At least I try to track down a problem that way.
And sorry I have no android knowhow so I can not help beside the general suggestions above.

Just to be clear… on the PC you also have the video? Or the video is only on Android?

I don’t think that FPP will work if you want to use video as a background because you somehow have to get the video content into the FPP. Not sure what the alteratives are on Android at this point. At first I thought maybe rendering your scene to a texture and overlaying that but I think we don’t transfer alpha through anymore like we used to (when using FPP)… that’s true on desktop also.

@pspeed

No, video is for android only.

@ia97lies

unfortunately it’s not getting much simpler because of the tango stuff - but I could try making a simpler example with normal android camera overlay

Ok, I made a minimal example which should work on any android phone. The MainActivity code is long - but most of it not interesting for you - but you need it to work.

Main.java: simply adds a blue cube and the glow filter

public class Main extends SimpleApplication
{
    private IJmeToAndroid _harness;

    public static void main(String[] args)
    {
        Main app = new Main();
        app.start();
    }

    @Override
    public void simpleInitApp()
    {
        _harness = getHarness();
        
        FilterPostProcessor fpp = new FilterPostProcessor(assetManager);
        BloomFilter bloom = new BloomFilter(BloomFilter.GlowMode.Objects);
        fpp.addFilter(bloom);
        viewPort.addProcessor(fpp);
        
        Box b = new Box(1f, 1f, 1f);
        Geometry geom = new Geometry("Box", b);

        Material mat = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
        mat.setColor("Color", ColorRGBA.Blue);
        mat.setColor("GlowColor", ColorRGBA.Blue);
        geom.setMaterial(mat);

        rootNode.attachChild(geom);
    }

    @Override
    public void simpleUpdate(float tpf) {}

    @Override
    public void simpleRender(RenderManager rm) {}

    public IJmeToAndroid getHarness() {
        return this._harness;
    }

    public void setHarnessListener(IJmeToAndroid harness) {
        this._harness = harness;
    }
}

IJmeToAndroid: Interface to access android activity from Main

public interface IJmeToAndroid {
    public Config getConfig();
}

MainActivity for Android: uses a second Activity with a surface to underlay the camera preview

/**
 *
 * @author http://hub.jmonkeyengine.org/t/augmented-reality-jmonkey/23699/6
 */
public class MainActivity extends AndroidHarness implements IJmeToAndroid {
    private Camera mCamera;
    private ARCameraActivity _preview;
    private Config _config;

    public MainActivity(){
        appClass = "de.imld.basic3d.Main";
        eglBitsPerPixel = 24;
        eglAlphaBits = 8;
        eglDepthBits = 16;
        eglSamples = 2;
        eglStencilBits = 0;
        frameRate = -1;
        joystickEventsEnabled = false;
        keyEventsEnabled = true;
        mouseEventsEnabled = true;
        finishOnAppStop = true;
        handleExitHook = true;
        exitDialogTitle = "Do you want to exit?";
        exitDialogMessage = "Home = Background, Exit = Terminate";
        screenFullScreen = true;
        splashPicID = 0;
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        if (app != null) ((Main)app).setHarnessListener(this);
        _config = new ConfigNativeAndroid();
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.settings, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        getFragmentManager().beginTransaction()
                .replace(android.R.id.content, new SettingsFragment())
                .addToBackStack(null).commit();
        return true;
    }

    public Config getConfig() {
        return _config;
    }

    public class SettingsFragment extends PreferenceFragment {
        @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);

            // Load the preferences from an XML resource
            addPreferencesFromResource(R.xml.preferences);
            Preference button = (Preference) getPreferenceManager().findPreference("exitlink");
            if (button != null) {
                button.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() {
                    @Override
                    public boolean onPreferenceClick(Preference arg0) {
                        if (getFragmentManager().getBackStackEntryCount() > 0) {
                            getFragmentManager().popBackStack();
                        }
                        return true;
                    }
                });
            }
        }
    }

    @Override
    public void layoutDisplay() {
        setContentView(R.layout.main);
        _preview = new ARCameraActivity(this, mCamera);
        FrameLayout preview = (FrameLayout) findViewById(id.cameraPreview);
        preview.addView(_preview);
        preview.addView(view);
    }

    public class ARCameraActivity extends SurfaceView implements SurfaceHolder.Callback {
        private SurfaceHolder mHolder;
        private boolean started;
        private Camera mCamera;
        private List<Camera.Size> mSupportedPreviewSizes;

        public ARCameraActivity(Context context, Camera camera){
            super(context);
            started = false;
            mCamera = camera;
            if (mCamera == null) mCamera = getCameraInstance();
            mSupportedPreviewSizes = mCamera.getParameters().getSupportedPreviewSizes();
            mHolder = getHolder();

            mHolder.addCallback(this);
            mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
        }

        @Override
        protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
            int suggestedWidth = getSuggestedMinimumWidth();
            int suggestedHeight = getSuggestedMinimumHeight();
            final int width = resolveSize(suggestedWidth, widthMeasureSpec);
            final int height = resolveSize(suggestedHeight, heightMeasureSpec);
            setMeasuredDimension(width, height);
        }

        public void surfaceCreated(SurfaceHolder holder) {
            try {
                if (mCamera != null) {
                    Camera.Parameters parameters = mCamera.getParameters();
                    //parameters.setPreviewSize(mPreviewSize.width, mPreviewSize.height);
                    parameters.setPreviewSize(1280, 720);
                    parameters.setPictureSize(1280, 720);
                    mCamera.setParameters(parameters);
                    mCamera.setPreviewDisplay(holder);
                }

            } catch (IOException e) {}
        }

        public void surfaceDestroyed(SurfaceHolder holder) {
            try {
                stop();
            } catch (Exception e) {}
        }

        public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
            if (mHolder.getSurface() == null) {
                return;
            }
            
            try {
                mCamera.stopPreview();
            } catch (Exception e) {}

            try {
                Camera.Parameters parameters = mCamera.getParameters();
                //parameters.setPreviewSize(mPreviewSize.width, mPreviewSize.height);
                parameters.setPreviewSize(1280, 720);
                parameters.setPictureSize(1280, 720);
                mCamera.setParameters(parameters);
                start();
            } catch (Exception e) {}
        }
        
        private Camera getCameraInstance() {
            Camera c = null;
            try {
                c = Camera.open();
            } catch (Exception e) {}
            return c;
        }
        
        public void start() {
            if (!started) {
                mCamera.startPreview();
                started = true;
            }
        }
        
        public void stop() {
            if (mCamera != null) {
                mCamera.stopPreview();
                // even though it is before
                mCamera.release();
                started = false;
                mCamera = null;
            }
        }
    }

    @Override
    public void onResume() {
        super.onResume(); 
    }

    @Override
    public void onPause() {
        super.onPause();
        if (mCamera != null) {
            mCamera.release();
            mCamera = null;
        }
    }
}

And at least the layout file which goes into: /project/android/res/layout/main.xml

<?xml version="1.0" encoding="UTF-8"?> 
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/cameraPreview" android:layout_height="fill_parent" android:layout_width="fill_parent" android:orientation="vertical"> 
    <!--<fragment android:id="@+id/jmeFragment" android:layout_height="match_parent" android:layout_width="match_parent" android:name="com.mycompany.mygame.MainActivity$JmeFragment"/> --> 
</FrameLayout>

And again, thank you so much for your time.

right there is your first mistake …

1 Like

what do you mean?