OpenGL 实现大眼和瘦脸

本文介绍了如何利用iOS的Vision框架和OpenGL进行图像处理,实现瘦脸和大眼的实时特效。通过设置顶点和纹理数据,以及使用特定的片元着色器算法,实现了面部特征点的识别和图像扭曲效果,创建了类似抖音滤镜的应用功能。
摘要由CSDN通过智能技术生成

借鉴博客:iOS原生框架Vision实现瘦脸大眼特效仿抖音特效相机之大眼瘦脸
本文达成效果如下图:

效果图


106个特征点如下图

特征点

原理解析

主要是以下3点,具体请前往参考博客原理解析

  • 1.圆内放大
  • 2.圆内缩小
  • 3.向某一点拉伸

用一张gif图来概括上面的内容,也是本文章最终的达成的效果,如开头所展示的效果图

经过前面我们了解了

  • 日常开发中OpenGL开发流程

  • 1.设置图层
  • 2.设置图形上下文
  • 3.设置渲染缓冲区(renderBuffer)
  • 4.设置帧缓冲区(frameBuffer)
  • 5.编译、链接着色器(shader)
  • 6.设置VBO (Vertex Buffer Objects)
  • 7.设置纹理
  • 8.渲染

这些基本步骤大致是不变的。这章是摄像头渲染+"多滤镜"渲染思想的结合提现。内容是感觉是增加了,但是实际的开发流程还是一样的。接下来让我们进入正题。
经过分析我们主要有以下3个工作:

需求图

核心代码:

    ///绘制面部特征点
    func renderFacePoint() {
        //MARK: - 1.绘制摄像头
        //使用着色器
        glUseProgram(renderProgram)
        //绑定frameBuffer
        glBindFramebuffer(GLenum(GL_FRAMEBUFFER), facePointFrameBuffer)
        
        //设置清屏颜色
        glClearColor(0.0, 0.0, 0.0, 1.0)
        //清除屏幕
        glClear(GLbitfield(GL_COLOR_BUFFER_BIT))
        
        //1.设置视口大小
        let scale = self.contentScaleFactor
        glViewport(0, 0, GLsizei(self.frame.size.width * scale), GLsizei(self.frame.size.height * scale))
        
       

#warning("注意⚠️:想要获取shader里面的变量,这里要记住要在glLinkProgram后面、后面、后面")
        //----处理顶点数据-------
        //将顶点数据通过renderProgram中的传递到顶点着色程序的position
        /*1.glGetAttribLocation,用来获取vertex attribute的入口的.
          2.告诉OpenGL ES,通过glEnableVertexAttribArray,
          3.最后数据是通过glVertexAttribPointer传递过去的。
         */
        //注意:第二参数字符串必须和shaderv.vsh中的输入变量:position保持一致
        let position = glGetAttribLocation(renderProgram, "position")

        //设置合适的格式从buffer里面读取数据
        glEnableVertexAttribArray(GLuint(position))

        //设置读取方式
        //参数1:index,顶点数据的索引
        //参数2:size,每个顶点属性的组件数量,1,2,3,或者4.默认初始值是4.
        //参数3:type,数据中的每个组件的类型,常用的有GL_FLOAT,GL_BYTE,GL_SHORT。默认初始值为GL_FLOAT
        //参数4:normalized,固定点数据值是否应该归一化,或者直接转换为固定值。(GL_FALSE)
        //参数5:stride,连续顶点属性之间的偏移量,默认为0;
        //参数6:指定一个指针,指向数组中的第一个顶点属性的第一个组件。默认为0
//        glVertexAttribPointer(GLuint(position), 3, GLenum(GL_FLOAT), GLboolean(GL_FALSE), GLsizei(MemoryLayout<GLfloat>.size * 5), UnsafeRawPointer(bitPattern: MemoryLayout<GLfloat>.size * 0))
        glVertexAttribPointer(GLuint(position), 3, GLenum(GL_FLOAT), GLboolean(GL_FALSE), 0, standardVertex)


        //----处理纹理数据-------
        //1.glGetAttribLocation,用来获取vertex attribute的入口的.
        //注意:第二参数字符串必须和shaderv.vsh中的输入变量:textCoordinate保持一致
        let textCoord = glGetAttribLocation(renderProgram, "textCoordinate")

        //设置合适的格式从buffer里面读取数据
        glEnableVertexAttribArray(GLuint(textCoord))

        //3.设置读取方式
        //参数1:index,顶点数据的索引
        //参数2:size,每个顶点属性的组件数量,1,2,3,或者4.默认初始值是4.
        //参数3:type,数据中的每个组件的类型,常用的有GL_FLOAT,GL_BYTE,GL_SHORT。默认初始值为GL_FLO
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值