IPhone drawing application (based on glPaint). Blend with white background

I am developing a drawing application. I tried to do this with CoreGraphics / Quartz 2D, and the curve drawing algorithm is pretty slow. Therefore, we decided to switch to OpenGL ES. I have never had OpenGL experience, so I found the glPaint example from apple and started playing with it.

I changed the way I erasemade the white background. How I got stuck with brushes and blending. In the example, Apple uses a white on black texture for the brush (first in the figure below). But this did not work for me (I played with different blending modes). So I decided to use different brushes, but I did not find a suitable way. I found some questions about stackoverflow, but they all went unanswered. Here is a photograph (from another question, thanks to Kevin Baymers ). Results http://www.straandlooper.com/GLPaint.png

So, the question is how to implement the beat as โ€œdesiredโ€ in the picture. And how to mix 2 strokes closer to real life experience (blue over yellow = dark green).

Thank.

There is current code (bit changed from glPaint) for the brush (from the method initWithFrame:

// Make sure the image exists
if(brushImage) {
  // Allocate  memory needed for the bitmap context
  brushData = (GLubyte *) calloc(width * height * 4, sizeof(GLubyte));
  // Use  the bitmatp creation function provided by the Core Graphics framework. 
  brushContext = CGBitmapContextCreate(brushData, width, width, 8, width * 4, CGImageGetColorSpace(brushImage), kCGImageAlphaPremultipliedLast);
  // After you create the context, you can draw the  image to the context.
  CGContextDrawImage(brushContext, CGRectMake(0.0, 0.0, (CGFloat)width, (CGFloat)height), brushImage);
  // You don't need the context at this point, so you need to release it to avoid memory leaks.
  CGContextRelease(brushContext);
  // Use OpenGL ES to generate a name for the texture.
  glGenTextures(1, &brushTexture);
  // Bind the texture name. 
  glBindTexture(GL_TEXTURE_2D, brushTexture);
  // Set the texture parameters to use a minifying filter and a linear filer (weighted average)
  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
  // Specify a 2D texture image, providing the a pointer to the image data in memory
  glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, brushData);
  // Release  the image data; it no longer needed
        free(brushData);
  // Make the current material colour track the current color
  glEnable( GL_COLOR_MATERIAL );
  // Enable use of the texture
  glEnable(GL_TEXTURE_2D);
  // Set a blending function to use
  glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
  // Enable blending
  glEnable(GL_BLEND);
  // Multiply the texture colour by the material colour.
  glTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );

}

//Set up OpenGL states
glMatrixMode(GL_PROJECTION);
CGRect frame = self.bounds;
glOrthof(0, frame.size.width, 0, frame.size.height, -1, 1);
glViewport(0, 0, frame.size.width, frame.size.height);
glMatrixMode(GL_MODELVIEW);

glDisable(GL_DITHER);
glEnable(GL_TEXTURE_2D);
glEnableClientState(GL_VERTEX_ARRAY);
  glEnable(GL_BLEND);




// Alpha blend each "dab" of paint onto background
glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );


//glBlendFunc(GL_SRC_COLOR, GL_ONE);
glEnable(GL_POINT_SPRITE_OES);
glTexEnvf(GL_POINT_SPRITE_OES, GL_COORD_REPLACE_OES, GL_TRUE);

self.brushScale = 3;
self.brushStep = 3;
self.brushOpacity = (1.0 / 1.5);

glPointSize(width / brushScale);

//Make sure to start with a cleared buffer
needsErase = YES;
[self erase];
+5
1

, . , , , . - C brush C dst :

C = C brush ร— C dst

, (1, 1, 0) (0, 1, 1) (0, 1, 0), .

, , . , A brush, A brush 1, , , A brush= 0, , . :

C = (C brush ร— C dst) ร— A brush + C dst ร— (1 - < > > )

OpenGL ES C = C src ร— S + C dst ร— D, , , :

C src= C brush ร— A brush

A src= A brush

S = C dst

D = (1 - A )

, , OpenGL ES. 4 :

  • .

  • -.
    GLPaint RGBA , RGB, . , , -. - CG GL_ALPHA:

    CGColorSpaceRef brushColorSpace = CGColorSpaceCreateDeviceGray();
    brushData = (GLubyte *) calloc(width * height, sizeof(GLubyte));
    brushContext = CGBitmapContextCreate(brushData, width, width, 8, width, brushColorSpace, kCGImageAlphaNone);
    CGColorSpaceRelease(brushColorSpace);
    

    glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, width, height, 0, GL_ALPHA, GL_UNSIGNED_BYTE, brushData);        
    
  • C src, A src, S D.
    -, , glColor4f, , OpenGL ES :

    C src= C brush

    A src= A brush

    A brush C src, ( PaintingView):

    glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
    glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_ALPHA);
    

    GL_TEXTURE_ENV_MODE GL_COMBINE C brush ร— 0 ( , , 3.7.12 OpenGL ES 1.1). GL_OPERAND0_RGB GL_SRC_ALPHA , .

    S D, , , ( , ):

    glBlendFunc(GL_DST_COLOR, GL_ONE_MINUS_SRC_ALPHA); 
    
  • , brush .
    , . - (.. , AppController), , :

    glColor4f(components[0] * kBrushOpacity, components[1] * kBrushOpacity, components[2] * kBrushOpacity, kBrushOpacity);
    

, , , , (, ). , , -, 2, :

glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

, ( ).

+18

All Articles