Reputation: 133
I'm using OpenGL ES 2.0, and using a Stencil Buffer. Below is code from a simple Stencil Buffer Demo I made. The Stenciling is only works properly on one device.
Devices are as follows:
Android 4.2.2, PowerVR SGX 544MP (GPU), Allwinner A10 tablet. (Stencil Buffer works perfectly on this device)
Android 4.1.2, Adreno 225 (GPU), Galaxy S III Phone. (Stencil Buffer does not work, some flickering with ghost image of stencil rarely.
Android 4.2.2, Mali-400MP (GPU), Rockchip rk30sdk tablet. (In initial testing, the Stencil Buffer was not working, after many changes it now seems to be working, status is questionable. Specific change that remedied in-op Stencil Buffer unknown at this point)
Same latest .APK gave the above results.
Application 'OpenGL 3D Showcase' from 'Play Store' was run on all three devices and 'showcase' #18 'Stencil Buffer Shadows'[OGL 1.1] work perfectly with no error messages. Source code is provided with the App and has been reviewed to no-avail.
Below is my Stencil code:
public void onDrawFrame(GL10 glUnused) {
// Clear the rendering surface.
glClear( GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT );
multiplyMM(viewProjectionMatrix, 0, projectionMatrix, 0, viewMatrix, 0);
invertM(invertedViewProjectionMatrix, 0, viewProjectionMatrix, 0);
//Start using the stencil
glEnable( GL_STENCIL_TEST );
//Disable rendering to the color buffer
glColorMask( false, false, false, false );
//Place a 1 where rendered
glStencilFunc( GL_ALWAYS, 1, 1 );
//Replace where rendered
glStencilOp( GL_REPLACE, GL_REPLACE, GL_REPLACE );
glDisable(GL_DEPTH_TEST);
glStencilMask(0xFF);//value used when writing to stencil buffer
// draw stencil triangle
rotateObjectInScene(0.0f, 0.0f, 0.0f);//x,y,z Object is rottated one full rotation ever 3 seconds within
colorProgram.useProgram();
colorProgram.setUniforms(modelViewProjectionMatrix, 0f, 0f, 1f);
DemoTriangleStencilObj.bindData(colorProgram);
DemoTriangleStencilObj.draw();
//Reenable color
glColorMask( true, true, true, true );
//Where a 1 was not rendered
glStencilFunc( GL_EQUAL, 1, 1 );//GL_EQUAL GL_NOTEQUAL
//Keep the pixel
glStencilOp( GL_KEEP, GL_KEEP, GL_KEEP );
glStencilMask(0x00);//disable writing to stencil buffer by setting value used to 0.
positionObjectInScene1(0.0f, 0.0f, 0.0f);//leave image/object fixed in center of screen
textureProgram1.useProgram();
textureProgram1.setUniforms(modelViewProjectionMatrix, texture_opengl);
openglImageDemoObj.bindData(textureProgram1);
openglImagerectanDemoObj.draw();
//Finished using stencil
glDisable( GL_STENCIL_TEST );
}
Init:
public void onSurfaceCreated(GL10 glUnused, EGLConfig config) {
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
}
public void onSurfaceChanged(GL10 glUnused, int width, int height) {
// Set the OpenGL viewport to fill the entire surface.
glViewport(0, 0, width, height);
// Landscape
orthoM(projectionMatrix, 0, -1, 1, -1f, 1f, -1f, 20f);
setLookAtM(viewMatrix, 0, 0f, 2.0f, 0.1f, 0.0f, 0f, 0f, 0f, 1f, 0f);
}
Init2:
All commented 'setEGLConfigChooser' calls have been tried.
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//Remove title bar
this.requestWindowFeature(Window.FEATURE_NO_TITLE);
//Remove notification bar
this.getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
//setContentView(R.layout.activity_fist_open_glproject_aactivity);
glSurfaceView = new GLSurfaceView(this);
final TheSurfaceRenderer theSurfaceRenderer = new TheSurfaceRenderer(this);
this.getApplicationContext();
final ActivityManager activityManager =
(ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
final ConfigurationInfo configurationInfo =
activityManager.getDeviceConfigurationInfo();
//final boolean supportsEs2 = false;//configurationInfo.reqGlEsVersion >= 0x20000;
final boolean supportsEs2 = configurationInfo.reqGlEsVersion >= 0x20000;
if (supportsEs2) {
// Request an OpenGL ES 2.0 compatible context.
glSurfaceView.setEGLContextClientVersion(2);
//glSurfaceView.setEGLConfigChooser(8, 8, 8, 8, 16, 0);//when use emulator, may be needed.
glSurfaceView.setEGLConfigChooser(new MultiSampleConfigChooser());
//glSurfaceView.setEGLConfigChooser(8, 8, 8, 8, 16, 8);
//glSurfaceView.setEGLConfigChooser(5,6,5,0,24,8);
//glSurfaceView.setEGLConfigChooser(5,6,5,0,16,8);
//glSurfaceView.setEGLConfigChooser(5,6,5,8,16,8);
// Assign our renderer.
//glSurfaceView.setRenderer(new AirHockeyRenderer(this));
glSurfaceView.setRenderer(theSurfaceRenderer);
rendererSet = true;
//Toast.makeText(this, "Renderer started", Toast.LENGTH_LONG).show();
} else {
Toast.makeText(this, "This device does not support OpenGL ES 2.0.",
Toast.LENGTH_LONG).show();
return;
}
setContentView(glSurfaceView);
}
Any ideas to track the issue? Any where else I'm likely to get help?(If need be, can contacting a MFG/Android/Google get me anywhere?)
Upvotes: 2
Views: 1908
Reputation: 11
In the code you provided, you set glStencilMask(0xFF) then later you do glStencilMask(0x00). OpenGL is a state machine, so whatever you last set is the current value--even when you clear. The default stencil mask value is 255 so your glClear works on the first frame. But after that, the stencil mask is 0 (because you set it that way) and so the stencil buffer does NOT get cleared. Do this at the top of your function:
public void onDrawFrame(GL10 glUnused) {
// Clear the rendering surface.
glStencilMask(0xFF);
glClear( GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT );
...
}
The glStencilMask function sets the write mask--clearing is a write operation, so you should typically set all stencil bits to write-able when clearing.
Upvotes: 1