DepthMask(false) in Android causing Frame Buffer corruption

This is my first post here, even though I’ve been using JME3 for almost 2 years now. I’m currently working on writing an Android game with JME3 and I have been running into strange depth buffer problems on android involving the depth buffer. I’m developing on a Nexus 5, but the problem also exists on a Nexus 7 (2012). Basically, I’ve narrowed it down to whenever something turns the DepthMask to false in a shader, the framebuffer gets corrupted.

Here is a picture of the corruption that happens when I try to use a Particle Emitter:

I’ve noticed the problem in everything from filters, to when using nifty gui, and most recently when using particle emitters. From my research, this appears to affect only certain Android devices. I finally decided to do something about it (I gotta have my particles!!!). I checked the forums here and I noticed a few people mentioning depth buffer weirdness in Android, but no solutions. So, I’m posting here to hopefully help someone in the future, or to maybe let one of the developers know about a potential fix.

This link explains whats going on. Basically whenever the DepthMask is set to false, and left at false when the page flip occurs, on some Android devices, the framebuffer will get corrupted. The fix is simple: to call glDepthMask(true) after finishing rendering. Well, after a bit of digging I figured a way to hook into the postRender using an AppState:

[java]import java.io.IOException;

import android.opengl.GLES20;

import com.jme3.app.Application;
import com.jme3.app.state.AppStateManager;
import com.jme3.effect.ParticleEmitter;
import com.jme3.export.JmeExporter;
import com.jme3.export.JmeImporter;
import com.jme3.renderer.RenderManager;
import com.jme3.renderer.ViewPort;
import com.jme3.scene.Node;
import com.jme3.scene.Spatial;
import com.jme3.scene.control.Control;

public class DepthBufferFix implements com.jme3.app.state.AppState {

@Override
public void cleanup() { }

@Override
public void initialize(AppStateManager arg0, Application arg1) {}

@Override
public boolean isEnabled() { return true; }

@Override
public boolean isInitialized() { return true; }

@Override
public void postRender() {
	GLES20.glDepthMask(true);
}

@Override
public void render(RenderManager arg0) {}

@Override
public void setEnabled(boolean arg0) {}

@Override
public void stateAttached(AppStateManager arg0) {}

@Override
public void stateDetached(AppStateManager arg0) {}

@Override
public void update(float arg0) {	}

}[/java]

and then in the simpleInitApp method of your SimpleApplication class:

[java] DepthBufferFix dbfix =new DepthBufferFix();
dbfix.setEnabled(true);
this.getStateManager().attach(dbfix);[/java]

Applying this fix, my Particle Emitters now work, and I’m fairly certain several other depth mask related problems will be solved. Below is a screenshot of the particles working as expected:

My solution of course, is a bandaid. I think the engine should probably set the glDepthMask back to true post render. But I wanted to put this out there for any fellow Android JME3 developers. Also, many thanks to all the developers of JME3, you guys are great!

5 Likes

Good find there!

Off topic: I wish you’d use birds instead of donuts. :wink:

interesting. I’ve had some depth problems using multiple viewports on android as well (HTC Sensation). I will see if your solution works.

Then we can look at a patch inside the AndroidRenderer where all GLES calls should be called :slight_smile:

@wezrule said: interesting. I've had some depth problems using multiple viewports on android as well (HTC Sensation). I will see if your solution works.

Then we can look at a patch inside the AndroidRenderer where all GLES calls should be called :slight_smile:

Yes, from what I can tell the HTC Sensation has an Adreno 220. My guess is any shader that is using DepthWrite Off and has glitching like what I showed above will probably benefit from this. Very likely any phones based off of the Adreno will benefit from this.

@madjack said: Good find there!

Off topic: I wish you’d use birds instead of donuts. :wink:

My daughter wants me to use french fries. I’ll take both suggestions to heart :wink:

@dbugman said: My daughter wants me to use french fries. I'll take both suggestions to heart ;)

It’s better if you use birds. Then you can call it Angry Pigs. :wink: