美文网首页OpenGLiOS 图像处理图片处理
iOS:用openGLES绘制各种常见图案(三角形,四边形,圆形

iOS:用openGLES绘制各种常见图案(三角形,四边形,圆形

作者: Theendisthebegi | 来源:发表于2018-11-08 16:28 被阅读4次

    首先是初始化openGL
    设置layer

    - (void)setupLayer
    {
    CAEAGLLayer *eaglLayer = (CAEAGLLayer *)self.layer;
    
    // CALayer 默认是透明的,必须将它设为不透明才能让其可见
    eaglLayer.opaque = YES;
    
    // 设置描绘属性,在这里设置不维持渲染内容以及颜色格式为 RGBA8
    eaglLayer.drawableProperties = [NSDictionary dictionaryWithObjectsAndKeys:
                                    [NSNumber numberWithBool:YES], kEAGLDrawablePropertyRetainedBacking, kEAGLColorFormatRGBA8, kEAGLDrawablePropertyColorFormat, nil];
    //设置放大倍数
    [self setContentScaleFactor:[[UIScreen mainScreen] scale]];
    }
    

    设置上下文

    - (void)setupContext{
    // 指定 OpenGL 渲染 API 的版本,在这里我们使用 OpenGL ES 2.0
    _context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2];
    
     // 设置为当前上下文
    if (!_context || ![EAGLContext setCurrentContext:_context]) {
        
        NSLog(@"Failed to initialize OpenGLES 2.0 context");
        
        exit(1);
    }
    }
    

    设置缓冲区

    - (void)setupBuffer{
    glDeleteFramebuffers(1, &_viewFramebuffer);
    
    _viewRenderbuffer = 0;
    
    glDeleteRenderbuffers(1, &_viewRenderbuffer);
    
    _viewRenderbuffer = 0;
    
    glGenFramebuffers(1, &_viewFramebuffer);
    
    glGenRenderbuffers(1, &_viewRenderbuffer);
    
    // 设置为当前 framebuffer
    glBindFramebuffer(GL_FRAMEBUFFER, _viewFramebuffer);
    
    glBindRenderbuffer(GL_RENDERBUFFER, _viewRenderbuffer);
    
    // 为 颜色缓冲区 分配存储空间
    [_context renderbufferStorage:GL_RENDERBUFFER fromDrawable:(id<EAGLDrawable>)self.layer];
    
    // 将 _colorRenderBuffer 装配到 GL_COLOR_ATTACHMENT0 这个装配点上
    glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, _viewRenderbuffer);
    
    glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_WIDTH, &_backingWidth);
    
    glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_HEIGHT, &_backingHeight);
    }
    

    着色器配置文件:

    #define VSH @"attribute vec4 Position;\
    attribute vec4 SourceColor;\
    varying vec4 DestinationColor;\
    void main(void) {\
    DestinationColor = SourceColor;\
    gl_Position = Position;\
    }"
    
    #define FSH @"varying lowp vec4 DestinationColor;\
    void main(void) {\
    gl_FragColor = DestinationColor;\
    }"
    

    三角形和矩形的渲染

    - (void)render {
    
    glClearColor(0, 1.0, 0.0, 1.0);
    
    glClear(GL_COLOR_BUFFER_BIT);
    
    CGFloat scale = [[UIScreen mainScreen] scale]; //获取视图放大倍数,可以把scale设置为1试试
    
    glViewport(0, 0, self.frame.size.width * scale, self.frame.size.height * scale); //设置视口大小
    
    //加载shader
    self.myProgram = [self loadShaders:VSH frag:FSH];
    
    //链接
    glLinkProgram(self.myProgram);
    
    GLint linkSuccess;
    
    glGetProgramiv(self.myProgram, GL_LINK_STATUS, &linkSuccess);
    
    if (linkSuccess == GL_FALSE) { //连接错误
        
        GLchar messages[256];
        
        glGetProgramInfoLog(self.myProgram, sizeof(messages), 0, &messages[0]);
        
        NSString *messageString = [NSString stringWithUTF8String:messages];
        
        NSLog(@"error:%@", messageString);
        
        return ;
        
    }else {
        
        NSLog(@"link ok");
        
        glUseProgram(self.myProgram); //成功便使用,避免由于未使用导致的的bug
    }
    
    GLuint position = glGetAttribLocation(self.myProgram, "Position");
    
    GLuint textCoor = glGetAttribLocation(self.myProgram, "SourceColor");
    
    const GLfloat Vertices[] = {
        -0.5f,-0.5f,0,0,0,0,// 左下,黑色
        0.5f,-0.5f,0,1,0,0, // 右下,红色
        0.5f,0.5f,0,0,1,0,  // 右上,绿色
        -0.5f,0.5f,0,0,0,1, // 左上,蓝色
    };
    
    // 索引数组,指定好了绘制三角形的方式
    // 与glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);一样。
    const GLubyte Indices[] = {
        0,1,2, // 三角形0
        0,2,3  // 三角形1
    };
    
    GLuint vertexBuffer;
    
    glGenBuffers(1, &vertexBuffer);
    // 绑定vertexBuffer到GL_ARRAY_BUFFER目标
    glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
    // 为VBO申请空间,初始化并传递数据
    glBufferData(GL_ARRAY_BUFFER, sizeof(Vertices), Vertices, GL_STATIC_DRAW);
    
    // 给_positionSlot传递vertices数据
    glVertexAttribPointer(position, 3, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 6, NULL);
    
    glEnableVertexAttribArray(position);
    
    // 取出Colors数组中的每个坐标点的颜色值,赋给_colorSlot
    glVertexAttribPointer(textCoor, 4, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 6, (float *)NULL + 3);
    
    glEnableVertexAttribArray(textCoor);
    
    if (_drawType == 1) {
        // Draw triangle
        if (_isHollow) glDrawArrays(GL_LINE_LOOP, 0, 4);   //GL_LINE_LOOP不带填充
        
        else  glDrawElements(GL_TRIANGLES, sizeof(Indices)/sizeof(Indices[0]), GL_UNSIGNED_BYTE, Indices);
    }else{
    
        glDrawArrays(_isHollow ? GL_LINE_LOOP : GL_TRIANGLES, 0, 3);   //GL_LINE_LOOP不带填充
    }
    
    [self.context presentRenderbuffer:GL_RENDERBUFFER];
    }
    

    至于圆形,因为要把圆切割成100份,和矩形有些不一样

     - (void)renderCircular {
    
    glClearColor(0, 1.0, 1.0, 1.0);
    
    glClear(GL_COLOR_BUFFER_BIT);
    
    CGFloat scale = [[UIScreen mainScreen] scale]; //获取视图放大倍数,可以把scale设置为1试试
    
    glViewport(0, 0, self.frame.size.width * scale, self.frame.size.height * scale); //设置视口大小
    
    //加载shader
    self.myProgram = [self loadShaders:VSH frag:FSH];
    
    //链接
    glLinkProgram(self.myProgram);
    
    GLint linkSuccess;
    
    glGetProgramiv(self.myProgram, GL_LINK_STATUS, &linkSuccess);
    
    if (linkSuccess == GL_FALSE) { //连接错误
        
        GLchar messages[256];
        
        glGetProgramInfoLog(self.myProgram, sizeof(messages), 0, &messages[0]);
        
        NSString *messageString = [NSString stringWithUTF8String:messages];
        
        NSLog(@"error:%@", messageString);
        
        return ;
        
    }else {
        
        NSLog(@"link ok");
        
        glUseProgram(self.myProgram); //成功便使用,避免由于未使用导致的的bug
    }
    
    GLuint position = glGetAttribLocation(self.myProgram, "Position");
    
    GLuint textCoor = glGetAttribLocation(self.myProgram, "SourceColor");
    
    GLint vertCount = 101; //分割份数
    
    Vertex vertext[vertCount];
    
    float delta = 2.0*M_PI/vertCount;
    
    float a = 0.8; //水平方向的半径
    float b = a * self.frame.size.width / self.frame.size.height;
    
    for (int i = 0; i < vertCount; i++) {
        GLfloat x = a * cos(delta * i);
        GLfloat y = b * sin(delta * i);
        GLfloat z = 0.0;
        vertext[i] = (Vertex){x, y, z, x, y, x+y};
        
        printf("%f , %f\n", x, y);
    }
    
    GLuint vertexBuffer;
    
    glGenBuffers(1, &vertexBuffer);
    // 绑定vertexBuffer到GL_ARRAY_BUFFER目标
    glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
    // 为VBO申请空间,初始化并传递数据
    glBufferData(GL_ARRAY_BUFFER, sizeof(vertext), vertext, GL_STATIC_DRAW);
    
    // 给_positionSlot传递vertices数据
    glVertexAttribPointer(position, 3, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 6, NULL);
    
    glEnableVertexAttribArray(position);
    
    // 取出Colors数组中的每个坐标点的颜色值,赋给_colorSlot
    glVertexAttribPointer(textCoor, 4, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 6, (float *)NULL + 3);
    
    glEnableVertexAttribArray(textCoor);
    
    glDrawArrays(_isHollow ? GL_LINE_LOOP : GL_TRIANGLE_FAN, 0, vertCount);//GL_LINE_LOOP 不带填充
    
    [self.context presentRenderbuffer:GL_RENDERBUFFER];
    }
    

    效果图:


    1782258-b1baee1ba0a400e7.png WechatIMG18.png 1782258-068214f7c72b54c4.png

    无填充:


    A89F966D-3184-4BEE-AADA-145514F7D367.jpeg 60672747-676A-4282-AB91-0C6CE173B1C6.jpeg 7F588FAD-626C-41BC-940D-442F7B8BE291.jpeg

    github代码地址

    相关文章

      网友评论

        本文标题:iOS:用openGLES绘制各种常见图案(三角形,四边形,圆形

        本文链接:https://www.haomeiwen.com/subject/ujevxqtx.html