开发者

Erase using brush in GLPaint

As part of modifying the GLPaint, I am trying to add erase functionality where user could select an eraser button and erase the painted area just as painting.

I am trying ha开发者_开发技巧ve a conditional statement within "renderLineFromPoint:(CGPoint)start toPoint:(CGPoint)end" method so that I could check whether the stroke is for painting or erasing.

For erasing I do not know how to make use of the "start" and "end" parameters for erasing. Is there any method call in OpenGL like glClear() that accepts these two parameter and does erase?

Any pointer will be very helpful. Thank you.


Along the same vein as Erase using brush in GLPaint, you could reuse the

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

method by having the condition:

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];
}

above the code:

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

Note, you'll need to implement isEraserBrushType, and store brushColourRed, brushColourGreen and brushColourBlue somehow.


I think I can solve this problem, although not a very good.

You can create a new function copy of "renderLineFromPoint", like this;

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

My English is poor. Can you understand what I said? Hope these can help you.


I attempted to use the accepted answer, however it would erase in a square pattern, whereas I wanted to erase using my own brush. Instead I used a different blending function.

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

The way this works is that the incoming (source) colour is multiplied by zero to completely disappear meaning that you don't actually paint anything new. Then the destination colour is set to be (1 - Source Alpha). So wherever the brush has colour the destination has no colour.


Another idea, if suppose your view's back ground is pure black you can simply call [self setBrushColorWithRed:0.0 green:0.0 blue:0.0] and then call renderPoint:ToPint: - This will draw in black (and the user may think that he is actually erasing.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜