4

我正在为 iPhone 开发一款涉及绘图/绘画机制的游戏,我在尝试创建一个可以擦除已经绘制的东西的工具时遇到了问题。

主要问题是绘制的背景不是纯色,而是静态图像或动画。我尝试在绘图中使用不同的混合选项和逻辑操作,但似乎没有任何效果。我是 OpenGL 的新手,所以我一定遗漏了一些东西。

有小费吗?

编辑:为了提供更多信息,我正在为我的画笔使用纹理并使用 glVertexPointer() 和 glDrawArrays() 来渲染它们。例如:

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

编辑 2:不幸的是,iPhone 上没有模板缓冲区。: (

编辑 3:iPhone 上提供了 Framebuffer 对象,这就是我所走的路。我还没有完全实现它,但到目前为止它看起来就像我想要的那样工作。谢谢大家!

4

5 回答 5

5

在您的场景上绘制一个全屏纹理四边形。当用户绘制笔触时,使用glTexSubImage2D来更新您的纹理。

glReadPixels/glDrawPixels 很慢。

使用 FrameBufferObjects 甚至更好,但我怀疑 iPhone 上是否有这个扩展(再说一次,我不确定,所以也许试试)。FBO 允许您直接绘制到纹理中,就好像它是另一个渲染上下文一样。

于 2008-11-18T16:24:46.933 回答
4

Stencil Buffer 肯定是解决此问题的最佳方法...您将节省时间、cpu 和潜在问题...,它们在 Iphone 上可用,您只需要创建一个 OpenGLlES 2.0 表面(不是 gles 1.0 或 1.1) .

        //Turn off writing to the Color Buffer and Depth Buffer
        //We want to draw to the Stencil Buffer only
        glColorMask(false, false, false, false);
        glDepthMask(false);

        //Enable the Stencil Buffer
        glEnable(GL_STENCIL_TEST);

        //Set 1 into the stencil buffer
        glStencilFunc(GL_ALWAYS, 1, 0xFFFFFFFF);
        glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE);

        //CALL YOUR DRAWING METHOD HERE


        //Turn on Color Buffer and Depth Buffer
        glColorMask(true, true, true, true);
        glDepthMask(true);

        //Only write to the Stencil Buffer where 1 is set
        glStencilFunc(GL_EQUAL, 1, 0xFFFFFFFF);
        //Keep the content of the Stencil Buffer
        glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);

        //CALL OUR DRAWING METHOD AGAIN

查找此示例: http ://www.opengl.org/resources/code/samples/glut_examples/examples/stenciltst.c

这是视觉结果: http ://www.opengl.org/resources/code/samples/glut_examples/examples/stenciltst.jpg

我已经在安卓和 iPhone 上实现了同样的橡皮擦工具,它就像一个魅力!

祝你好运 !

干杯!

于 2011-05-17T14:20:44.227 回答
2

您没有提供太多信息,但我假设您将它们“绘制”的任何内容存储到缓冲区中,然后将其绘制在屏幕上,如下所示:

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

使用绘图-> ImageData 作为缓冲区。你可以做的是有一个单独的背景缓冲区并首先绘制它。然后擦除工具将简单地将绘图缓冲区变白(将所有值,包括alpha,一直向上)。

要使此解决方案起作用,您必须打开混合并关闭深度测试

 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);

那是你要找的吗?

于 2008-11-15T04:16:10.867 回答
2

您可以使用模板缓冲区进行此操作。模板缓冲区是一个特殊的缓冲区,它保存每个像素的信息,类似于深度缓冲区。与深度缓冲区不同,您可以决定在绘制时如何更改模板缓冲区以及它如何影响是否绘制到颜色缓冲区的决定。为此,您可以在任何绘图操作之前设置特定状态。这是你要做的:

  • 在用户擦除时,将“擦除”区域绘制到模板缓冲区中(使用 StencilOp,见下文)。您可以为此使用任何 GL 绘图功能。

  • 在每个渲染过程中,首先绘制背景(如果需要,可以在此处使用负模板测试仅绘制背景的“已擦除”部分 - 可能会提高性能)。

  • 然后,为所有其他绘图操作启用模板测试。然后,OpenGL 将只绘制到“未擦除”区域。

设置模板缓冲区如何影响绘图(或不影响绘图)的函数:glStencilFunc()

设置模板缓冲区本身如何受绘图影响的函数:glStencilOp()

进一步的解释,以及这些的论点: http ://www.opengl.org/resources/code/samples/sig99/advanced99/notes/node117.html

于 2008-11-16T07:15:50.083 回答
1

使用 glBlendFunc(GL_ONE, GL_ZERO) 模式可以听清楚。

于 2010-07-04T07:06:30.303 回答