美文网首页
OpenGL系列之十九:OpenGL人脸贴纸

OpenGL系列之十九:OpenGL人脸贴纸

作者: itfitness | 来源:发表于2023-01-06 16:46 被阅读0次

    目录

    相关文章

    OpenGL系列之一:OpenGL第一个程序
    OpenGL系列之二:绘制三角形
    OpenGL系列之三:三角形顶点增加颜色
    OpenGL系列之四:绘制四边形
    OpenGL系列之五:绘制点和线
    OpenGL系列之六:绘制立方体
    OpenGL系列之七:纹理贴图
    OpenGL系列之八:立方体纹理贴图
    OpenGL系列之九:glsl着色器语言
    OpenGL系列之十:VAO、VBO、EBO的应用
    OpenGL系列之十一:Shader图片转场切换动画
    OpenGL系列之十二:Shader燃烧动画
    OpenGL系列之十三:实现Shader绚丽动画
    OpenGL系列之十四:实现相机抖音特效
    OpenGL系列之十五:实现美颜相机
    OpenGL系列之十六:实现大眼特效
    OpenGL系列之十七:实现人脸贴纸
    OpenGL系列之十八:FBO离屏渲染

    参考文章

    https://blog.csdn.net/YuQing_Cat/article/details/84070361

    效果展示

    代码实现

    这里我们以OpenGL系列之十七:实现人脸贴纸,这篇文章的代码为基础(这篇文章是使用OpenCV实现的贴纸),OpenGL实现贴纸有个好处就是可以直接使用背景透明的图片,不用像OpenCV那样还得弄一个背景,然后通过掩膜实现透明,然后在OpenGL中实现贴纸也比较简单,直接开启混合模式渲染即可关键代码如下:

    /**
     * 绘制
     */
    void CCRenderTZ::paintGL(float x,float y,float rotate)
    {
        //开启混合模式:将多张图片进行混合(贴图)
        glEnable(GL_BLEND);
        glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
    
        //这一步是算出贴纸渲染的位置
        glViewport(x - width / 2,(textureHeight - y) - height / 2,width,height);
    //    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
        drawShaderAnim(rotate);
    
        //关闭混合模式
        glDisable(GL_BLEND);
        //恢复窗口大小
        glViewport(0,0,textureWidth,textureHeight);
    }
    

    由于需要随着人脸旋转来调整贴纸的角度,因此在这里也需要传入人脸的倾斜角度,这里用的算法与OpenGL系列之十七:实现人脸贴纸这篇文章一样,然后贴纸旋转也是使用glm实现的,代码如下:

    void CCRenderTZ::drawShaderAnim(float rotate) {
    
        u_value += 0.015f;
    
        glm::mat4x4  objectMat;
        glm::mat4x4  objectTransMat = glm::translate(glm::mat4(1.0f), glm::vec3(0.0f, 0.0f, -1));
        //贴纸旋转
        glm::mat4x4  objectRotMat = glm::rotate(glm::mat4(1.0f),glm::radians(rotate),glm::vec3(0.0f, 0.0f, 10.0) );
        glm::mat4x4  objectScaleMat = glm::scale(glm::mat4(1.0f),glm::vec3(0.6f, 0.6f, 0.0) );
    
        glm::mat4 projMat = glm::perspective(glm::radians(60.0f), 1.0f, 0.0f, 1000.0f);
    
        objectMat = projMat * objectTransMat * objectRotMat * objectScaleMat;
    
        ccOpenGlShader.Bind();
    
        ccOpenGlShader.SetUniformValue("u_mat",objectMat);
        //设置变化的值
        ccOpenGlShader.SetUniformValue("uValue",u_value);
    
        ccVAO.Bind();
    
        glActiveTexture(GL_TEXTURE1);
        //给变量utexture0设置值
        glBindTexture(GL_TEXTURE_2D,textureId);
        ccOpenGlShader.SetUniformValue("utexture0",textureId);
    
        glDrawElements(GL_TRIANGLE_STRIP,6,GL_UNSIGNED_SHORT,(void *)0);
    
        glBindTexture(GL_TEXTURE_2D, 0);
        ccOpenGlShader.Release();
        ccVAO.Release();
    }
    

    使用的时候也是直接传入鼻子的定位点和旋转角度即可

    //贴图旋转
        int angle = get_angle(u_LeftEyeCenterPos.x,u_LeftEyeCenterPos.y,u_RightEyeCenterPos.x,u_RightEyeCenterPos.y);
    
        //当右眼的y坐标大于左眼的y坐标的时候,反着转
        if(u_RightEyeCenterPos.y > u_LeftEyeCenterPos.y){
            angle = - angle;
        }
        ccRenderTz->paintGL(noiseCenterPos.x,noiseCenterPos.y,angle);
    

    案例源码

    https://gitee.com/itfitness/opengl-picture-sticker

    相关文章

      网友评论

          本文标题:OpenGL系列之十九:OpenGL人脸贴纸

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