OpenGL和相机预览 - 预乘alpha - 混合在一起得到“过饱和”的颜色

时间:2012-08-07 15:44:38

标签: opengl-es-2.0 android-camera galaxy glsurfaceview premultiplied-alpha

好的,这是我的OpenGL问题我真的无法解决。 Galaxy S1和S2上的一切都运行良好,似乎有几乎相同的GPU。 但是当我尝试制作AR-App时,我总是会在相机预览的顶部出现透明像素问题。它只出现在像素是透明的并且看起来像“烧焦的颜色”或值溢出或类似的东西时。所以请告诉我我做错了什么,或者如果你有S3就试试看。也许我刚刚破了? 我为你创建了一个小的测试程序。请看一下:

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();
    }
}

CameraView看起来像这样:

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;
    }
}

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);            
    }       
}

还有一个小型的MatrixStack Class,但我不认为这里会出现问题:

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; 
    }

}

好吧,就是这样。看起来相机预览是“过度曝光”我的gl片段。 请至少尝试此代码。我仍然希望手机出现问题。 无论如何,谢谢你的帮助,  托拜厄斯

1 个答案:

答案 0 :(得分:2)

好的,我得到了答案。 问题是alpha值的预乘。 所以用最简单的方式来写:

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

即使我不明白为什么它在旧系统上运行得很好而且我仍然不确定如何在Gl1.0上管理它,我无法编写自己的着色器代码。 所以希望这有助于任何有同样问题的人! 谢谢,  托拜厄斯