androidopengl-esaugmented-realitytranslucency

Problem drawing squares when GLSurface is TRANSLUCENT. Square gets drawn twice


I'm doing my first steps in OpenGL for Android, for developing Augmented Reality apps and I'm having a bad time integrating OpenGL shapes in front of the camera image. The program is supposed to draw a square in the XZ plane (assuming that Z axis is pointing up) over the camera image, but I'm getting two squares and they are smaller than if I don't use the camera.

Here's a bit of code.

In the main activity, I set the views and sensors like this:

protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    //Create an Instance with this Activity
    glSurface = new GLSurfaceView(this);
    //Set our own Renderer
    MyRenderer renderer = new Lesson02();
    glSurface.setRenderer(renderer);
    glSurface.getHolder().setFormat(PixelFormat.TRANSLUCENT);

    //Set the GLSurface as View to this Activity
    setContentView(glSurface);

    mCameraView = new CameraView(this);
    addContentView(mCameraView, new LayoutParams(LayoutParams.WRAP_CONTENT,
            LayoutParams.WRAP_CONTENT));

    mSensorManager = (SensorManager) getSystemService(SENSOR_SERVICE);

    List<Sensor> listSensors = mSensorManager
            .getSensorList(Sensor.TYPE_ACCELEROMETER);
    if (listSensors.size() > 0) {
        mSensorManager.registerListener(renderer,
                listSensors.get(0), SensorManager.SENSOR_DELAY_UI);
    }

    listSensors = mSensorManager.getSensorList(Sensor.TYPE_MAGNETIC_FIELD);
    if (listSensors.size() > 0) {
        mSensorManager.registerListener(renderer,
                listSensors.get(0), SensorManager.SENSOR_DELAY_UI);
    }
}

The onDraw method of my renderer do something like this:

public void onDrawFrame(GL10 gl) {
    // Get rotation matrix from the sensor
    SensorManager.getRotationMatrix(rotationMatrix, null,
                                    mAccelerometerValues, mMagneticValues);
    // As the documentation says, we are using the device as a compass in
    // landscape mode
    SensorManager.remapCoordinateSystem(rotationMatrix,
                                        SensorManager.AXIS_Y, 
                                        SensorManager.AXIS_MINUS_X,
                                        remappedRotationMatrix);

    //Clear Screen And Depth Buffer
    gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);

    // Load remapped matrix
    gl.glMatrixMode(GL10.GL_MODELVIEW);
    //Reset The Current Modelview Matrix
    gl.glLoadIdentity();    
    gl.glLoadMatrixf(remappedRotationMatrix, 0);

    // Draw square
    gl.glTranslatef(-1.2f, 18.0f, 0.0f);
    //gl.glTranslatef(0.0f, -1.2f, -6.0f);  //Move down 1.2 Unit And Into The Screen 6.0
    square.draw(gl);                        //Draw the square
}

Finally, I inicialize everything within the onSurfaceCreated method like this:

public void onSurfaceCreated(GL10 gl, EGLConfig config) {       
    gl.glShadeModel(GL10.GL_SMOOTH);            //Enable Smooth Shading
    gl.glClearColor(0.0f, 0.0f, 0.0f, 0.5f);            //Black Background
    gl.glClearDepthf(1.0f);                 //Depth Buffer Setup
    gl.glEnable(GL10.GL_DEPTH_TEST);            //Enables Depth Testing
    gl.glDepthFunc(GL10.GL_LEQUAL);             //The Type Of Depth Testing To Do

    /*
     * By default, OpenGL enables features that improve quality but reduce
     * performance. One might want to tweak that especially on software
     * renderer.
     */
    gl.glDisable(GL10.GL_DITHER);

    /*
     * Some one-time OpenGL initialization can be made here probably based
     * on features of this particular context
     */
    gl.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT, GL10.GL_FASTEST);
}

If I comment the line

glSurface.getHolder().setFormat(PixelFormat.TRANSLUCENT);

within the activity it draws the square good and smooth, and only once. But when I make it translucent or even transparent, it draws two smaller squares that are not well-drawn when I spin the mobile.

If anyone knows what's going on, it'd be very appreciated.

Thanks!!


Solution

  • Just found out the solution looking at the demos. Within my main activity, I need to set the EGL configuration chooser. Something like this should be written in the onCreate method of the main activity (in which I add the opengl view and the camera view):

    protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
    
            //Create an Instance with this Activity
            glSurface = new GLSurfaceView(this);
            // We want an 8888 pixel format because that's required for a 
            //translucent window. And we want a depth buffer. 
            glSurface.setEGLConfigChooser(8, 8, 8, 8, 16, 0);  // <-- NEW LINE ADDED
            //Set our own Renderer
            MyRenderer renderer = new MyRenderer ();
            glSurface.setRenderer(renderer);
            glSurface.getHolder().setFormat(PixelFormat.TRANSLUCENT);
    
            //Set the GLSurface as View to this Activity
            setContentView(glSurface);
    
            mCameraView = new CameraView(this);
            addContentView(mCameraView, new LayoutParams(LayoutParams.WRAP_CONTENT,
                    LayoutParams.WRAP_CONTENT));
    
                    // More code ...
    }
    

    Apparently, that line is necessary for having a translucent opengl window.