4

I’m working on a kind of iPhone game where player travels through programmically generated wormhole. To draw the wormhole I chose to draw to arrays of textured vertical lines a pixel width to implement top and bottom walls of the wormhole. Every frame all the lines must be shifted left to implement the player movement and new lines must be drown in free space at right. But drawing 1000 textured rectangles every frame is killing my FPS. And I’m looking for a solution to save all the lines that was drown at previous frame and redraw them altogether to the new shifted position. It would be terrific if there is a way to draw textured rectangles in some kind of buffer that is bigger than screen, and then render this buffer to the screen.

I guest these are newbie questions cause I’m totally new in OpenGL. I spent hours trying to figure this out, but haven’t succeeded. So Any help appreciated.

genpfault
  • 51,148
  • 11
  • 85
  • 139
Marmot
  • 117
  • 8

2 Answers2

3

To expand on @Jerry's answer, I'll walk you through the steps, since you're new. First, we'll create the frame buffer object:

GLuint framebuffer;
glGenFramebuffersOES(1, &framebuffer);
glBindFramebufferOES(GL_FRAMEBUFFER_OES, framebuffer);

Next, we'll create the empty texture to hold our snapshot. This is just the usual OpenGL texture creation stuff, and you can modify it to fit your needs, of course. The only line to notice is the glTexImage2D line - note that instead of pixel data as the last coordinate, you can pass NULL, which creates an empty texture.

GLuint texture;
glGenTextures(1, &texture);

glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, texture);

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);

glBindTexture(GL_TEXTURE_2D, 0);
glDisable(GL_TEXTURE_2D);

Now we bind the texture to the frame buffer:

glFramebufferTexture2DOES(GL_FRAMEBUFFER_OES, GL_COLOR_ATTACHMENT0_OES, GL_TEXTURE_2D, texture, 0);

and check to see if everything went OK:

if(glCheckFramebufferStatusOES(GL_FRAMEBUFFER_OES) != GL_FRAMEBUFFER_COMPLETE_OES)
    return false; // uh oh, something went wrong

Now we're all set up to draw!

glBindFramebufferOES(GL_FRAMEBUFFER_OES, framebuffer);
// do drawing here
glBindFramebufferOES(GL_FRAMEBUFFER_OES, 0);

And finally, clean up the frame buffer, if you don't need it any more:

glDeleteFramebuffersOES(1, &framebuffer);

Some caveats:

  1. The size of the frame buffer must be a power-of-two.
  2. You can go up to 1024x1024 on the latest iPhone, but there may be no need to have that level of detail.
Jesse Beder
  • 33,081
  • 21
  • 109
  • 146
  • Actually, there is an extension to OpenGL ES 1.1 that lets the newer iOS devices support non-power-of-two textures: http://stackoverflow.com/questions/4760174/rendering-to-non-power-of-two-texture-on-iphone/4761453#4761453 , and the 1024x1024 texture size has been supported since the original iPhone, not just the newer devices. In fact, in my testing I was able to go up to 2048x2048 on even the original iPhone, despite what the documentation says. – Brad Larson Feb 14 '11 at 16:24
1

Offhand I don't know the exact size that'll be available on a particular model of iPhone, but the general idea would be to use a Frame Buffer Object (FBO) to render to a texture, then you can blit pieces from that texture to the screen buffer.

Jerry Coffin
  • 476,176
  • 80
  • 629
  • 1,111