Android 如何获得;“提供”;调用GLDraweElements后具有帧缓冲区中glReadPixels的图像

Android 如何获得;“提供”;调用GLDraweElements后具有帧缓冲区中glReadPixels的图像,android,bitmap,opengl-es,Android,Bitmap,Opengl Es,我用OpenGLES2.0的片段着色器修改了一些图像的亮度、对比度和饱和度。而且。。。为了保存修改后的图像,我使用了这种方法 public static Bitmap saveTexture(int texture, int width, int height) { int[] frame = new int[1]; GLES20.glGenFramebuffers(1, frame, 0); GLES20.glBindFramebuffer(GLES20.GL_FRAM

我用OpenGLES2.0的片段着色器修改了一些图像的亮度、对比度和饱和度。而且。。。为了保存修改后的图像,我使用了这种方法

public static Bitmap saveTexture(int texture, int width, int height) {
    int[] frame = new int[1];
    GLES20.glGenFramebuffers(1, frame, 0);
    GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, frame[0]);
    GLES20.glFramebufferTexture2D(GLES20.GL_FRAMEBUFFER, GLES20.GL_COLOR_ATTACHMENT0, GLES20.GL_TEXTURE_2D, texture, 0);

    ByteBuffer buffer = ByteBuffer.allocate(width * height * 4);
    GLES20.glReadPixels(0, 0, width, height, GLES20.GL_RGBA, GLES20.GL_UNSIGNED_BYTE, buffer);
    Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
    bitmap.copyPixelsFromBuffer(buffer);

    GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, 0);
    GLES20.glDeleteFramebuffers(1, frame, 0);

    return bitmap;
}
但是,此方法返回原始图像,而不是修改。怎么了? 请告诉我如何解决这个问题/


我补充了更多的信息。 此代码是我的GLSurfaceView.Renderer代码

@Override
public void onSurfaceCreated(GL10 gl10, EGLConfig eglConfig) {
    mTextureID = OpenGLTools.loadImageTexture(mBitmap, true);
    GLES20.glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
    mProgram = OpenGLTools.loadProgram(VERTEX_SHADER, FRAGMENT_SHADER);
}

@Override
public void onSurfaceChanged(GL10 gl10, int width, int height) {
    GLES20.glViewport(0, 0, width, height);
}

@Override
public void onDrawFrame(GL10 gl10) {
    GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);
    draw();
}

public void draw() {
    if (!GLES20.glIsProgram(mProgram)) OpenGLTools.loadProgram(VERTEX_SHADER, FRAGMENT_SHADER);
    GLES20.glUseProgram(mProgram);

    int positionHandle = GLES20.glGetAttribLocation(mProgram, "position");
    GLES20.glVertexAttribPointer(positionHandle, 3, GLES20.GL_FLOAT, false, 0, mVertexBuffer);
    GLES20.glEnableVertexAttribArray(positionHandle);

    int textureCoordinateHandle = GLES20.glGetAttribLocation(mProgram, "inputTextureCoordinate");
    GLES20.glVertexAttribPointer(textureCoordinateHandle, 2, GLES20.GL_FLOAT, false, 0, mTexCoordBuffer);
    GLES20.glEnableVertexAttribArray(textureCoordinateHandle);

    int brightness = GLES20.glGetUniformLocation(mProgram, "brightness");
    GLES20.glUniform1f(brightness, mEditParams.mBrightness / 200.0f);
    int contrast = GLES20.glGetUniformLocation(mProgram, "contrast");
    GLES20.glUniform1f(contrast, mEditParams.mContrast / 200.0f);
    int saturation = GLES20.glGetUniformLocation(mProgram, "saturation");
    GLES20.glUniform1f(saturation, (mEditParams.mSaturation + 100) / 100.0f);

    GLES20.glDrawElements(GLES20.GL_TRIANGLES, 6, GLES20.GL_UNSIGNED_SHORT, mDrawListBuffer);

    GLES20.glDisableVertexAttribArray(positionHandle);
    GLES20.glDisableVertexAttribArray(textureCoordinateHandle);
}

public Bitmap getBitmap() {
    return OpenGLTools.saveTexture(mTextureID, mBitmap.getWidth(), mBitmap.getHeight());
}
而且。。。这是OpenGLTools类中的代码

public static int loadImageTexture(final Bitmap bitmap, final boolean recycle) {
    int[] textureNames = new int[1];
    GLES20.glGenTextures(1, textureNames, 0);
    GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textureNames[0]);
    GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, bitmap, 0);

    GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_LINEAR);
    GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_LINEAR);
    GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_CLAMP_TO_EDGE);
    GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_CLAMP_TO_EDGE);

    if (recycle) {
        bitmap.recycle();
    }

    return textureNames[0];
}

public static int loadProgram(final String vsc, final String fsc) {
    int[] success = new int[1];

    int vshader = GLES20.glCreateShader(GLES20.GL_VERTEX_SHADER);
    GLES20.glShaderSource(vshader, vsc);
    GLES20.glCompileShader(vshader);
    GLES20.glGetShaderiv(vshader, GLES20.GL_COMPILE_STATUS, success, 0);

    if (success[0] == 0) {
        Log.e("CheckLog", "Could not compile vertex shader : " + GLES20.glGetShaderInfoLog(vshader));
        GLES20.glDeleteShader(vshader);
        return 0;
    }

    int fshader = GLES20.glCreateShader(GLES20.GL_FRAGMENT_SHADER);
    GLES20.glShaderSource(fshader, fsc);
    GLES20.glCompileShader(fshader);
    GLES20.glGetShaderiv(fshader, GLES20.GL_COMPILE_STATUS, success, 0);
    if (success[0] == 0) {
        Log.e("CheckLog", "Could not compile fragment shader : " + GLES20.glGetShaderInfoLog(fshader));
        GLES20.glDeleteShader(fshader);
        return 0;
    }

    int program = GLES20.glCreateProgram();
    GLES20.glAttachShader(program, vshader);
    GLES20.glAttachShader(program, fshader);
    GLES20.glLinkProgram(program);
    GLES20.glGetProgramiv(program, GLES20.GL_LINK_STATUS, success, 0);
    if (success[0] <= 0) {
        Log.e("CheckLog", "Could not link OpenGLES program :" + GLES20.glGetProgramInfoLog(program));
        GLES20.glDeleteProgram(program);
        return 0;
    } else {
        Log.i("CheckLog", "Linked OpenGLES program");
    }

    return program;
}

public static Bitmap saveTexture(int texture, int width, int height) {
    int[] frame = new int[1];
    GLES20.glGenFramebuffers(1, frame, 0);
    GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, frame[0]);
    GLES20.glFramebufferTexture2D(GLES20.GL_FRAMEBUFFER, GLES20.GL_COLOR_ATTACHMENT0, GLES20.GL_TEXTURE_2D, texture, 0);

    ByteBuffer buffer = ByteBuffer.allocate(width * height * 4);
    GLES20.glReadPixels(0, 0, width, height, GLES20.GL_RGBA, GLES20.GL_UNSIGNED_BYTE, buffer);
    Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
    bitmap.copyPixelsFromBuffer(buffer);

    GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, 0);
    GLES20.glDeleteFramebuffers(1, frame, 0);

    return bitmap;
}
public static int loadImageTexture(最终位图、最终布尔循环){
int[]textureNames=新int[1];
GLES20.glGenTextures(1,TextureName,0);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D,TextureName[0]);
GLUtils.texImage2D(GLES20.GL_纹理_2D,0,位图,0);
GLES20.glTexParameteri(GLES20.GL_纹理_2D,GLES20.GL_纹理_MAG_过滤器,GLES20.GL_线性);
GLES20.glTexParameteri(GLES20.GL_纹理_2D,GLES20.GL_纹理_最小_过滤器,GLES20.GL_线性);
GLES20.glTexParameteri(GLES20.GL_纹理_2D、GLES20.GL_纹理_包裹、GLES20.GL_夹紧至边缘);
GLES20.glTexParameteri(GLES20.GL_纹理2D、GLES20.GL_纹理包裹、GLES20.GL_夹紧至边缘);
如果(回收){
bitmap.recycle();
}
返回纹理名称[0];
}
公共静态整数加载程序(最终字符串vsc、最终字符串fsc){
int[]成功=新int[1];
int vshader=GLES20.glCreateShader(GLES20.GL_顶点_着色器);
glShaderSource(vshader,vsc);
GLES20.glCompileShader(vshader);
GLES20.glGetShaderiv(vshader,GLES20.GL_编译状态,成功,0);
如果(成功[0]==0){
Log.e(“CheckLog”,“无法编译顶点着色器:”+GLES20.glGetShaderInfoLog(vshader));
GLES20.glDeleteShader(vshader);
返回0;
}
int fshader=GLES20.glCreateShader(GLES20.GL_片段_着色器);
GLES20.glShaderSource(fshader,fsc);
GLES20.glCompileShader(fshader);
GLES20.glGetShaderiv(fshader,GLES20.GL_编译状态,成功,0);
如果(成功[0]==0){
Log.e(“CheckLog”,“无法编译片段着色器:”+GLES20.glGetShaderInfoLog(fshader));
GLES20.glDeleteShader(fshader);
返回0;
}
int program=GLES20.glCreateProgram();
GLES20.glAttachShader(程序,vshader);
GLES20.glAttachShader(程序,fshader);
GLES20.glLinkProgram(程序);
GLES20.glGetProgramiv(程序,GLES20.GLU链接状态,成功,0);

如果(success[0]将原始纹理句柄作为
texture
参数输入传递到
saveTexture()
,那么这就是要保存回磁盘的数据也就不足为奇了

实际上,您不想保存纹理-您想保存活动帧缓冲区的内容-因此该功能不是代码所需的功能。请尝试此功能:

public static Bitmap saveTexture(int width, int height) {   
    ByteBuffer buffer = ByteBuffer.allocate(width * height * 4);
    GLES20.glReadPixels(0, 0, width, height, GLES20.GL_RGBA, GLES20.GL_UNSIGNED_BYTE, buffer);
    Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
    bitmap.copyPixelsFromBuffer(buffer);      
    return bitmap;
}

你能发布一些相关的代码吗?如果你保存了一些东西,那么上面的代码是有效的,你只是输入了错误的输入,所以错误不在上面的代码中。我添加了相关的代码。请检查。你的代码工作得很好。但是还有一个问题。来自活动帧缓冲区的图像位于因为默认帧缓冲区(活动帧缓冲区),所以整个黑色图像的分辨率很小不大于显示分辨率。因此,我想我需要知道如何将结果图像渲染到大帧缓冲区而不是默认帧缓冲区。如果您知道,请告诉我。无论如何,谢谢。如果您需要渲染大于屏幕的内容,则需要渲染到离屏帧缓冲区。