Использование FBO больше 256x256 на Android вызывает визуальные артефакты - PullRequest
2 голосов
/ 08 ноября 2011

Я пытаюсь перенести приложение iPhone на Android, и я застрял, пытаясь заставить мой Framebuffer-код работать. Я обнаружил, что всякий раз, когда я использую FBO 512x512 или 1024x1024 на Android, буфер повреждается, что приводит к рисованию множества артефактов. 256x256 FBO работают нормально.

Я создал небольшой проект, который воспроизводит проблему. Вы можете скачать весь проект 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, но все они ведут себя одинаково. Я тестирую Nexus One под управлением 2.3.6.

Рендеринг текстуры 512x512 без FBO работает нормально, поэтому проблема связана с FBO. Я застрял на этом некоторое время - я был бы очень признателен за любую помощь!

1 Ответ

2 голосов
/ 09 ноября 2011

Это действительно странное поведение. Я могу получить правильный рендеринг на своем HTC Desire, если добавлю вызов к glClear в начале onSurfaceCreated. Еще более странным является то, что, по-видимому, не имеет значения, очищается ли только буфер цвета или глубины, оно работает даже при передаче 0 в качестве битовой маски. Я предполагаю, что это только скрывает реальную причину, которая все еще неизвестна.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...