在Android上使用大于256x256的FBO会导致视觉瑕疵

时间:2011-11-07 21:47:20

标签: android opengl-es

我正在尝试将iPhone应用程序移植到Android上,而我却试图让我的Framebuffer代码正常工作。我发现,无论何时我在Android上使用512x512或1024x1024 FBO,缓冲区都会被破坏,从而导致大量工件被绘制。 256x256 FBO工作正常。

我已经建立了一个可以重现问题的小项目。您可以通过this link下载整个repro项目,但我也在这里粘贴了重要的部分:

class GLRenderer implements GLSurfaceView.Renderer {

    int TextureID;
    int FrameBufferID;

    public void onSurfaceCreated(GL10 gl, EGLConfig config) {

        //Create texture
        int[] buf = new int[1];
        gl.glGenTextures(1, buf, 0);
        TextureID = buf[0];

        gl.glBindTexture(GL11.GL_TEXTURE_2D, TextureID);
        gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER, GL10.GL_NEAREST);
        gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER, GL10.GL_LINEAR);

        //Render our jpeg into the texture as the background
        GLUtils.texImage2D(GL11.GL_TEXTURE_2D, 0, FBOTestActivity.BackgroundBitmap, 0);

        GL11ExtensionPack gl11ep = (GL11ExtensionPack) gl;

        //Create a framebuffer
        gl11ep.glGenFramebuffersOES(1, buf, 0);
        FrameBufferID = buf[0];

        gl11ep.glBindFramebufferOES(GLES11Ext.GL_FRAMEBUFFER_OES, FrameBufferID);
        gl11ep.glFramebufferTexture2DOES(GLES11Ext.GL_FRAMEBUFFER_OES, GLES11Ext.GL_COLOR_ATTACHMENT0_OES, GL11.GL_TEXTURE_2D, TextureID, 0);

        //Render a rectangle into the framebuffer
        gl.glMatrixMode(GL11.GL_PROJECTION);
        gl.glLoadIdentity();
        gl.glOrthof(0, FBOTestActivity.Size, 0, FBOTestActivity.Size, -1, 1);
        gl.glMatrixMode(GL11.GL_MODELVIEW);
        gl.glViewport(0,0, FBOTestActivity.Size, FBOTestActivity.Size);

        gl.glVertexPointer(2, GL11.GL_FLOAT, 0, MakeBuffer(new float[] { 64, 64, 192, 64, 64, 192, 192,192 }));
        gl.glEnableClientState(GL11.GL_VERTEX_ARRAY); 
        gl.glDrawArrays(GL11.GL_TRIANGLE_STRIP, 0, 4);

        //Unbind
        gl11ep.glBindFramebufferOES(GLES11Ext.GL_FRAMEBUFFER_OES, 0);
    }

    public void onSurfaceChanged(GL10 gl, int w, int h) {
        gl.glViewport(0, 0, w, h);
    }

    private FloatBuffer MakeBuffer(float[] arr)
    {
        ByteBuffer vbb = ByteBuffer.allocateDirect(2 * 4 * 8);
        vbb.order(ByteOrder.nativeOrder());
        FloatBuffer fb = vbb.asFloatBuffer();
        fb.put(arr);
        fb.position(0);
        return fb;
    }

    public void onDrawFrame(GL10 gl) {
        gl.glMatrixMode(GL11.GL_PROJECTION); 
        gl.glLoadIdentity();
        gl.glOrthof(0f, 1.0f, 1f, 0f, -1.0f, 1.0f);
        gl.glMatrixMode(GL11.GL_MODELVIEW);

        gl.glClearColor(255, 0,0, 255);
        gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);

        //Just render the texture.  It should show our background with a white rectangle in front.
        gl.glEnableClientState(GL11.GL_VERTEX_ARRAY);
        gl.glEnableClientState(GL11.GL_TEXTURE_COORD_ARRAY);

        gl.glEnable(GL11.GL_TEXTURE_2D);
        gl.glBindTexture(GL11.GL_TEXTURE_2D, TextureID);
        gl.glVertexPointer(2, GL11.GL_FLOAT, 0, MakeBuffer(new float[] { 0, 0, 0, 1, 1, 0, 1, 1 }));
        gl.glTexCoordPointer(2, GL11.GL_FLOAT, 0, MakeBuffer(new float[] {0, 0, 0, 1, 1, 0, 1, 1}));
        gl.glDrawArrays(GL11.GL_TRIANGLE_STRIP, 0, 4);

    }
}

如果我在256x256纹理上运行它,一切都很好,我看到了:

如果我使用512x512纹理(或1024x1024)运行它,我会看到:

OpenGL没有返回任何错误,并且此代码在iPhone上正常运行。我尝试过Android 2.1,2.2和2.3,但它们都表现得一样。我在运行2.3.6的Nexus One上进行测试。

在没有FBO的情况下自行渲染512x512纹理可以正常工作,因此问题与FBO有关。我已经坚持了一段时间 - 我非常感谢任何帮助!

1 个答案:

答案 0 :(得分:2)

这确实是一种奇怪的行为。如果我在glClear的开头添加对onSurfaceCreated的调用,我可以在我的HTC Desire上获得正确的渲染。更奇怪的是,如果仅清除颜色或深度缓冲区似乎并不重要,它甚至在将0作为位掩码时起作用。我猜这只是隐藏了仍然未知的真正原因。