如何获得“渲染"?调用glDrawElements之后从FrameBuffer用glReadPixels生成图像 [英] How to get "rendered" image with glReadPixels from FrameBuffer after calling glDrawElements

查看:88
本文介绍了如何获得“渲染"?调用glDrawElements之后从FrameBuffer用glReadPixels生成图像的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我通过OpenGL ES 2.0的片段着色器修改了某些图像的亮度,对比度和饱和度.还有...为了保存修改后的图像,我使用了这种方法.

I modified brightness, contrast, and saturation of some image by fragment shader of OpenGL ES 2.0. And... to save modified image, I used this method.

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

但是,此方法返回原始图像,未修改.怎么了?请告诉我如何解决此问题.:/

But, this method return the original image, not modified. What is wrong? Please advise me how to resolve this. :/

我添加了更多信息.这段代码是我的GLSurfaceView.Renderer的代码.

I added more information. This code is my GLSurfaceView.Renderer's code.

@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类中的代码.

And... this is the code in OpenGLTools class.

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

如果我触摸保存"按钮,则会在OpenGLES上下文中调用 getBitmap 方法.我可以更改 Bitmap 的参数(亮度,对比度和饱和度),并实时显示在显示屏上.但是,当我触摸保存按钮时,更改的参数不会应用到保存的图像.我想使用更改后的参数保存图像.

If I touch save button, getBitmap method is called in the OpenGLES context. I can change the Bitmap's parameters(brightness, contrast and saturation) and it shows up on display in real time. However, changed parameters are not applied the saved image when I touch the save button. I want to save the image with changed parameters.

推荐答案

您要将原始纹理句柄作为输入 saveTexture() texture 参数传递,因此毫不奇怪,这就是您要保存回磁盘的数据.

You're passing the original texture handle as the texture parameter input into saveTexture(), so it's no surprise that that is the data you are saving back to disk.

您实际上并不想保存纹理-您想要保存活动帧缓冲区的内容-因此该功能不是您的代码所需要的.试试这个:

You don't actually want to save a texture - you want to save the contents of the active framebuffer - so that function isn't what your code needs. Try this one:

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

这篇关于如何获得“渲染"?调用glDrawElements之后从FrameBuffer用glReadPixels生成图像的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆