首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >用opengl绘制具有模糊效果的图像

用opengl绘制具有模糊效果的图像
EN

Stack Overflow用户
提问于 2013-02-28 16:53:42
回答 4查看 1.8K关注 0票数 1

我和this question有同样的要求

我现在在我的opengl视图上设置了UIImage。下面是我用来设置uiimage的完整代码。此外,它还包括绘图代码。使用下面的代码,我能够设置图像并在其上绘图。

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

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

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

我已经使用了苹果的一些GLPaint代码来绘图。

代码语言:javascript
复制
 - (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上调用

代码语言:javascript
复制
- (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);

    }
}

有什么解决方法可以实现这一点吗?我马上就要实现我的目标了,但是如果遇到here.Any的麻烦,我会很感激的。

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2013-03-15 12:06:23

我找到解决方案了..。

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

我刚刚在_updateContent方法之后的LayoutSubviews方法中添加了以下代码

代码语言:javascript
复制
        // 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)

现在这段代码可以完美地工作了。

票数 1
EN

Stack Overflow用户

发布于 2013-02-28 18:04:15

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

票数 1
EN

Stack Overflow用户

发布于 2013-03-13 22:48:28

您可以尝试使用This Link中的openGL代码

或者试试这个

代码语言:javascript
复制
CGSize offset;
float blur;//set this variable as per your requirement
offset.width = 10;
offset.height = -10;

CGContextSetShadow(context, offset, blur);
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/15131213

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档