Take the 2-minute tour ×
Game Development Stack Exchange is a question and answer site for professional and independent game developers. It's 100% free, no registration required.

I'm trying to write some code to do post processing in OpenGL ES2 on the iPhone. All is fine an dandy, except I am having trouble working out how to scale the texture rendered in the rendering step, such that it ends up pixel-aligned to the final image displayed on the screen.

I'm using a 512x512 texture, as provided by Apple's Texture2D class, to store my off screen rendering, and then mapping that onto a quad and rendering to cover the whole screen. The thing ends up taking up half of the screen vertically, more than the width of the screen, and is positioned about 2/3rds of the way down. Here's my setup:

        // Create render to texture targets
        for (int i = 0; i < 2; i++)
        {
            textures[i] = [[Texture2D alloc] initWithData:0 
                                     pixelFormat:kTexture2DPixelFormat_RGBA8888
                                     pixelsWide:512
                                     pixelsHigh:512
                                     contentSize:CGSizeMake(512, 512)];

            // create framebuffer
            glGenFramebuffers(1, &textureFrameBuffers[i]);
            glBindFramebuffer(GL_FRAMEBUFFER, textureFrameBuffers[i]);

            // attach renderbuffer
            glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, textures[i].name, 0);

            // unbind frame buffer
            glBindFramebuffer(GL_FRAMEBUFFER, 0);       
        }
        // Setup our render to texture quad
        // Screen bounds are usually -1 to 1 on both axis, but we 
        // multiply 'y' coords by (2.0/3.0) in the vertex shader so that we
        // get to use a square coordinate system that matches the screen ratio.
        float xSize = 1.0f;
        float ySize = 1.5f;
        quadPoints[0] = -xSize;
        quadPoints[1] = -ySize;
        quadPoints[2] = -xSize;
        quadPoints[3] = ySize;
        quadPoints[4] = xSize;
        quadPoints[5] = -ySize;
        quadPoints[6] = xSize;
        quadPoints[7] = ySize;

I'm doing ping pong rendering, hence the 2 offscreen targets. I've tried fiddling with xSize and ySize to make the thing stretch out beyond the bounds of the screen, such that the texture aligns properly, but can't seem to get it right.

To render with a single post processing step, I do

// Bind to first offscreen framebuffer
glBindFramebuffer(GL_FRAMEBUFFER, textureFrameBuffers[0]);
glViewport(0, 0, backingWidth, backingHeight);

// Render scene

// Bind to the screen framebuffer, and render the previously generated texture through our
// post processing shaders.
GLuint currentProgram = [[postProcessPrograms objectAtIndex:i] intValue];
glUseProgram(currentProgram);
GLuint sourceTexture = (i % 2 == 0)? textures[0].name : textures[1].name;
// Render the texture
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
glEnableVertexAttribArray(ATTRIB_VERTEX);
glVertexAttribPointer(ATTRIB_VERTEX, 2, GL_FLOAT, 0, 0, quadPoints);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);

// Show our buffer
glBindRenderbuffer(GL_RENDERBUFFER, colorRenderbuffer);
[context presentRenderbuffer:GL_RENDERBUFFER];

Any help would be great - I feel like i'm missing something obvious!

share|improve this question

1 Answer 1

It's a bit tricky to tell exactly without seeing your shader, but there are a couple of things you may be able to do differently:

  • Use scale AND bias to control the rendering In effect, this becomes:

    float xSize = 1.0f;
    float ySize = 1.5f;
    float xBias = 0.0f;
    float yBias = 0.5f; // use whatever works, or figure it out analytically.
    quadPoints[0] = -xSize + xBias;
    quadPoints[1] = -ySize + yBias;
    quadPoints[2] = -xSize + xBias;
    quadPoints[3] = ySize + yBias;
    quadPoints[4] = xSize + xBias;
    quadPoints[5] = -ySize + yBias;
    quadPoints[6] = xSize + xBias;
    quadPoints[7] = ySize + yBias;
    

    (play with bias to see how it affects your image)

  • Use texture coordinates to control where on the texture each point in your quad is anchored to. You can specify them in a separate array called texCoords like this:

  texCoords[0] = 0.0f;  // (0,0)
  texCoords[1] = 0.0f;
  texCoords[2] = 0.0f;  // (0,1)
  texCoords[3] = 1.0f;
  texCoords[4] = 1.0f;  // (1,0)
  texCoords[5] = 0.0f;
  texCoords[6] = 1.0f;  // (1,1)
  texCoords[7] = 1.0f;
  glEnableVertexAttribArray(ATTRIB_TEXCOORD)
  glVertexAttribPointer(ATTRIB_TEXCOORD, 2, GL_FLOAT, 0, sizeof(float)*2, texCoords);
.. or you can interleave them in your quadPoints array.

share|improve this answer
    
Thanks! Totally forgot to specify texture coordinates separately. Not entirely sure how it's working - probably forgot to unbind some similar looking ones somewhere else. I think i've been thinking about this the wrong way. When using the 512x512 'texture target', I should be using glViewport with the actual screen dimensions, such that I end up rendering what would normally be displayed to the screen to the screen-sized chunk of the texture target. Then, I can use texture coordinates to properly bind that portion of the texture over the quad, leaving the unused part of the texture off screen. –  Scott Aug 24 '10 at 12:53

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.