0

好吧,這是我的OpenGL問題,我真的無法修復。一切工作正常的Galaxy S1和S2似乎有幾乎相同的GPU。 但是,當我嘗試製作AR-App時,我總是會在我的相機預覽頂部出現透明像素問題。它只在像素透明且看起來像「燒焦的顏色」或值溢出或類似的東西時出現。所以請告訴我我做錯了什麼,或者如果你有S3,請嘗試一下。也許我的只是壞了? 我爲你創建了一個小型測試程序。請看看這個:OpenGL和相機預覽 - 預乘alpha - 混合在一起會得到「過飽和」的顏色

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類,但我不認爲會有成爲一個問題在這裏:

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片段。 請至少嘗試此代碼。我仍然希望我的手機出現問題。 謝謝你的幫助, Tobias

+0

你可以嘗試發佈一個乾淨,容易理解的問題形象?我看到了您在第一篇文章中發佈的圖片,但這非常繁忙,很難分辨發生了什麼。也許就像一個展示這種「過度曝光」的簡單漸變?請顯示您正在混合的兩幅源圖像。 – Tim 2012-08-07 22:02:36

回答

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管理這個我無法編寫自己的着色器代碼。 所以希望這有助於任何有同樣問題的人! 謝謝, 托比亞斯

+0

遇到同樣的問題後,我不覺得你有什麼是真正的解決方案。 您所做的只是通過削弱您嘗試融入相機預覽的顏色來減少「溢出」的情況。 例如,如果您有一個案例,例如某個像素的相機預覽是(1.0,1.0,1.0),並且您想在其上混合某些東西,那麼您仍然會遇到溢出問題。 我想知道這是什麼真正的解決方案... – ZeDuS 2013-08-19 18:22:24

+0

轉到http://www.khronos.org/opengles/sdk/docs/man/ 並選擇: glBlendEquation。 看起來像三星的Galaxy S3根本沒有: 「這些方程的結果被限制在[0,1]範圍內」 – ZeDuS 2013-08-19 18:59:30