1.动态网格滤镜特效
1.1顶点着色器
#version 300 es
layout(location = 0) in vec3 attr_position;
layout(location = 1) in vec2 attr_uv;uniform mat4   uni_mat;
out vec2   v_texcoord;void main(void)
{v_texcoord = attr_uv;gl_Position = uni_mat* vec4(attr_position,1.0);
}

传入的是MVP矩阵和材质坐标

1.2片元着色器
#version 300 es
precision mediump float;
//precision highp float;uniform sampler2D uni_textureY;
uniform sampler2D uni_textureU;
uniform sampler2D uni_textureV;in vec2 v_texcoord;
out vec4 fragColor;uniform float u_offset;//偏移量
uniform vec2 texSize;//纹理尺寸vec4 YuvToRgb(vec2 uv){vec3 yuv;vec3 rgb;yuv.x = texture(uni_textureY, uv).r;yuv.y = texture(uni_textureU, uv).r - 0.5;yuv.z = texture(uni_textureV, uv).r - 0.5;rgb = mat3( 1,1,1, 0,-0.39465,2.03211,1.13983,-0.58060,0) * yuv;return vec4(rgb, 1);
}void main(void)
{vec2 imgTexCoord = v_texcoord * texSize;//将纹理坐标系转换为图片坐标系float sideLength = texSize.y / 6.0;//网格的边长float maxOffset = 0.15 * sideLength;//设置网格线宽度的最大值float x = mod(imgTexCoord.x, floor(sideLength));float y = mod(imgTexCoord.y, floor(sideLength));float offset = u_offset * maxOffset;if(offset <= x&& x <= sideLength - offset&& offset <= y&& y <= sideLength - offset){fragColor = YuvToRgb(v_texcoord);}else{fragColor = vec4(1.0, 1.0, 1.0, 1.0);}
}

YuvToRgb:这个用于将yuv的数据转成rgb渲染到屏幕上

动态网格主要是将纹理划分为多个网格,然后根据一个偏移量动态改变网格的宽度。

mod:返回 x – y * floor (x / y) ,即求模计算 %

floor:返回小于等于 x 的最大整数值

计算之前需要将纹理坐标系转换为图片坐标系,保证网格没有被拉伸。

2.分屏特效
2.1顶点着色器
#version 300 es
layout(location = 0) in vec3 attr_position;
layout(location = 1) in vec2 attr_uv;uniform mat4   uni_mat;
out vec2   v_texcoord;void main(void)
{v_texcoord = attr_uv;gl_Position = uni_mat* vec4(attr_position,1.0);
}

这块主要是顶点数据以及材质,所以跟上边的是一样的

2.2片元着色器
#version 300 es
precision mediump float;
//precision highp float;uniform sampler2D uni_textureY;
uniform sampler2D uni_textureU;
uniform sampler2D uni_textureV;in vec2 v_texcoord;
out vec4 fragColor;vec4 YuvToRgb(vec2 uv){vec3 yuv;vec3 rgb;yuv.x = texture(uni_textureY, uv).r;yuv.y = texture(uni_textureU, uv).r - 0.5;yuv.z = texture(uni_textureV, uv).r - 0.5;rgb = mat3( 1,1,1, 0,-0.39465,2.03211,1.13983,-0.58060,0) * yuv;return vec4(rgb, 1);
}void main(void)
{/*四分屏  效果正常*/vec2 newTexCoord = v_texcoord;if(newTexCoord.x < 0.5){newTexCoord.x = newTexCoord.x * 2.0;}else{newTexCoord.x = (newTexCoord.x - 0.5) * 2.0;}if(newTexCoord.y < 0.5){newTexCoord.y = newTexCoord.y * 2.0;}else{newTexCoord.y = (newTexCoord.y - 0.5) * 2.0;}fragColor = YuvToRgb(newTexCoord);
}

分屏滤镜的原理是在多个指定区域内对整个纹理进行下采样(缩小),从而实现整个图像在多个区域内多次显示。

3.缩放的圆特效
3.1顶点着色器
#version 300 es
layout(location = 0) in vec3 attr_position;
layout(location = 1) in vec2 attr_uv;uniform mat4   uni_mat;
out vec2   v_texcoord;void main(void)
{v_texcoord = attr_uv;gl_Position = uni_mat* vec4(attr_position,1.0);
}

这块主要是顶点数据以及材质,所以跟上边的是一样的

3.2片元着色器
#version 300 es
precision mediump float;
//precision highp float;uniform sampler2D uni_textureY;
uniform sampler2D uni_textureU;
uniform sampler2D uni_textureV;in vec2 v_texcoord;
out vec4 fragColor;uniform float u_offset;//偏移量
uniform vec2 texSize;//纹理尺寸vec4 YuvToRgb(vec2 uv){vec3 yuv;vec3 rgb;yuv.x = texture(uni_textureY, uv).r;yuv.y = texture(uni_textureU, uv).r - 0.5;yuv.z = texture(uni_textureV, uv).r - 0.5;rgb = mat3( 1,1,1, 0,-0.39465,2.03211,1.13983,-0.58060,0) * yuv;return vec4(rgb, 1);
}void main(void)
{vec2 imgTex = v_texcoord * texSize;//将纹理坐标系转换为图片坐标系float r = (u_offset + 0.2 ) * texSize.x;   //0.2 表示圆圈的默认大小if(distance(imgTex, vec2(texSize.x / 2.0, texSize.y / 2.0)) < r){fragColor = YuvToRgb(v_texcoord);}else{fragColor = vec4(1.0, 1.0, 1.0, 1.0);}}
4.渲染程序部分
void MSDynamicGridLine::UpdateYUVData(MSYUVData_Frame *yuvFrame) {if(yuvFrame == nullptr ){return;}if(m_nVideoH != yuvFrame->height || m_nVideoW != yuvFrame->width){if(nullptr != m_pBufYuv420p){free(m_pBufYuv420p);m_pBufYuv420p=nullptr;}}m_nVideoW =  yuvFrame->width;m_nVideoH = yuvFrame->height;m_yFrameLength = yuvFrame->luma.length;m_uFrameLength = yuvFrame->chromaB.length;m_vFrameLength = yuvFrame->chromaR.length;//申请内存存一帧yuv图像数据,其大小为分辨率的1.5倍int nLen = m_yFrameLength + m_uFrameLength +m_vFrameLength;if(nullptr == m_pBufYuv420p){m_pBufYuv420p = ( unsigned char*) malloc(nLen);}memcpy(m_pBufYuv420p,yuvFrame->luma.dataBuffer,m_yFrameLength);memcpy(m_pBufYuv420p+m_yFrameLength,yuvFrame->chromaB.dataBuffer,m_uFrameLength);memcpy(m_pBufYuv420p+m_yFrameLength +m_uFrameLength,yuvFrame->chromaR.dataBuffer,m_vFrameLength);m_bUpdateData =true;
}

这个方法用于更新YUV数据,由于数据是从相机过来的,跟opengl 不是一个线程,所以需要通过内存共享的方式进行拷贝。

void MSDynamicGridLine::Render(MSGLCamera *pCamera) {glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);if(m_bUpdateData == false){return;}static MSVertex triangleVert[] = {{-1, 1,  1,     0,0},{-1, -1,  1,    0,1},{1,  1,  1,     1,0},{1,  -1,  1,    1,1},};glm::mat4x4  objectMat = glm::mat4x4(1.0);glm::mat4x4  objectTransMat = glm::translate(glm::mat4(1.0f), glm::vec3(0.0f, 0.0f, -5));objectMat = objectMat * objectTransMat;objectMat = pCamera->projectionMatrix * pCamera->viewMatrix * objectMat ;m_pOpenGLShader->Bind();m_pOpenGLShader->SetUniformValue("uni_mat",objectMat);m_pOpenGLShader->EnableAttributeArray("attr_position");m_pOpenGLShader->SetAttributeBuffer("attr_position",GL_FLOAT,triangleVert,3,sizeof(MSVertex));m_pOpenGLShader->EnableAttributeArray("attr_uv");m_pOpenGLShader->SetAttributeBuffer("attr_uv",GL_FLOAT,&triangleVert[0].u,2,sizeof(MSVertex));m_PeriodicFrameIndex++;float progress = GetFrameProgress();m_pOpenGLShader->SetUniformValue("u_offset",0.2f * progress);LOGD("m_nVideoW is %d,progress is %f",m_nVideoW,progress);if (m_nVideoW>0){m_pOpenGLShader->SetUniformValue("texSize",glm::vec2(m_nVideoW,m_nVideoH));}else{m_pOpenGLShader->SetUniformValue("texSize",glm::vec2(720,1280));}m_pOpenGLShader->SetUniformValue("uni_textureY",0);glActiveTexture(GL_TEXTURE0);glBindTexture(GL_TEXTURE_2D, m_textures[0]);glPixelStorei(GL_UNPACK_ALIGNMENT, 1);glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, m_nVideoW, m_nVideoH, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, m_pBufYuv420p);glPixelStorei(GL_UNPACK_ALIGNMENT, 4);glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);m_pOpenGLShader->SetUniformValue("uni_textureU",1);glActiveTexture(GL_TEXTURE1);glBindTexture(GL_TEXTURE_2D, m_textures[1]);glPixelStorei(GL_UNPACK_ALIGNMENT, 1);glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE,m_nVideoW/2, m_nVideoH/2, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, (char*)(m_pBufYuv420p+m_yFrameLength));glPixelStorei(GL_UNPACK_ALIGNMENT, 4);glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);m_pOpenGLShader->SetUniformValue("uni_textureV",2);glActiveTexture(GL_TEXTURE2);glBindTexture(GL_TEXTURE_2D, m_textures[2]);glPixelStorei(GL_UNPACK_ALIGNMENT, 1);glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, m_nVideoW/2, m_nVideoH/2, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, (char*)(m_pBufYuv420p+m_yFrameLength+m_uFrameLength));glPixelStorei(GL_UNPACK_ALIGNMENT, 4);glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);glBindTexture(GL_TEXTURE_2D, 0);m_pOpenGLShader->DisableAttributeArray("attr_position");m_pOpenGLShader->DisableAttributeArray("attr_uv");m_pOpenGLShader->Release();return;
}
  • 将参数传递给shader:mvp矩阵、顶点、偏移量等
  • 生成三个纹理,用于承载yuv三个分量的数据
  • 然后进行绘制glDrawArrays

Android OpenGL ES 3.0 相机基础滤镜相关推荐

  1. Android OpenGL ES 2.0 屏幕坐标和3D世界坐标转换

    Android OpenGL ES 2.0 屏幕坐标和3D世界坐标转换 查看全文 http://www.taodudu.cc/news/show-6705596.html 相关文章: word中如何加 ...

  2. 使用Android OpenGL ES 2.0绘图之五:添加运动

    传送门☞Android兵器谱☞转载请注明☞http://blog.csdn.net/leverage_1229 传送门☞系统架构设计☞转载请注明☞http://blog.csdn.net/levera ...

  3. 使用Android OpenGL ES 2.0绘图之一:搭建一个OpenGL ES环境

    传送门☞Android兵器谱☞转载请注明☞http://blog.csdn.net/leverage_1229 传送门☞系统架构设计☞转载请注明☞http://blog.csdn.net/levera ...

  4. 使用Android OpenGL ES 2.0绘图之三:绘制形状

    传送门 ☞ 轮子的专栏 ☞ 转载请注明 ☞ http://blog.csdn.net/leverage_1229 在定义好待绘制的形状之后,就要开始绘制它们了.使用OpenGL ES 2.0绘制形状可 ...

  5. Android opengl es 3.0 + ndk 绘画涂鸦项目

    前言 写一个opengl es 3.0 + ndk 的绘画涂鸦项目,命名为白板哈哈哈,记录自己遇到的问题,顺便学到的知识整合一遍,算是对自己一段时间的总结. 项目地址:Whiteboard 如果对你有 ...

  6. android opengl es 纹理 不同设备 白色,android – OpenGL ES 2.0纹理没有在某些设备上显示...

    早上好,这是2个纹理非幂的典型例子. 由于多种原因,纹理在分辨率上需要2的幂,这是一个非常常见的错误,每个人都碰巧陷入这个陷阱:)我也是. 2个纹理的非功率在某些设备/ GPU上运行平稳的事实,仅仅取 ...

  7. 使用Android OpenGL ES 2.0绘图之四:应用投影和相机视图

    传送门☞Android兵器谱☞转载请注明☞http://blog.csdn.net/leverage_1229 传送门☞系统架构设计☞转载请注明☞http://blog.csdn.net/levera ...

  8. 使用Android OpenGL ES 2.0绘图之二:定义形状

    传送门☞Android兵器谱☞转载请注明☞http://blog.csdn.net/leverage_1229 传送门☞系统架构设计☞转载请注明☞http://blog.csdn.net/levera ...

  9. android opengl es 2.0 编程指南,Android OpenGL ES 2.0 初次体验

    本文目录 一. OpenGL ES是什么? 二. OpenGL ES的版本 三. EGL是什么? 四. 需要知道的两个方法 五. 在Android中使用OpenGL ES的步骤 六. 例子1:简单的程 ...

  10. Android OpenGL ES 2.0绘制简单三角形

    实现步骤 l  实现一个工具类ShalderUtil,用于将着色器代码加载进显卡进行编译 l  实现一个三角形Triangle类 在该类中加载着色器.初始化顶点数据.初始化着色器以及绘制三角形方法 l ...

最新文章

  1. 2018-2019-2 网络对抗技术 20165320 Exp4 恶意代码分析
  2. java公平所与非公平所_一张图读懂Java非公平锁与公平锁
  3. More Effective C++: 01基础议题
  4. php如何通过变量销毁unset的过程讲解
  5. Navicat for MySQL - 破解
  6. [html] 你知道短链接的生成原理吗?
  7. 查询数据库前十条数据_入门数据分析的一些建议
  8. inject 响应式_Vue 3 组合式 provide/inject
  9. java中的随机生成算法_随机生成算法的java代码太复杂了
  10. CentOS7源码安装Python3
  11. C语言经典100道编程案例
  12. 计算机自动开机什么愿意,电脑自动开关机是什么原因 怎么解决呢
  13. java 堆栈内存例子,内存溢出OOM和堆栈溢出SOF的示例
  14. OpenGLES2.0渲图步骤:绘几何图形、图片处理、离屏渲染(3)
  15. 用 vs 跑 lvgl 模拟器
  16. python 题目是idle的文件模式是什么_python的idle如何使用
  17. 雲禾遗密:Web3js调用智能合约查看某账户ERC20代币数量
  18. 基于SSM框架的音乐网站系统设计与实现
  19. dism 分割镜像_DISM对原版镜像进行改造___整合驱动及补丁
  20. go 判断切片是否存在某元素_Golang切片(Slice)

热门文章

  1. 储能市场规模将达1000亿元 化工人才招聘需求上涨
  2. 【bfs】jzoj1235 洪水 纪中集训提高B组
  3. 5000元高端投影仪双十一怎么选?极米H6 4K高亮定焦版成为首选
  4. CDA数据分析师和北京联通进行企业内训合作
  5. 会员电商和传统电商的区别在哪里?
  6. 上海程序员哭诉:36岁被裁员,存款仅余80万,感觉天塌了!
  7. 自己买双色球杀号选号花费中奖记录地址
  8. SpringBoot中使用邮箱接口
  9. 如何做一个合格的微软技术工程师
  10. 工程师职称评审的好处