2010-10-29 22 views
8

作为修改GLPaint的一部分,我试图添加擦除功能,用户可以在其中选择一个橡皮擦按钮并将绘制区域与绘画一样擦除。在GLPaint中使用笔刷清除

我想在"renderLineFromPoint:(CGPoint)start toPoint:(CGPoint)end"方法中有一个条件语句,以便我可以检查笔画是用于绘画还是擦除。

对于擦除,我不知道如何使用“start”和“end”参数进行擦除。是否有任何方法调用OpenGL像glClear()接受这两个参数,并擦除?

任何指针都会非常有帮助。谢谢。

+0

可行吗? – blacky 2010-10-29 04:27:20

+0

的确是这样,在我的绘画应用程序 – thgc 2012-10-06 13:15:33

回答

9

除了同样为Erase using brush in GLPaint,可以通过具有条件重用

- (void)renderLineFromPoint:(CGPoint)start toPoint:(CGPoint)end 

方法

// Render the vertex array 
glVertexPointer(2, GL_FLOAT, 0, eraseBuffer); 
glDrawArrays(GL_POINTS, 0, vertexCount); 

注意,你”需要实现isEraserBrushType,并存储brushColourRed,brushColourGreen和brushColourBl不知何故。

+1

它带有长方形刷(我认为它的画笔图像大小 - 64/64)删除,不与当前的画笔图像。任何想法是为什么? – 2012-06-30 20:23:27

+0

我猜这就是为什么这不是一个被接受的答案。 @zlog我也想知道这一点。任何想法如何擦除画笔图像,而不是刷边界框? – taber 2012-07-06 14:31:59

+4

刚刚发现此帖:http:// stackoverflow。com/questions/4074955/blending-a-texture-to-erase-alpha-values-softly-with-opengl using'glBlendFunc(GL_ZERO,GL_ONE_MINUS_SRC_ALPHA)'似乎有诀窍。 – taber 2012-07-06 16:59:39

4

我想我可以解决这个问题,虽然不是很好。

您可以像这样创建一个新的“renderLineFromPoint”函数副本;

- (void) drawErase:(CGPoint)start toPoint:(CGPoint)end 
{ 
    static GLfloat*  eraseBuffer = NULL; 
    static NSUInteger eraseMax = 64; 

    NSUInteger   vertexCount = 0, 
    count, 
    i; 

    [EAGLContext setCurrentContext:context]; 
    glBindFramebufferOES(GL_FRAMEBUFFER_OES, viewFramebuffer); 

    // Convert locations from Points to Pixels 
    CGFloat scale = 1.0;//self.contentScaleFactor; 
    start.x *= scale; 
    start.y *= scale; 
    end.x *= scale; 
    end.y *= scale; 

    // Allocate vertex array buffer 
    if(eraseBuffer == NULL) 
     eraseBuffer = malloc(eraseMax * 2 * sizeof(GLfloat)); 

    // Add points to the buffer so there are drawing points every X pixels  
    count = MAX(ceilf(sqrtf((end.x - start.x) * (end.x - start.x) + (end.y - start.y) * (end.y - start.y))/kBrushPixelStep), 1); 

    for(i = 0; i < count; ++i) { 
     if(vertexCount == eraseMax) { 
      eraseMax = 2 * eraseMax; 
      eraseBuffer = realloc(eraseBuffer, eraseMax * 2 * sizeof(GLfloat)); 
     } 

     eraseBuffer[2 * vertexCount + 0] = start.x + (end.x - start.x) * ((GLfloat)i/(GLfloat)count); 
     eraseBuffer[2 * vertexCount + 1] = start.y + (end.y - start.y) * ((GLfloat)i/(GLfloat)count); 
     vertexCount += 1; 
    } 
    //} 
    //glEnable(GL_BLEND); // 打开混合 
     //glDisable(GL_DEPTH_TEST); // 关闭深度测试 
     //glBlendFunc(GL_SRC_ALPHA, GL_ONE); // 基于源象素alpha通道值的半透明混合函数 

     //You need set the mixed-mode 
    glBlendFunc(GL_ONE, GL_ZERO); 
     //the erase brush color is transparent. 
    glColor4f(0, 0, 0, 0.0); 

    // Render the vertex array 
    glVertexPointer(2, GL_FLOAT, 0, eraseBuffer); 
    glDrawArrays(GL_POINTS, 0, vertexCount); 

    // Display the buffer 
    glBindRenderbufferOES(GL_RENDERBUFFER_OES, viewRenderbuffer); 
    [context presentRenderbuffer:GL_RENDERBUFFER_OES]; 

     // at last restore the mixed-mode 
    glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); 
} 

我的英语很差。你能理解我说的吗? 希望这些可以帮助你。

if (isEraserBrushType) { 
    glBlendFunc(GL_ONE, GL_ZERO); 
    glColor4f(0, 0, 0, 0.0); 
} else { 
    glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); 
    [self setBrushColorWithRed:brushColourRed green:brushColourGreen blue:brushColourBlue]; 
} 

上面的代码:

+0

通过zlog作品给出的答案这是一个完美的答案...工作对我来说.. – Heena 2013-03-05 09:21:12

-2

另一个想法,如果假设你的视图的回地面是纯黑色的,你可以简单地调用[self setBrushColorWithRed:0.0 green:0.0 blue:0.0]然后调用renderPoint:ToPint: - 这将在黑画(以及用户可能会认为他实际上是擦除

0

我试图使用公认的答案,但是它会擦除一个方形图案,而我想用我自己的画笔抹掉。相反,我使用了不同的混合功能。

if (self.isErasing) { 
    glBlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_ALPHA); 
    [self setBrushColorWithRed:0 green:0 blue:0]; 
} else { 
    glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); 
} 

这种工作方式是,传入(源)颜色乘以至c完全消失意味着你实际上没有画任何新东西。然后将目标颜色设置为(1 - 来源Alpha)。所以无论在哪里刷颜色目的地有没有颜色。