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

2023-01-06  本文已影响0人  itfitness

目录

相关文章

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

上一篇下一篇

猜你喜欢

热点阅读