1

我和这个问题有同样的要求

我现在处于在我的 opengl 视图上设置 UIImage 的情况。下面是我用来设置 uiimage 的完整代码。它还包括绘图代码。使用下面的代码,我可以设置图像并在其上绘图。

当我不在背景中设置图像时,它允许我绘制模糊和平滑的绘图

但是如果我设置背景图像,它会绘制实体图

我想在背景图像上平滑绘图。

我使用了苹果的一些 GLPaint 代码进行绘图。

 - (id)initWithCoder:(NSCoder*)coder
{
    CGImageRef      brushImage;
    CGContextRef    brushContext;
    GLubyte         *brushData;
    size_t          width, height;

    if ((self = [super initWithCoder:coder]))
    {
        CAEAGLLayer *eaglLayer = (CAEAGLLayer *)self.layer;
        eaglLayer.opaque = NO;
        eaglLayer.drawableProperties = [NSDictionary dictionaryWithObjectsAndKeys:
                                        [NSNumber numberWithBool:YES], kEAGLDrawablePropertyRetainedBacking,
                                        kEAGLColorFormatRGBA8, kEAGLDrawablePropertyColorFormat,
                                        nil];

        _context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES1];
        if (!_context || ![EAGLContext setCurrentContext:_context])
        {
            return nil;
        }

        {
            brushImage = [UIImage imageNamed:@"Brush.png"].CGImage;

            width = CGImageGetWidth(brushImage);
            height = CGImageGetHeight(brushImage);

            if(brushImage) {
                brushData = (GLubyte *) calloc(width * height * 4, sizeof(GLubyte));
                brushContext = CGBitmapContextCreate(brushData, width, width, 8, width * 4, CGImageGetColorSpace(brushImage), kCGImageAlphaPremultipliedLast);
                CGContextSetLineCap(UIGraphicsGetCurrentContext(), kCGLineCapRound);
                CGContextDrawImage(brushContext, CGRectMake(0.0, 0.0, (CGFloat)width, (CGFloat)height), brushImage);
                CGContextRelease(brushContext);
                glGenTextures(1, &brushTexture);
                glBindTexture(GL_TEXTURE_2D, brushTexture);
                glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
                glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, brushData);
                free(brushData);
            }
        }

        // Setup 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);
        glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);

        glEnable(GL_POINT_SPRITE_OES);
        glTexEnvf(GL_POINT_SPRITE_OES, GL_COORD_REPLACE_OES, GL_TRUE);
        glPointSize(10);

    }
    return self;
}



  - (void)layoutSubviews
    {
        [EAGLContext setCurrentContext:_context];
        [self destroyFramebuffer];
        [self createFramebuffer];

        if (texture)    {
            [self _updateContent];
            glDeleteTextures(1, &texture);
            texture = 0;
        }
    }


    - (void)_updateContent {
        NSUInteger width = self.frame.size.width;
        NSUInteger height = self.frame.size.height;

        CGFloat texWidth = (1.0 * width)/TEX_SIZE;
        CGFloat texHeight = (1.0 * height)/TEX_SIZE;

        GLfloat verts[12] = {
            0, height,
            width, height,
            width, 0,
            0, height,
            0, 0,
            width, 0
        };

        GLfloat txcoord[12] = {
            0, texHeight,
            texWidth, texHeight,
            texWidth, 0,
            0, texHeight,
            0, 0,
            texWidth, 0
        };

        [EAGLContext setCurrentContext:_context];
        glBindFramebufferOES(GL_FRAMEBUFFER_OES, _viewFramebuffer);
        glVertexPointer(2, GL_FLOAT, 0, verts);
        glTexCoordPointer(2, GL_FLOAT, 0, txcoord);
        glDrawArrays(GL_TRIANGLES, 0, 6);

        glDisableClientState(GL_TEXTURE_COORD_ARRAY);

        glBindRenderbufferOES(GL_RENDERBUFFER_OES, _viewRenderbuffer);
        [_context presentRenderbuffer:GL_RENDERBUFFER_OES];

        glDisable(GL_TEXTURE_2D);
        glDisable(GL_BLEND);

    }


   - (void)setContent:(UIImage*)image
{

    if (image) {
        //        self.isNotEmpty = YES;
        CGImageRef contentImage = image.CGImage;

        [EAGLContext setCurrentContext:_context];

        CGFloat w = CGImageGetWidth(contentImage);
        CGFloat h = CGImageGetHeight(contentImage);

        GLubyte *data = (GLubyte *)calloc(TEX_SIZE * TEX_SIZE * 4, sizeof(GLubyte));

        CGContextRef ctx = CGBitmapContextCreate(data, TEX_SIZE, TEX_SIZE, 8, TEX_SIZE * 4, CGImageGetColorSpace(contentImage), kCGImageAlphaPremultipliedLast);
        CGContextScaleCTM(ctx, 1, -1);
        CGContextTranslateCTM(ctx, 0, -TEX_SIZE);
        CGContextDrawImage(ctx, CGRectMake(0, 0, w, h), contentImage);
        CGContextRelease(ctx);

        if (!texture) {
            glGenTextures(1, &texture);
        }
        glBindTexture(GL_TEXTURE_2D, texture);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, TEX_SIZE, TEX_SIZE, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
        free(data);
    } 
    [self setNeedsLayout];        
    glDisable(GL_VERTEX_ARRAY);
}

//在touchedMoved上调用

- (void) renderLineFromPoint:(CGPoint)start toPoint:(CGPoint)end
{
    glEnable(GL_BLEND);
    if(1){
        sharedDelegate = [AppDelegate appDelegate];

        static GLfloat*     vertexBuffer = NULL;
        static NSUInteger   vertexMax = 64;
        NSUInteger          vertexCount = 0,
        count,
        i;
        GLenum err;

        glColor4f(1.0, 0.0, 1.0, 1.0);

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

        // Allocate vertex array buffer
        if(vertexBuffer == NULL)
            vertexBuffer = malloc(vertexMax * 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 == vertexMax) {
                vertexMax = 2 * vertexMax;
                vertexBuffer = realloc(vertexBuffer, vertexMax * 2 * sizeof(GLfloat));
            }

            vertexBuffer[2 * vertexCount + 0] = start.x + (end.x - start.x) * ((GLfloat)i / (GLfloat)count);
            vertexBuffer[2 * vertexCount + 1] = start.y + (end.y - start.y) * ((GLfloat)i / (GLfloat)count);
            vertexCount += 1;
        }

        if(sharedDelegate.boolIsEraser)
        {
            glColor4f(1.0, 1.0, 1.0, 0.5);
            glBlendFunc( GL_ZERO, GL_ONE_MINUS_SRC_ALPHA);
        }
        // Render the vertex array
        glVertexPointer(2, GL_FLOAT, 0, vertexBuffer);
        glDrawArrays(GL_POINTS, 0, vertexCount);

        if(sharedDelegate.boolIsEraser){
            // at last restore the  mixed-mode
            glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
        }

        glBindRenderbufferOES(GL_RENDERBUFFER_OES, _viewRenderbuffer);
        [_context presentRenderbuffer:GL_RENDERBUFFER_OES];

        err = glGetError();
        if (err != GL_NO_ERROR)
            NSLog(@"Error in frame. glError: 0x%04X", err);

    }
}

有什么解决方法可以做到这一点?我快到了我的目标,但严重卡在这里。任何帮助将不胜感激。

4

4 回答 4

1

我得到了解决方案...

剩下的事情是在我在 opengl 视图中绘制 UIImage 之后,我需要设置我的 opengl 状态。我在初始化画笔纹理时做的同样的事情......

LayoutSubviews我只是在方法之后的_updateContent方法中添加了下面的代码

        // Setup 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);
        glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);

        glEnable(GL_POINT_SPRITE_OES);
        glTexEnvf(GL_POINT_SPRITE_OES, GL_COORD_REPLACE_OES, GL_TRUE)

现在这段代码运行良好..

于 2013-03-15T04:06:22.570 回答
1

您可以尝试将阴影颜色设置为与描边颜色相同,并将描边模糊半径设置为从您希望模糊延伸的描边边缘的任意点。您可能希望将阴影偏移设置为CGSizeZero.

于 2013-02-28T10:04:14.733 回答
1

您可以从此链接尝试 openGL 代码

或试试这个

CGSize offset;
float blur;//set this variable as per your requirement
offset.width = 10;
offset.height = -10;

CGContextSetShadow(context, offset, blur);
于 2013-03-13T14:48:27.960 回答
0

您可以使用 CGContextSetBlendMode(context, kCGBlendModeClear) ike 真正的橡皮擦效果

于 2013-03-03T17:53:56.817 回答