Image format 'Depth24' is unsupported

Hi team,

I started playing with jME3.1-Beta2 and android and I am getting the error below:

My Setup:

  1. Created a Basic Test Android Application.
  2. Added a FXAA filter to the scene.
  3. Converted my app to run android.
  4. Runs fine on Window, but on Android I get this error.
  5. Device Galaxy Note 4
  6. Settings on android:

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

com.jme3.renderer.RendererException: Image format 'Depth24' is unsupported by the video hardware.
 	at com.jme3.renderer.opengl.TextureUtil.getImageFormatWithError(TextureUtil.java:101)
 	at com.jme3.renderer.opengl.TextureUtil.uploadTexture(TextureUtil.java:243)
 	at com.jme3.renderer.opengl.GLRenderer.updateTexImageData(GLRenderer.java:2212)
 	at com.jme3.renderer.opengl.GLRenderer.updateRenderTexture(GLRenderer.java:1500)
 	at com.jme3.renderer.opengl.GLRenderer.updateFrameBufferAttachment(GLRenderer.java:1531)
 	at com.jme3.renderer.opengl.GLRenderer.updateFrameBuffer(GLRenderer.java:1581)
 	at com.jme3.renderer.opengl.GLRenderer.setFrameBuffer(GLRenderer.java:1736)
 	at com.jme3.renderer.RenderManager.renderViewPort(RenderManager.java:1072)
 	at com.jme3.renderer.RenderManager.render(RenderManager.java:1145)
 	at com.jme3.app.SimpleApplication.update(SimpleApplication.java:253)
 	at com.jme3.app.AndroidHarness.update(AndroidHarness.java:497)
 	at com.jme3.system.android.OGLESContext.onDrawFrame(OGLESContext.java:336)
 	at android.opengl.GLSurfaceView$GLThread.guardedRun(GLSurfaceView.java:1649)
 	at android.opengl.GLSurfaceView$GLThread.run(GLSurfaceView.java:1354)

I debugged my code and it seems that something is overriding the eglDepthBits = 16; to 24

I will try and find it. Might be on my side but I do not change that specifically.

Is there anyone out there that have experienced this problem before…

I am still stuck.

Here is my code:
MainApplication

package mygame;

import com.jme3.app.SimpleApplication;
import com.jme3.light.AmbientLight;
import com.jme3.light.DirectionalLight;
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.FXAAFilter;
import com.jme3.renderer.RenderManager;
import com.jme3.scene.Geometry;
import com.jme3.scene.shape.Box;

/**
 * This is the Main Class of your Game. You should only do initialization here.
 * Move your Logic into AppStates or Controls
 *
 * @author normenhansen
 */
public class Main extends SimpleApplication {
    
    private FilterPostProcessor fpp;

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

    @Override
    public void simpleInitApp() {
        
        addSunLight(ColorRGBA.White);
        addBox(1, 1, 1, Vector3f.UNIT_Y, ColorRGBA.randomColor());
        addBox(10, 0.1f, 10, Vector3f.ZERO, ColorRGBA.randomColor());
        
        flyCam.setMoveSpeed(10);
        flyCam.setRotationSpeed(1);
        
        cam.setLocation(new Vector3f(-10, 5, 10));
        cam.lookAt(Vector3f.ZERO, Vector3f.UNIT_Y);
        
        fpp = new FilterPostProcessor(assetManager);
        
        FXAAFilter fXAAFilter = new FXAAFilter();
        fpp.addFilter(fXAAFilter);
        
        getViewPort().addProcessor(fpp);

    }
    
    private void addBox(float xE, float yE, float zE, Vector3f position, ColorRGBA colorRGBA) {
        /* A colored lit cube. Needs light source! */
        Box boxMesh = new Box(xE, yE, zE);
        Geometry boxGeo = new Geometry("Colored Box", boxMesh);
        Material boxMat = new Material(assetManager, "Common/MatDefs/Light/Lighting.j3md");
        boxMat.setBoolean("UseMaterialColors", true);
        boxMat.setColor("Ambient", colorRGBA);
        boxMat.setColor("Diffuse", colorRGBA);
        boxGeo.setMaterial(boxMat);
        boxGeo.setLocalTranslation(position);
        rootNode.attachChild(boxGeo);
    }
    
    /**
     * Adds sunlight to the scene.
     *
     * @param parent
     * @return
     */
    public DirectionalLight addSunLight(ColorRGBA colorRGBA) {
        DirectionalLight sun = new DirectionalLight();
        sun.setDirection((new Vector3f(-0.25f, -0.45f, -0.25f)).normalizeLocal());
        sun.setColor(colorRGBA);
        rootNode.addLight(sun);
        /**
         * A white ambient light source.
         */
        AmbientLight ambient = new AmbientLight();
        ambient.setColor(ColorRGBA.White.mult(0.5f));
        rootNode.addLight(ambient);

        return sun;
    }

    @Override
    public void simpleUpdate(float tpf) {
        //TODO: add update code
    }

    @Override
    public void simpleRender(RenderManager rm) {
        //TODO: add render code
    }
}

AndroidActivity:

package com.bruynhuis.testpost;
 
import com.jme3.app.DefaultAndroidProfiler;
import android.app.Activity;
import android.app.FragmentManager;
import android.os.Bundle;
import android.view.Window;
import android.view.WindowManager;
import com.jme3.app.AndroidHarnessFragment;
import java.util.logging.Level;
import java.util.logging.LogManager;
 
public class MainActivity extends Activity {
    /*
     * Note that you can ignore the errors displayed in this file,
     * the android project will build regardless.
     * Install the 'Android' plugin under Tools->Plugins->Available Plugins
     * to get error checks and code completion for the Android project files.
     */
 
    public MainActivity(){
        // Set the default logging level (default=Level.INFO, Level.ALL=All Debug Info)
        LogManager.getLogManager().getLogger("").setLevel(Level.INFO);
    }
 
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        // Set window fullscreen and remove title bar
        requestWindowFeature(Window.FEATURE_NO_TITLE);
        getWindow().setFlags(
                WindowManager.LayoutParams.FLAG_FULLSCREEN,
                WindowManager.LayoutParams.FLAG_FULLSCREEN);
        setContentView(R.layout.main);
 
        // find the fragment
        FragmentManager fm = getFragmentManager();
        AndroidHarnessFragment jmeFragment =
                (AndroidHarnessFragment) fm.findFragmentById(R.id.jmeFragment);
 
        // uncomment the next line to add the default android profiler to the project
        //jmeFragment.getJmeApplication().setAppProfiler(new DefaultAndroidProfiler());
    }
 
 
    public static class JmeFragment extends AndroidHarnessFragment {
        public JmeFragment() {
            // Set main project class (fully qualified path)
            appClass = "mygame.Main";
 
            // Set the desired EGL configuration
            eglBitsPerPixel = 24;
            eglAlphaBits = 0;
            eglDepthBits = 16;
            eglSamples = 0;
            eglStencilBits = 0;
 
            // Set the maximum framerate
            // (default = -1 for unlimited)
            frameRate = -1;
 
            // Set the maximum resolution dimension
            // (the smaller side, height or width, is set automatically
            // to maintain the original device screen aspect ratio)
            // (default = -1 to match device screen resolution)
            maxResolutionDimension = -1;
 
            // Set input configuration settings
            joystickEventsEnabled = false;
            keyEventsEnabled = true;
            mouseEventsEnabled = true;
 
            // Set application exit settings
            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.";
 
            // Set splash screen resource id, if used
            // (default = 0, no splash screen)
            // For example, if the image file name is "splash"...
            //     splashPicID = R.drawable.splash;
            splashPicID = 0;
        }
    }
}

Okay for those interested, I made some progress…

  1. I had to force the FilterPostProcessor’s depth texture image format to Depth16:
fpp.getDepthTexture().getImage().setFormat(Image.Format.Depth16);
  1. Had to force the Filter Texture image format also but to RGBA8:
if (fpp.getFilterTexture() != null) {
                fpp.getFilterTexture().getImage().setFormat(Image.Format.RGBA8);
            }  
  1. Then on my filters I had to override the default image formats:
    @Override
    protected Image.Format getDefaultPassDepthFormat() {
        return Image.Format.Depth16;
    }

    @Override
    protected Image.Format getDefaultPassTextureFormat() {
        return Image.Format.RGBA8;
    }

That kind of helped with most of my filters except the one’s which requires a depth texture:

protected boolean isRequiresDepthTexture() {
        return true;
    }

Any advice on the last point??? @nehon

Sorry I missed this post. I think I remember we changed the Depth precision to 24… but it was a long time ago… I guess we could check i f the hardware supports it an fallback to lower values… the “Depth” format is already supposed to pick the best fit… but I think it just pick the first fit and was selecting Depth16 even when depth24 was available.
It’s safe to do it as you did, even if I reckon it’s a bit cumbersome.

2 Likes

Thanks nehon for the feedback and I can work with it as is for now, but I think for future users of jME3.1 and Android that it should be fixed.

Thanks again.

I’m going through the same issue, but the workaround from @ndebruyn did not work for me since ‘fpp.getDepthTexture()’ and ‘fpp.getFilterTexture()’ return null. I’m deploying my app to a real device, not an emulator. Does anyone know how to fix it?

Did you manage somehow to make any filter work on Android?

Currently, I’ve tried your solution and it worked to remove the “Image format ‘Depth24’ is unsupported” but it started to trow a java.lang.IllegalStateException: Framebuffer has erronous attachment, which seems to be a known issue:

and from nehon:

what doesn’t give me too much hope in this issue. I’ve tried with FXAA and the CartoonEdgeFilter so far, both with the same result.

The full stack trace in this case is (almost identical to the one in the linked posts):

 java.lang.IllegalStateException: Framebuffer has erronous attachment.
     at com.jme3.renderer.opengl.GLRenderer.checkFrameBufferError(GLRenderer.java:1417)
     at com.jme3.renderer.opengl.GLRenderer.updateFrameBuffer(GLRenderer.java:1590)
     at com.jme3.renderer.opengl.GLRenderer.setFrameBuffer(GLRenderer.java:1735)
     at com.jme3.renderer.RenderManager.renderViewPort(RenderManager.java:1072)
     at com.jme3.renderer.RenderManager.render(RenderManager.java:1153)
     at com.jme3.app.SimpleApplication.update(SimpleApplication.java:253)
     at com.jme3.app.AndroidHarnessFragment.update(AndroidHarnessFragment.java:577)
     at com.jme3.system.android.OGLESContext.onDrawFrame(OGLESContext.java:342)
     at android.opengl.GLSurfaceView$GLThread.guardedRun(GLSurfaceView.java:1535)
     at android.opengl.GLSurfaceView$GLThread.run(GLSurfaceView.java:1240)

This should be fixed on latest master:

It still throw the same issue for CartoonEdge (just some line number changes) and a different one for FXAA:

CartoonEdge:

java.lang.IllegalStateException: Framebuffer has erronous attachment.
     at com.jme3.renderer.opengl.GLRenderer.checkFrameBufferError(GLRenderer.java:1486)
     at com.jme3.renderer.opengl.GLRenderer.updateFrameBuffer(GLRenderer.java:1659)
     at com.jme3.renderer.opengl.GLRenderer.setFrameBuffer(GLRenderer.java:1800)
     at com.jme3.renderer.RenderManager.renderViewPort(RenderManager.java:1082)
     at com.jme3.renderer.RenderManager.render(RenderManager.java:1166)

FXAA:

Symbol g_ResolutionInverse defined with different precision in vertex and fragment shaders.
     at com.jme3.renderer.opengl.GLRenderer.updateShaderData(GLRenderer.java:1348)
     at com.jme3.renderer.opengl.GLRenderer.setShader(GLRenderer.java:1360)
     at com.jme3.material.logic.DefaultTechniqueDefLogic.render(DefaultTechniqueDefLogic.java:94)
     at com.jme3.material.Technique.render(Technique.java:166)
     at com.jme3.material.Material.render(Material.java:974)
     at com.jme3.renderer.RenderManager.renderGeometry(RenderManager.java:614)
     at com.jme3.post.FilterPostProcessor.renderProcessing(FilterPostProcessor.java:230)
     at com.jme3.post.FilterPostProcessor.renderFilterChain(FilterPostProcessor.java:314)
     at com.jme3.post.FilterPostProcessor.postFrame(FilterPostProcessor.java:334)
     at com.jme3.renderer.RenderManager.renderViewPort(RenderManager.java:1114)
     at com.jme3.renderer.RenderManager.render(RenderManager.java:1166)
     at com.jme3.app.SimpleApplication.update(SimpleApplication.java:253)
     at com.jme3.app.AndroidHarnessFragment.update(AndroidHarnessFragment.java:577)
     at com.jme3.system.android.OGLESContext.onDrawFrame(OGLESContext.java:342)
     at android.opengl.GLSurfaceView$GLThread.guardedRun(GLSurfaceView.java:1535)
     at android.opengl.GLSurfaceView$GLThread.run(GLSurfaceView.java:1240)

Hi,

I want to learn how this OpenGL texture support work too :). So, does my problem below would be fixed with the new master as well? Could it be that OpenGL team does not know that something does not work perfectly with my old laptop?

I have multiple laptop and PCs, but that laptop is the one with oldest hardware, which I use to test my mininum hardware requirement.

Thank you.

Yes that one should be fixed as well

Thank you.