views:

1596

answers:

6

I'm working on a game for the iPhone that has a drawing/paint mechanic involved and I'm having problems trying to create a tool that would erase things already painted.

The main problem is that the background being painted on is not a solid color but a static image or animation. I've tried using different blending options and logical operations in drawing but nothing seemed to work. I'm new to OpenGL so I must be missing something.

Any tips?

EDIT: To give a little more information, I'm using textures for my brushes and using glVertexPointer() and glDrawArrays() to render them. For example:

glBindTexture(GL_TEXTURE_2D, circleBrush);
glVertexPointer(3, GL_FLOAT, 0, verts);
glTexCoordPointer(2, GL_FLOAT, 0, coords);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);

EDIT 2: Unfortunately, stencil buffers are not available on the iPhone. : (

EDIT 3: Framebuffer objects are available on the iPhone and that is the road I took. I haven't fully implemented it yet, but so far it looks like it works the way I wanted it to. Thanks everyone!

+2  A: 

You don't give much info, but I assume that your storing whatever they "paint" into a buffer and then drawing it on screen like this:

 glWindowPos2i(X, Y);
 glDrawPixels(drawing->Width, drawing->Height, drawing->Format, 
              GL_UNSIGNED_BYTE, drawing->ImageData);

With drawing->ImageData being the buffer. What you could do is have a separate background buffer and draw it first. Then the erase tool will simply white-out the the drawing buffer(turning all the values, including alpha, all the way up).

For this solution to work you'd have to turn on blending and turn off depth testing.

 glEnable(GL_BLEND);
 glDisable(GL_DEPTH_TEST);
 glWindowPos2i(X, Y);
 //background never changes
 glDrawPixels(background->Width, background->Height, background->Format, 
              GL_UNSIGNED_BYTE, background->ImageData);
 glWindowPos2i(X, Y);
 glDrawPixels(drawing->Width, drawing->Height, drawing->Format, 
              GL_UNSIGNED_BYTE, drawing->ImageData);
 glEnable(GL_DEPTH_TEST);
 glDisable(GL_BLEND);

Is that what you're looking for?

Whaledawg
A: 

You could use the stencil buffer for this operation. The stencil buffer is a special buffer which holds information for every pixel, similiar to the depth buffer. Unlike the depth buffer, you decide how the stencil buffer is altered while drawing and how it influences the decision to draw into the color buffer or not. To do so, you can set the specific states before any drawing operation. Here is what you do:

  • At the time the users erases, draw the "erased" region into the stencil buffer (using StencilOp, see below). You can use any GL drawing function for that.

  • In every rendering pass, first draw the background (if you want, you can use a negative stencil test here to only draw the "erased" part of the background - may increase performance).

  • Then, enable the stencil test for all other drawing operations. OpenGL will then only draw to the "non-erased" regions.

The function to set how the stencil buffer should influence drawing (or not): glStencilFunc()

The function to set how the stencil buffer itself is influenced by drawing: glStencilOp()

Further explanation, also with the arguments for these: http://www.opengl.org/resources/code/samples/sig99/advanced99/notes/node117.html

ypnos
This would have been the perfect solution, but unfortunately Stencil Buffers are not available on the iPhone.
Rijnd
+3  A: 

Draw a full-screen textured quad over your scene. When the user draws a brush stroke, use glTexSubImage2D to update the your texture.

glReadPixels/glDrawPixels is slow.

Using FrameBufferObjects is even better, but I doubt this extention is available on the iPhone (then again, I don't know for sure, so maybe try it). FBO's allow you to draw directly into a texture as if it were another rendering context.

Do you have code examples of either of these? It would be much appreciated
Erika
A: 

Hey there, I am trying to accomplish something similar, how did you end up implementing this?

Did you figure this out?
Erika
A: 

you did create erase tool?

if you did, can you help me? because i am doing same functionality.

i have two overlapping image. when i move my finger on top of the image that part should be erase and underlining image should be display.

i was trying before one week but i did not got success.

Can you help me?

Thank you

milanjansari
Did you figure this out?
Erika
A: 

Using glBlendFunc(GL_ONE, GL_ZERO) mode can earse.