Question

Okay here is my OpenGL Problem I really can't fix. Everything works fine on the Galaxy S1 and on an S2 which seems to have almost the same GPU. But when I try to make an AR-App I always get a problem with transparent pixels on top of my camera preview. It only appears when the pixels are transparent and looks like "Burned colors" or value overflow or something like that. So please tell me what I'm doing wrong or try it if you have a S3. Maybe mine is just broken?? I created a small testprogram for you. Please take a look at this:

public class MainActivity extends Activity {
private GLSurfaceView mGLView;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        mGLView = new GLSurfaceView(this);
        mGLView.setEGLContextClientVersion(2);
        mGLView.setEGLConfigChooser(8, 8, 8, 8, 16, 0);
        mGLView.getHolder().setFormat(PixelFormat.TRANSLUCENT);
        mGLView.setZOrderOnTop(true);        
        GameRenderer renderer = new GameRenderer();
        mGLView.setRenderer(renderer);
        setContentView(new CameraView(this), new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
        addContentView(mGLView, new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
    }

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

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

The CameraView looks like that:

public class CameraView extends SurfaceView implements SurfaceHolder.Callback{

    SurfaceHolder surfaceHolder;
    Camera camera;

    public CameraView(Context context, AttributeSet attrs) {
        super(context, attrs);
        surfaceHolder = getHolder();
        surfaceHolder.addCallback(this);
    }

    /**
     * @param context
     */
    public CameraView(Context context) {
        super(context);
        surfaceHolder = getHolder();
        surfaceHolder.addCallback(this);
    }

    @Override
    public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
        try {
            Camera.Parameters parameters = camera.getParameters();
            parameters.setPreviewSize(w, h);
            camera.setParameters(parameters);
        } catch (Exception e) {
            Log.w("CameraView", "Exception:" , e);
        }
        camera.startPreview();
    }


    @Override
    public void surfaceCreated(SurfaceHolder holder) {
        camera = Camera.open();
        try {
            camera.setPreviewDisplay(holder);
        } catch (IOException exception) {
            camera.release();
            camera = null;
        }   
    }

    @Override
    public void surfaceDestroyed(SurfaceHolder arg0) {
        camera.stopPreview();
        camera.release();
        camera = null;
    }
}

The GameRenderer:

public class GameRenderer implements GLSurfaceView.Renderer {

    private final String vertexShaderCode = 
        "uniform mat4 uMVPMatrix;   \n" +
        "attribute vec4 vPosition;  \n" +
        "void main(){               \n" +
            " gl_Position = uMVPMatrix * vPosition; \n" +
        "}  \n";

    private final String fragmentShaderCode = 
        "void main(){                       \n" +
            " gl_FragColor = vec4(1.0, 1.0, 1.0, 0.3); \n" +        
        "}                                  \n";

    private int loadShader(int type, String shaderCode){
        int shader = GLES20.glCreateShader(type); 
        GLES20.glShaderSource(shader, shaderCode);
        GLES20.glCompileShader(shader);        
        return shader;
    }

    // END OF SHADER STUFF

    private int mProgram;
    private int maPositionHandle;
    private int muMVPMatrixHandle;

    private FloatBuffer triangleVB;

    public GameRenderer() {
    }

    public void onSurfaceCreated(GL10 unused, EGLConfig config) {
        GLES20.glClearColor(0,0,0,0); 
        initShapes();
        int vertexShader = loadShader(GLES20.GL_VERTEX_SHADER, vertexShaderCode);
        int fragmentShader = loadShader(GLES20.GL_FRAGMENT_SHADER, fragmentShaderCode);
        mProgram = GLES20.glCreateProgram();            
        GLES20.glAttachShader(mProgram, vertexShader);  
        GLES20.glAttachShader(mProgram, fragmentShader); 
        GLES20.glLinkProgram(mProgram);              
        maPositionHandle = GLES20.glGetAttribLocation(mProgram, "vPosition");
        GLES20.glUseProgram(mProgram);
        MatrixStack.initStack();
    }

    public void onDrawFrame(GL10 unused) {
        GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT | GLES20.GL_DEPTH_BUFFER_BIT);
        drawGround();    
    }

    private void drawGround() {
        GLES20.glVertexAttribPointer(maPositionHandle, 3, GLES20.GL_FLOAT, false, 0, triangleVB);
        GLES20.glEnableVertexAttribArray(maPositionHandle); 
        Matrix.multiplyMM(MatrixStack.getMVPMatrix(), 0, MatrixStack.getMVMatrix(), 0, MatrixStack.getMVMatrix(), 0);
        Matrix.multiplyMM(MatrixStack.getMVPMatrix(), 0, MatrixStack.getPMatrix(), 0, MatrixStack.getMVPMatrix(), 0);
        GLES20.glUniformMatrix4fv(muMVPMatrixHandle, 1, false, MatrixStack.getMVPMatrix(), 0);
        GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, 4);
        GLES20.glDisableVertexAttribArray(maPositionHandle);
    }

    public void onSurfaceChanged(GL10 unused, int width, int height) {
        GLES20.glViewport(0, 0, width, height);
        float ratio = (float) width / height;
        Matrix.frustumM(MatrixStack.getPMatrix(), 0, -ratio, ratio, -1, 1, 1, 1000);
        muMVPMatrixHandle = GLES20.glGetUniformLocation(mProgram, "uMVPMatrix");
        Matrix.setLookAtM(MatrixStack.getMVMatrix(), 0,  0, 0,-1,  0, 0, 0,  0, 1, 0);
    }  

    private void initShapes(){  
        float triangleCoords[] = {
            -15f, -2f,  15f,
             15f, -2f,  15f,
            -15f, -2f, -15f,         
             15f, -2f, -15f
        }; 
        ByteBuffer vbb = ByteBuffer.allocateDirect(triangleCoords.length * 4); 
        vbb.order(ByteOrder.nativeOrder());
        triangleVB = vbb.asFloatBuffer();  
        triangleVB.put(triangleCoords);    
        triangleVB.position(0);            
    }       
}

And a small MatrixStack Class but I don't think there will be a problem here:

public class MatrixStack {

    private static Stack<float[]> matrixStack = new Stack<float[]>();   

    private static float[] MVMatrix = new float[16];
    private static float[] PMatrix = new float[16];
    private static float[] MVPMatrix = new float[16];

    protected static void initStack(){
        float[] basisMatrix = new float[16];
        Matrix.setIdentityM(basisMatrix, 0);
        matrixStack.push(basisMatrix);
        MVMatrix = basisMatrix;
        Matrix.setIdentityM(PMatrix, 0);
    }

    public static float[] getMVMatrix(){
        return MVMatrix; 
    }

    public static float[] getPMatrix(){
        return PMatrix; 
    }

    public static float[] getMVPMatrix(){
        return MVPMatrix; 
    }

}

So well, thats all. Looks like the camera preview is "overexposing" my gl fragment. Please try this code at least. I still hope there is just something wrong with my phone. Thank you anyway for your help, Tobias

Was it helpful?

Solution

Alright, I got an answer for that. The problem was the premultiplication for the alpha values. So in the easiest way it is enough to write:

vec3 color = clamp(textureColor.rgb * lightWeighting.xyz, 0.0, 1.0);
color *= 0.5; // premultiply by alpha
gl_FragColor = vec4(color, 0.5);

Even though I don't see why it worked perfectly fine on older systems and it I'm still not sure how to manage this on Gl1.0 where I can't write my own shader code. So hope this helps to anyone who has the same problem! Thanks, Tobias

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top