目录

相关文章
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);
网友评论