1

I really can't wrap my mind around this:

Previously I couldn't get Framebuffers to work, but I've got it going now. However, there is this incredibly weird mirroring going on with the texture generated from the framebuffer, and I have no idea why. Basically, I will try to draw a texture at 0,0 using GL_TRIANGLE_FAN, and the texture appears as normal (more or less) in the top right corner, but also appears in the bottom left corner, mirrored. If I fill up most or all of my viewport area with the same texture, the result is an ugly z-fighting overlap.

Screenshots will do this more justice.

Original image:

Original http://img301.imageshack.us/img301/1518/testsprite.png

Drawn 80x80 at (0,0)

80x80 http://img407.imageshack.us/img407/8339/screenshot20100106at315.png

Drawn 100x180 at (0,0)

100x180 http://img503.imageshack.us/img503/2584/screenshot20100106at316.png

Drawn 320x480 at (0,0)

320x480 http://img85.imageshack.us/img85/9172/screenshot20100106at317.png

And here is my code:

Set up the view:

//Apply the 2D orthographic perspective.
glViewport(0,0,320,480);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrthof(0, 320, 480, 0, -10000.0f, 100.0f);

//Disable depth testing.
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glDisable(GL_DEPTH_TEST);

//Enable vertext and texture coordinate arrays.
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);

glShadeModel(GL_SMOOTH);

glClearColor(0.5f, 0.5f, 0.5f, 1.0f);   

glGetError(); // Clear error codes

sprite = [Sprite createSpriteFromImage:@"TestSprite.png"];
[sprite retain];

[self createTextureBuffer];

Create the texture buffer.

- (void) createTextureBuffer
{
    // generate texture
    glGenTextures(1, &bufferTexture);
    glBindTexture(GL_TEXTURE_2D, bufferTexture);
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 512, 512, 0,  GL_RGBA, GL_UNSIGNED_BYTE, NULL);     // check if this is right

    // generate FBO
    glGenFramebuffersOES(1, &framebuffer);
    glBindFramebufferOES(GL_FRAMEBUFFER_OES, framebuffer);
    // associate texture with FBO
    glFramebufferTexture2DOES(GL_FRAMEBUFFER_OES, GL_COLOR_ATTACHMENT0_OES, GL_TEXTURE_2D, bufferTexture, 0);

    // clear texture bind
    glBindTexture(GL_TEXTURE_2D,0);

    // check if it worked (probably worth doing :) )
    GLuint status = glCheckFramebufferStatusOES(GL_FRAMEBUFFER_OES);
    if (status != GL_FRAMEBUFFER_COMPLETE_OES)
    {
        printf("FBO didn't work...");
    }   
}

Run the render loop.

- (void)drawView
{
    [self drawToTextureBuffer];

    // Make sure that you are drawing to the current context
    [EAGLContext setCurrentContext:context];

    //Bind the GLView's buffer.
    glBindFramebufferOES(GL_FRAMEBUFFER_OES, viewFramebuffer);
    glViewport(0, 0, 320, 480);

    //Clear the graphics context.
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    //Push the matrix so we can keep it as it was previously.
    glPushMatrix();

    //Rotate to match landscape mode.
    glRotatef(90.0, 0, 0, 1);
    glTranslatef(0.0f, -320.0f, 0.0f);

    //Store the coordinates/dimensions from the rectangle.
    float x = 0.0f;
    float y = 0.0f;
    float w = 480.0f;
    float h = 320.0f;

    // Set up an array of values to use as the sprite vertices.
    GLfloat vertices[] =
    {
        x,  y,
        x,  y+h,
        x+w,    y+h,
        x+w,    y
    };

    // Set up an array of values for the texture coordinates.
    GLfloat texcoords[] =
    {
        0,  0,
        0,  1,
        1,  1,
        0,  1
    };

    //Render the vertices by pointing to the arrays.
    glVertexPointer(2, GL_FLOAT, 0, vertices);
    glTexCoordPointer(2, GL_FLOAT, 0, texcoords);

    // Set the texture parameters to use a linear filter when minifying.
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);

    //Enable 2D textures.
    glEnable(GL_TEXTURE_2D);

    //Bind this texture.
    glBindTexture(GL_TEXTURE_2D, bufferTexture);

    //Finally draw the arrays.
    glDrawArrays(GL_TRIANGLE_FAN, 0, 4);

    //Restore the model view matrix to prevent contamination.
    glPopMatrix();

    GLenum err = glGetError();
    if (err != GL_NO_ERROR)
    {
        NSLog(@"Error on draw. glError: 0x%04X", err);
    }


    glBindRenderbufferOES(GL_RENDERBUFFER_OES, viewRenderbuffer);
    [context presentRenderbuffer:GL_RENDERBUFFER_OES];
}

On the first pass, the render loop will draw the image into the FBO.

- (void)drawToTextureBuffer
{
    if (!bufferWasCreated)
    {
        // render to FBO
        glBindFramebufferOES(GL_FRAMEBUFFER_OES, framebuffer);
        // set the viewport as the FBO isn't be the same dimension as the screen
        glViewport(0, 0, 512, 512);

        glPushMatrix();



        //Store the coordinates/dimensions from the rectangle.
        float x = 0.0f;
        float y = 0.0f;
        float w = 320.0f;
        float h = 480.0f;

        // Set up an array of values to use as the sprite vertices.
        GLfloat vertices[] =
        {
            x,  y,
            x,  y+h,
            x+w,    y+h,
            x+w,    y
        };

        // Set up an array of values for the texture coordinates.
        GLfloat texcoords[] =
        {
            0,  0,
            0,  1,
            1,  1,
            1,  0
        };

        //Render the vertices by pointing to the arrays.
        glVertexPointer(2, GL_FLOAT, 0, vertices);
        glTexCoordPointer(2, GL_FLOAT, 0, texcoords);

        // Set the texture parameters to use a linear filter when minifying.
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);

        //Allow transparency and blending.
        glEnable(GL_BLEND);
        glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

        //Enable 2D textures.
        glEnable(GL_TEXTURE_2D);

        //Bind this texture.
        glBindTexture(GL_TEXTURE_2D, sprite.texture);

        //Finally draw the arrays.
        glDrawArrays(GL_TRIANGLE_FAN, 0, 4);

        //Restore the model view matrix to prevent contamination.
        glPopMatrix();

        GLenum err = glGetError();
        if (err != GL_NO_ERROR)
        {
            NSLog(@"Error on draw. glError: 0x%04X", err);
        }

        //Unbind this buffer.
        glBindFramebufferOES(GL_FRAMEBUFFER_OES, 0);

        bufferWasCreated = YES;
    }
}
4

1 回答 1

5

texcoords的输入 - (void)drawView似乎是错误的

GLfloat texcoords[] =
{
    0,  0,
    0,  1,
    1,  1,
    0,  1     << HERE should be 1, 0
};
于 2010-01-06T23:45:30.647 回答