2011-09-27 30 views
0

我想通过不在渲染缓冲区或帧缓冲区上调用glClear来保存Open GL ES2应用程序中屏幕上呈现的任何内容。Android GL ES2缓冲区问题:乱码数据

这对物理Nook颜色一直工作正常。但是当运行在物理的Nexus One(运行Android 2.3.6)时,我得到了第一次渲染之后缓冲区内容出现乱码的问题。为了便于说明,下面的屏幕显示了Nexus One和Nook Color中相同的代码的外观。该代码几乎是从com.example.android.apis.graphics.GLES20TriangleRenderer(第8级示例源代码集)逐字记录的。

/* 
* Copyright (C) 2009 The Android Open Source Project 
* 
* Licensed under the Apache License, Version 2.0 (the "License"); 
* you may not use this file except in compliance with the License. 
* You may obtain a copy of the License at 
* 
*  http://www.apache.org/licenses/LICENSE-2.0 
* 
* Unless required by applicable law or agreed to in writing, software 
* distributed under the License is distributed on an "AS IS" BASIS, 
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
* See the License for the specific language governing permissions and 
* limitations under the License. 
*/ 

package com.example.android.apis.graphics; 

import java.io.IOException; 
import java.io.InputStream; 
import java.nio.ByteBuffer; 
import java.nio.ByteOrder; 
import java.nio.FloatBuffer; 

import javax.microedition.khronos.egl.EGLConfig; 
import javax.microedition.khronos.opengles.GL10; 

import android.content.Context; 
import android.graphics.Bitmap; 
import android.graphics.BitmapFactory; 
import android.opengl.GLES20; 
import android.opengl.GLSurfaceView; 
import android.opengl.GLUtils; 
import android.opengl.Matrix; 
import android.os.SystemClock; 
import android.util.Log; 

import com.example.android.apis.R; 

class GLES20TriangleRenderer implements GLSurfaceView.Renderer { 

public GLES20TriangleRenderer(Context context) { 
    mContext = context; 
    mTriangleVertices = ByteBuffer.allocateDirect(mTriangleVerticesData.length 
      * FLOAT_SIZE_BYTES).order(ByteOrder.nativeOrder()).asFloatBuffer(); 
    mTriangleVertices.put(mTriangleVerticesData).position(0); 
} 

public void onDrawFrame(GL10 glUnused) { 
    // Ignore the passed-in GL10 interface, and use the GLES20 
    // class's static methods instead. 
    GLES20.glClearColor(0.0f, 0.0f, 1.0f, 1.0f); 
    GLES20.glClear(GLES20.GL_DEPTH_BUFFER_BIT | GLES20.GL_COLOR_BUFFER_BIT); 
    GLES20.glUseProgram(mProgram); 
    checkGlError("glUseProgram"); 

    GLES20.glActiveTexture(GLES20.GL_TEXTURE0); 
    GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mTextureID); 

    mTriangleVertices.position(TRIANGLE_VERTICES_DATA_POS_OFFSET); 
    GLES20.glVertexAttribPointer(maPositionHandle, 3, GLES20.GL_FLOAT, false, 
      TRIANGLE_VERTICES_DATA_STRIDE_BYTES, mTriangleVertices); 
    checkGlError("glVertexAttribPointer maPosition"); 
    mTriangleVertices.position(TRIANGLE_VERTICES_DATA_UV_OFFSET); 
    GLES20.glEnableVertexAttribArray(maPositionHandle); 
    checkGlError("glEnableVertexAttribArray maPositionHandle"); 
    GLES20.glVertexAttribPointer(maTextureHandle, 2, GLES20.GL_FLOAT, false, 
      TRIANGLE_VERTICES_DATA_STRIDE_BYTES, mTriangleVertices); 
    checkGlError("glVertexAttribPointer maTextureHandle"); 
    GLES20.glEnableVertexAttribArray(maTextureHandle); 
    checkGlError("glEnableVertexAttribArray maTextureHandle"); 

    long time = SystemClock.uptimeMillis() % 4000L; 
    float angle = 0.090f * ((int) time); 
    Matrix.setRotateM(mMMatrix, 0, angle, 0, 0, 1.0f); 
    Matrix.multiplyMM(mMVPMatrix, 0, mVMatrix, 0, mMMatrix, 0); 
    Matrix.multiplyMM(mMVPMatrix, 0, mProjMatrix, 0, mMVPMatrix, 0); 

    GLES20.glUniformMatrix4fv(muMVPMatrixHandle, 1, false, mMVPMatrix, 0); 
    GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, 3); 
    checkGlError("glDrawArrays"); 
} 

public void onSurfaceChanged(GL10 glUnused, int width, int height) { 
    // Ignore the passed-in GL10 interface, and use the GLES20 
    // class's static methods instead. 
    GLES20.glViewport(0, 0, width, height); 
    float ratio = (float) width/height; 
    Matrix.frustumM(mProjMatrix, 0, -ratio, ratio, -1, 1, 3, 7); 
} 

public void onSurfaceCreated(GL10 glUnused, EGLConfig config) { 
    // Ignore the passed-in GL10 interface, and use the GLES20 
    // class's static methods instead. 
    mProgram = createProgram(mVertexShader, mFragmentShader); 
    if (mProgram == 0) { 
     return; 
    } 
    maPositionHandle = GLES20.glGetAttribLocation(mProgram, "aPosition"); 
    checkGlError("glGetAttribLocation aPosition"); 
    if (maPositionHandle == -1) { 
     throw new RuntimeException("Could not get attrib location for aPosition"); 
    } 
    maTextureHandle = GLES20.glGetAttribLocation(mProgram, "aTextureCoord"); 
    checkGlError("glGetAttribLocation aTextureCoord"); 
    if (maTextureHandle == -1) { 
     throw new RuntimeException("Could not get attrib location for aTextureCoord"); 
    } 

    muMVPMatrixHandle = GLES20.glGetUniformLocation(mProgram, "uMVPMatrix"); 
    checkGlError("glGetUniformLocation uMVPMatrix"); 
    if (muMVPMatrixHandle == -1) { 
     throw new RuntimeException("Could not get attrib location for uMVPMatrix"); 
    } 

    /* 
    * Create our texture. This has to be done each time the 
    * surface is created. 
    */ 

    int[] textures = new int[1]; 
    GLES20.glGenTextures(1, textures, 0); 

    mTextureID = textures[0]; 
    GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mTextureID); 

    GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, 
      GLES20.GL_NEAREST); 
    GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, 
      GLES20.GL_TEXTURE_MAG_FILTER, 
      GLES20.GL_LINEAR); 

    GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_S, 
      GLES20.GL_REPEAT); 
    GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_T, 
      GLES20.GL_REPEAT); 

    InputStream is = mContext.getResources() 
     .openRawResource(R.raw.robot); 
    Bitmap bitmap; 
    try { 
     bitmap = BitmapFactory.decodeStream(is); 
    } finally { 
     try { 
      is.close(); 
     } catch(IOException e) { 
      // Ignore. 
     } 
    } 

    GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, bitmap, 0); 
    bitmap.recycle(); 

    Matrix.setLookAtM(mVMatrix, 0, 0, 0, -5, 0f, 0f, 0f, 0f, 1.0f, 0.0f); 
} 

private int loadShader(int shaderType, String source) { 
    int shader = GLES20.glCreateShader(shaderType); 
    if (shader != 0) { 
     GLES20.glShaderSource(shader, source); 
     GLES20.glCompileShader(shader); 
     int[] compiled = new int[1]; 
     GLES20.glGetShaderiv(shader, GLES20.GL_COMPILE_STATUS, compiled, 0); 
     if (compiled[0] == 0) { 
      Log.e(TAG, "Could not compile shader " + shaderType + ":"); 
      Log.e(TAG, GLES20.glGetShaderInfoLog(shader)); 
      GLES20.glDeleteShader(shader); 
      shader = 0; 
     } 
    } 
    return shader; 
} 

private int createProgram(String vertexSource, String fragmentSource) { 
    int vertexShader = loadShader(GLES20.GL_VERTEX_SHADER, vertexSource); 
    if (vertexShader == 0) { 
     return 0; 
    } 

    int pixelShader = loadShader(GLES20.GL_FRAGMENT_SHADER, fragmentSource); 
    if (pixelShader == 0) { 
     return 0; 
    } 

    int program = GLES20.glCreateProgram(); 
    if (program != 0) { 
     GLES20.glAttachShader(program, vertexShader); 
     checkGlError("glAttachShader"); 
     GLES20.glAttachShader(program, pixelShader); 
     checkGlError("glAttachShader"); 
     GLES20.glLinkProgram(program); 
     int[] linkStatus = new int[1]; 
     GLES20.glGetProgramiv(program, GLES20.GL_LINK_STATUS, linkStatus, 0); 
     if (linkStatus[0] != GLES20.GL_TRUE) { 
      Log.e(TAG, "Could not link program: "); 
      Log.e(TAG, GLES20.glGetProgramInfoLog(program)); 
      GLES20.glDeleteProgram(program); 
      program = 0; 
     } 
    } 
    return program; 
} 

private void checkGlError(String op) { 
    int error; 
    while ((error = GLES20.glGetError()) != GLES20.GL_NO_ERROR) { 
     Log.e(TAG, op + ": glError " + error); 
     throw new RuntimeException(op + ": glError " + error); 
    } 
} 

private static final int FLOAT_SIZE_BYTES = 4; 
private static final int TRIANGLE_VERTICES_DATA_STRIDE_BYTES = 5 * FLOAT_SIZE_BYTES; 
private static final int TRIANGLE_VERTICES_DATA_POS_OFFSET = 0; 
private static final int TRIANGLE_VERTICES_DATA_UV_OFFSET = 3; 
private final float[] mTriangleVerticesData = { 
     // X, Y, Z, U, V 
     -1.0f, -0.5f, 0, -0.5f, 0.0f, 
     1.0f, -0.5f, 0, 1.5f, -0.0f, 
     0.0f, 1.11803399f, 0, 0.5f, 1.61803399f }; 

private FloatBuffer mTriangleVertices; 

private final String mVertexShader = 
    "uniform mat4 uMVPMatrix;\n" + 
    "attribute vec4 aPosition;\n" + 
    "attribute vec2 aTextureCoord;\n" + 
    "varying vec2 vTextureCoord;\n" + 
    "void main() {\n" + 
    " gl_Position = uMVPMatrix * aPosition;\n" + 
    " vTextureCoord = aTextureCoord;\n" + 
    "}\n"; 

private final String mFragmentShader = 
    "precision mediump float;\n" + 
    "varying vec2 vTextureCoord;\n" + 
    "uniform sampler2D sTexture;\n" + 
    "void main() {\n" + 
    " gl_FragColor = texture2D(sTexture, vTextureCoord);\n" + 
    "}\n"; 

private float[] mMVPMatrix = new float[16]; 
private float[] mProjMatrix = new float[16]; 
private float[] mMMatrix = new float[16]; 
private float[] mVMatrix = new float[16]; 

private int mProgram; 
private int mTextureID; 
private int muMVPMatrixHandle; 
private int maPositionHandle; 
private int maTextureHandle; 

private Context mContext; 
private static String TAG = "GLES20TriangleRenderer"; 

}

不同的是,我除去glClear呼叫所以它成为这样的:

public void onDrawFrame(GL10 glUnused) { 
    // Ignore the passed-in GL10 interface, and use the GLES20 
    // class's static methods instead. 
    //GLES20.glClearColor(0.0f, 0.0f, 1.0f, 1.0f); 
    GLES20.glClear(GLES20.GL_DEPTH_BUFFER_BIT);// | GLES20.GL_COLOR_BUFFER_BIT); 

该代码基本上旋转在中心的矩形。我也尝试渲染纹理渲染缓冲区,然后渲染渲染缓冲区纹理,并遇到相同的结果(渲染缓冲区在第一次调用GLES20.glDrawArrays后出现乱码,结果与坏屏幕截图非常相似)。

我是ES2的新手。我究竟做错了什么?

坏(在Nexus One):http://www.putpix.com/b/files/2849/devicebad.png

好(上Nook Color的):http://www.putpix.com/b/files/2849/devicegood.png

回答

0

如果不通话清晰,结果是不确定的。

特别是,屏幕通常是双缓冲的,所以你的程序会看到在不同时间出现的多个缓冲区。也没有义务缓冲区有史以来是你以前见过的相同。