我如何在GLPaint中绘制背景图片和临时图纸?
我正在为iPad编写一个GLPaint-esque绘图应用程序,但是我碰到了一个绊脚石。 具体来说,我现在正在努力实现两件事情:
1)可以绘制到的背景图像。
2)绘制临时形状的能力,例如你可以绘制一条线,但最终的形状只有在手指抬起之后才能完成。
对于背景图片,我明白这个想法是将图像绘制到VBO中,然后在每一行绘制之前绘制图像。 这是好的,但现在我需要添加绘制临时形状的能力…与kEAGLDrawablePropertyRetainedBacking设置为YES(如在GLPaint)临时显然不是临时的! 将保留的背景属性设置为NO对临时对象非常有用,但是现在我以前的徒手画线没有保留。
这里最好的办法是什么? 我是否应该使用多个EAGLLayer? 我发现的所有文档和教程似乎都表明,大多数情况下,应该可以使用单层。 他们还说,保留的支持应该总是设置为NO。 有没有办法在这样的configuration中工作我的应用程序? 我尝试将每个绘图点存储到不断扩展的顶点数组中,以便重绘每个框架,但是由于绘制的精灵数量太多,所以无法正常工作。
我真的很感激任何帮助,因为我在网上search,没有发现任何东西!
我从那以后find了解决这个问题的办法。 最好的方法似乎是使用自定义帧缓冲区对象和渲染到纹理。 在提出这个问题之前,我还没有听说过这个,但是对于OpenGLer工具箱来说,它看起来是一个非常有用的工具!
对于那些可能想要做类似的事情,这个想法是,你创build一个FBO并附加一个纹理(而不是一个渲染缓冲区)。 然后,你可以绑定这个FBO并像其他任何东西一样绘制它,唯一的区别是绘图在屏幕外渲染。 然后,所有你需要做的显示纹理是绑定主FBO和绘制纹理(使用一个四边形)。
所以在我的实现中,我使用了两个不同的FBO,每个FBO都有一个用于“保留”的图像(用于徒手绘制),另一个用于“临时”图像(用于临时graphics)。 每次渲染一个框架,我首先绘制一个背景纹理(在我的情况下,我只是使用了Texture2D类),然后绘制保留的纹理,最后如果需要绘制划痕纹理。 绘制临时形状时,所有内容都将渲染到划痕纹理,并在每帧的开始时清除。 一旦完成,划痕纹理被绘制到保留的纹理。
以下是可能对某人使用的一些代码片段:
1)创build帧缓冲区(我只显示一对夫妇在这里节省空间!):
// ---------- DEFAULT FRAMEBUFFER ---------- // // Create framebuffer. glGenFramebuffersOES(1, &viewFramebuffer); glBindFramebufferOES(GL_FRAMEBUFFER_OES, viewFramebuffer); // Create renderbuffer. glGenRenderbuffersOES(1, &viewRenderbuffer); glBindRenderbufferOES(GL_RENDERBUFFER_OES, viewRenderbuffer); // Get renderbuffer storage and attach to framebuffer. [context renderbufferStorage:GL_RENDERBUFFER_OES fromDrawable:layer]; glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_COLOR_ATTACHMENT0_OES, GL_RENDERBUFFER_OES, viewRenderbuffer); glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES, GL_RENDERBUFFER_WIDTH_OES, &backingWidth); glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES, GL_RENDERBUFFER_HEIGHT_OES, &backingHeight); // Check for completeness. status = glCheckFramebufferStatusOES(GL_FRAMEBUFFER_OES); if (status != GL_FRAMEBUFFER_COMPLETE_OES) { NSLog(@"Failed to make complete framebuffer object %x", status); return NO; } // Unbind framebuffer. glBindFramebufferOES(GL_FRAMEBUFFER_OES, 0); // ---------- RETAINED FRAMEBUFFER ---------- // // Create framebuffer. glGenFramebuffersOES(1, &retainedFramebuffer); glBindFramebufferOES(GL_FRAMEBUFFER_OES, retainedFramebuffer); // Create the texture. glColor4f(0.0f, 0.0f, 0.0f, 0.0f); glGenTextures(1, &retainedTexture); glEnable(GL_TEXTURE_2D); glBindTexture(GL_TEXTURE_2D, retainedTexture); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1024, 1024, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glBindTexture(GL_TEXTURE_2D, 0); // Attach the texture as a renderbuffer. glFramebufferTexture2DOES(GL_FRAMEBUFFER_OES, GL_COLOR_ATTACHMENT0_OES, GL_TEXTURE_2D, retainedTexture, 0); // Check for completeness. status = glCheckFramebufferStatusOES(GL_FRAMEBUFFER_OES); if (status != GL_FRAMEBUFFER_COMPLETE_OES) { NSLog(@"Failed to make complete framebuffer object %x", status); return NO; } // Unbind framebuffer. glBindFramebufferOES(GL_FRAMEBUFFER_OES, 0);
2)绘制到渲染到纹理的FBO:
// Ensure that we are drawing to the current context. [EAGLContext setCurrentContext:context]; glBindFramebufferOES(GL_FRAMEBUFFER_OES, retainedFramebuffer); glViewport(0, 0, 1024, 1024); // DRAWING CODE HERE
3)将各种纹理呈现给主FBO,并呈现:
glBindFramebufferOES(GL_FRAMEBUFFER_OES, viewFramebuffer); glViewport(0, 0, backingWidth, backingHeight); glClearColor(1.0f, 1.0f, 1.0f, 1.0f); // Clear to white. glClear(GL_COLOR_BUFFER_BIT); glEnableClientState(GL_VERTEX_ARRAY); glEnableClientState(GL_TEXTURE_COORD_ARRAY); [self drawBackgroundTexture]; [self drawRetainedTexture]; [self drawScratchTexture]; glDisableClientState(GL_VERTEX_ARRAY); glDisableClientState(GL_TEXTURE_COORD_ARRAY); glBindRenderbufferOES(GL_RENDERBUFFER_OES, viewRenderbuffer); [context presentRenderbuffer:GL_RENDERBUFFER_OES];
例如,使用[self drawRetainedTexture]
绘制绘制保留的纹理将使用以下代码:
// Bind the texture. glBindTexture(GL_TEXTURE_2D, retainedTexture); // Destination coords. GLfloat retainedVertices[] = { 0.0, backingHeight, 0.0, backingWidth, backingHeight, 0.0, 0.0, 0.0, 0.0, backingWidth, 0.0, 0.0 }; // Source coords. GLfloat retainedTexCoords[] = { 0.0, 1.0, 1.0, 1.0, 0.0, 0.0, 1.0, 0.0 }; // Draw the texture. glVertexPointer(3, GL_FLOAT, 0, retainedVertices); glTexCoordPointer(2, GL_FLOAT, 0, retainedTexCoords); glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); // Unbind the texture. glBindTexture(GL_TEXTURE_2D, 0);
很多代码,但我希望能帮助别人。 这肯定让我难住了一段时间!